186 #include "SystemOfUnits.h"
187 #include "PhysicalConstants.h"
189 #include "StTrsParameterizedAnalogSignalGenerator.hh"
190 #ifndef TPC_DATABASE_PARAMETERS
191 #include "StTpcLocalSectorCoordinate.hh"
193 #include "StDbUtilities/StTpcLocalSectorCoordinate.hh"
195 #if defined (__SUNPRO_CC) && __SUNPRO_CC >= 0x500
198 #include "StTrsRandom.hh"
200 static const double sigmaL = .037*centimeter/::sqrt(centimeter);
202 static const double sqrtTwoPi = ::sqrt(twopi);
205 static const double FractionCut = 0.7;
216 mPadResponseFunctionSigmaOuter(0.3913),
217 mPadResponseFunctionSigmaInner(0.1964)
224 mDriftVelocity = mSCDb->driftVelocity(13);
226 mSamplingFrequency = mElectronicsDb->samplingFrequency();
227 mTimeBinWidth = 1./mSamplingFrequency;
229 mTau =mElectronicsDb->tau();
230 mPadResponseFunctionSigma =0;
233 mFractionSampled=1.0;
244 mChargeFractionOuter.push_back(0.33);
245 mChargeFractionOuter.push_back(0.32);
246 mChargeFractionOuter.push_back(0.2515);
247 mChargeFractionOuter.push_back(0.0856);
248 mChargeFractionOuter.push_back(0.01607);
249 mChargeFractionOuter.push_back(0.0036);
250 mChargeFractionInner.push_back(0.333);
251 mChargeFractionInner.push_back(0.298);
252 mChargeFractionInner.push_back(0.038);
253 mChargeFractionInner.push_back(0.00181);
254 mChargeFractionInner.push_back(0.0000);
255 mChargeFractionInner.push_back(0.0000);
262 mNumberOfEntriesInTable=4000;
264 errorFunctionTableBuilder();
266 mCentralPad = mCentralRow = 0;
267 mNumberOfRows = mGeomDb->numberOfRows();
268 mNumberOfInnerRows = mGeomDb->numberOfInnerRows();
269 mFrischGrid = mGeomDb->frischGrid();
270 rowNormalization = padWidth = padLength = 0;
271 zoffset = wire_to_plane_coupling = 0;
272 delx = gridMinusZ = sigma_x = 0;
273 dely = constant = localYDirectionCoupling = 0;
274 timeOfSignal = chargeOfSignal = 0;
276 sigmaLoverTau = sigmaL/mTau;
277 lambda = lambdasqr=0;
283 mAdcConversion=mElectronicsDb->adcConversion();
284 landauConstant=0.2703;
287 expConstant=1.56538/10.;
291 GausConstant[0]=0.2482;
293 GausSigma2[0]=1.326*1.326;
295 ExpConstant[0]=1.46831;
296 ExpSlope[0]=-0.569438;
299 GausConstant[1]=0.315;
301 GausSigma2[1]=1.464*1.464;
303 ExpConstant[1]=1.44213;
304 ExpSlope[1]=-0.55952;
307 GausConstant[2]=0.2153;
309 GausSigma2[2]=1.636*1.636;
311 ExpConstant[2]=1.4916;
312 ExpSlope[2]=-0.55763;
317 GausSigma2[3]=1.83*1.83;
319 ExpConstant[3]=1.73945;
320 ExpSlope[3]=-0.57317;
323 GausConstant[4]=0.1861;
325 GausSigma2[4]=1.983*1.983;
327 ExpConstant[4]=1.54719;
328 ExpSlope[4]=-0.544514;
330 GausConstant[5]=0.1734;
332 GausSigma2[5]=2.17*2.17;
334 ExpConstant[5]=1.70843;
335 ExpSlope[5]=-0.54852;
340 StTrsParameterizedAnalogSignalGenerator::~StTrsParameterizedAnalogSignalGenerator() {}
343 StTrsParameterizedAnalogSignalGenerator::instance()
346 #ifndef ST_NO_EXCEPTIONS
347 throw domain_error(
"StTrsParameterizedAnalogSignalGenerator::instance() Invalid Arguments");
349 cerr <<
"StTrsParameterizedAnalogSignalGenerator::instance() Invalid Arguments" << endl;
350 cerr <<
"Cannot create Instance" << endl;
351 cerr <<
"Exitting..." << endl;
368 void StTrsParameterizedAnalogSignalGenerator::errorFunctionTableBuilder()
374 Double_t x = 1.0*cntr*mRangeOfTable/mNumberOfEntriesInTable;
375 Double_t y = TMath::Erf(x);
376 mErrorFunctionTable.push_back(y);
379 }
while(cntr < mNumberOfEntriesInTable);
382 void StTrsParameterizedAnalogSignalGenerator::localArrayBuilder()
384 int rows=mNumberOfRows;
387 for(row=0;row<rows;row++)
388 {
int max_pads=mGeomDb->numberOfPadsAtRow(row+1);
389 mPadsAtRow[row]=max_pads;
390 yCentroid[row]=transformer.yFromRow(20,row+1);
391 for(pad=0;pad<max_pads;pad++)
392 { xCentroid[row][pad]=transformer.xFromPad(20,row+1,pad+1);
402 double StTrsParameterizedAnalogSignalGenerator::erf_fast(
double argument)
const
406 float a =argument/mRangeOfTable*mNumberOfEntriesInTable;
409 index = (int)(a+0.5);
410 if(index>=mNumberOfEntriesInTable)
return 1.0;
411 return mErrorFunctionTable[index];}
413 {index = (int)(-a+0.5);
414 if(index>=mNumberOfEntriesInTable)
return -1.0;
415 return -mErrorFunctionTable[index];}
421 void StTrsParameterizedAnalogSignalGenerator::inducedChargeOnPad(
StTrsWireHistogram* wireHistogram, Int_t sector)
422 {
double offset=transformer.zFromTB(0,sector,45);
426 double InOuterFactor=1.0075;
427 double charge_fraction[7];
430 double pitch=mGeomDb->anodeWirePitch();
438 PR(wireHistogram->minWire());
439 PR(wireHistogram->maxWire());
441 if(wireHistogram->minWire()<0) {
442 cerr <<
"Wire Plane is empty" << endl;
445 double x,y,z,xCentroidOfPad,yCentroidOfPad;
449 tZero=mElectronicsDb->tZero();
451 mDriftVelocity = mSCDb->driftVelocity(sector);
453 mSamplingFrequency = mElectronicsDb->samplingFrequency();
454 mTimeBinWidth = 1./mSamplingFrequency;
455 mTau =mElectronicsDb->tau();
456 int bin_start,bin_end;
457 int pad_start,pad_end=max(mPadsAtRow[mNumberOfInnerRows-1],mPadsAtRow[mNumberOfRows-1])+1;
458 int row_start,row_end;
459 int pad_shift,pad_shift0=-999999;
461 bin_end=mGeomDb->numberOfTimeBuckets();
463 row_end= mNumberOfRows;
465 int Nrbp = row_end*bin_end*pad_end;
470 for(
int jj=wireHistogram->minWire(); jj<=wireHistogram->maxWire(); jj++) {
474 aTpcWire currentWire = wireHistogram->getWire(jj);
475 aTpcWire::iterator iter;
479 int timeBinUpperLimit = 6;
480 int timeBinLowerLimit = 2;
481 double dAvalanch=0.015;
482 int bin_low,bin_high;
487 double *D,Dx,sigmaLz,Dt,sigmaLt;
489 for(iter = currentWire.begin();
490 iter != currentWire.end();
492 const int id = iter->id();
493 z=iter->position().z();
496 Dt=D[2]/mDriftVelocity;
500 mCentralRow = transformer.rowFromLocal(iter->position(),sector);
501 if ((mCentralRow <= 13 && z > -0.2) ||
502 (mCentralRow > 13 && z > -0.4)) {z = - z;}
504 cout<<
"wrong z in function StTrsPara..e..."<<z<<endl;
508 sigmaLz=sigmaL* ::sqrt(z);
509 sigmaLt=sigmaLz/mDriftVelocity;
511 (z-offset)/mDriftVelocity;
515 if(signalTime<0.)
continue;
519 pulseHeight= iter->numberOfElectrons();
521 bin_low=max(0,(
int)(signalTime/mTimeBinWidth)-timeBinLowerLimit+1);
522 bin_high=min(max_bin-1,(
int)(signalTime/mTimeBinWidth)+timeBinUpperLimit);
532 for(
int itbin=bin_low;itbin<=bin_high;itbin++){
533 SignalInTimeBin[itbin]=0.;
534 timeBinT = itbin*mTimeBinWidth;
536 t=(timeBinT-signalTime)/mTau;
538 SignalInTimeBin[itbin]=landauConstant*exp(-(t-landauMean)*(t-landauMean))/(2.*landauSigma*landauSigma)*mTimeBinWidth/mTau;
540 SignalInTimeBin[itbin]=expConstant*exp(t*expSlope)*mTimeBinWidth/mTau;
547 int index=(int)((A-0.6)/0.2);
548 if(index>=5.5)index=5;
549 for(
int itbin=bin_low;itbin<=bin_high;itbin++){
550 SignalInTimeBin[itbin]=0.;
551 timeBinT = itbin*mTimeBinWidth;
553 t=(timeBinT-signalTime)/mTau;
555 SignalInTimeBin[itbin]=GausConstant[index]*exp(-(t-GausMean[index])*(t-GausMean[index])/(2.*GausSigma2[index]))*mTimeBinWidth/mTau;
557 SignalInTimeBin[itbin]=ExpConstant[index]*exp(t*ExpSlope[index])*mTimeBinWidth/mTau;}
582 x=iter->position().x();
583 y=iter->position().y();
588 sigma_x = iter->sigmaT();
597 mCentralRow = transformer.rowFromLocal(iter->position(), sector)-1;
605 if(y < mGeomDb->outerSectorEdge()) {
607 mRowLimits.second= mCentralRow;
608 mRowLimits.first= mCentralRow;
610 mPadResponseFunctionSigma= mPadResponseFunctionSigmaInner;
613 wire_to_plane_coupling=0.533*InOuterFactor;
614 charge_fraction[0]=mChargeFractionInner[0];
615 charge_fraction[1]=mChargeFractionInner[1];
616 charge_fraction[2]=mChargeFractionInner[2];
617 charge_fraction[3]=mChargeFractionInner[3];
618 charge_fraction[4]=mChargeFractionInner[4];
619 charge_fraction[5]=mChargeFractionInner[5];
623 mRowLimits.first = max(mCentralRow - mDeltaRow, mNumberOfInnerRows);
624 mRowLimits.second = min(mCentralRow + mDeltaRow,mNumberOfRows-1);
627 mPadResponseFunctionSigma= mPadResponseFunctionSigmaOuter;
630 wire_to_plane_coupling=0.512;
631 charge_fraction[0]=mChargeFractionOuter[0];
632 charge_fraction[1]=mChargeFractionOuter[1];
633 charge_fraction[2]=mChargeFractionOuter[2];
634 charge_fraction[3]=mChargeFractionOuter[3];
635 charge_fraction[4]=mChargeFractionOuter[4];
636 charge_fraction[5]=mChargeFractionOuter[5];
642 sigma_xpad2=sigma_x *sigma_x+ mPadResponseFunctionSigma*mPadResponseFunctionSigma;
643 for(
int irow2=mRowLimits.second; irow2>=mRowLimits.first; irow2--) {
645 PadsAtRow=mPadsAtRow[irow2]-1;
646 yCentroidOfPad = yCentroid[irow2];
649 dely = fabs(yCentroidOfPad-y);
650 wire_index=(int)(fabs(dely)/pitch+0.5);
652 localYDirectionCoupling =charge_fraction[wire_index];
654 localYDirectionCoupling =0.;
655 if(localYDirectionCoupling<1.e-5)
continue;
660 mCentralPad = (Int_t) transformer.padFromLocal(iter->position(),sector,irow2+1)-1;
661 if(mCentralPad> PadsAtRow)mCentralPad= PadsAtRow;
665 mPadLimits.first = max(mCentralPad - mDeltaPad ,0);
666 mPadLimits.second =min(mCentralPad +mDeltaPad ,PadsAtRow);
667 pad_shift0=PadsAtRow;
670 for(
int ipad2=mPadLimits.first; ipad2<=mPadLimits.second; ipad2++) {
679 xCentroidOfPad = xCentroid[irow2][ipad2];
682 delx = xCentroidOfPad-x;
690 localXDirectionCoupling[ipad2]= mPadResponseFunctionSigma/Dx*(erf_fast((Dx/2-delx)/::sqrt(2*sigma_xpad2))-erf_fast((-Dx/2-delx)/::sqrt(2*sigma_xpad2)))*0.5;
700 chargeOfSignal=localYDirectionCoupling*localXDirectionCoupling[ipad2]*pulseHeight*mGain;
701 if(chargeOfSignal<0.)
continue;
705 for(
int itbin2=bin_low;itbin2<=bin_high;itbin2++){
708 index=(irow2*pad_end+ipad2)*bin_end+itbin2;
710 addSignal(
id, chargeOfSignal*SignalInTimeBin[itbin2], *(SignalSum+index));
718 pad_shift=(PadsAtRow-pad_shift0)/2;
720 for(
int ipad22=mPadLimits.first; ipad22<=mPadLimits.second; ipad22++) {
725 if((ipad22+pad_shift)<0||(ipad22+pad_shift)> PadsAtRow)
continue;
739 chargeOfSignal=localYDirectionCoupling*localXDirectionCoupling[ipad22]*pulseHeight*mGain ;
742 if(chargeOfSignal<0.)
continue;
752 for(
int itbin22=bin_low;itbin22<=bin_high;itbin22++){
753 index=irow2*bin_end*pad_end+(ipad22+pad_shift)*bin_end+itbin22;
756 addSignal(
id, chargeOfSignal*SignalInTimeBin[itbin22], *(SignalSum+index));
778 for(
int irow3=row_start;irow3<row_end;irow3++)
781 int pad_end2= mPadsAtRow[irow3];
782 for(
int ipad3=pad_start;ipad3<pad_end2;ipad3++)
784 mDiscreteAnalogTimeSequence.clear();
785 for(
int itbin3=bin_start;itbin3<bin_end;itbin3++)
787 index=irow3*pad_end*bin_end+ipad3*bin_end+itbin3;
789 double a=(*(SignalSum+index)).Sum;
793 a+=(addNoise(mNoiseRMS)*mAdcConversion);
795 if(a<=mSignalThreshold)
continue;
796 int id = SignalId(*(SignalSum+index));
797 mElectronicSignal.setId(
id);
798 mElectronicSignal.setTime(itbin3);
799 mElectronicSignal.setAmplitude(a*normalFactor);
800 mDiscreteAnalogTimeSequence.push_back(mElectronicSignal);
804 if(mDiscreteAnalogTimeSequence.size()>0)mSector->assignTimeBins(irow3+1,ipad3+1,mDiscreteAnalogTimeSequence);
811 double StTrsParameterizedAnalogSignalGenerator::realShaperResponse(
double tbin,
StTrsAnalogSignal& sig)
825 K = sigmaLoverTau*::sqrt((tzero- mTimeShiftOfSignalCentroid)/mDriftVelocity);
832 lambda = (tzero - t)/(K*mTau) + K;
833 lambdasqr = lambda*lambda;
835 value = .5/(mTau)*sqr(K)*exp(K*(lambda-.5*K))*
836 ( .5*(1+lambdasqr)*(1-erf_fast(lambda)) -
838 lambda/sqrtTwoPi*exp(-.5*lambdasqr));
844 value *= sig.amplitude();
850 void StTrsParameterizedAnalogSignalGenerator::addSignal(
const int id,
const double signal,
SignalSum_t &S) {
853 if (! S.TrackId ) S.TrackId = id;
855 if ( S.TrackId !=
id && S.Sum < 2*signal) S.TrackId = id;
860 int StTrsParameterizedAnalogSignalGenerator::SignalId(
SignalSum_t &S) {
861 return S.TrackId > 0 ? S.TrackId : 0;
865 double StTrsParameterizedAnalogSignalGenerator::addNoise(
double sigma)
869 y = StTrsRandom::inst().Rndm();
870 if (!y) y = StTrsRandom::inst().Rndm();
871 z = StTrsRandom::inst().Rndm();
874 return sigma*sin(x)*::sqrt(-2*::log(y));
879 void StTrsParameterizedAnalogSignalGenerator::sampleAnalogSignal()
881 cout <<
"StTrsParameterizedAnalogSignalGenerator::sampleAnalogSignal()" << endl;
886 #ifndef ST_NO_TEMPLATE_DEF_ARGS
887 vector<StTrsAnalogSignal> continuousAnalogTimeSequence;
890 vector<StTrsAnalogSignal, allocator<StTrsAnalogSignal> > continuousAnalogTimeSequence;
895 int timeBinUpperLimit = 7;
896 int timeBinLowerLimit = 3;
900 int bin_low,bin_high;
902 max_bin=mGeomDb->numberOfTimeBuckets();
904 for(
int irow=1; irow<=mSector->numberOfRows(); irow++) {
905 max_pad=mSector->numberOfPadsInRow(irow);
906 for(
int ipad=1; ipad<=max_pad; ipad++) {
908 continuousAnalogTimeSequence = mSector->timeBinsOfRowAndPad(irow,ipad);
910 mDiscreteAnalogTimeSequence.clear();
914 if(!continuousAnalogTimeSequence.size())
continue;
921 for(mTimeSequenceIterator = continuousAnalogTimeSequence.begin();
922 mTimeSequenceIterator!=continuousAnalogTimeSequence.end();
923 mTimeSequenceIterator++) {
925 signalTime = mTimeSequenceIterator->time();
926 pulseHeight=mTimeSequenceIterator->amplitude();
927 bin_low=max(0,(
int)(signalTime/mTimeBinWidth)-timeBinLowerLimit+1);
928 bin_high=min(max_bin,(
int)(signalTime/mTimeBinWidth)+timeBinUpperLimit);
932 for(
int itbin=bin_low;itbin<=bin_high;itbin++){
933 timeBinT = itbin*mTimeBinWidth;
934 K = sigmaLoverTau*::sqrt((signalTime- mTimeShiftOfSignalCentroid)/mDriftVelocity);
935 lambda = (-timeBinT +signalTime)/(K*mTau) + K;
936 lambdasqr = lambda*lambda;
937 SignalInTimeBin[itbin]+=(sqr(K)*exp(K*(lambda-.5*K))*
938 ( .5*(1+lambdasqr)*(1-erf_fast(lambda)) -
940 lambda/sqrtTwoPi*exp(-.5*lambdasqr)))
952 for(
int itbin=0;itbin<max_bin;itbin++){
956 if( SignalInTimeBin[itbin]<mSignalThreshold)
continue;
963 mElectronicSignal.setTime(itbin);
964 mElectronicSignal.setAmplitude(SignalInTimeBin[itbin]);
965 mDiscreteAnalogTimeSequence.push_back(mElectronicSignal);
971 mSector->assignTimeBins(irow,ipad,mDiscreteAnalogTimeSequence);