00001
00002
00003
00004
00005
00006
00008 #include "PhotonTransport.h"
00009
00010 #include <TRandom.h>
00011 #include <TRandom3.h>
00012
00013 #include "MessageService/MsgService.h"
00014 #include "MinosObjectMap/MomNavigator.h"
00015 #include "JobControl/JobCModuleRegistry.h"
00016
00017 #include "Digitization/DigiScintHit.h"
00018 #include "Digitization/DigiPE.h"
00019 #include "Record/SimSnarlRecord.h"
00020 #include "Record/SimSnarlHeader.h"
00021
00022 #include "PhotonTransportModule.h"
00023 #include "PhotonTransportMaker.h"
00024 #include "PhotonConfiguration.h"
00025
00026 #include "Plex/PlexHandle.h"
00027
00028 #include "Calibrator/Calibrator.h"
00029
00030 #include "Conventions/MinosMaterial.h"
00031
00032 #include "Util/LoadMinosPDG.h"
00033
00034 #include <TFile.h>
00035 #include <TNtuple.h>
00036 #include <TNtupleD.h>
00037
00038 #include <cmath>
00039
00040 JOBMODULE(PhotonTransport, "PhotonTransport",
00041 "Photon transport from energy deposition to photoelectroncs");
00042 CVSID("$Id: PhotonTransport.cxx,v 1.16 2009/05/19 18:19:17 kasahara Exp $");
00043
00044
00045
00046
00047 PhotonTransport::PhotonTransport() :
00048 fName_PhotonComputer("photonDefaultModel"),
00049 fName_BluePhotonTracker("photonDefaultModel"),
00050 fName_WlsFibreModel("photonDefaultModel"),
00051 fName_GreenPhotonTracker("photonDefaultModel"),
00052 fName_NoiseMaker("photonDefaultModel"),
00053 fName_Afterpulser("photonDefaultModel"),
00054 fDebugFileName(""),
00055 fDebugMask(0xFFFF),
00056 fRandomSeed(0),
00057 fRandom(new TRandom3),
00058 fProtonRangeTable("PHOTONPROTONRANGE"),
00059 fElectronRangeTable("PHOTONELECTRONRANGE"),
00060 fPhotonComputer(0),
00061 fBluePhotonTracker(0),
00062 fWlsFibreModel(0),
00063 fGreenPhotonTracker(0),
00064 fNoiseMaker(0),
00065 fAfterpulser(0),
00066 fDebugFile(0),
00067 fDebugNtuple(0),
00068 fBadHitNtuple(0)
00069 {
00070
00071 LoadMinosPDG();
00072
00073 CreateModelObjects();
00074
00075
00076
00077
00078 }
00079
00080
00081
00082 PhotonTransport::~PhotonTransport()
00083 {
00084
00085
00086
00087 if(fPhotonComputer) delete fPhotonComputer;
00088 if(fBluePhotonTracker) delete fBluePhotonTracker;
00089 if(fWlsFibreModel) delete fWlsFibreModel;
00090 if(fGreenPhotonTracker) delete fGreenPhotonTracker;
00091 if(fNoiseMaker) delete fNoiseMaker;
00092 if(fAfterpulser) delete fAfterpulser;
00093 if(fRandom) delete fRandom;
00094 if(fDebugFile){
00095 TDirectory* savedir = gDirectory;
00096 fDebugFile->cd();
00097 if ( fDebugNtuple ) fDebugNtuple->Write(NULL,TObject::kOverwrite);
00098 if ( fBadHitNtuple ) fBadHitNtuple->Write(NULL,TObject::kOverwrite);
00099 fDebugFile->Close();
00100 delete fDebugFile;
00101 savedir -> cd();
00102 }
00103 }
00104
00105
00106
00107 JobCResult PhotonTransport::Ana(const MomNavigator* mom )
00108 {
00109 SimSnarlRecord* simrec = dynamic_cast<SimSnarlRecord*>
00110 (mom->GetFragment("SimSnarlRecord"));
00111 if ( !simrec ) {
00112 MSG("Photon",Msg::kWarning) << "No SimSnarlRecord in Mom" << endl;
00113 return JobCResult::kFailed;
00114 }
00115
00116 const PhotonEventResult* per = dynamic_cast<const PhotonEventResult*>(simrec->FindComponent("PhotonEventResult"));
00117 if(per) per->Print();
00118 else MSG("Photon",Msg::kWarning) << "Can't find PhotonEventResult" << endl;
00119
00120
00121
00122
00123 return JobCResult::kPassed;
00124 }
00125
00126
00127
00128 JobCResult PhotonTransport::Reco(MomNavigator* mom)
00129 {
00133 return Ana(mom);
00134 }
00135
00136
00137
00138 JobCResult PhotonTransport::Get(MomNavigator* mom)
00139 {
00140
00141
00142
00143
00144
00145 SimSnarlRecord* simsnarl = 0;
00146 TObject* tobj;
00147 TIter fragiter = mom->FragmentIter();
00148
00149 fPeTotal = 0;
00150
00151
00152 while( ( tobj = fragiter.Next() ) ) {
00153 simsnarl = dynamic_cast<SimSnarlRecord*>(tobj);
00154 if(simsnarl) break;
00155 }
00156
00157
00158 if(!simsnarl) {
00159 MSG("Photon",Msg::kError) << "No SimSnarl found. You must run RerootToTruthModule()!" << endl;
00160 return JobCResult::kFailed;
00161 }
00162
00163 RecJobHistory& jobhist
00164 = const_cast<RecJobHistory&>(simsnarl->GetJobHistory());
00165 jobhist.CreateJobRecord(RecJobHistory::kPhotonTransport);
00166
00167 fSimHeader = simsnarl->GetSimSnarlHeader();
00168 if(fSimHeader ==0){
00169 MSG("Photon",Msg::kError) << "Cannot find SimSnarlHeader in SimSnarl." << endl;
00170 return JobCResult::kFailed;
00171 }
00172
00173
00174
00175
00176 fRandom->SetSeed( fSimHeader->GetRun()
00177 + fSimHeader->GetSnarl()
00178 + fRandomSeed );
00179
00180
00181 VldContext simContext = fSimHeader->GetVldContext();
00182
00183
00184 fContext = VldContext(simContext.GetDetector(),SimFlag::kMC,simContext.GetTimeStamp());
00185
00186 Calibrator::Instance().Reset(fContext);
00187
00188
00189 fEventResult.Reset();
00190
00191 JobCResult res;
00192
00193
00194 fHitList =
00195 dynamic_cast<const TObjArray*>(simsnarl->FindComponent(0,"DigiScintHits"));
00196 if(fHitList) {
00197
00198
00199 if( dynamic_cast<const TObjArray*>(simsnarl->FindTemporary(0,"DigiListPe")) != 0) {
00200 MSG("Photon",Msg::kError) << "Found pre-existing DigPE list. Aborting." << std::endl;
00201 return JobCResult::kFailed;
00202 } else {
00203 fPeList = new TObjArray(0);
00204 fPeList->SetName("DigiListPe");
00205 fPeList->SetOwner(true);
00206 }
00207
00208
00209 res = SimulateEvent();
00210
00211 } else {
00212
00213 MSG("Photon",Msg::kError) << "Can't find scint hit array.\n";
00214 return JobCResult::kFailed;
00215
00216 };
00217
00218 simsnarl->AdoptTemporary(fPeList);
00219
00220
00221 simsnarl->AdoptComponent(new PhotonEventResult(fEventResult));
00222 MSG("Photon",Msg::kSynopsis) << fEventResult;
00223
00224 return res;
00225 }
00226
00227
00228
00229 const Registry& PhotonTransport::DefaultConfig() const
00230 {
00231
00232
00233
00234
00235 return PhotonConfiguration();
00236 }
00237
00238
00239
00240 void PhotonTransport::Config(const Registry& r)
00241 {
00242
00243
00244
00245
00246 MSG("Photon",Msg::kDebug) << "PhotonTransport::Config" << endl;
00247
00248 r.Get("randomSeed",fRandomSeed);
00249
00250 const char* str;
00251 Bool_t modelChanged = false;
00252 if( r.Get("PhotonComputer", str))
00253 if(fName_PhotonComputer != std::string(str))
00254 { modelChanged=true; fName_PhotonComputer = str; }
00255
00256 if( r.Get("BluePhotonTracker", str))
00257 if(fName_BluePhotonTracker != std::string(str))
00258 { modelChanged=true; fName_BluePhotonTracker = str; }
00259
00260 if( r.Get("WlsFibreModel", str))
00261 if(fName_WlsFibreModel != std::string(str))
00262 { modelChanged=true; fName_WlsFibreModel = str; }
00263
00264 if( r.Get("GreenPhotonTracker",str))
00265 if(fName_GreenPhotonTracker != std::string(str))
00266 { modelChanged=true; fName_GreenPhotonTracker = str; }
00267
00268 if( r.Get("NoiseMaker",str))
00269 if(fName_NoiseMaker != std::string(str))
00270 { modelChanged=true; fName_NoiseMaker = str; }
00271
00272 if( r.Get("Afterpulser",str))
00273 if(fName_Afterpulser != std::string(str))
00274 { modelChanged=true; fName_Afterpulser = str; }
00275
00276 if(modelChanged) CreateModelObjects();
00277
00278 fPhotonComputer-> Configure(r);
00279 fBluePhotonTracker-> Configure(r);
00280 fWlsFibreModel-> Configure(r);
00281 fGreenPhotonTracker->Configure(r);
00282 fNoiseMaker-> Configure(r);
00283 fAfterpulser-> Configure(r);
00284
00285 r.Get("ElectronFudgeThreshEnergy",fElectronFudgeThreshEnergy);
00286 r.Get("ElectronFudgeThreshDist", fElectronFudgeThreshDist);
00287
00288 r.Get("DebugMask",fDebugMask);
00289 r.Get("DebugFileName",str);
00290 fDebugFileName = str;
00291
00292 }
00293
00294
00295
00296 void PhotonTransport::BeginJob()
00297 {
00298
00299
00300
00301
00302 if(fDebugFileName.length()>0) {
00303 if (fDebugFile) delete fDebugFile;
00304 TDirectory* savedir = gDirectory;
00305 fDebugFile = new TFile(fDebugFileName.c_str(),"RECREATE");
00306 if ( fDebugMask & 1 ) fDebugNtuple = new TNtuple("pes","pes",
00307 "plane:strip:end:thit:tblue:tgreen:tpe:gcosx:gx");
00308 if ( fDebugMask & 2 ) fBadHitNtuple = new TNtupleD("badhit","badhit",
00309 "pE:pId:pln:stp:t0:xl0:yl0:zl0:xg0:yg0:zg0:dS:dE:failmode");
00310 savedir -> cd();
00311 }
00312 }
00313
00314
00316 void PhotonTransport::CreateModelObjects()
00317 {
00318 if(fPhotonComputer) delete fPhotonComputer;
00319 if(fBluePhotonTracker) delete fBluePhotonTracker;
00320 if(fWlsFibreModel) delete fWlsFibreModel;
00321 if(fGreenPhotonTracker) delete fGreenPhotonTracker;
00322 if(fNoiseMaker) delete fNoiseMaker;
00323 if(fAfterpulser) delete fAfterpulser;
00324
00325 fPhotonComputer = PhotonTransportMaker::Create(fName_PhotonComputer);
00326 fBluePhotonTracker = PhotonTransportMaker::Create(fName_BluePhotonTracker);
00327 fWlsFibreModel = PhotonTransportMaker::Create(fName_WlsFibreModel);
00328 fGreenPhotonTracker = PhotonTransportMaker::Create(fName_GreenPhotonTracker);
00329 fNoiseMaker = PhotonTransportMaker::Create(fName_NoiseMaker);
00330 fAfterpulser = PhotonTransportMaker::Create(fName_Afterpulser);
00331
00332 if(!fPhotonComputer) { MSG("Photon",Msg::kFatal) << "FATAL: No such module: " << fName_PhotonComputer << endl; exit(1);};
00333 if(!fBluePhotonTracker) { MSG("Photon",Msg::kFatal) << "FATAL: No such module: " << fName_BluePhotonTracker << endl; exit(1);};
00334 if(!fWlsFibreModel) { MSG("Photon",Msg::kFatal) << "FATAL: No such module: " << fName_WlsFibreModel << endl; exit(1);};
00335 if(!fGreenPhotonTracker) { MSG("Photon",Msg::kFatal) << "FATAL: No such module: " << fName_GreenPhotonTracker << endl; exit(1);};
00336 if(!fNoiseMaker) { MSG("Photon",Msg::kFatal) << "FATAL: No such module: " << fName_NoiseMaker << endl; exit(1);};
00337 if(!fAfterpulser) { MSG("Photon",Msg::kFatal) << "FATAL: No such module: " << fName_Afterpulser << endl; exit(1);};
00338
00339
00340 fPhotonComputer-> SetRandom(fRandom);
00341 fBluePhotonTracker-> SetRandom(fRandom);
00342 fWlsFibreModel-> SetRandom(fRandom);
00343 fGreenPhotonTracker->SetRandom(fRandom);
00344 fNoiseMaker-> SetRandom(fRandom);
00345 fAfterpulser-> SetRandom(fRandom);
00346 }
00347
00348
00349
00350 JobCResult PhotonTransport::ConfirmModelObjects()
00351 {
00352
00353 if(!fPhotonComputer) {
00354 MSG("Photon",Msg::kError) << "Photon Transport Model PhotonComputer = "
00355 << fName_PhotonComputer
00356 << " is not registed. Aborting!"
00357 << endl;
00358 return JobCResult::kFatal;
00359 }
00360
00361 if(!fBluePhotonTracker) {
00362 MSG("Photon",Msg::kError) << "Photon Transport Model BluePhotonTracker = "
00363 << fName_BluePhotonTracker
00364 << " is not registed. Aborting!"
00365 << endl;
00366 return JobCResult::kFatal;
00367 }
00368
00369 if(!fWlsFibreModel) {
00370 MSG("Photon",Msg::kError) << "Photon Transport Model WlsFibreModel = "
00371 << fName_WlsFibreModel
00372 << " is not registed. Aborting!"
00373 << endl;
00374 return JobCResult::kFatal;
00375 }
00376
00377 if(!fGreenPhotonTracker) {
00378 MSG("Photon",Msg::kError) << "Photon Transport Model GreenPhotonTracker = "
00379 << fName_GreenPhotonTracker
00380 << " is not registed. Aborting!"
00381 << endl;
00382 return JobCResult::kFatal;
00383 }
00384
00385 if(!fNoiseMaker) {
00386 MSG("Photon",Msg::kError) << "Photon Transport Model NoiseMaker = "
00387 << fName_NoiseMaker
00388 << " is not registed. Aborting!"
00389 << endl;
00390 return JobCResult::kFatal;
00391 }
00392
00393 if(!fAfterpulser) {
00394 MSG("Photon",Msg::kError) << "Photon Transport Model Afterpulser = "
00395 << fName_Afterpulser
00396 << " is not registed. Aborting!"
00397 << endl;
00398 return JobCResult::kFatal;
00399 }
00400
00401 return JobCResult::kAOK;
00402 }
00403
00404
00406 JobCResult PhotonTransport::SimulateEvent()
00407 {
00408 JobCResult res = JobCResult::kPassed;
00409 res = ConfirmModelObjects();
00410 if(res.HaveError()) return res;
00411
00412 fProtonRangeTable.Reset(fContext);
00413 fElectronRangeTable.Reset(fContext);
00414
00415
00416 fPhotonComputer-> DoReset(fContext);
00417 fBluePhotonTracker-> DoReset(fContext);
00418 fWlsFibreModel-> DoReset(fContext);
00419 fGreenPhotonTracker->DoReset(fContext);
00420 fNoiseMaker ->DoReset(fContext);
00421 fAfterpulser ->DoReset(fContext);
00422
00423 TObject* tobj;
00424 TIter hitarrayIter(fHitList);
00425 while( (tobj = hitarrayIter.Next()) ) {
00426 DigiScintHit* scinthit = dynamic_cast<DigiScintHit*>(tobj);
00427 if(scinthit) {
00428 JobCResult hitRes = SimulateScintHit(scinthit);
00429 res |= hitRes;
00430 }
00431 }
00432
00433 res |= AddNoise();
00434
00435 res |= AddAfterpulsing();
00436
00437 if((fEventResult.energyDiscardedGeom+
00438 fEventResult.energyDiscardedBad) > 1.0*Munits::MeV)
00439 MSG("Photon",Msg::kError)
00440 << "Run: " << fSimHeader->GetRun()
00441 << " Event: " << fSimHeader->GetSnarl()
00442 << " Threw out "
00443 << fEventResult.energyDiscardedGeom/Munits::MeV << " MeV (bad geom) and "
00444 << fEventResult.energyDiscardedBad/Munits::MeV << " MeV (bad hits) of a total "
00445 << fEventResult.totalHitEnergy/Munits::MeV << " MeV in the event"
00446 << endl;
00447
00448 fEventResult.totalStripsHit = fEventResult.fStripsHit.size();
00449 fEventResult.totalPixels = fEventResult.fPixelsHit.size();
00450
00451 return res;
00452 }
00453
00454 enum EBoundaryStatus { kBoundOkay,
00455 kX1OffEnd,
00456 kX2OffEnd,
00457 kInsideBypass,
00458 kY1OffWidth,
00459 kY2OffWidth,
00460 kZ1OffThick,
00461 kZ2OffThick };
00462
00463 const char* kBoundaryString [] = { "OK",
00464 "X1 off end",
00465 "X2 off end",
00466 "Inside bypass",
00467 "Y1 off width",
00468 "Y2 off width",
00469 "Z1 off thick",
00470 "Z2 off thick" };
00471
00472 int PhotonTransport::VerifyScintHit(DigiScintHit* hit,UgliStripHandle ustrip)
00473 {
00474
00475
00476
00477
00478 if(fabs(hit->X1()) > (ustrip.GetHalfLength()+0.1*Munits::cm)) return kX1OffEnd;
00479 if(fabs(hit->X2()) > (ustrip.GetHalfLength()+0.1*Munits::cm)) return kX2OffEnd;
00480
00481
00482 if(ustrip.WlsBypass()>0.) {
00483 float x01 = hit->X1() + ustrip.GetHalfLength();
00484 float x02 = hit->X2() + ustrip.GetHalfLength();
00485 float p_neg = ustrip.PartialLength(StripEnd::kNegative);
00486 float p_pos = ustrip.GetHalfLength()*2.0 - ustrip.PartialLength(StripEnd::kPositive);
00487 bool good = false;
00488 if((x01<p_neg) && (x02<p_neg)) good = true;
00489 if((x01>p_pos) && (x02>p_pos)) good = true;
00490 if(good==false) return kInsideBypass;
00491 }
00492
00493 if(fabs(hit->Y1()) > ustrip.GetHalfWidth()) return kY1OffWidth;
00494 if(fabs(hit->Y2()) > ustrip.GetHalfWidth()) return kY2OffWidth;
00495 if(fabs(hit->Z1()) > ustrip.GetHalfThickness()) return kZ1OffThick;
00496 if(fabs(hit->Z2()) > ustrip.GetHalfThickness()) return kZ2OffThick;
00497 return 0;
00498 }
00499
00500 JobCResult PhotonTransport::SimulateScintHit(DigiScintHit* hit)
00501 {
00503
00504
00505 if(!hit) {
00506 MSG("Photon",Msg::kWarning) << "SimulateScintHit got null ScintHit." << endl;
00507 return JobCResult::kWarning;
00508 }
00509
00510 UgliGeomHandle ugli = UgliGeomHandle(fContext);
00511
00512
00513 UgliStripHandle ustrip = ugli.GetStripHandle(hit->StripEndId());
00514
00515
00516
00517 if(! ustrip.IsValid()) {
00518 MAXMSG("Photon",Msg::kWarning,10) << "Throwing out hit with no Ugli info: " << hit->StripEndId().AsString() << std::endl;
00519 hit -> SetFailBit(DigiScintHit::kInvalidStrip);
00520 return JobCResult::kWarning;
00521 }
00522
00523
00524 if(hit->DE()<0.) {
00525 MAXMSG("Photon",Msg::kWarning,5)
00526 << "DigiScintHit has negative energy ("
00527 << hit->DE()/Munits::GeV
00528 << " GeV). Throwing it out." << endl;
00529 hit -> SetFailBit(DigiScintHit::kNegEnergy);
00530 return JobCResult::kWarning;
00531 }
00532
00533 if(hit->DE()==0.) {
00534 MAXMSG("Photon",Msg::kWarning,5)
00535 << "DigiScintHit has zero energy. Throwing it out." << endl;
00536 hit -> SetFailBit(DigiScintHit::kNullEnergy);
00537 return JobCResult::kWarning;
00538 }
00539
00540 fEventResult.totalHits +=1;
00541 fEventResult.totalHitEnergy += hit->DE();
00542 fEventResult.fStripsHit.insert(hit->StripEndId().Build18BitPlnStripKey());
00543
00544 DigiScintHit* computerHit = hit;
00545
00546
00547
00548 PlexHandle plex(fContext);
00549 PlexStripEndId seid1(hit->StripEndId()); seid1.SetEnd(StripEnd::kPositive);
00550 PlexStripEndId seid2(hit->StripEndId()); seid2.SetEnd(StripEnd::kNegative);
00551 int numEndsReadOut = 0;
00552 if(plex.GetPixelSpotId(seid1).IsValid()) numEndsReadOut++;
00553 if(plex.GetPixelSpotId(seid2).IsValid()) numEndsReadOut++;
00554 if(numEndsReadOut==0) return JobCResult::kPassed;
00555
00556
00557 int badBoundary = VerifyScintHit(hit,ustrip);
00558
00559 if(badBoundary>0) {
00560 MAXMSG("Photon",Msg::kWarning,20)
00561 << "DigiScintHit geometry inconsistency: is not contained in strip " << endl
00562 << " Boundary violation: " << badBoundary
00563 << " " << kBoundaryString[badBoundary] << endl
00564 << " Strip: " <<hit->StripEndId().AsString()
00565 << " dE = " << hit->DE()/Munits::MeV << " MeV "
00566 << " dx = " << hit->DS()/Munits::cm << " cm " << endl
00567 << " ScintHit coords: "
00568 << Form("(%.2f,%.2f,%.2f) cm ",hit->X1()/Munits::cm,hit->Y1()/Munits::cm,hit->Z1()/Munits::cm)
00569 << "to"
00570 << Form("(%.2f,%.2f,%.2f) cm",hit->X2()/Munits::cm,hit->Y2()/Munits::cm,hit->Z2()/Munits::cm)
00571 << endl
00572 << " Ugli Geometry: "
00573 << Form("(+/-%.2f, +/-%.2f,+/-%.2f) cm",ustrip.GetHalfLength()/Munits::cm,ustrip.GetHalfWidth()/Munits::cm,ustrip.GetHalfThickness()/Munits::cm)
00574 << ".. skipping it." << endl;
00575 if ( fBadHitNtuple ) {
00576 Int_t failmode = 1;
00577 FillBadHitNtuple(hit,failmode);
00578 }
00579 hit -> SetFailBit(DigiScintHit::kBadGeom);
00580 fEventResult.hitsDiscardedGeom +=1;
00581 fEventResult.energyDiscardedGeom += hit->DE();
00582 return JobCResult::kWarning;
00583 }
00584
00585 if(hit->DS()<=0.) {
00586
00587
00588
00589 if(hit->ParticleId()==2212) {
00590
00591 double range = fProtonRangeTable.Interpolate(hit->ParticleKineticEnergy()/Munits::MeV);
00592 MinosMaterial::StdMaterial_t fStdMatSc=MinosMaterial::ePolystyreneMinos;
00593 double fRoSc=MinosMaterial::Density(fStdMatSc);
00594
00595 double dx = range / fRoSc * Munits::cm;
00596
00597 MSG("Photon",Msg::kDebug) << "dx==0 for a proton. Table lookup gives range of "
00598 << dx/Munits::mm << " mm for KE of "
00599 << hit->ParticleKineticEnergy()/Munits::MeV << " MeV" << endl;
00600
00601 if(dx<=0.0) {
00602 MSG("Photon",Msg::kDebug) << "dx<=0 for a proton, after table lookup!";
00603 if ( fBadHitNtuple ) {
00604 Int_t failmode = 3;
00605 FillBadHitNtuple(hit,failmode);
00606 }
00607 hit -> SetFailBit(DigiScintHit::kNullPath);
00608 fEventResult.hitsDiscardedBad+=1;
00609 fEventResult.energyDiscardedBad+=hit->DE();
00610 return JobCResult::kWarning;
00611 }
00612
00613
00614
00615 static DigiScintHit* tempHit = 0;
00616 if(tempHit) delete tempHit;
00617 tempHit = new DigiScintHit(hit->TrackId(),hit->ParticleId(),
00618 hit->ParticleEnergy(), hit->StripEndId(),
00619 hit->T1(), hit->X1(), hit->Y1(), hit->Z1(),
00620 hit->T2(), hit->X2(), hit->Y2(), hit->Z2(),
00621 dx, hit->DE());
00622 computerHit = tempHit;
00623
00624 } else {
00625
00626 MAXMSG("Photon",Msg::kWarning,5)
00627 << "DigiScintHit has zero path length. Throwing it out." << endl;
00628
00629 if ( fBadHitNtuple ) {
00630 Int_t failmode = 2;
00631 FillBadHitNtuple(hit,failmode);
00632 }
00633
00634 hit -> SetFailBit(DigiScintHit::kNullPath);
00635 fEventResult.hitsDiscardedBad+=1;
00636 fEventResult.energyDiscardedBad+=hit->DE();
00637 return JobCResult::kAOK;
00638 }
00639 }
00640
00641
00642 if(abs(hit->ParticleId())==11) {
00643
00644 if((hit->ParticleKineticEnergy() < fElectronFudgeThreshEnergy) ||
00645 (hit->DS() < fElectronFudgeThreshDist) ) {
00646
00647
00648
00649 double E1 = hit->ParticleKineticEnergy();
00650 double E2 = E1 - hit->DE();
00651 if(E2<0) E2 = 0;
00652 double dE = E1-E2;
00653
00654
00655 double Range1 = fElectronRangeTable.Interpolate(E1);
00656 double Range2 = fElectronRangeTable.Interpolate(E2);
00657 double dX = Range1-Range2;
00658
00659
00660
00661 static DigiScintHit* tempHit = 0;
00662 if(tempHit) delete tempHit;
00663 tempHit = new DigiScintHit(hit->TrackId(),hit->ParticleId(),
00664 hit->ParticleEnergy(), hit->StripEndId(),
00665 hit->T1(), hit->X1(), hit->Y1(), hit->Z1(),
00666 hit->T2(), hit->X2(), hit->Y2(), hit->Z2(),
00667 dX, dE);
00668 computerHit = tempHit;
00669 }
00670 }
00671
00672
00673 PhotonCount demand;
00674
00675
00676 demand.SetBlueTotal(0);
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 Bool_t hitOK = fPhotonComputer->
00688 ComputePhotons(computerHit,
00689 fBluePhotonTracker->GetBluePrescaleFactor(),
00690 fWlsFibreModel->GetWlsPrescaleFactor(),
00691 fGreenPhotonTracker->GetGreenPrescaleFactor(),
00692 demand);
00693
00694 if(!hitOK) {
00695 if ( fBadHitNtuple ) {
00696 Int_t failmode = 4;
00697 FillBadHitNtuple(hit,failmode);
00698 }
00699 hit -> SetFailBit(DigiScintHit::kPhotonComputer);
00700 fEventResult.hitsDiscardedBad+=1;
00701 fEventResult.energyDiscardedBad+=hit->DE();
00702 return JobCResult::kAOK;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 Int_t nBlue_Total=0;
00719 Int_t nBlue_Pos=0;
00720 Int_t nBlue_Neg=0;
00721 Int_t nGreen_Total=0;
00722 Int_t nGreen_Pos=0;
00723 Int_t nGreen_Neg=0;
00724 Int_t nPe_Total = 0;
00725 Int_t nPe_Pos=0;
00726 Int_t nPe_Neg=0;
00727
00728 DigiPhoton* bluePhoton =0;
00729 DigiPhoton* greenPhoton =0;
00730 DigiPE* pe =0;
00731
00732 bool done = false;
00733 while(!done) {
00734
00735
00736
00737 if(bluePhoton) delete bluePhoton;
00738 if(greenPhoton) delete greenPhoton;
00739 if(pe) delete pe;
00740 bluePhoton = 0;
00741 greenPhoton = 0;
00742 pe = 0;
00743
00744
00745
00746
00747
00748
00749
00750 if(nBlue_Total == demand.GetBlue_Total()) done = true;
00751
00752
00753 if( (nBlue_Pos == demand.GetBlue_Pos()) &&
00754 (nBlue_Neg == demand.GetBlue_Neg()) ) done = true;
00755
00756
00757
00758 if(demand.GetGreen_Total() == nGreen_Total) done = true;
00759
00760
00761 if( (nGreen_Pos == demand.GetGreen_Pos()) &&
00762 (nGreen_Neg == demand.GetGreen_Neg()) ) done = true;
00763
00764
00765 if(nPe_Total == demand.GetPe_Total()) done = true;
00766
00767
00768 if( (nPe_Pos == demand.GetPe_Pos()) &&
00769 (nPe_Neg == demand.GetPe_Neg()) ) done = true;
00770
00771 if(done) break;
00772
00773
00774
00775
00776
00777
00778
00779 StripEnd::StripEnd_t direction = StripEnd::kUnknown;
00780
00781
00782 if(demand.IsDirectional()) {
00783
00784
00785 if( (nBlue_Pos < demand.GetBlue_Pos()) ||
00786 (nGreen_Pos < demand.GetGreen_Pos()) ||
00787 (nPe_Pos < demand.GetPe_Pos()) ) {
00788 direction = StripEnd::kPositive;
00789 } else {
00790 direction = StripEnd::kNegative;
00791 }
00792 }
00793
00794
00795
00796 Bool_t blue_hit = fBluePhotonTracker->ScintPhotonToFibreHit(hit,
00797 ustrip,
00798 bluePhoton);
00799
00800 if(!bluePhoton) continue;
00801
00802 nBlue_Total++;
00803 if(direction==StripEnd::kPositive) nBlue_Pos++;
00804 if(direction==StripEnd::kNegative) nBlue_Neg++;
00805
00806
00807 if(!blue_hit) continue;
00808
00809
00810
00811 Bool_t fibre_hit =
00812 fWlsFibreModel->FibreHitToGreenPhoton(ustrip,
00813 direction,
00814 bluePhoton,
00815 greenPhoton);
00816
00817 if(!fibre_hit) continue;
00818
00819 nGreen_Total++;
00820 if(direction==StripEnd::kPositive) nGreen_Pos++;
00821 if(direction==StripEnd::kNegative) nGreen_Neg++;
00822
00823
00824
00825
00826
00827 Bool_t greenSurvived =
00828 fGreenPhotonTracker->GreenPhotonToPe( ustrip,
00829 greenPhoton,
00830 pe,
00831 direction);
00832
00833
00834 if((!greenSurvived)||(!pe)) continue;
00835
00836 nPe_Total++;
00837 if(direction==StripEnd::kPositive) nPe_Pos++;
00838 if(direction==StripEnd::kNegative) nPe_Neg++;
00839
00840
00841
00842
00843
00844 if(pe->GetPixelSpotId().IsValid()) {
00845 fEventResult.totalPE += 1;
00846 fEventResult.fPixelsHit.insert(pe->GetPixelSpotId().GetUniquePixelEncodedValue());
00847 fPeList->Add(pe);
00848
00849 if(fDebugNtuple)
00850 fDebugNtuple->Fill(hit->Plane(),hit->Strip(),(float)direction,
00851 hit->T1(), bluePhoton->T(),
00852 greenPhoton->T(), pe->GetTime(),
00853 greenPhoton->GetCosX(),
00854 greenPhoton->X()
00855 );
00856
00857 pe = 0;
00858 }
00859 };
00860
00861 MSG("Photon",Msg::kDebug) << "Hit: "
00862 << hit->DE()/Munits::MeV << " MeV -> "
00863 << nBlue_Total << " blue -> "
00864 << nGreen_Total << " green -> "
00865 << nPe_Total << " pe"
00866 << endl;
00867
00868 MSG("Photon",Msg::kVerbose) << "Hit result:" << endl
00869 << "Blue photons: Total ( " << nBlue_Total << " / " << demand.GetBlue_Total() << " ) "
00870 << " +ve ( "<< nBlue_Pos << " / " << demand.GetBlue_Pos() << " ) "
00871 << " -ve ( "<< nBlue_Neg << " / " << demand.GetBlue_Neg() << " ) " << endl
00872 << "Green photons: Total ( " << nGreen_Total << " / " << demand.GetGreen_Total() << " ) "
00873 << " +ve ( "<< nGreen_Pos << " / " << demand.GetGreen_Pos() << " ) "
00874 << " -ve ( "<< nGreen_Neg << " / " << demand.GetGreen_Neg() << " ) " << endl
00875 << "Photoelectrons: Total ( " << nPe_Total << " / " << demand.GetPe_Total() << " ) "
00876 << " +ve ( "<< nPe_Pos << " / " << demand.GetPe_Pos() << " ) "
00877 << " -ve ( "<< nPe_Neg << " / " << demand.GetPe_Neg() << " ) " << endl;
00878
00879 fEventResult.bluePhotons+=nBlue_Total;
00880 fEventResult.greenPhotons+=nGreen_Total;
00881
00882 fEventResult.bluePhotons_nonprescaled += (Int_t)(nBlue_Total/(fBluePhotonTracker->GetBluePrescaleFactor()
00883 *fWlsFibreModel->GetWlsPrescaleFactor()
00884 *fGreenPhotonTracker->GetGreenPrescaleFactor() ) );
00885 fEventResult.greenPhotons_nonprescaled += (Int_t)(nGreen_Total/fGreenPhotonTracker->GetGreenPrescaleFactor());
00886
00887
00888
00889 if(bluePhoton) delete bluePhoton;
00890 if(greenPhoton) delete greenPhoton;
00891 if(pe) delete pe;
00892
00893 return JobCResult::kPassed;
00894 }
00895
00896 JobCResult PhotonTransport::AddNoise()
00897 {
00901
00902
00903 const double kBig = 1e99;
00904 Double_t tstart = kBig;
00905 Double_t tend = -kBig;
00906 TObject* tobj;
00907 TIter hitarrayIter(fHitList);
00908 while( (tobj = hitarrayIter.Next()) ) {
00909 DigiScintHit* scinthit = dynamic_cast<DigiScintHit*>(tobj);
00910 if(scinthit) {
00911 if(scinthit->T1()<tstart) tstart = scinthit->T1();
00912 if(scinthit->T2()>tend) tend = scinthit->T2();
00913 }
00914 }
00915
00916
00917 if(tstart== kBig) return JobCResult::kFailed;
00918 if(tend ==-kBig) return JobCResult::kFailed;
00919
00920 std::vector<DigiPE*> peNoiseList;
00921
00922 MSG("Photon",Msg::kDebug) << "Calling NoiseMaker t=(" << tstart << ", " << tend << ")\n";
00923 fNoiseMaker->MakeNoise(peNoiseList,tstart,tend);
00924
00925 for(UInt_t i=0;i<peNoiseList.size();i++) {
00926 fPeList->Add(peNoiseList[i]);
00927 }
00928 fEventResult.noisePE += peNoiseList.size();
00929 fEventResult.totalPE += peNoiseList.size();
00930
00931
00932 return JobCResult::kPassed;
00933 }
00934
00935
00936 JobCResult PhotonTransport::AddAfterpulsing()
00937 {
00941
00942
00943 std::vector<DigiPE*> apList;
00944 std::vector<DigiPE*> peList;
00945
00946 MSG("Photon",Msg::kDebug) << "Calling Afterpulser." << std::endl;
00947
00948 peList.resize(fPeList->GetEntries(),0);
00949 for(UInt_t i=0; i<peList.size(); i++) {
00950 peList[i] = dynamic_cast<DigiPE*>((*fPeList)[i]);
00951 }
00952
00953 fAfterpulser->MakeAfterpulses(peList,apList);
00954
00955 for(UInt_t i=0;i<apList.size();i++) {
00956 fPeList->Add(apList[i]);
00957 }
00958 fEventResult.afterpulsePE += apList.size();
00959 fEventResult.totalPE += apList.size();
00960
00961
00962 return JobCResult::kPassed;
00963 }
00964
00965
00966 void PhotonTransport::Print(Option_t* ) const
00967 {
00968 MSG("Photon",kInfo) << "PhotonTransport Configuration:" << endl;
00969 if(fPhotonComputer) fPhotonComputer->Print("c");
00970 if(fBluePhotonTracker) fBluePhotonTracker->Print("b");
00971 if(fWlsFibreModel) fWlsFibreModel->Print("w");
00972 if(fGreenPhotonTracker) fWlsFibreModel->Print("g");
00973 if(fNoiseMaker) fNoiseMaker->Print("n");
00974 if(fAfterpulser) fAfterpulser->Print("n");
00975 }
00976
00977
00978 void PhotonTransport::FillBadHitNtuple(const DigiScintHit* hit,
00979 Int_t failmode) {
00982
00983
00984 UgliGeomHandle ugli = UgliGeomHandle(fContext);
00985 const UgliStripHandle& uglistp = ugli.GetStripHandle(hit->StripEndId());
00986 TVector3 vlocal0(hit->X1(),hit->Y1(),hit->Z1());
00987 const TVector3& vglobal0 = uglistp.LocalToGlobal(vlocal0);
00988
00989 fBadHitNtuple -> Fill(hit->ParticleEnergy(),
00990 hit->ParticleId(),hit->Plane(),hit->Strip(),
00991 hit->T1(),hit->X1(),hit->Y1(),hit->Z1(),
00992 (Float_t)(vglobal0.X()),(Float_t)vglobal0.Y(),
00993 (Float_t)vglobal0.Z(),
00994 hit->DS(),hit->DE(),failmode);
00995
00996 return;
00997 }
00998
00999