167 #include "StTrsChargeSegment.hh"
170 #if defined(__SUNPRO_CC) && __SUNPRO_CC < 0x500
171 #include <ospace/stl/src/randgen.cpp>
174 #ifndef ST_NO_NAMESPACES
175 using std::random_shuffle;
178 #include "StPhysicalHelix.hh"
179 #include "StParticleTable.hh"
180 #include "StParticleDefinition.hh"
182 #include "StDbUtilities/StTpcCoordinateTransform.hh"
183 #include "StTrsDeDx.hh"
184 #include "StTrsRandom.hh"
187 extern "C" float dislan_(
float &x);
188 float dislan(
float x) {
return (x<-10.)? 0.:dislan_(x);}
191 RandFlat StTrsChargeSegment::mFlatDistribution(mEngine);
193 StTrsChargeSegment::StTrsChargeSegment()
195 mSector12Position(mPosition),
201 mNumberOfElectrons(-1),
214 mSector12Position(mPosition),
220 mNumberOfElectrons(ne),
224 StTrsChargeSegment::~StTrsChargeSegment() { }
227 void StTrsChargeSegment::whichGEANTParticle(
double& particleMass,
int& charge)
231 particleMass = pDef->mass();
232 charge = (int) (pDef->charge());
235 cout <<
"Mass is Undefined (" << mPid <<
")" << endl;
236 particleMass = 0*GeV;
242 #ifndef ST_NO_TEMPLATE_DEF_ARGS
243 void StTrsChargeSegment::split(
StTrsDeDx* gasDb,
246 list<StTrsMiniChargeSegment>* listOfMiniSegments)
248 void StTrsChargeSegment::split(
StTrsDeDx* gasDb,
254 #ifndef ST_NO_NAMESPACES
255 using namespace units;
258 #ifndef ST_NO_TEMPLATE_DEF_ARGS
259 vector<int> ionization(StTrsDeDx::numberOfElectrons);
260 vector<float> theIonization;
263 vector<int, allocator<int> > ionization(StTrsDeDx::numberOfElectrons);
264 vector<float, allocator<float> > theIonization;
271 if (mNumberOfElectrons<0)
272 mNumberOfElectrons = (mDE)/(gasDb->W());
288 whichGEANTParticle(particleMass, charge);
294 if(subSegments > 1) {
298 double deltaS = mDs/
static_cast<double>(subSegments);
301 gasDb->setPadLength(deltaS*centimeter);
306 theIonization.clear();
311 double ionizationLeft = mNumberOfElectrons;
313 for(
int ii=0; ii<(subSegments-1); ii++) {
316 double betaGamma = abs(mMomentum)/particleMass;
319 gasDb->electrons(ionization, betaGamma);
321 gasDb->electrons(ionization);
324 if(ionization[StTrsDeDx::total] > ionizationLeft) {
325 theIonization.push_back(ionizationLeft);
328 theIonization.push_back(ionization[StTrsDeDx::total]);
331 ionizationLeft -= theIonization.back();
335 theIonization.push_back(ionizationLeft);
338 random_shuffle(theIonization.begin(), theIonization.end(),StTrsRandom::inst());
349 (magDb->at(mSector12Position)).z(),
358 double newPosition = -mDs/2. + deltaS/2.;
367 for(
int i=0; i<subSegments; i++) {
371 if(!theIonization[i]) {
372 newPosition += deltaS;
382 listOfMiniSegments->push_back(aMiniSegment);
384 newPosition += deltaS;
389 else if(subSegments == 1) {
394 if(aSingleMiniSegment.position().z()>0)listOfMiniSegments->push_back(aSingleMiniSegment);
400 #ifndef ST_NO_TEMPLATE_DEF_ARGS
401 void StTrsChargeSegment::tssSplit(
StTrsDeDx* gasDb,
404 list<StTrsMiniChargeSegment>* listOfMiniSegments)
406 void StTrsChargeSegment::tssSplit(
StTrsDeDx* gasDb,
412 #ifndef ST_NO_NAMESPACES
413 using namespace units;
420 if (mNumberOfElectrons<0)
424 mNumberOfElectrons = fabs(mDE)/(gasDb->W());
439 double totalNumberOfSubSegments = ::pow(2.,(numberOfLevels-1));
441 #ifndef ST_NO_TEMPLATE_DEF_ARGS
443 vector<vector<double> > ionizationSegments;
446 vector<double, allocator<double> > tmp;
447 typedef vector<double, allocator<double> > iSegs;
448 vector<iSegs , allocator<iSegs> > ionizationSegments;
455 double minimumIonizingdEdx =
456 gasDb->betheBlochTSS(3.*GeV,1,.938*GeV);
459 for(ii=0; ii<numberOfLevels; ii++)
460 ionizationSegments.push_back(tmp);
465 ionizationSegments[0].push_back(this->numberOfElectrons());
471 whichGEANTParticle(particleMass, charge);
478 double numberOfSubSegmentsInCurrentLevel;
479 double numberOfSubSegmentsInPreviousLevel;
482 gasDb->betheBlochTSS(abs(this->momentum()),charge,particleMass);
485 double mip = dEdxBethe/minimumIonizingdEdx;
489 for(ii=1; ii<numberOfLevels; ii++) {
490 numberOfSubSegmentsInCurrentLevel = 1<<(ii);
491 float dL = mDs/numberOfSubSegmentsInCurrentLevel;
496 numberOfSubSegmentsInPreviousLevel = 1<<(ii-1);
497 for(jj=0; jj<numberOfSubSegmentsInPreviousLevel; jj++) {
498 double parentdEdx = ionizationSegments[(ii-1)][jj];
500 double lengthOfSegmentToBeSplit = dL*2.;
501 double dEAverage = dEdxBethe*(lengthOfSegmentToBeSplit);
504 (parentdEdx*gasDb->W())/dEAverage;
512 xBinary = binaryPartition((lengthOfSegmentToBeSplit/centimeter),
515 ionizationSegments[ii].push_back(xBinary*parentdEdx);
516 ionizationSegments[ii].push_back((1.-xBinary)*parentdEdx);
527 mDs/
static_cast<double>(totalNumberOfSubSegments);
537 (magDb->at(mSector12Position)).z(),
546 double newPosition = -mDs/2. + deltaS/2.;
552 for(
unsigned int i=0; i<ionizationSegments[(numberOfLevels-1)].size(); i++) {
555 ionizationSegments[(numberOfLevels-1)][i],
557 if(aMiniSegment.position().z()>0)listOfMiniSegments->push_back(aMiniSegment);
559 newPosition += deltaS;
578 double StTrsChargeSegment::sigmaParameter(
double l,
double derelave,
double xmip,
int index)
const
580 double beta[2] = {1.0, 2.0};
581 double b[2] = {0.0, -0.02};
582 double gamma[2] = {.0041, .0052};
583 double c[2] = {-1.02, -1.02};
584 double delta[2] = {-.022,-.0058};
585 double d[2] = {-1.88, -1.92};
587 double a = ::pow(xmip,delta[index])+d[index]+b[index]*derelave;
588 double alpha = (::pow(xmip,gamma[index])+c[index])/(::pow(derelave,beta[index]));
589 return (::pow(l,alpha)+a);
592 double StTrsChargeSegment::meanParameter(
double l,
double derelave,
double xmip,
int index)
const
594 double a[2] = {0.367, 0.267};
595 double alpha[2] = {.05, .1};
596 double beta[2] = {.2, 1.0};
597 double gamma[2] = {.0423, .0852};
599 return ( (a[index]*::pow(l,gamma[index])*::pow(xmip,alpha[index]))/(::pow(derelave,beta[index])) );
602 double StTrsChargeSegment::xReflectedGauss(
double x0,
double sig)
const
604 double granularity = .001;
605 double root2Sigma = M_SQRT2*sig;
606 double denom = TMath::Erf((1.-x0)/root2Sigma) + TMath::Erf(x0/root2Sigma);
607 double testValue = mFlatDistribution.shoot();
615 p =.5*(1. + (TMath::Erf((x-x0)/root2Sigma) + TMath::Erf((x+x0-1)/root2Sigma))/denom);
616 if( (fabs(testValue-p)<granularity) || (fabs(xhi-xlo)<1.e-7)) {
619 else if (testValue>p) {
628 double StTrsChargeSegment::xReflectedLandau(
double x0,
double sig)
const
631 double granularity = .001;
633 float arg3 = (1.-x0)/sig;
634 float arg4 = -x0/sig;
636 float dlan3 = dislan(arg3);
637 float dlan4 = dislan(arg4);
639 double denom = dlan3 - dlan4;
641 double testValue = mFlatDistribution.shoot();
654 arg2 = (1.-x-x0)/sig;
655 dlan1 = dislan(arg1);
656 dlan2 = dislan(arg2);
657 if (isnan(dlan1)) dlan1=0;
658 p = .5*(1. + (dlan1 - dlan2)/denom);
659 if( (fabs(testValue-p)<granularity) ) {
662 else if (testValue>p) {
668 if(counter++ == 100){
669 cout <<
"Probable race condition in loop in StTrsChargeSegement::xReflectedLandau" << endl;
670 PR(arg1); PR(arg2); PR(arg3); PR(arg4);
676 double StTrsChargeSegment::binaryPartition(
double l,
double derelave,
double xmip)
const
684 double x0 = fabs(meanParameter(l,derelave,xmip,index));
685 double sig = fabs(sigmaParameter(l,derelave,xmip,index));
692 value = xReflectedGauss(x0,sig);
695 value = xReflectedLandau(x0,sig);
704 return os <<
"(Pos:" << seg.position() <<
", mon:" << seg.momentum()
705 <<
", id:" << seg.id()
706 <<
", dE:" << seg.dE()
707 <<
", dS:" << seg.ds()
708 <<
", pid:" << seg.pid()