// // ================================================================================ // Straw tube response simulation // // // // mandatory call at the beginning // once to set constants // // void TConst(Double_t Radius, Double_t pSTP, Double_t ArP, Double_t CO2P); // // Pysical (garfield) values: // Radius Press (pSTP) % Ar (ArP) % CO2 (CO2P) // 0.4 1 0.9 0.1 // 0.5 1 0.9 0.1 // 0.5 2 0.8 0.2 // // // initialization at each track for MC applications // // define particle and its in-out hits // void TInit(Double_t Mass, Double_t Momentum, Double_t InOut[]) // // void PutWireXYZ(Double_t w1, Double_t w2, Double_t w3, // Double_t w4, Double_t w5, Double_t w6); define the wire // // Double_t PartToTime(Double_t Mass, Double_t Momentum, // Double_t InOut[] ); straw time // // Double_t PartToADC(); ADC charge // signal corresponding to the energy loss of StrawCharge // for energy loss simulation // // where: // // pSTP = pressure in bar // Radius = tube radius // ArP and CO2P percentages of Argon and CO2 // w1:w6 = coordinates of the extremes of the straw wire (straw axis) // Mass, Momentm = mass and momentum of the MC particle // InOut[0:5] = straw input and output coordinates traversed from the MC particle // // Routine for off line reconstruction // // Double_t TimnsToDiscm(Double_t time); from time (ns) to // radius in cm // where: // time: measured drift time in ns // // // // For other applications see the routines listed in TStraw.h // // Author: A. Rotondi (november 2005, revised and extended in August 2006) // // ================================================================================ // #include "TRandom.h" #include "TMath.h" #include "TStraw.h" #include "TImage.h" #include "TVector3.h" #include "TVectorD.h" #include "TMatrixD.h" #include "TMatrixDEigen.h" ClassImp(TStraw); // ============================================================ TStraw::TStraw() { CNumb=0; memset(CumClus,0,sizeof(CumClus)); memset(PolyaCum,0,sizeof(PolyaCum)); memset(Xs,0,sizeof(Xs)); // class constructor // clear CNumb=0; CDist.clear(); CDistC.clear(); CNele.clear(); CNeleT.clear(); TeleTime.clear(); AmplSig.clear(); Pulse.clear(); PulseT.clear(); WDist.clear(); } // ---------------------------------------------------------------------- void TStraw::TConst(Double_t R1, Double_t P1, Double_t A1, Double_t C1) { // set constants for the simulation // Input // P1 = tube absolute pressure pSTP // R1 = tube radius Radius // A1 = argon percentage ArPerc // C1 = C=2 percentage C=2Perc // Radius=R1; pSTP=P1; // Input for the media (volume percentages) ArPerc = A1; CO2Perc = C1; // cluster dimensions in Ar and CO2 (experimantal values) // Double_t PClus[20] = // {0., .656, .150, .064, .035, .0225, .0155, .0105, .0081, // .0061, .0049, .0039, .0030, .0025, .0020, .0016, .0012, // .00095, .00075, .00063}; // Fischle fit Double_t PClus[20] = {0., .802, .0707, .020, .013, .008, .006, .005, .006, .008, .009, .007, .0050, .0040, .0033, .0029, .0025, .0023, .0022, .002}; // Lapique 1st calculation // Double_t PClus[20] = // {0., .841, .0340, .021, .013, .008, .006, .004, .003, // .008, .013, .008, .0050, .004, .0030, .0028, .0025, // .0023, .0022, .002}; // Lapique 2nd calculation // Double_t PClus[20] = // {0., .656, .150, .064, .035, .0225, .0155, .0105, .0081, // .0061, .0049, .0039, .0030, .0025, .0020, .0016, .0012, // .00080, .00059, .00045}; // Fischle empirical // PDouble_t Clus[20] = // {0., .656, .148, .0649, .0337, .0244, .0141, .0078, .0095, // .0063, .0062, .0042, .0028, .0018, .0023, .0017, .0014, // .00060, .00050, .00063}; // Fischle exp Double_t CO2Clus[20] = {0., .730, .162, .038, .020, .0110, .0147, .0060, .0084, .0052, .0020, .0042, .0021, .0025, .0038, .0021, .0009, .00013, .00064, .00048}; // Fischle exp // Double_t CH4Clus[20] = // {0., .786, .120, .032, .013, .0098, .0055, .0057, .0027, // .0029, .0020, .0016, .0013, .0010, .0012, .0006, .0005, // .00042, .00037, .00033}; // Fischle exp CH4Perc = 0.07; // ----------------------------------------------------- // gain of the avalanche // Ar/CO2 90/10 1 bar (NTP) MAGY GARFIELD 20-7-2006 GasGain=90000.; // argon ---------------------------------------------------- AAr = 39.948; // Argon (39.948) ZAr= 18.0; // Argon (18) RhoAr = pSTP*1.78*1.e-03; // g/cm3 (1.78 mg/cm3) IAr = 188*1.e-09; // ionization potential (GeV) (188 eV) WiAr =26.7; // energy to create an ion pair (standard 26.7 eV) NclAr = 23.; // cluster/cm in Argon // CO2 ----------------------------------------------------- ACO2 = 44; // CO2 ZCO2 = 22.; // CO2 RhoCO2 = pSTP*1.98*1.e-03; // g/cm3 CO2 (1.98 mg/cm3) ICO2 = 95.8*1.e-09; // ionization potential (GeV) (188 eV) WiCO2 = 33.0; // energy to create an ion pair (33 eV) NclCO2 = 35.5; // clusters/cm CO2 35.5 // Methane CH4 --------------------------------------------------------- ACH4 = 16; // CO2 (39.948) ZCH4 = 10.; // CO2 (18) RhoCH4 = pSTP*0.71*1.e-03; // g/cm3 CO2 (0.71 mg/cm3) ICH4 = 40.6*1.e-09; // ionization potential (GeV) (188 eV) WiCH4 = 28.0; // energy to create an ion pair NclCH4 = 25.0; // Input for the media (weight percentages) ---------------------------- ArWPerc = ArPerc *AAr /(ArPerc*AAr + CO2Perc*ACO2); CO2WPerc = CO2Perc*ACO2/(ArPerc*AAr + CO2Perc*ACO2); // mixture densiies ---------------------------------------------------- RhoMixCO2 = 1./((ArWPerc/RhoAr) + (CO2WPerc/RhoCO2)); RhoMixCH4 = 1./((ArWPerc/RhoAr) + (CH4WPerc/RhoCH4)); //---------------------------------------------------------------------- // particles (Gev, energy losses in Kev) PZeta = 1; // projectile charge piMass = 0.139; // particle mass (GeV) eMass = 0.511/1000.; // electron mass (GeV) (0.511 MeV) prMass = 0.93827; // proton mass (GeV) // --------------------------------------------------------------------- // thresholds for the straw tubes (default values) see TInit for current values Thresh1=10; Thresh2=30; // channels for the signal Nchann = 500; // ---------------------------------------------Emin------------------------ NPolya= 100; // steps for the calculation of the Polya distributions Xmax=0.; // Polya istribution is calculated between o and Xmax (see Polya) bPolya = 0.5; Polya(bPolya); // cumulative of the Polya distribution // ----------------------------------------------------------------------- // cumulative for the number of electron per cluster Double_t Wnorm = (ArPerc*NclAr + CO2Perc*NclCO2); CumClus[0]=(ArPerc*NclAr*PClus[0] + CO2Perc*NclCO2*CO2Clus[0])/Wnorm; //for(Int_t i=1; i<=20; i++) --->> out of bounds was changed for(Int_t i=1; i<20; i++) { CumClus[i]=(ArPerc*NclAr*PClus[i] + CO2Perc*NclCO2*CO2Clus[i])/Wnorm + CumClus[i-1]; } CumClus[20]=1.; Double_t sum=0.; for(Int_t i=0; i<=19; i++) { sum += PClus[i]; //cout<<" PClus["< micron // MAGY Ar/CO2 90/10 20-7-2006 GARFIELD Double_t SigL = DiffLong(DDistcm); // ... in cm SigL *= 1.e-04; // in cm // tranverse coefficient (GARFIELD) cm--> micron // MAGY Ar/CO2 90/10 20-7-2006 GARFIELD Double_t SigT = DiffTran(DDistcm); SigT *= 1.e-04; // in cm // sampling of Longitudinal and Transverse diffusion Double_t difL = gRandom->Gaus(0.,SigL); Double_t difT = gRandom->Gaus(0.,SigT); // vector addition to the distance // the transverse component has the same dir cos of the wire XX += difL*cosx + difT*Wp; YY += difL*cosy + difT*Wq; ZZ += difL*cosz + difT*Wr; //cout<<" XYZ+ dif "< (Int_t) Cutoff) ido = (Int_t) Cutoff; for(Int_t k=0; k0){ Double_t A = 1.03e-03; Double_t B = 3.95; Double_t C = 0.228; Double_t D = -3.839e-02; Double_t E = 1.148e-03; elesig = A*exp(B*log(x)-C*x)*(1+D*x+E*x*x); } return elesig; } // ===================================================================== Int_t TStraw::StrawSignal(Int_t nsteps) { // creation of nstep values of // the straw global Pulse (sum on all clusters) // return the number of primary electrons PulseMax=0; Pulse.clear(); PulseT.clear(); AmplSig.clear(); Int_t neltot = TimeEle(); // creation and size of TeleTime (electron times) Double_t Tmax = 1.e-25; for(Int_t k=0; k< neltot; k++) if(TmaxUniform() + 0.01*Pmax*(sin(6.28*PulseT.at(k)/120.)); // if(Pulse[k]<0) Pulse[k] *= -1.; } PulseMax=Pmax; // set variable threshold for the signals Thresh1=0.05*Pmax; Thresh2=0.15*Pmax; return neltot; } // ===================================================================== Int_t TStraw::StrawTime() { // simulate the discrimination of the straw signal // and give the time // discriminator technique: set 2 threshold, select the first one // (the low one) only if the second one is fired (FINUDA system) PulseTime=0.; Int_t ind=0; Int_t flag1=0; Int_t flag2=0; for(Int_t k=0; k<(Int_t) Pulse.size(); k++){ if(flag1==0 && Pulse[k]>Thresh1) { flag1=1; ind=k; } if(Pulse[k]Thresh2) { flag2=1; break; } } if(flag1==1 && flag2==1) PulseTime=PulseT.at(ind); return ind; } // ===================================================================== Double_t TStraw::TrueDist(Double_t Point[]) { // service routine that finds the distance in cm from the wire // by knowing the wire coordinates (class variables) // and the input-output points Point[6] Double_t truedist = 0; // wire director cosines Double_t Wlength = sqrt( (Wx2-Wx1)*(Wx2-Wx1) + (Wy2-Wy1)*(Wy2-Wy1) + (Wz2-Wz1)*(Wz2-Wz1) ); Wp = (Wx2-Wx1)/Wlength; Wq = (Wy2-Wy1)/Wlength; Wr = (Wz2-Wz1)/Wlength; // director cosines of the given track Double_t Modu = sqrt( (Point[3]*Point[0])*(Point[3]*Point[0]) + (Point[4]*Point[1])*(Point[4]*Point[1]) + (Point[5]*Point[2])*(Point[5]*Point[2]) ); Double_t dcx = (Point[3]-Point[0])/Modu; Double_t dcy = (Point[4]-Point[1])/Modu; Double_t dcz = (Point[5]-Point[2])/Modu; //distance formula Double_t p1 = (Point[0]-Wx1)*(dcy*Wr-dcz*Wq); Double_t p2 =-(Point[1]-Wy1)*(dcx*Wr-dcz*Wp); Double_t p3 = (Point[2]-Wz1)*(dcx*Wq-dcy*Wp); Double_t Det = p1+p2+p3; Double_t Disc = sqrt( (dcy*Wr-dcz*Wq)*(dcy*Wr-dcz*Wq) + (dcz*Wp-dcx*Wr)*(dcz*Wp-dcx*Wr) + (dcx*Wq-dcy*Wp)*(dcx*Wq-dcy*Wp) ); if(Disc >0) truedist = TMath::Abs(Det/Disc); return truedist; // distance in cm } // ===================================================================== Double_t TStraw::TimnsToDiscm(Double_t time) { // distance in cm from time in ns for pSTP =1 and pSTP=2 atm // utility routine for the track reconstruction //last update: A. Rotondi 3-3-2007 Double_t drift, truer; // 1 absolute atm (NTP) 20-7-2006 GARFIELd Ar/CO2 90/10 MAGY // ns --> mm if(pSTP < 1.9) { if(Radius < 0.5){ // 1600 V 4 mm variable theshold // drift = -5.68738e-02 +7.06505e-03*time // +3.70423e-03*pow(time,2) -1.39795e-04*pow(time,3) // +2.59863e-06*pow(time,4) -2.75729e-08*pow(time,5) // +1.69315e-10*pow(time,6) -5.59127e-13*pow(time,7) // +7.66371e-16*pow(time,8); // 1600 V 4 mm fixed threshold // drift = 7.50700e-02 -4.58303e-02*time // +6.01476e-03*pow(time,2) -1.78491e-04*pow(time,3) // +2.82377e-06*pow(time,4) -2.60709e-08*pow(time,5) // +1.40082e-10*pow(time,6) -4.04386e-13*pow(time,7) // +4.81504e-16*pow(time,8); drift = -0.070 -1.18253e-02 -1.65315e-02 *time +6.18870e-03 *pow(time,2) -2.50647e-04 *pow(time,3) +5.15779e-06 *pow(time,4) -6.04826e-08 *pow(time,5) +4.07345e-10 *pow(time,6) -1.46437e-12 *pow(time,7) +2.17349e-15 *pow(time,8); } else{ // 1600 V 5 mm drift = - 7.43091e-02 + 6.34826e-03 *time + 2.70409e-03 *pow(time,2) - 7.96339e-05 *pow(time,3) + 1.12156e-06 *pow(time,4) - 8.76461e-09 *pow(time,5) + 3.87359e-11 *pow(time,6) - 9.05398e-14 *pow(time,7) + 8.69003e-17 *pow(time,8); } } else { // 2 absolute atm 5 mm 80/20 (1 bar overpressure) if(time < 100.) { drift = + 1.71849e-02 - 3.99942e-02 *time + 8.96815e-03 *pow(time,2) - 3.23438e-04 *pow(time,3) + 4.88349e-06 *pow(time,4) - 2.27659e-08 *pow(time,5) - 1.00527e-10 *pow(time,6) - 6.18934e-13 *pow(time,7) + 2.69373e-14 *pow(time,8) - 1.26629e-16 *pow(time,9); } else{ drift = - 2.65873e-01 + 6.20514e-02 *time + 3.42564e-05 *pow(time,2) - 1.17871e-05 *pow(time,3) + 1.59485e-07 *pow(time,4) - 9.61794e-10 *pow(time,5) + 2.79989e-12 *pow(time,6) - 3.20470e-15 *pow(time,7); } // correction of the systematic shift for r=0.5 cm 2 atm // if( drift<=4.8){ // truer= 2.36461e-01 -5.01598e-01*drift + 3.89468*pow(drift,2) // -4.17036*pow(drift,3) +2.19117*pow(drift,4) // -6.02374e-01*pow(drift,5) +8.32138e-02*pow(drift,6) // -4.55919e-03*pow(drift,7); // drift= TMath::Abs(truer); // } } drift = 0.1*drift; if(drift < 0.) drift=0.; return drift; } // -------------------------------------------------------------------------------- Double_t TStraw::PartToTime(Double_t xPMass, Double_t xPMom, Double_t InOut[]) { // find the time of a particle of mass xPmass, momentum xPMom, with // input-output coordinate InOut[6] // Useful for MC pplication after a call to PutWireXYZ TInit(xPMass, xPMom, InOut); // start the event Out1 = StrawCharge(); // energy loss (GeV) to generate charge Out2 = StrawSignal(Nchann); // generate the straw signal Out3 = StrawTime(); // find the straw drift time PulseTime return PulseTime; } // -------------------------------------------------------------------------------- Double_t TStraw::PartToADC() { // return the energy loss in the tube as charge signal // taking into account the Polya fluctuations Double_t ADCsignal=0.; for(Int_t j=1; j<= NNClus; j++){ for(Int_t jc=1; jc<=(Int_t) CNeleT[j-1]; jc++) ADCsignal += bPolya * GasGain * PolyaSamp(); } return ADCsignal; } // -------------------------------------------------------------------------------- Double_t TStraw::DiffLong(Double_t Distcm) { // return the longitudinal diffusion // from cm to microns // MAGY GARFIELD Ar/CO2 90/10 1 bar (NTP) 20-7-2006 // Double_t DiffMic; if(pSTP<1.9){ if(Radius < 0.5){ // 4 mm 1600 V 90/10 DiffMic = 0.896 + 1387.*Distcm - 1.888e+04*pow(Distcm,2) + 1.799e+05*pow(Distcm,3) - 9.848e+05*pow(Distcm,4) + 3.009e+06*pow(Distcm,5) - 4.777e+06*pow(Distcm,6) + 3.074e+06*pow(Distcm,7); } else{ // 5 mm 1600 V DiffMic = 1.537 + 1246.*Distcm - 1.357e+04*pow(Distcm,2) + 1.049e+05*pow(Distcm,3) - 4.755e+05*pow(Distcm,4) + 1.211e+06*pow(Distcm,5) - 1.6e+06*pow(Distcm,6) + 8.533e+05*pow(Distcm,7); } } else{ // 2000V 5 mm 2 bar 80/20 DiffMic = 2.135 +818.*Distcm - 1.044e+04*pow(Distcm,2) + 8.31e+04*pow(Distcm,3) - 3.492e+05*pow(Distcm,4) + 7.959e+05*pow(Distcm,5) - 9.378e+05*pow(Distcm,6) + 4.492e+05*pow(Distcm,7); } return DiffMic; } // -------------------------------------------------------------------------------- Double_t TStraw::DiffTran(Double_t Distcm) { // return the transverse diffusion in microns // from cm to microns // MAGY GARFIELD Ar/CO2 90/10 1 bar (NTP) 20-7-2006 // Double_t DiffMic; if(pSTP<1.9){ if(Radius < 0.5){ // 4 mm 1600 V 90/10 // DiffMic = + 0.8513 + 1648.*Distcm - 1.085e+04*pow(Distcm,2) // + 7.38e+04*pow(Distcm,3) - 3.025e+05*pow(Distcm,4) // + 6.067e+05*pow(Distcm,5) - 4.643e+04*pow(Distcm,6); DiffMic = + 1.482 + 1529.*Distcm - 6755.*pow(Distcm,2) + 2.924e+04*pow(Distcm,3) - 0.9246e+05*pow(Distcm,4) + 1.548e+05*pow(Distcm,5) - 1.002e+05*pow(Distcm,6); } else{ // 5 mm 1600 V 90/10 DiffMic = + 1.482 + 1529.*Distcm - 6755.*pow(Distcm,2) + 2.924e+04*pow(Distcm,3) - 0.9246e+05*pow(Distcm,4) + 1.548e+05*pow(Distcm,5) - 1.002e+05*pow(Distcm,6); } } else{ // 5 mm 2000 V 2 bar 80/20 DiffMic = +2.094 + 1138.*Distcm - 7557.*pow(Distcm,2) + 2.968e+04*pow(Distcm,3) - 6.577e+04*pow(Distcm,4) + 7.581e+04*pow(Distcm,5) - 3.497e+04*pow(Distcm,6); } return DiffMic; } // -------------------------------------------------------- Double_t TStraw::DistEle(Double_t time) { // dist in cm from time in ns for pSTP =1 and pSTP=2 // utility routine for the >SINGLE< electron reconstruction //last update: A. Rotondi 20-7-2006 Double_t drift; // 1 absolute atm (NTP) 20-7-2006 GARFIELd Ar/CO2 90/10 MAGY // ns --> cm time *= 0.001; // time in micro s if(pSTP < 2.) { if(Radius <0.5){ // 1600 V 4 mm 90/10 drift = 0.001629 + 6.194*time - 56.55*pow(time,2) + 355.8*pow(time,3) - 903.2*pow(time,4); } else{ // 1600 V 5 mm 90/10 drift = 0.003365 + 5.734*time - 41.88*pow(time,2) + 191.2*pow(time,3) - 333.4*pow(time,4) ; } } else { // 2 absolute atm 2000 V 5 mm 80/20 (1 bar overpressure) drift = 0.003365 + 7.056*time - 62.28*pow(time,2) + 306.1*pow(time,3) - 558.7*pow(time,4); } return drift; // in cm }