00001 #include "PhotonDefaultModel.h"
00002 #include "PhotonTransportMaker.h"
00003 #include "ScintPhoton.h"
00004 #include "MessageService/MsgService.h"
00005 #include "Digitization/DigiSignal.h"
00006 #include "ChannelNoiseRates.h"
00007 #include <cmath>
00008
00009 CVSID( "$Id: PhotonDefaultModel.cxx,v 1.30 2008/11/19 17:23:26 rhatcher Exp $" );
00010
00011 ClassImp(PhotonDefaultModel)
00012
00013 PhotonTransportMakerProxy<PhotonDefaultModel>
00014 gPhotonDefaultProxy("photonDefaultModel");
00015
00016
00018
00019 PhotonDefaultModel::PhotonDefaultModel()
00020 {
00021 Configure(PhotonConfiguration());
00022 }
00023
00025
00026 void
00027 PhotonDefaultModel::Configure( const Registry& r )
00028 {
00029
00030 ScintPhoton::Configure(r);
00031
00032 MSG("Photon",Msg::kDebug) << "Configuring DefaultModel." << std::endl;
00033
00034 double tmpd;
00035 int tmpi;
00036
00037 if (r.Get("OverallLightOutput",tmpd)) fOverallLightOutput = tmpd;
00038 if (r.Get("BirksConstant",tmpd)) fBirksConstant = tmpd;
00039 if (r.Get("ScintDecayTime",tmpd)) fScintDecayTime = tmpd;
00040 if (r.Get("ClearFibreIndex",tmpd)) fClearFibreIndex = tmpd;
00041 if (r.Get("FibreRadius",tmpd)) fFibreRadius = tmpd;
00042 if (r.Get("FibreFlurorDecayTime",tmpd)) fFibreFlurorDecayTime = tmpd;
00043
00044 if (r.Get("OuterCladdingIndex",tmpd)) fOuterCladdingIndex = tmpd;
00045 if (r.Get("InnerCladdingIndex",tmpd)) fInnerCladdingIndex = tmpd;
00046 if (r.Get("FibreIndex",tmpd)) fFibreIndex = tmpd;
00047 if (r.Get("FibreVelocityFudge",tmpd)) fFibreVelocityFudge = tmpd;
00048 if (r.Get("FibreCoreRadius",tmpd)) fFibreCoreRadius = tmpd;
00049 if (r.Get("ReflectorFibreReflec",tmpd)) fReflectorFibreReflec = tmpd;
00050 if (r.Get("QuantumEfficiency",tmpd)) fQuantumEfficiency = tmpd;
00051
00052 if (r.Get("FibreAttenN1",tmpd)) fFibreAttenN1 = tmpd;
00053 if (r.Get("FibreAttenN2",tmpd)) fFibreAttenN2 = tmpd;
00054 if (r.Get("FibreAttenLength1",tmpd)) fFibreAttenLength1 = tmpd;
00055 if (r.Get("FibreAttenLength2",tmpd)) fFibreAttenLength2 = tmpd;
00056 if (r.Get("ClearFibreAttenN1",tmpd)) fClearFibreAttenN1 = tmpd;
00057 if (r.Get("ClearFibreAttenN2",tmpd)) fClearFibreAttenN2 = tmpd;
00058 if (r.Get("ClearFibreAttenLength1",tmpd)) fClearFibreAttenLength1 = tmpd;
00059 if (r.Get("ClearFibreAttenLength2",tmpd)) fClearFibreAttenLength2 = tmpd ;
00060
00061 if (r.Get("DarkNoiseRate",tmpd)) fDarkNoiseRate = tmpd;
00062 if (r.Get("GreenNoiseRate",tmpd)) fGreenNoiseRate = tmpd;
00063 if (r.Get("NoiseWindow",tmpd)) fNoiseWindow = tmpd;
00064 if (r.Get("PoissonNoiseMean",tmpd)) fPoissonNoiseMean = tmpd;
00065 if (r.Get("ExpTailFraction",tmpd)) fExpTailFraction = tmpd;
00066 if (r.Get("FDNoiseRate",tmpi)) fDetectorNoiseRate = tmpi;
00067
00068 if (r.Get("UseSimpleNoiseModel",tmpi)) fUseSimpleNoiseModel = tmpi;
00069
00070
00071 SetBluePrescaleFactor(1.0);
00072 SetWlsPrescaleFactor(0.2);
00073 SetGreenPrescaleFactor(fQuantumEfficiency);
00074
00075
00076 }
00077
00078 void
00079 PhotonDefaultModel::Reset( const VldContext& )
00080 {
00081
00082
00083
00084
00085
00086 if ( (fContext.GetDetector() == Detector::kFar)
00087 && fUseSimpleNoiseModel==0 ) {
00088 DbiResultPtr<ChannelNoiseRates> resPtr(fContext);
00089 if (!resPtr.GetNumRows())
00090 MSG("Photon", Msg::kFatal) << "Got no DB rows with noise rates!"
00091 << endl;
00092
00093 for (UInt_t irow=0; irow < resPtr.GetNumRows(); ++irow) {
00094 const ChannelNoiseRates* cnr = resPtr.GetRow(irow);
00095 chanhitsmap[cnr->GetChAdd()+5329*cnr->GetCrate()]=cnr->GetNormRate();
00096 }
00097 }
00098 }
00099
00101
00102
00103
00104
00105 Bool_t
00106 PhotonDefaultModel::ComputePhotons( const DigiScintHit* inHit,
00107 Double_t inBluePrescale,
00108 Double_t inWlsPrescale,
00109 Double_t inGreenPrescale,
00110 PhotonCount& outCount )
00111 {
00112
00113 if(!inHit) return false;
00114 double dE = inHit->DE();
00115 double dx = inHit->DS();
00116
00117 double dEdx = dE/dx;
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 const double kLightYield = ( 1/100.
00129 * 1e9
00130 * inBluePrescale
00131 * inWlsPrescale
00132 * inGreenPrescale
00133 );
00134
00135
00136
00137 const double kFudgeFactor = 2.0;
00138
00139
00140 double meanBlue = ( kLightYield * kFudgeFactor * fOverallLightOutput
00141 * dE/(1. + fBirksConstant*dEdx) );
00142
00143
00144 int nblue = fRandom->Poisson(meanBlue);
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 outCount.SetBlueTotal( nblue );
00156 return true;
00157 }
00158
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 Bool_t
00170 PhotonDefaultModel::ScintPhotonToFibreHit( const DigiScintHit* hit,
00171 const UgliStripHandle& inStrip,
00172 DigiPhoton* &outPhoton )
00173 {
00174 outPhoton = NULL;
00175
00176
00177
00178 if(!hit) return false;
00179
00180
00181 ScintPhoton* photon = new ScintPhoton();
00182
00183
00184
00185 Double_t delta = fRandom->Rndm();
00186 TVector3 x1(hit->X1(),hit->Y1(),hit->Z1());
00187 TVector3 x2(hit->X2(),hit->Y2(),hit->Z2());
00188
00189 TVector3 p = x1 + delta*(x2-x1);
00190 Double_t t = hit->T1() + delta * (hit->T2() - hit->T1())
00191 + fRandom->Exp(fScintDecayTime);
00192
00193
00194
00195
00196
00197 bool ok;
00198 do {
00199 TVector3 dir(0,0,0);
00200 photon->Reset(fRandom,
00201 hit,
00202 inStrip,
00203 p, t,
00204 dir);
00205
00206 photon->Propagate();
00207 ok = ! photon->GeomError();
00208 } while(!ok);
00209
00210
00211 outPhoton = (DigiPhoton*) photon;
00212
00213
00214
00215 if(inStrip.WlsBypass() > 0.) {
00216 float x = outPhoton->X();
00217
00218
00219 if( ( (x + inStrip.GetHalfLength()) > inStrip.PartialLength(StripEnd::kNegative) )
00220 && ( (inStrip.GetHalfLength() - x) > inStrip.PartialLength(StripEnd::kPositive) )
00221 ) {
00222
00223
00224 return false;
00225 }
00226 }
00227
00228 return (photon->InFibre());
00229 }
00230
00231
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 Bool_t
00245 PhotonDefaultModel::FibreHitToGreenPhoton( const UgliStripHandle& inStrip,
00246 StripEnd::StripEnd_t inDirection,
00247 DigiPhoton* inBluePhoton,
00248 DigiPhoton* &outGreenPhoton
00249 )
00250 {
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 outGreenPhoton = NULL;
00262 if(!inBluePhoton) return false;
00263
00264
00265 TVector3 dir;
00266 TVector3 x0;
00267 while(true) {
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 double R = fFibreCoreRadius;
00283 double r = sqrt(fRandom->Rndm())*R;
00284 x0.SetXYZ(inBluePhoton->X(),0,r);
00285
00286
00287 double cosTheta = 2.*fRandom->Rndm()-1.0;
00288 double sinTheta = sqrt(1.0-cosTheta*cosTheta);
00289 double phi = 2.*TMath::Pi()*fRandom->Rndm();
00290 dir.SetXYZ( cosTheta,
00291 sinTheta*TMath::Cos(phi),
00292 sinTheta*TMath::Sin(phi) );
00293
00294
00295 double xv = r*dir.z();
00296 double v2 = sinTheta*sinTheta;
00297 if(v2==0) return false;
00298
00299 double lambda = (-xv + sqrt(xv*xv + v2*(R*R-r*r)) )/v2;
00300
00301 TVector3 xhit = x0 + lambda*dir;
00302
00303
00304 TVector3 n(0, -xhit.y()/R, -xhit.z()/R);
00305
00306
00307 double cosAngle = n.Dot(dir);
00308 double sinAngle = sqrt(1.-cosAngle*cosAngle);
00309 if(sinAngle > (fOuterCladdingIndex/fFibreIndex)) {
00310
00311 break;
00312 } else {
00313
00314
00315
00316
00317
00318 }
00319 }
00320
00321
00322 if(inStrip.IsMirrored(StripEnd::kPositive)||inStrip.IsMirrored(StripEnd::kNegative)) {
00323
00324
00325
00326 } else {
00327
00328
00329 switch(inDirection) {
00330 case StripEnd::kPositive:
00331 dir.SetX(fabs(dir.X()));
00332 break;
00333
00334 case StripEnd::kNegative:
00335 dir.SetX(-fabs(dir.X()));
00336 break;
00337
00338 default:
00339
00340 break;
00341 }
00342 }
00343
00344
00345
00346 if(dir.X() ==0) return false;
00347
00348
00349
00350
00351 Double_t decayTime = fRandom->Exp(fFibreFlurorDecayTime);
00352
00353 outGreenPhoton = new DigiPhoton( inBluePhoton->ParentHit(),
00354 0,
00355 inBluePhoton->T() + decayTime,
00356 x0,
00357 dir
00358 );
00359
00360
00361 return true;
00362 }
00363
00364
00366
00367
00368
00369
00370 Bool_t
00371 PhotonDefaultModel::GreenPhotonToPe( const UgliStripHandle& inStrip,
00372 DigiPhoton* inGreenPhoton,
00373 DigiPE* &outPe,
00374 StripEnd::StripEnd_t &outEnd)
00375 {
00376 outPe = NULL;
00377 if(!inGreenPhoton) return false;
00378
00379
00380 StripEnd::StripEnd_t dir =
00381 (inGreenPhoton->GetCosX()>0) ? StripEnd::kPositive : StripEnd::kNegative;
00382
00383 StripEnd::StripEnd_t readout = dir;
00384
00385
00386 if(inStrip.IsMirrored(dir)) {
00387
00388
00389 if(fRandom->Rndm() > fReflectorFibreReflec) {
00390 return false;
00391 }
00392
00393
00394 readout = (dir==StripEnd::kPositive) ? StripEnd::kNegative : StripEnd::kPositive;
00395 }
00396
00397
00398
00399
00400 double distToCenter = (inGreenPhoton->GetCosX()>0) ? (-inGreenPhoton->X())
00401 : (inGreenPhoton->X());
00402
00403 Double_t greenDist =
00404 distToCenter
00405 +inStrip.GetHalfLength()
00406 +inStrip.WlsPigtail(readout);
00407
00408
00409
00410
00411
00412
00413
00414
00415 double bypassExtra = 0;
00416 if(inStrip.WlsBypass() >0) {
00417 bypassExtra = ( inStrip.PartialLength(StripEnd::kNegative) +
00418 inStrip.PartialLength(StripEnd::kPositive) +
00419 inStrip.WlsBypass() -
00420 inStrip.GetHalfLength()*2.0 );
00421
00422
00423 float x_break =0.5* (inStrip.PartialLength(StripEnd::kNegative)
00424 - inStrip.PartialLength(StripEnd::kPositive) );
00425
00426 if(inGreenPhoton->X() < x_break) {
00427
00428 if(dir==StripEnd::kPositive) greenDist+= bypassExtra;
00429 } else {
00430
00431 if(dir==StripEnd::kNegative) greenDist+= bypassExtra;
00432 }
00433 }
00434
00435 if(readout!=dir) {
00436
00437 greenDist+= inStrip.GetHalfLength()*2.0;
00438 greenDist+= bypassExtra;
00439 greenDist+= inStrip.WlsPigtail(dir)*2.0;
00440
00441 }
00442
00443
00444
00445 Double_t clearDist = inStrip.ClearFiber(readout);
00446
00447
00448
00449 greenDist /= fabs(inGreenPhoton->GetCosX());
00450 clearDist /= fabs(inGreenPhoton->GetCosX());
00451
00452
00453
00454
00455
00456
00457
00458
00459 double norm_g = 1.0/(fFibreAttenN1+fFibreAttenN2);
00460
00461
00462
00463 double greenAtten = norm_g * ( fFibreAttenN1 * exp(-greenDist/fFibreAttenLength1) +
00464 fFibreAttenN2 * exp(-greenDist/fFibreAttenLength2) );
00465
00466
00467 if(fRandom->Rndm() > greenAtten) return false;
00468
00469
00470
00471 double norm_c = 1.0/(fClearFibreAttenN1+fClearFibreAttenN2);
00472
00473
00474 double clearAtten = norm_c * ( fClearFibreAttenN1 * exp(-clearDist/fClearFibreAttenLength1) +
00475 fClearFibreAttenN2 * exp(-clearDist/fClearFibreAttenLength2) );
00476
00477
00478 if(fRandom->Rndm() > clearAtten) return false;
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 double time = inGreenPhoton->T()
00489 + greenDist * fFibreIndex * fFibreVelocityFudge / Munits::c_light
00490 + clearDist * fClearFibreIndex * fFibreVelocityFudge / Munits::c_light;
00491
00492 PlexStripEndId seid = inStrip.GetSEId();
00493 seid.SetEnd(readout);
00494
00495 PlexHandle plex(fContext);
00496 PlexPixelSpotId psid = plex.GetPixelSpotId(seid);
00497
00498 outPe = new DigiPE( time, psid, inGreenPhoton->ParentHit() );
00499 outEnd = readout;
00500
00501 return true;
00502 }
00503
00504 void
00505 PhotonDefaultModel::MakeNoise( std::vector<DigiPE*> &peList,
00506 Double_t t_start,
00507 Double_t t_end )
00508 {
00513
00514
00515
00516
00517 if ( (fContext.GetDetector() != Detector::kFar)
00518 || fUseSimpleNoiseModel ) {
00519 MakeNoiseOld(peList, t_start, t_end);
00520 return;
00521 }
00522
00523
00524 double t1 = t_start - fNoiseWindow*0.5;
00525 double t2 = t_end + fNoiseWindow*0.5;
00526 double dt = t2-t1;
00527
00528 MSG("Photon",Msg::kDebug) << "Computing noise for window at" << t1
00529 << " s for " << (t2-t1)/Munits::ns << " ns."
00530 << std::endl;
00531
00532 PlexHandle plex(fContext);
00533
00534 const std::vector<PlexStripEndId>& stripEnds = plex.GetAllStripEnds();
00535
00536
00537 Double_t fibreHits = dt * fDetectorNoiseRate;
00538
00539 Int_t nGreenHits = fRandom->Poisson(fibreHits);
00540 MSG("Photon",Msg::kDebug)
00541 << "Creating " << nGreenHits << " green WLS noise hits.\n";
00542
00543
00544 for(int i=0; i<nGreenHits; i++) {
00545
00546 Int_t whichSeid = fRandom->Integer((int)stripEnds.size());
00547
00548
00549 while ( fRandom->Uniform(0,1) >
00550 GetStripEndRate(stripEnds[whichSeid] , plex) )
00551 whichSeid = fRandom->Integer((int)stripEnds.size());
00552
00553 PlexPixelSpotId psid = plex.GetPixelSpotId(stripEnds[whichSeid]);
00554 if(psid.IsValid()) {
00555 Int_t npe = 0;
00556
00557 while (npe==0) npe=fRandom->Poisson(fPoissonNoiseMean);
00558 Double_t hitTime = fRandom->Uniform(t1,t2);
00559 for (int j=0; j<npe; ++j) {
00560 DigiPE* pe = new DigiPE( hitTime,
00561 psid,
00562 DigiSignal::kDarkNoise );
00563 peList.push_back(pe);
00564 }
00565 }
00566 }
00567
00568 Int_t nExpHits = fRandom->Poisson(fibreHits*fExpTailFraction);
00569 for (Int_t i=0; i<nExpHits; ++i) {
00570
00571 Int_t whichSeid = fRandom->Integer((int)stripEnds.size());
00572
00573
00574 while ( fRandom->Uniform(0,1) > GetStripEndRate(stripEnds[whichSeid] , plex))
00575 whichSeid = fRandom->Integer((int)stripEnds.size());
00576
00577 PlexPixelSpotId psid = plex.GetPixelSpotId(stripEnds[whichSeid]);
00578
00579 Int_t npe = 4+TMath::Nint(fRandom->Exp(0.7));
00580 Double_t hitTime = fRandom->Uniform(t1,t2);
00581 for (int j=0; j<npe; ++j) {
00582 DigiPE* pe = new DigiPE( hitTime,
00583 psid,
00584 DigiSignal::kFibreLight );
00585 peList.push_back(pe);
00586 }
00587 }
00588 }
00589
00590 Float_t
00591 PhotonDefaultModel::GetStripEndRate(PlexStripEndId seid,
00592 PlexHandle ph)
00593 {
00594
00595
00596
00597 RawChannelId rcid = ph.GetRawChannelId(seid);
00598 UShort_t chadd = rcid.GetChAdd();
00599 Int_t crate = rcid.GetCrate();
00600 MSG("Photon",Msg::kDebug) << "chanhitsmap[" << chadd+5329*crate
00601 << "] = " << chanhitsmap[chadd+5329*crate]
00602 << endl;
00603 return chanhitsmap[chadd+5329*crate];
00604 }
00605
00606 void
00607 PhotonDefaultModel::MakeNoiseOld( std::vector<DigiPE*> &peList,
00608 Double_t t_start,
00609 Double_t t_end )
00610 {
00615
00616
00617 double t1 = t_start - fNoiseWindow*0.5;
00618 double t2 = t_end + fNoiseWindow*0.5;
00619 double dt = t2-t1;
00620
00621 MSG("Photon",Msg::kDebug) << "Computing noise using simple noise"
00622 << " model for window at" << t1
00623 << " s for " << (t2-t1)/Munits::ns << " ns."
00624 << std::endl;
00625
00626 PlexHandle plex(fContext);
00627
00628 const std::vector<PlexPixelSpotId>& tubes = plex.GetAllTubes();
00629
00630
00631 Double_t pmtHits = (double)tubes.size() * dt * fDarkNoiseRate;
00632
00633 Int_t nPmtHits = fRandom->Poisson(pmtHits);
00634 MSG("Photon",Msg::kDebug) << "Creating " << nPmtHits
00635 << " dark noise hits.\n";
00636
00637
00638 for(int i=0; i<nPmtHits; i++) {
00639
00640 Int_t whichPmt = fRandom->Integer((int)tubes.size());
00641
00642 PlexPixelSpotId psid = tubes[whichPmt];
00643 if(psid.GetElecType()==ElecType::kQIE) {
00644 psid.SetPixel(fRandom->Integer(64));
00645 psid.SetSpot(1);
00646 }
00647 if(psid.GetElecType()==ElecType::kVA) {
00648 psid.SetPixel(fRandom->Integer(16));
00649 psid.SetSpot(fRandom->Integer(8)+1);
00650 }
00651 if(psid.IsValid()) {
00652 DigiPE* pe = new DigiPE( fRandom->Uniform(t1,t2),
00653 psid,
00654 DigiSignal::kDarkNoise );
00655 peList.push_back(pe);
00656 }
00657 }
00658
00659
00660 const std::vector<PlexStripEndId>& stripEnds = plex.GetAllStripEnds();
00661
00662
00663 Double_t fibreHits = (double)stripEnds.size() * dt * fGreenNoiseRate;
00664
00665 Int_t nGreenHits = fRandom->Poisson(fibreHits);
00666 MSG("Photon",Msg::kDebug) << "Creating " << nGreenHits
00667 << " green WLS noise hits.\n";
00668
00669
00670 for(int i=0; i<nGreenHits; i++) {
00671
00672 Int_t whichSeid = fRandom->Integer((int)stripEnds.size());
00673
00674 PlexPixelSpotId psid = plex.GetPixelSpotId(stripEnds[whichSeid]);
00675
00676 if(psid.IsValid()) {
00677 DigiPE* pe = new DigiPE( fRandom->Uniform(t1,t2),
00678 psid,
00679 DigiSignal::kFibreLight );
00680 peList.push_back(pe);
00681 }
00682 }
00683 }
00684
00685
00686 void PhotonDefaultModel::MakeAfterpulses( const std::vector<DigiPE*>& ,
00687 std::vector<DigiPE*>& )
00688 {
00695
00696 return;
00697 }
00698
00699
00700
00701
00702 void PhotonDefaultModel::Print(Option_t*option) const
00703 {
00704 if(option[0]=='c') {
00705 MSG("Photon",Msg::kInfo) << "-<PhotonComputer> PhotonDefaultModel:-----" << endl;
00706 MSG("Photon",Msg::kInfo) << " OverallLightOutput: " << fOverallLightOutput << endl;
00707 MSG("Photon",Msg::kInfo) << " Birk's Constant: " << fBirksConstant << endl;
00708 }
00709 if(option[0]=='b') {
00710 MSG("Photon",Msg::kInfo) << "-<BluePhotonTracker> PhotonDefaultModel:-----" << endl;
00711
00712 }
00713 if(option[0]=='w') {
00714 MSG("Photon",Msg::kInfo) << "-<WlsFibreModel> PhotonDefaultModel:-----" << endl;
00715
00716 }
00717 if(option[0]=='g') {
00718 MSG("Photon",Msg::kInfo) << "-<GreenPhotonTracker> PhotonDefaultModel:-----" << endl;
00719 MSG("Photon",Msg::kInfo) << " ReflectorFibreReflec: " << fReflectorFibreReflec << endl;
00720 MSG("Photon",Msg::kInfo) << " Quantum Efficiency: " << fQuantumEfficiency << endl;
00721
00722 }
00723 if(option[0]=='n') {
00724 MSG("Photon",Msg::kInfo) << "-<NoiseMaker> PhotonDefaultModel:-----" << endl;
00725
00726 }
00727 }
00728