154 #ifndef ST_NO_EXCEPTIONS
155 # include <stdexcept>
156 # if !defined(ST_NO_NAMESPACES)
157 using std::range_error;
162 #include "SystemOfUnits.h"
163 #ifndef ST_NO_NAMESPACES
164 using namespace units;
166 #include "StTrsWireHistogram.hh"
167 #include "StTrsRandom.hh"
172 RandGauss StTrsWireHistogram::mGaussianDistribution(mEngine);
182 mDoGasGainFluctuations(true),
183 mGasGainCalculationDone(false),
184 mDoSingleElectronMultiplication(false),
189 mSectorWires.reserve(10000);
191 random=&(StTrsRandom::inst());
192 mNumberOfEntriesInTable=4000;
194 mNumberOfInnerSectorAnodeWires =
195 mGeomDb->numberOfInnerSectorAnodeWires();
196 mNumberOfOuterSectorAnodeWires =
197 mGeomDb->numberOfOuterSectorAnodeWires();
199 mTotalNumberOfAnodeWires =
200 mNumberOfInnerSectorAnodeWires + mNumberOfOuterSectorAnodeWires;
201 mSectorWires.resize(mTotalNumberOfAnodeWires);
204 gasGainCalculation();
205 mGasGainCalculationDone =
true;
206 FreqFunctionTableBuilder();
208 dx[0]=mOmegaTau*0.14/::sqrt((1+mOmegaTau*mOmegaTau)*(1+mOmegaTau*mOmegaTau)*0.75+0.25);
209 dx[1]=mOmegaTau*0.04/::sqrt((1+mOmegaTau*mOmegaTau)*(1+mOmegaTau*mOmegaTau)*0.925+0.075);
220 StTrsWireHistogram::~StTrsWireHistogram() {}
222 void StTrsWireHistogram::FreqFunctionTableBuilder()
227 Double_t x = 1.0*cntr*mRangeOfTable/mNumberOfEntriesInTable;
228 Double_t y = TMath::Erf(x);
229 mFreqFunctionTable.push_back(y);
231 }
while(cntr < mNumberOfEntriesInTable);
234 double StTrsWireHistogram::table_fast(
double argument)
const
241 float a =argument/mRangeOfTable*mNumberOfEntriesInTable;
244 index = (int)(a+0.5);
245 if(index>=mNumberOfEntriesInTable)
return 1.0;
246 return mFreqFunctionTable[index];}
248 {index = (int)(-a+0.5);
249 if(index>=mNumberOfEntriesInTable)
return -1.0;
250 return -mFreqFunctionTable[index];}
261 std::cerr <<
"Cannot make a second instance of StTrsWireHistogram() " << endl;
262 std::cerr <<
"Continuing..." << endl;
271 double Q=bin.numberOfElectrons();
273 double innerSectorBoundary = mGeomDb->firstOuterSectorAnodeWire() - 0.5*mGeomDb->anodeWirePitch();
275 double yCoordinateOfHit = random->Gaus(bin.position().y(),(bin.sigmaT()+d[1]/12)/::sqrt(Q));
276 double sigma=bin.sigmaT();
277 double D=mGeomDb->anodeWirePitch()/2.;
284 double yMax=yCoordinateOfHit+1.5*sigma+dy/2.0;
285 double yMin=yCoordinateOfHit-1.5*sigma-dy/2.0;
289 int WireHigh,WireLow;
290 if(yCoordinateOfHit < innerSectorBoundary) {
292 (int)((yMax - mGeomDb->firstInnerSectorAnodeWire())/mGeomDb->anodeWirePitch()+0.5);
294 (int)((yMin - mGeomDb->firstInnerSectorAnodeWire())/mGeomDb->anodeWirePitch() + .5);
295 WireHigh=min(mGeomDb->numberOfInnerSectorAnodeWires() - 1,WireHigh);
296 WireLow=max(1,WireLow);
301 WireHigh=(int)((yMax - mGeomDb->firstOuterSectorAnodeWire())/mGeomDb->anodeWirePitch() + .5);
303 WireLow =(int)((yMin - mGeomDb->firstOuterSectorAnodeWire())/mGeomDb->anodeWirePitch() + .5);
304 WireHigh=min(mGeomDb->numberOfOuterSectorAnodeWires() - 1,WireHigh)+mGeomDb->numberOfInnerSectorAnodeWires();
305 WireLow=max(1,WireLow)+mGeomDb->numberOfInnerSectorAnodeWires();
319 for(WireIndex=WireLow;WireIndex<=WireHigh;WireIndex++)
321 for(gWire=-2;gWire<2;gWire++){
323 y2=(wireCoordinate(WireIndex)+w*gWire+w/2+D+dy-yCoordinateOfHit)/sigma/M_SQRT2;
324 y1=(wireCoordinate(WireIndex)+w*gWire+w/2-D+dy-yCoordinateOfHit)/sigma/M_SQRT2;
325 y4=(wireCoordinate(WireIndex)+w*gWire+w/2+D-dy-yCoordinateOfHit)/sigma/M_SQRT2;
326 y3=(wireCoordinate(WireIndex)+w*gWire+w/2-D-dy-yCoordinateOfHit)/sigma/M_SQRT2;
331 Prob=y2*table_fast(y2)-y1*table_fast(y1)
332 -y4*table_fast(y4)+y3*table_fast(y3)
333 +1./::sqrt(M_PI)*(exp(-y2*y2)- exp(-y1*y1)
334 +exp(-y3*y3)- exp(-y4*y4));
335 Prob=Prob*sigma/dy/4.0*M_SQRT2;
337 nQOnWire= (int)(Prob* Q+0.5);
338 Qtotal+=(int)nQOnWire;
339 if( Qtotal> Q)nQOnWire--;
353 newx=random->Gaus(bin.position().x(),(bin.sigmaT()+d[0]/12)/::sqrt(nQOnWire));
355 newz=random->Gaus(bin.position().z(),(bin.sigmaL()+d[2]/12)/::sqrt(nQOnWire));
358 if(sector>12.5)newx+=dx[gWire+2];
371 wireCoordinate(WireIndex),
382 double avalancheFactor = nQOnWire;
384 if(nQOnWire<6.5)mDoSingleElectronMultiplication=1;
386 if(mDoSingleElectronMultiplication) {
389 polyaAvalanche(WireIndex,avalancheFactor );
393 gaussianAvalanche(WireIndex, avalancheFactor);
397 if(avalancheFactor<0.5)
continue;
399 theNewSegment(position,0,bin.sigmaL(),sigma,bin.d(),bin.id());
400 theNewSegment.setNumberOfElectrons((
int)(avalancheFactor+0.5));
410 double distanceToWire =
411 fabs(yCoordinateOfHit - wireCoordinate(WireIndex));
413 #ifndef ST_NO_NAMESPACES
414 using namespace units;
416 double increase = 250*micrometer/millimeter*distanceToWire;
418 double oldDriftLength = bin.position().z();
419 theNewSegment.position().setZ((oldDriftLength+increase));
442 mSectorWires[WireIndex].push_back(theNewSegment);
446 if (mMin<0) mMin = WireIndex;
447 if (mMax<0) mMax = WireIndex;
448 if (mMin >WireIndex ) mMin = WireIndex;
449 if (mMax <WireIndex) mMax = WireIndex;
461 void StTrsWireHistogram::clear()
468 int sz = mSectorWires.size();
469 mSectorWires.clear();
470 mSectorWires.resize(sz);
476 double StTrsWireHistogram::wireCoordinate(
int index)
const
478 double wireY = (index < mNumberOfInnerSectorAnodeWires) ?
479 mGeomDb->firstInnerSectorAnodeWire() + (index)*mGeomDb->anodeWirePitch() :
480 mGeomDb->firstOuterSectorAnodeWire() + (index-mGeomDb->numberOfInnerSectorAnodeWires())*mGeomDb->anodeWirePitch();
485 aTpcWire& StTrsWireHistogram::getWire(
int num)
487 if(num>=0 && num<mTotalNumberOfAnodeWires) {
488 return mSectorWires[num];
491 #ifndef ST_NO_EXCEPTIONS
492 throw range_error(
"Bounds error in StTrsWireHistogram::wire()");
494 std::cerr <<
"Bounds error...only " << mTotalNumberOfAnodeWires <<
" wires." << endl;
495 std::cerr <<
"Exitting..." << endl;
496 return mSectorWires[0];
502 aTpcWirePlane& StTrsWireHistogram::getWireHistogram()
520 void StTrsWireHistogram::setDoGasGainFluctuations(
bool doIt)
523 if(doIt && !mDoGasGain)
526 mDoGasGainFluctuations = doIt;
531 void StTrsWireHistogram::setGasGainInnerSector(
double v)
533 mInnerSectorGasGain = v;
534 cout <<
"Gas gain IS: " << mInnerSectorGasGain << endl;
538 void StTrsWireHistogram::setGasGainOuterSector(
double v)
540 mOuterSectorGasGain = v;
541 cout <<
"Gas gain OS: " << mOuterSectorGasGain << endl;
544 double StTrsWireHistogram::polya(){
547 x=StTrsRandom::inst().Rndm()*8.0;
548 y=StTrsRandom::inst().Rndm();
549 }
while(y>2.4395225*x*::sqrt(x)/exp(x));
553 double StTrsWireHistogram::polyaAvalanche(
int iWire,
double numElec)
555 double gasGainFactor;
556 double electrons = 0;
558 mInnerSectorGasGain=3558;
560 mOuterSectorGasGain=1310;
561 if(mDoGasGainFluctuations) {
564 gasGainFactor = polya();
565 electrons += gasGainFactor;
567 }
while(ctr<numElec);
569 electrons =(iWire < mNumberOfInnerSectorAnodeWires) ?
570 electrons*b*mInnerSectorGasGain:
571 electrons*b*mOuterSectorGasGain;
574 electrons = (iWire < mNumberOfInnerSectorAnodeWires) ?
575 numElec*mInnerSectorGasGain :
576 numElec*mOuterSectorGasGain;
580 double StTrsWireHistogram::exponentialAvalanche(
int iWire,
double numElec)
582 double gasGainFactor;
583 double electrons = 0;
584 mInnerSectorGasGain=3558;
586 mOuterSectorGasGain=1310;
587 if(mDoGasGainFluctuations) {
590 gasGainFactor = (iWire < mNumberOfInnerSectorAnodeWires) ?
591 mExponentialDistribution.shoot(mInnerSectorGasGain) :
592 mExponentialDistribution.shoot(mOuterSectorGasGain);
593 electrons += gasGainFactor;
595 }
while(ctr<numElec);
598 electrons = (iWire < mNumberOfInnerSectorAnodeWires) ?
599 numElec*mInnerSectorGasGain :
600 numElec*mOuterSectorGasGain;
605 double StTrsWireHistogram::gaussianAvalanche(
int iWire,
double numElec)
615 mInnerSectorGasGain=3558;
617 mOuterSectorGasGain=1310;
619 if(mDoGasGainFluctuations)
620 return (iWire < mNumberOfInnerSectorAnodeWires) ?
621 mGaussianDistribution.shoot(mInnerSectorGasGain*numElec,mInnerSectorGasGain*::sqrt(numElec*b)):
622 mGaussianDistribution.shoot(mOuterSectorGasGain*numElec,mOuterSectorGasGain*::sqrt(numElec*b));
626 return (iWire < mNumberOfInnerSectorAnodeWires) ?
627 mInnerSectorGasGain*numElec:
628 mOuterSectorGasGain*numElec;
634 double StTrsWireHistogram::noFluctuations(
int wireIndex)
const
636 return (wireIndex<mNumberOfInnerSectorAnodeWires) ?
637 mInnerSectorGasGain : mOuterSectorGasGain;
640 void StTrsWireHistogram::gasGainCalculation()