#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 | |
| 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 | |
| const Double_t | gkDefaultStageGains [13] |
| const Double_t | gkDefaultSecEmmRatio = 4.5 |
| const Double_t | gkNLWindowBefore = 1.8056 * Munits::ns |
| const Double_t | gkNLWindowAfter = 0.9841 * Munits::ns |
| Double_t | fsDynodeSkipRate = 0.00 |
| Double_t | fsNLThreshold = 5 |
| Double_t | fsNonlinearityScale = 1.5 |
|
||||||||||||||||
|
Definition at line 38 of file SimPmtM64Oxford.cxx. References 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 }
|
|
|
Definition at line 21 of file SimPmtM64Oxford.h. 00021 {};
|
|
|
Definition at line 122 of file SimPmtM64Oxford.cxx. References fSkippingGain, fStageGains, SimPmt::GetGainAndWidth(), gkDefaultSecEmmRatio, gkDefaultStageGains, 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 }
|
|
|
Reimplemented from SimPmtM64Full. Definition at line 635 of file SimPmtM64Oxford.cxx. References SimPmtM64Full::Config(), fsDynodeSkipRate, fsNLThreshold, fsNonlinearityScale, fsPmtDoChargeSmear, 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 }
|
|
||||||||||||||||
|
Reimplemented from SimPmtM64. Definition at line 255 of file SimPmtM64Oxford.cxx. References 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 }
|
|
||||||||||||
|
Reimplemented from SimPmtM64. Definition at line 569 of file SimPmtM64Oxford.cxx. References fsNLThreshold. 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 }
|
|
|
Reimplemented from SimPmtM64. Definition at line 108 of file SimPmtM64Oxford.cxx. References CalStageGains(), 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 }
|
|
||||||||||||
|
Definition at line 291 of file SimPmtM64Oxford.cxx. References 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 }
|
|
||||||||||||
|
Definition at line 323 of file SimPmtM64Oxford.cxx. References 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 }
|
|
|
Definition at line 382 of file SimPmtM64Oxford.cxx. References SimPixelTimeBucket::AddCharge(), SimPmtBucketIterator::Bucket(), SimPmtBucketIterator::BucketId(), SimPmtM64::BucketToStartTime(), SimPmtM64::BucketToStopTime(), SimPmtBucketIterator::End(), SimPixelTimeBucket::fCharge, SimPixelTimeBucket::fTime, GenNonlinearCharge(), SimPmt::GetBucket(), SimPixelTimeBucket::GetCharge(), SimPixelTimeBucket::GetDigiPEXtalk(), SimPmtTimeBucket::GetPixelBucket(), SimPixelTimeBucket::GetTotalPEXtalk(), MSG, SimPmtBucketIterator::Next(), 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 }
|
|
|
Reimplemented from SimPmtM64Full. Definition at line 606 of file SimPmtM64Oxford.cxx. References SimPixelTimeBucket::AddCharge(), SimPmtBucketIterator::Bucket(), SimPmtBucketIterator::End(), GenChargeFromPE(), SimPmtTimeBucket::GetPixelBucket(), SimPixelTimeBucket::GetTotalPEXtalk(), and SimPmtBucketIterator::Next(). 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 }
|
|
|
Reimplemented from SimPmt. Definition at line 654 of file SimPmtM64Oxford.cxx. References SimPmt::CopyPEtoPEXtalk(), fsPmtDoChargeSmear, 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 }
|
|
|
Definition at line 62 of file SimPmtM64Oxford.h. |
|
|
Definition at line 58 of file SimPmtM64Oxford.h. |
|
|
Definition at line 101 of file SimPmtM64Oxford.cxx. Referenced by Config(). |
|
|
Definition at line 57 of file SimPmtM64Oxford.h. Referenced by CalStageGains(), and SimFirstDynodes(). |
|
|
Definition at line 102 of file SimPmtM64Oxford.cxx. Referenced by Config(), and GenNonlinearCharge(). |
|
|
Definition at line 103 of file SimPmtM64Oxford.cxx. Referenced by Config(). |
|
|
Definition at line 83 of file SimPmtM64Oxford.cxx. Referenced by Config(), and SimulatePmt(). |
|
|
Definition at line 56 of file SimPmtM64Oxford.h. Referenced by CalStageGains(), SimFirstDynodes(), and SimLaterDynodes(). |
|
|
Definition at line 55 of file SimPmtM64Oxford.h. Referenced by Reset(). |
|
|
Definition at line 91 of file SimPmtM64Oxford.cxx. Referenced by CalStageGains(). |
|
|
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 85 of file SimPmtM64Oxford.cxx. Referenced by CalStageGains(). |
|
|
Definition at line 95 of file SimPmtM64Oxford.cxx. |
|
|
Definition at line 94 of file SimPmtM64Oxford.cxx. |
1.3.9.1