#include <SimPmtM64Oxford.h>
Inheritance diagram for SimPmtM64Oxford:

Public Member Functions | |
| SimPmtM64Oxford (PlexPixelSpotId tube, VldContext context, TRandom *random=NULL) | |
| virtual | ~SimPmtM64Oxford () |
| virtual void | Reset (const VldContext &context) |
| virtual void | SimulateCharges () |
| virtual void | SimulatePmt () |
| virtual void | Config (Registry &config) |
Protected Member Functions | |
| virtual Float_t | GenChargeFromPE (Int_t pixel, Int_t spot, Float_t pe) |
| virtual UInt_t | SimFirstDynodes (Int_t pixel, Int_t nPe) |
| virtual UInt_t | SimLaterDynodes (Int_t pixel, Int_t neToD3) |
| virtual Bool_t | CalStageGains () |
| virtual void | SimulateAnodeEffects () |
| virtual Float_t | GenNonlinearCharge (Int_t pixel, Float_t inCharge) |
Static Protected Attributes | |
| static Bool_t | fsPmtDoChargeSmear = true |
Private Attributes | |
| Bool_t | fStagesBuilt |
| Double_t | fStageGains [65][13] |
| Double_t | fSkippingGain [65] |
| Bool_t | fOneSpot |
| VldContext | fLastVldContext |
Static Private Attributes | |
| static const Double_t | gkDefaultStageGains [13] |
| static const Double_t | gkDefaultSecEmmRatio = 4.5 |
| static const Double_t | gkNLWindowBefore = 1.8056 * Munits::ns |
| static const Double_t | gkNLWindowAfter = 0.9841 * Munits::ns |
| static Double_t | fsDynodeSkipRate = 0.00 |
| static Double_t | fsNLThreshold = 5 |
| static Double_t | fsNonlinearityScale = 1.5 |
Definition at line 14 of file SimPmtM64Oxford.h.
| SimPmtM64Oxford::SimPmtM64Oxford | ( | PlexPixelSpotId | tube, | |
| VldContext | context, | |||
| TRandom * | random = NULL | |||
| ) |
Definition at line 38 of file SimPmtM64Oxford.cxx.
References Msg::kFatal, Msg::kWarning, and MSG.
00040 : 00041 SimPmtM64Full(tube,context,random) 00042 { 00043 // check if multiple spots are active on the tube (probably 00044 // fNSpots == 1) i'm trusting that, at the very least, fNSpots is 00045 // always non-zero & positive 00046 fOneSpot = true; 00047 00048 fStagesBuilt = false; 00049 00050 if (fNSpots != 1) { 00051 fOneSpot = false; 00052 MSG("DetSim",Msg::kWarning) << "This PMT has " << fNSpots 00053 << " spots! Ready for a rough ride?" 00054 << endl; 00055 } 00056 00057 //Do some safty checks... hopefully i'll rewrite sensitive bits 00058 //with vectors, then we shouldn't need this. But for now: 00059 if (fNPixels > 64) { 00060 //were in big trouble... there pixel arrays going out of bounds 00061 MSG("DetSim",Msg::kFatal) << "Too many pixels! /n" 00062 << "Cant continue without memory carnage!" 00063 << endl; 00064 assert(0); //Die in dishonor 00065 } 00066 00067 00068 Reset(context); 00069 00070 }
| virtual SimPmtM64Oxford::~SimPmtM64Oxford | ( | ) | [inline, virtual] |
| Bool_t SimPmtM64Oxford::CalStageGains | ( | ) | [protected, virtual] |
Definition at line 122 of file SimPmtM64Oxford.cxx.
References SimPmt::fNPixels, SimPmt::fNSpots, fOneSpot, fSkippingGain, fStageGains, SimPmt::GetGainAndWidth(), gkDefaultSecEmmRatio, gkDefaultStageGains, Msg::kInfo, and MSG.
Referenced by Reset().
00123 { 00124 Bool_t success = false; 00125 00126 //Calculate the default total Gain 00127 Double_t DefaultTubeGain = 1; 00128 for (Int_t i = 1; i <= 12; i++) { 00129 DefaultTubeGain *= gkDefaultStageGains[i]; 00130 } 00131 00132 00133 for (Int_t pix = 1 ; pix <= fNPixels ; pix++){ 00134 00135 //Initialise the stage gains for each pixels 00136 for (Int_t i = 0; i <= 12; i++) { 00137 fStageGains[pix][i] = gkDefaultStageGains[i]; 00138 } 00139 00140 //Get the gain and width from the database 00141 Double_t thisPixelGain = 0; 00142 Double_t thisPixelWidth = 0; 00143 00144 if ( fOneSpot ) { 00145 00146 success = GetGainAndWidth(pix, 1, thisPixelGain, thisPixelWidth); 00147 //cout << "pixel: " << pix << endl; 00148 //cout << "Gain set to " << thisPixelGain << endl; 00149 //cout << "Width set to " << thisPixelWidth << endl;; 00150 } 00151 00152 else{ 00153 //Sum over active spots 00154 // as far as i know, there should only ever be one active spot. 00155 Double_t tempGain = 0; 00156 Double_t tempWidth = 0; 00157 Int_t nActiveSpots = 0; 00158 00159 for (Int_t spotit = 1; spotit <= fNSpots; spotit++){ 00160 GetGainAndWidth(pix, spotit, tempGain, tempWidth); 00161 if (( tempGain > 0 ) && ( tempWidth > 0 )){ 00162 thisPixelGain += tempGain; 00163 thisPixelWidth += tempWidth; 00164 nActiveSpots++; 00165 } //if (spot is okay) 00166 } //for (spots) 00167 00168 thisPixelGain /= nActiveSpots; 00169 thisPixelWidth /= nActiveSpots; 00170 00171 } // >1 spots (else) 00172 00173 // Truncate gains to 3 * 10^6 (should be much less) 00174 if (thisPixelGain > 3e6){ 00175 MSG("DetSim",Msg::kInfo ) << "Huge gain in DB: " << thisPixelGain 00176 << "\tTruncating to 3e6" << endl; 00177 thisPixelGain = 3e6; 00178 } 00179 //Calculate secondary emission (amplification at D1) correction 00180 //here we are modeling variation in the width of the 1pe peak 00181 //as being entirely due to an variation in the first stage gain 00182 00183 //first compute true (as opposed to effective) SecEmmRatio 00184 //See NuMi NOTE-Scint-934 for details 00185 00186 Double_t secEmmCrtn = 1; 00187 Double_t effSecEmmRatio = 1/( thisPixelWidth*thisPixelWidth ); //(rho) 00188 00189 //quick(er) method (accurate to ~0.6%, which is plenty) 00190 //secEmmCrtn = ( (effSecEmmRatio + 0.25) / (gkDefaultSecEmmRatio + 0.25) ); 00191 00192 //cout << "recal : "<< secEmmCrtn <<endl; 00193 00194 //full, slow(er) method 00195 secEmmCrtn = effSecEmmRatio * ( 1. + sqrt( 1. + 1./effSecEmmRatio ) ); 00196 secEmmCrtn /= gkDefaultSecEmmRatio * (1. + sqrt(1.+1./gkDefaultSecEmmRatio ) ); 00197 //cout << "full recal : "<< secEmmCrtn <<endl; 00198 00199 fStageGains[pix][1] *= secEmmCrtn; 00200 00201 //do inverse correction to other stages to renormalise gain 00202 00203 secEmmCrtn = pow(secEmmCrtn, 1./11.); 00204 00205 //cout << "inv recal = "<< 1./secEmmCrtn << endl; 00206 00207 for(Int_t i = 2; i <= 12; i++){ 00208 fStageGains[pix][i] /= secEmmCrtn; 00209 } //for (dynodes 2->12) 00210 00211 //calculate skipping gain 00212 // using g(skip) = ( g(1)^(1/beta) + g(2)^(1/beta) )^beta 00213 // with beta = 0.890199 00214 00215 const Double_t beta = 0.890199; //Measured at test stand 00216 00217 //cout << "D1 :" << fStageGains[pix][1] << endl; 00218 //cout << "D2 :" << fStageGains[pix][2] << endl; 00219 00220 fSkippingGain[pix] = pow( fStageGains[pix][1], 1./ beta ) 00221 + pow( fStageGains[pix][2], 1./ beta ); 00222 00223 //cout << "skipping gain :" << fSkippingGain[pix] << endl; 00224 00225 fSkippingGain[pix] = pow( fSkippingGain[pix], beta ); 00226 00227 //cout << "skipping gain " << fSkippingGain[pix] << endl; 00228 00229 00230 //Re-calculate pixel gain 00231 00232 Double_t gainRatio = 0; 00233 gainRatio = thisPixelGain / DefaultTubeGain ; 00234 //cout << "gainratio " << gainRatio << endl; 00235 00236 gainRatio = pow(gainRatio, 1./12.); 00237 00238 //apply correction 00239 00240 for (Int_t i = 0; i <= 12; i++) { 00241 fStageGains[pix][i] *= gainRatio; 00242 } 00243 00244 00245 //Fix the Dynode skipping gains 00246 fSkippingGain[pix] = fSkippingGain[pix] * gainRatio * gainRatio; 00247 00248 } //for (pix) 00249 00250 return success; 00251 }
| void SimPmtM64Oxford::Config | ( | Registry & | config | ) | [virtual] |
Reimplemented from SimPmtM64Full.
Definition at line 635 of file SimPmtM64Oxford.cxx.
References SimPmtM64Full::Config(), fsDynodeSkipRate, fsNLThreshold, fsNonlinearityScale, fsPmtDoChargeSmear, SimPmt::fsPmtDoNonlinearity, and Registry::Get().
00636 { 00637 double dtmp; 00638 int itmp; 00639 if(config.Get("pmtDoChargeSmear",itmp)) fsPmtDoChargeSmear = itmp; 00640 if(config.Get("pmtM64DynodeSkipRate",dtmp)) fsDynodeSkipRate = dtmp; 00641 if(config.Get("pmtM64NLThreshold",dtmp)) fsNLThreshold = dtmp; 00642 if(config.Get("pmtM64NonlinearityScale",dtmp)) fsNonlinearityScale =dtmp; 00643 00644 SimPmtM64Full::Config(config); 00645 00646 // A non linearity scale of zero is equivalent to no nonlinearity, 00647 // so turn it off now because it would also cause a FPE. 00648 // this is quicker than checking each time we go past. 00649 if (0 == fsNonlinearityScale) fsPmtDoNonlinearity = 0; 00650 }
| Float_t SimPmtM64Oxford::GenChargeFromPE | ( | Int_t | pixel, | |
| Int_t | spot, | |||
| Float_t | pe | |||
| ) | [protected, virtual] |
Reimplemented from SimPmtM64.
Definition at line 255 of file SimPmtM64Oxford.cxx.
References Munits::e_SI, Msg::kError, Msg::kInfo, MSG, SimFirstDynodes(), and SimLaterDynodes().
Referenced by SimulateCharges().
00257 { 00258 if (spot != 1) { 00259 MSG("DetSim",Msg::kError) << "Amplifiying a pe in spot "<< spot 00260 << "! This is okay... /n" 00261 << "But Non-linearity will fail" 00262 << endl; 00263 } // spot != 1 00264 00265 if (pe <= 0) return 0; 00266 00267 Int_t nPe = (Int_t) pe; 00268 00269 if (nPe > 1200){ 00270 //Scream like a baby 00271 MSG("DetSim",Msg::kInfo ) << "BIG pulse seen: " << nPe 00272 << " photoelectons." 00273 << "\tTruncating to 1200" << endl; 00274 nPe = 1200; 00275 } 00276 //this process is divided into two stages: 00277 //the first dynodes, where individual photons count 00278 //the later dynodes, where we don't notice individual photons 00279 00280 00281 UInt_t neFromD2 = SimFirstDynodes(pixel, nPe); 00282 UInt_t neToAnode = SimLaterDynodes(pixel, neFromD2); 00283 00284 return neToAnode * Munits::e_SI; 00285 00286 }
| Float_t SimPmtM64Oxford::GenNonlinearCharge | ( | Int_t | pixel, | |
| Float_t | inCharge | |||
| ) | [protected, virtual] |
Reimplemented from SimPmtM64.
Definition at line 569 of file SimPmtM64Oxford.cxx.
References Munits::e_SI, fsNLThreshold, and fsNonlinearityScale.
Referenced by SimulateAnodeEffects().
00571 { 00572 //Debug 00573 //if (fsNonlinearityScale == 0) {cout << "fsnls: exactly 0" << endl;} 00574 //else {cout << "fsnls: " << fsNonlinearityScale << endl;} 00575 00576 //Note on Tuning parameters: threshold(fsNLThreshold) and dGdQ 00577 00578 //Threshold in terms of (approx) number of pes in window. 00579 //For pulses similar in shape to the oxford test stand, and a ~3ns window 00580 //the non-linearity `turns on' for pulses sizes (in pe) of ~7 times 00581 //this threshold. 00582 00583 //dGdQ is the (Default) rate at which the gain drops off at threshold 00584 //increasing fsNonlinearityScale -> NL turns on more quickly 00585 00586 Float_t scaleNL = 1.; 00587 const Float_t qInPe = linCharge / (1e6 * Munits::e_SI); 00588 00589 const Float_t dGdQ = 3.9e-3; //Best tune from Test Stand 00590 00591 //Exponential drop off model: 00592 if (qInPe > fsNLThreshold) { 00593 const Float_t alpha = 2 * dGdQ * fsNonlinearityScale; 00594 //makes everything easier to read. 00595 00596 scaleNL = 1 - TMath::Exp( -alpha * (qInPe - fsNLThreshold) ); 00597 scaleNL /= alpha * ( qInPe - fsNLThreshold ); 00598 00599 } // if (above threshold) 00600 00601 return linCharge * scaleNL; 00602 00603 }
| void SimPmtM64Oxford::Reset | ( | const VldContext & | context | ) | [virtual] |
Reimplemented from SimPmtM64.
Definition at line 108 of file SimPmtM64Oxford.cxx.
References CalStageGains(), SimPmt::fsRebuildGainMap, fStagesBuilt, and SimPmtM64::Reset().
00109 { 00110 //Do the inherited M64 reset stuff 00111 SimPmtM64::Reset(context); 00112 00113 //Reset the gains 00114 if((!fStagesBuilt)||fsRebuildGainMap) { 00115 CalStageGains(); 00116 fStagesBuilt = true; 00117 } 00118 }
| UInt_t SimPmtM64Oxford::SimFirstDynodes | ( | Int_t | pixel, | |
| Int_t | nPe | |||
| ) | [protected, virtual] |
Definition at line 291 of file SimPmtM64Oxford.cxx.
References SimPmt::fRandom, fsDynodeSkipRate, fSkippingGain, and fStageGains.
Referenced by GenChargeFromPE().
00292 { 00293 //bah. maybe i have to burn random numbers in a binomial to 00294 //do this transparently 00295 //i'm pretty sure this does the same thing though 00296 00297 //Simulate 'skipping' path 00298 Float_t meanSkipping = nPe * fsDynodeSkipRate; 00299 UInt_t neThatSkip = 00300 fRandom->Poisson( meanSkipping * fSkippingGain[pixel] ); 00301 00302 //simulate 'normal' path 00303 Float_t meanElectrons = 6.5; 00304 UInt_t neFromPrevDynode = nPe ; //values for saftey 00305 00306 //at dynode 1 00307 meanElectrons = fStageGains[pixel][1] * nPe * (1 - fsDynodeSkipRate); 00308 neFromPrevDynode = (UInt_t) fRandom->PoissonD(meanElectrons); 00309 00310 //& at dynode 2 00311 meanElectrons = fStageGains[pixel][2] * neFromPrevDynode; 00312 neFromPrevDynode = (UInt_t) fRandom->PoissonD(meanElectrons); 00313 00314 //add in skipping electrons 00315 neFromPrevDynode += neThatSkip; 00316 00317 return neFromPrevDynode; 00318 }
| UInt_t SimPmtM64Oxford::SimLaterDynodes | ( | Int_t | pixel, | |
| Int_t | neToD3 | |||
| ) | [protected, virtual] |
Definition at line 323 of file SimPmtM64Oxford.cxx.
References SimPmt::fRandom, and fStageGains.
Referenced by GenChargeFromPE().
00324 { 00325 // Int_t switchPoint = 6; 00326 // //Change this if you want. It must be >= 3 and <= 12 00327 // //speed = low, accuracy = high (recommend >5) 00328 00329 00330 // //At this dynode, switch from simulating each dynode individually 00331 // // to simulating everything in one go. 00332 // //It only works for Gaussian statistics! 00333 // //The main speed issue is with generating Poisson statisics, 00334 // //so bigger speed increases can be acheived by switching 00335 // //at or before dynode 5. But this nessicerily gives bigger errors. 00336 // //There's no such thing as a free lunch! 00337 00338 // //saftey net: switchPoint MUST stay within these bounds. 00339 // if (switchPoint < 3) switchPoint = 3; 00340 // if (switchPoint > 12) switchPoint = 12; 00341 00342 // Float_t meanElectrons = 29.3; //Value is just for saftey 00343 // UInt_t neFromPrevDynode = neToD3; 00344 00345 // for (Int_t i = 3; i < switchPoint ; i++) { 00346 // meanElectrons = fStageGains[pixel][i] * (Float_t) neFromPrevDynode; 00347 // neFromPrevDynode = fRandom->Poisson(meanElectrons); 00348 // } 00349 00350 // //calculate gaussian mean & width. 00351 // // see NuMI note 661 for detail relating to the `extraWidth' calculation 00352 00353 // Float_t extraWidth = 1; 00354 // Float_t gausGain = fStageGains[pixel][switchPoint]; 00355 00356 // for (Int_t i = (switchPoint + 1) ; i <= 12; i++ ) { 00357 // extraWidth = 1. + ( extraWidth * fStageGains[pixel][i] ); 00358 // gausGain *= fStageGains[pixel][i]; 00359 // } 00360 00361 // //do gaussian amplification 00362 00363 // Float_t gausMean = neFromPrevDynode * gausGain; 00364 // Float_t gausWidth = sqrt(gausMean * extraWidth); 00365 00366 // neFromPrevDynode = UInt_t(fRandom->Gaus(0,1) *gausWidth + gausMean + 0.5 ); 00367 00368 //.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 00369 // If you want to do everything properly this does the job: 00370 00371 Float_t meanElectrons = 29.3; //Value is just for saftey 00372 UInt_t neFromPrevDynode = neToD3; 00373 for (Int_t i = 3; i <= 12; i++) { 00374 meanElectrons = fStageGains[pixel][i] * (Float_t) neFromPrevDynode; 00375 neFromPrevDynode = (UInt_t) fRandom->PoissonD(meanElectrons); 00376 } 00377 00378 return neFromPrevDynode; 00379 }
| void SimPmtM64Oxford::SimulateAnodeEffects | ( | ) | [protected, virtual] |
Definition at line 382 of file SimPmtM64Oxford.cxx.
References SimPixelTimeBucket::AddCharge(), SimPmtM64::BucketToStartTime(), SimPmtM64::BucketToStopTime(), Munits::fC, SimPixelTimeBucket::fCharge, SimPmt::fNPixels, SimPmt::fNSpots, fOneSpot, fsPmtDoChargeSmear, SimPmt::fsPmtDoNonlinearity, SimPixelTimeBucket::fTime, GenNonlinearCharge(), SimPmt::GetBucket(), SimPixelTimeBucket::GetCharge(), SimPmtTimeBucket::GetPixelBucket(), gkNLWindowAfter, gkNLWindowBefore, Msg::kError, DigiSignal::kLeakFromNextBucket, DigiSignal::kLeakFromPrevBucket, Msg::kVerbose, MSG, SimPmtM64Full::NextBucketFraction(), SimPmtM64Full::PrevBucketFraction(), and SimPixelTimeBucket::SetTruthBit().
Referenced by SimulatePmt().
00383 { 00384 //Saftey check: 00385 //if there are several spots active then there will be problems 00386 Int_t activeSpot = 1; //the only spot considered in NL corrections 00387 00388 if (!fOneSpot) { 00389 MSG("DetSim",Msg::kError ) << "This tube has" << fNSpots 00390 << " spots active! Only PEs in spot " 00391 << activeSpot << " will be considered." 00392 << endl; 00393 } 00394 00395 // This uses the time structure of the pe lists to calculate the 00396 // amount of charge active in the pmt in a window near each pe. 00397 // this is used to calculate a non linearity correction, which is 00398 // subtracted from the pixel bucket charge. 00399 00400 // The charge is then smeared into nearby buckets using a charge pulse 00401 // shape t^3 exp[-1.6*t]. 00402 00403 // make something to store the pe non-linearity digests 00404 typedef std::vector<PeNLDigest_t> AllPePixelList_t; 00405 00406 std::vector<AllPePixelList_t> allPeList(fNPixels + 1); 00407 // zeroth element is empty, so that AllPeList[n] corresponds to 00408 // pixel # n, using pixels numbered 1 -> 64 ( NOT 0 ->63 ) 00409 00410 // Iterate over all time buckets 00411 // in each time bucket: add DigiPE summaries to the lists 00412 for(SimPmtBucketIterator it(*this); !it.End(); it.Next()) { 00413 Int_t bucketId = it.BucketId(); 00414 SimPmtTimeBucket& pmtBucket = it.Bucket(); 00415 00416 // iterate over pixels 00417 for(Int_t pix = 1 ; pix <= fNPixels ; pix++) { 00418 SimPixelTimeBucket& pixelBucket = pmtBucket.GetPixelBucket(pix); 00419 Float_t q = 0.; 00420 if ( pixelBucket.GetTotalPEXtalk() ) { 00421 q = pixelBucket.GetCharge(); 00422 q /= pixelBucket.GetTotalPEXtalk(); 00423 } 00424 00425 //get the pe list associated with this pixel in this time bucket 00426 SimPixelTimeBucket::PeList_t& peInThisBkt 00427 = pixelBucket.GetDigiPEXtalk(activeSpot); 00428 // spot issues... And this time, i cant iterate over spots because 00429 // that wouldn't be time ordered! 00430 00431 SimPixelTimeBucket::PeList_t::iterator peItr 00432 = peInThisBkt.begin(); 00433 00434 for ( ; peItr != peInThisBkt.end() ; peItr++ ) { 00435 00436 //make a pe summary 00437 PeNLDigest_t peInfo(bucketId, peItr->first, q); 00438 //cout << peInfo.fBucketNo << endl; 00439 00440 //store it in the relevent vector 00441 allPeList[pix].push_back(peInfo); 00442 00443 } //for (pes) 00444 } //for (pixels) 00445 } //for (pmt time buckets) 00446 00447 MSG("DetSim",Msg::kVerbose) << "Constructed pe list for non-linearity" 00448 << endl; 00449 00450 00451 // Now we have nice long lists of pe's spanning all time buckets 00452 // lets nonlinear-ise! 00453 00454 // iterate over pixels 00455 for(Int_t pix = 1 ; pix <= fNPixels ; pix++) { 00456 00457 // iterate over pes 00458 AllPePixelList_t::iterator currPeItr = allPeList[pix].begin(); 00459 for ( ; currPeItr != allPeList[pix].end() ; ++currPeItr) { 00460 00461 //Get the bucketId and some references. 00462 //Need these for Nonlinearity & charge smearing 00463 Int_t bucketId = currPeItr->fBucketNo; 00464 SimPmtTimeBucket& pmtBkt = GetBucket(bucketId); 00465 SimPixelTimeBucket& pixelBucket = pmtBkt.GetPixelBucket(pix); 00466 00467 Double_t chargeRatio = 1; //if no nonlinearity 00468 00469 00470 if (fsPmtDoNonlinearity){ 00471 //Non-linearity 00472 // count up how much charge is nearby 00473 Float_t peTime = currPeItr->fTime; 00474 Float_t nearbyCharge = 0; 00475 AllPePixelList_t::iterator nearbyPeItr = currPeItr; 00476 Float_t dt = 0; 00477 00478 // look back 00479 while ( nearbyPeItr != allPeList[pix].begin() ) { 00480 --nearbyPeItr; 00481 dt = peTime - nearbyPeItr->fTime; 00482 if ( dt > gkNLWindowBefore ) break; 00483 nearbyCharge += nearbyPeItr->fCharge; 00484 00485 } //while (past pes) 00486 00487 //look forward, include current pe 00488 nearbyPeItr = currPeItr; 00489 00490 while (nearbyPeItr != allPeList[pix].end() ) { 00491 dt = nearbyPeItr->fTime - peTime; 00492 if ( dt > gkNLWindowAfter ) break; 00493 nearbyCharge += nearbyPeItr->fCharge; 00494 ++nearbyPeItr; 00495 } //while (future pes) 00496 00497 00498 // calculate NL correction based on this amount 00499 // newCharge is the nonlinearised charge for all the pes in 00500 // the window, we want it for just one. 00501 if (nearbyCharge){ 00502 // because it is possable have pes but no charge 00503 // (no seconday emission at some stage) 00504 chargeRatio = GenNonlinearCharge( pix, nearbyCharge ); 00505 chargeRatio /= nearbyCharge; 00506 } 00507 00508 // use this correction to reduce the charge in this bucket 00509 Float_t deltaq = (chargeRatio - 1) * currPeItr->fCharge; 00510 pixelBucket.AddCharge(deltaq); 00511 00512 } // if (fsDoNonlinearity) 00513 00514 00515 00516 if (fsPmtDoChargeSmear){ 00517 //Smear the charge about 00518 00519 // "This smushes charge into the next and previous QIE buckets. 00520 // It's assumed that digiPE occours at the peak of the pulse, 00521 // which has a shape of t^3 exp(-t*1.6). 00522 // Some of the charge gets put into the next and previous buckets. 00523 // Note that the truth info is lost: you will now get digits with 00524 // no signal info... but that's the way it goes, I'm afraid." 00525 00526 Float_t startTime = BucketToStartTime(bucketId); 00527 Float_t stopTime = BucketToStopTime(bucketId); 00528 00529 SimPmtTimeBucket& nextPmtBucket = GetBucket(bucketId + 1); 00530 SimPixelTimeBucket& nextPixBucket = nextPmtBucket.GetPixelBucket(pix); 00531 SimPmtTimeBucket& prevPmtBucket = GetBucket(bucketId - 1); 00532 SimPixelTimeBucket& prevPixBucket = prevPmtBucket.GetPixelBucket(pix); 00533 00534 //How much into the adjacent buckets? 00535 Float_t qNext = currPeItr->fCharge * chargeRatio; 00536 qNext *= NextBucketFraction ( stopTime - currPeItr->fTime ); 00537 Float_t qPrev = currPeItr->fCharge * chargeRatio; 00538 qPrev *= PrevBucketFraction ( currPeItr->fTime - startTime ); 00539 00540 //cout << "Time from boundary = " << (currPeItr->fTime - startTime) * 1e9 <<endl; 00541 00542 //Add charge to next bucket, and set truth bits if there is a 00543 //non-trivial amount. 00544 nextPixBucket.AddCharge(qNext); 00545 if ( qNext > 1.0 * Munits::fC ) { 00546 nextPixBucket.SetTruthBit(DigiSignal::kLeakFromPrevBucket); 00547 } 00548 00549 //Add charge to previous bucket, and set truth bits if there is a 00550 //non-trivial amount. 00551 prevPixBucket.AddCharge(qPrev); 00552 if ( qPrev > 1.0 * Munits::fC ) { 00553 prevPixBucket.SetTruthBit(DigiSignal::kLeakFromNextBucket); 00554 } 00555 00556 //remove the same amount of charge from the current bucket 00557 pixelBucket.AddCharge( -(qPrev + qNext) ); 00558 00559 } // if (fsDoChargeSmear) 00560 } // for (pes) 00561 } // for (pixels) 00562 00563 MSG("Detsim",Msg::kVerbose) << "Nonlinearity and Charge smearing done" 00564 << endl; 00565 00566 }
| void SimPmtM64Oxford::SimulateCharges | ( | ) | [virtual] |
Reimplemented from SimPmtM64Full.
Definition at line 606 of file SimPmtM64Oxford.cxx.
References SimPmt::fNPixels, SimPmt::fNSpots, SimPmt::fTotalCharge, and GenChargeFromPE().
Referenced by SimulatePmt().
00607 { 00608 fTotalCharge =0; 00609 00610 //cout << "PMT total pe " << GetTotalPe() << endl; 00611 00612 //Iterate over all time buckets. 00613 for(SimPmtBucketIterator it(*this); !it.End(); it.Next()) { 00614 SimPmtTimeBucket& pmtBucket = it.Bucket(); 00615 00616 //Iterate over pixels 00617 for(Int_t pix = 1 ; pix <= fNPixels ; pix++) { 00618 SimPixelTimeBucket& pixelBucket = pmtBucket.GetPixelBucket(pix); 00619 Float_t nPe = pixelBucket.GetTotalPEXtalk(); 00620 00621 //Generate a charge in the pixel bucket 00622 //iterate over spots (...) 00623 for (Int_t spot = 1 ; spot <= fNSpots ; spot++){ 00624 Float_t q = GenChargeFromPE( pix, spot, nPe ); 00625 //cout << "Anode charge = " << q << endl; 00626 pixelBucket.AddCharge(q); 00627 fTotalCharge += q; 00628 } //for (spots) 00629 } //for (pixels) 00630 } // for (pmt time buckets) 00631 }
| void SimPmtM64Oxford::SimulatePmt | ( | ) | [virtual] |
Reimplemented from SimPmt.
Definition at line 654 of file SimPmtM64Oxford.cxx.
References SimPmt::CopyPEtoPEXtalk(), SimPmt::fsPmtDoChargeCrosstalk, fsPmtDoChargeSmear, SimPmt::fsPmtDoDarkNoise, SimPmt::fsPmtDoNonlinearity, SimPmt::fsPmtDoOpticalCrosstalk, SimulateAnodeEffects(), SimPmt::SimulateChargeCrosstalk(), SimulateCharges(), SimPmt::SimulateDarkNoise(), and SimPmtM64::SimulateOpticalXtalk().
00655 { 00656 // 00657 // Reimplemented from SimPmt. Nonlinearity and Charge smearing are both done 00658 // in a new function SimulateAnodeEffects. 00659 // 00660 //cout << "*************************************************************" << endl; 00661 // cout << " Start simulation." << endl; 00662 //cout << "*************************************************************" << endl; 00663 //Print(); 00664 00665 if(fsPmtDoOpticalCrosstalk) SimulateOpticalXtalk(); // Move single PEs around for crosstalk 00666 else CopyPEtoPEXtalk(); // A null operation. 00667 00668 //cout << "*************************************************************" << endl; 00669 // cout << " After Optical." << endl; 00670 //cout << "*************************************************************" << endl; 00671 //Print(); 00672 00673 SimulateCharges(); // Simulate the dynode chain to get anode charge. 00674 00675 //cout << "*************************************************************" << endl; 00676 //cout << " After Charges." << endl; 00677 //cout << "*************************************************************" << endl; 00678 //Print(); 00679 00680 if(fsPmtDoDarkNoise) SimulateDarkNoise(); // Add some charge to some pixels by dark noise. 00681 if(fsPmtDoChargeSmear || 00682 fsPmtDoNonlinearity ) SimulateAnodeEffects(); // Apply the nonlinearity 00683 if(fsPmtDoChargeCrosstalk) SimulateChargeCrosstalk(); // Crosstalk some charge around. 00684 //cout << "*************************************************************" << endl; 00685 //cout << " Final." << endl; 00686 //cout << "*************************************************************" << endl; 00687 //Print(); 00688 }
VldContext SimPmtM64Oxford::fLastVldContext [private] |
Definition at line 62 of file SimPmtM64Oxford.h.
Bool_t SimPmtM64Oxford::fOneSpot [private] |
Definition at line 58 of file SimPmtM64Oxford.h.
Referenced by CalStageGains(), and SimulateAnodeEffects().
Double_t SimPmtM64Oxford::fsDynodeSkipRate = 0.00 [static, private] |
Double_t SimPmtM64Oxford::fSkippingGain[65] [private] |
Definition at line 57 of file SimPmtM64Oxford.h.
Referenced by CalStageGains(), and SimFirstDynodes().
Double_t SimPmtM64Oxford::fsNLThreshold = 5 [static, private] |
Double_t SimPmtM64Oxford::fsNonlinearityScale = 1.5 [static, private] |
Bool_t SimPmtM64Oxford::fsPmtDoChargeSmear = true [static, protected] |
Definition at line 40 of file SimPmtM64Oxford.h.
Referenced by Config(), SimulateAnodeEffects(), and SimulatePmt().
Double_t SimPmtM64Oxford::fStageGains[65][13] [private] |
Definition at line 56 of file SimPmtM64Oxford.h.
Referenced by CalStageGains(), SimFirstDynodes(), and SimLaterDynodes().
Bool_t SimPmtM64Oxford::fStagesBuilt [private] |
const Double_t SimPmtM64Oxford::gkDefaultSecEmmRatio = 4.5 [static, private] |
const Double_t SimPmtM64Oxford::gkDefaultStageGains [static, private] |
Initial value:
{0, 6.5397, 4.5583, 4.5583,
2.4593, 2.4593, 2.4593,
2.4593, 2.4593, 2.4593,
2.4593, 2.4593, 4.5583}
Definition at line 43 of file SimPmtM64Oxford.h.
Referenced by CalStageGains().
const Double_t SimPmtM64Oxford::gkNLWindowAfter = 0.9841 * Munits::ns [static, private] |
const Double_t SimPmtM64Oxford::gkNLWindowBefore = 1.8056 * Munits::ns [static, private] |
1.4.7