00001 #include "SimDetector.h"
00002 #include "SimPmt.h"
00003 #include "SimPmtMaker.h"
00004
00005 #include "SimVaElectronics.h"
00006 #include "SimElectronics.h"
00007 #include "SimElecMaker.h"
00008
00009 #include "SimDaqTrigger.h"
00010 #include "SimDaqTrigMaker.h"
00011
00012 #include "Digitization/DigiScintHit.h"
00013 #include "Digitization/DigiPE.h"
00014
00015 #include "MessageService/MsgService.h"
00016
00017 SimDetector* gDetector = NULL;
00018
00019 CVSID("$Id: SimDetector.cxx,v 1.58 2008/11/18 17:31:02 rhatcher Exp $");
00020 ClassImp(SimDetector)
00021
00022 SimDetector::SimDetector( VldContext context, TRandom* random ) :
00023 fContext(context),
00024 fPlex(context),
00025 fRandom(random),
00026 fFarElectronics(NULL),
00027 fNearElectronics(NULL)
00028 {
00029 if(fRandom ==NULL) {
00030 fRandom = gRandom;
00031 }
00032
00033
00034 fClearPmtList = 0;
00035 fM64Model = "SimPmtM64Full";
00036 fM16Model = "SimPmtUTM16";
00037 fFarElecModel = "SimVaElectronics";
00038 fNearElecModel = "SimQieElectronics";
00039
00040
00041 fFarElectronics = SimElecMaker::Create(fFarElecModel,context,fRandom);
00042 fNearElectronics = SimElecMaker::Create(fNearElecModel,context,fRandom);
00043
00044 fDaqTriggerMask = 0xFF;
00045 for(int i=0;i<kSimMaxTriggers;i++)
00046 fDaqTriggers[i] = 0;
00047
00048 MSG("DetSim",Msg::kDebug) << "SimDetector::Constructor. Context: " << fContext.AsString() << endl;
00049
00050 gDetector = this;
00051 }
00052
00053 SimDetector::~SimDetector( void )
00054 {
00055 if(fFarElectronics) delete fFarElectronics;
00056 if(fNearElectronics) delete fNearElectronics;
00057
00058
00059 fDigits.clear();
00060
00061
00062 SimPmtList::iterator it;
00063 for(it = fPmts.begin(); it!= fPmts.end(); it++) {
00064 if(it->second) delete it->second;
00065 fPmts.erase(it);
00066 }
00067 fPmts.clear();
00068 fActivePmts.clear();
00069 }
00070
00071 Registry& SimDetector::DefaultConfig( void )
00072 {
00073
00074 static Registry r;
00075
00076
00077 std::string name = "SimDetector.config.default";
00078 r.SetName(name.c_str());
00079
00080
00081 r.UnLockValues();
00082
00083 r.Set("clearPmtList",0);
00084
00085
00086 r.Set("M64Model","SimPmtM64Oxford");
00087 r.Set("M16Model","SimPmtM16UTTimed");
00088 r.Set("pmtM16DefaultGain",60);
00089 r.Set("pmtM64DefaultGain",100);
00090 r.Set("pmtDoOpticalCrosstalk",1);
00091 r.Set("pmtDoChargeCrosstalk",1);
00092 r.Set("pmtDoNonlinearity",0);
00093 r.Set("pmtDoDarkNoise",1);
00094 r.Set("pmtApplyGainDrift",0);
00095 r.Set("pmtScaleOpticalCrosstalk",1.0);
00096 r.Set("pmtScaleChargeCrosstalk",1.0);
00097
00098 r.Set("pmtScaleAdjacentChargeCrosstalk",1.0);
00099 r.Set("pmtScaleDiagonalChargeCrosstalk",1.0);
00100 r.Set("pmtScaleAdjacentOpticalCrosstalk",1.0);
00101 r.Set("pmtScaleDiagonalOpticalCrosstalk",1.0);
00102 r.Set("pmtHamamatsuPixelNumbering",0);
00103 r.Set("pmtChargeSlop",1.6);
00104 r.Set("pmtDoChargeSmear",1);
00105 r.Set("pmtM64DynodeSkipRate",0.00);
00106 r.Set("pmtM64NLThreshold",3.0);
00107 r.Set("pmtM64NonlinearityScale",1.0);
00108 r.Set("pmtRebuildGainMap",0);
00109
00110
00111 r.Set("farElecModel", "SimVaTimedElectronics");
00112 r.Set("nearElecModel","SimQieElectronics");
00113 r.Set("doLookupNonlinearity",1);
00114
00115
00116 r.Set("vaGain", 0.375/Munits::fC );
00117 r.Set("vaPedWidth", 2.8);
00118 r.Set("vaTimeSmearingMode", SimTimeSmearingMode::kBreitWigner);
00119 r.Set("vaTimingWidth", 0.);
00120 r.Set("vaSparsifyThresh", 17);
00121 r.Set("vaDynodeThresh", 57);
00122 r.Set("vaNonlinearity",1);
00123 r.Set("vaLinearityP0",24.);
00124 r.Set("vaLinearityP1",16091.3);
00125 r.Set("vaLinearityP2",4.63);
00126 r.Set("vaLinearityP3",13267.);
00127 r.Set("vaLinearityP4",7085.12);
00128
00129
00130 r.Set("varcTriggerMode", SimVarcTriggerMode::k2of36);
00131 r.Set("varcTriggerWindow", 400.*Munits::ns);
00132 r.Set("vaChipRandomDeadRate",700.*Munits::hertz);
00133 r.Set("vaChipDeadTime",5*Munits::microsecond);
00134 r.Set("vaShapingTime",500.*Munits::ns);
00135
00136
00137 r.Set("qieDoLookukp",1);
00138 r.Set("qieDacCharge",1.4*Munits::fC);
00139 r.Set("qieDaqPerRangeZeroAac",1.6);
00140 r.Set("qieFlipLowAdc",30.);
00141 r.Set("qieFlipHighAdc",180.);
00142 r.Set("qiePedestalWidthAdc",1.5);
00143 r.Set("qieAdcRms",0.0);
00144 r.Set("qiePedestalDac",50);
00145 r.Set("qieSparsifyThresh",70);
00146
00147
00148 r.Set("applyTrigger",3);
00149 r.Set("daqTrigTimingMethod",SimDaqTrigger::kGap);
00150 r.Set("daqTrigTimeGap",156.0*Munits::ns);
00151 r.Set("daqTrigTimeWindow",117.0*Munits::ns);
00152 r.Set("daqTrigReadoutWindowStart",5500.*Munits::ns);
00153 r.Set("daqTrigReadoutWindowStop",187*Munits::ns);
00154 r.Set("daqTriggerMask",0xFF);
00155
00156
00157
00158 Registry trigger2;
00159 trigger2.SetName("trigger2");
00160 trigger2.Set("type","PlaneTrigger");
00161 trigger2.Set("thresh",0.0);
00162 trigger2.Set("N",4);
00163 trigger2.Set("M",5);
00164 r.Set("trigger2",trigger2);
00165
00166
00167
00168
00169
00170 Registry trigger5;
00171 trigger5.SetName("trigger5");
00172 trigger5.Set("type","EnergyTrigger");
00173 trigger5.Set("thresh",1500.);
00174 trigger5.Set("Nhits",6);
00175 trigger5.Set("N",2);
00176 trigger5.Set("M",4);
00177 r.Set("trigger5",trigger5);
00178
00179
00180
00181 for(int i=0;i<kSimMaxTriggers;i++) {
00182 Registry triggerN;
00183 if(!(r.Get(Form("trigger%d",i),triggerN))) {
00184 triggerN.SetName(Form("trigger%d",i));
00185 r.Set(Form("trigger%d",i),triggerN);
00186 }
00187 }
00188
00189 return r;
00190 }
00191
00192 void SimDetector::Config( Registry& config )
00193 {
00194
00195 const char* s;
00196
00197
00198 config.Get("clearPmtList",fClearPmtList);
00199
00200
00201 config.Get("M64Model",s);
00202 if(SimPmtMaker::HasRegisteredClass(s)) fM64Model = s;
00203 else
00204 MSG("DetSim",Msg::kError) << "M64 Pmt Model " << s
00205 << " is not known. Reverting to default." << endl;
00206
00207 config.Get("M16Model",s); fM16Model = s;
00208 if(SimPmtMaker::HasRegisteredClass(s)) fM16Model = s;
00209 else
00210 MSG("DetSim",Msg::kError) << "M16 Pmt Model " << s
00211 << " is not known. Reverting to default." << endl;
00212
00213
00214 SimPmt* m16 = SimPmtMaker::Create(fM16Model,PlexPixelSpotId(),
00215 fContext,fRandom);
00216 m16->Config(config);
00217 delete m16;
00218
00219 SimPmt* m64 = SimPmtMaker::Create(fM64Model,PlexPixelSpotId(),
00220 fContext,fRandom);
00221 m64->Config(config);
00222 delete m64;
00223
00224
00225 config.Get("farElecModel",s);
00226 if(SimElecMaker::HasRegisteredClass(s)) fFarElecModel = s;
00227 else
00228 MSG("DetSim",Msg::kError) << "Far Detector Electronics Model " << s
00229 << " is not known. Reverting to default." << endl;
00230 config.Get("nearElecModel",s);
00231 if(SimElecMaker::HasRegisteredClass(s)) fNearElecModel = s;
00232 else
00233 MSG("DetSim",Msg::kError) << "Near Detector Electronics Model " << s
00234 << " is not known. Reverting to default." << endl;
00235
00236
00237 if(fFarElectronics) delete fFarElectronics;
00238 if(fNearElectronics) delete fNearElectronics;
00239 fFarElectronics = SimElecMaker::Create(fFarElecModel, fContext,fRandom);
00240 fNearElectronics = SimElecMaker::Create(fNearElecModel,fContext,fRandom);
00241
00242 fFarElectronics ->Config(config);
00243 fNearElectronics->Config(config);
00244
00245
00246 config.Get("applyTrigger", fApplyTrigger);
00247 config.Get("daqTrigTimingMethod", fDaqTrigTimingMethod);
00248 config.Get("daqTrigTimeGap", fDaqTrigTimeGap);
00249 config.Get("daqTrigTimeWindow", fDaqTrigTimeWindow);
00250 config.Get("daqTrigReadoutWindowStart",fDaqTrigReadoutWindowStart);
00251 config.Get("daqTrigReadoutWindowStop", fDaqTrigReadoutWindowStop);
00252 config.Get("daqTriggerMask", fDaqTriggerMask);
00253
00254
00255 Registry trigConfig;
00256 for(int itrig = 0; itrig<kSimMaxTriggers; itrig++) {
00257 if(fDaqTriggers[itrig]) delete fDaqTriggers[itrig];
00258 fDaqTriggers[itrig] = 0;
00259
00260 if( config.Get(Form("trigger%d",itrig),trigConfig) ) {
00261 const char* triggerType = 0;
00262 if( trigConfig.Get("type",triggerType) ) {
00263 fDaqTriggers[itrig] = SimDaqTrigMaker::Create(triggerType);
00264 if(fDaqTriggers[itrig]) {
00265 fDaqTriggers[itrig]->Configure(trigConfig);
00266 } else {
00267 MSG("DetSim",Msg::kError) << "Trigger " << itrig << ": type=" << triggerType << " not known!" << endl;
00268 }
00269 }
00270 }
00271 }
00272
00273 }
00274
00275
00276 void SimDetector::Reset( VldContext context )
00277 {
00278 MSG("DetSim",Msg::kDebug) << "SimDetector::Reset. Context: " << fContext.AsString() << endl;
00279
00280
00281 fDigits.clear();
00282 fSnarls.clear();
00283
00284
00285 fContext = context;
00286 fPlex = PlexHandle(context);
00287
00288
00289
00290 if(fClearPmtList) {
00291
00292
00293 SimPmtList::iterator it;
00294 for(it = fPmts.begin(); it!= fPmts.end(); it++) {
00295 if(it->second) delete it->second;
00296 fPmts.erase(it);
00297 }
00298 fPmts.clear();
00299 } else {
00300
00301
00302 SimPmtList::iterator it;
00303 for(it = fPmts.begin(); it!= fPmts.end(); it++) {
00304 SimPmt* pmt = it->second;
00305 pmt->Reset(context);
00306 }
00307 }
00308
00309 fActivePmts.clear();
00310
00311 if(SimPixelTimeBucket::GetGlobalPixelBuckets()>0) {
00312 MSG("DetSim",Msg::kError) << "Error: Memory leak detected: total SimPixelTimeBuckets after reset is "
00313 << SimPixelTimeBucket::GetGlobalPixelBuckets() << endl;
00314 }
00315
00316
00317 if(fNearElectronics) fNearElectronics->Reset(fContext);
00318 if(fFarElectronics) fFarElectronics->Reset(fContext);
00319
00320
00321 fDigiPeStorage.clear();
00322 }
00323
00324 void SimDetector::Clean()
00325 {
00326
00327 fDigits.clear();
00328
00329
00330 SimPmtList::iterator it;
00331 for(it = fPmts.begin(); it!= fPmts.end(); it++) {
00332 if(it->second) delete it->second;
00333 fPmts.erase(it);
00334 }
00335 fPmts.clear();
00336 }
00337
00338
00339 void SimDetector::AddDigiPEList( const TObjArray* peListObj )
00340 {
00345
00346 fPeList = peListObj;
00347 if(!fPeList) MSG("DetSim",Msg::kError) << "Null PE list input into SimDetector.. will probably crash." << endl;
00348 }
00349
00350
00351
00352
00353
00354 void SimDetector::Simulate( void )
00355 {
00356 DistributePEs();
00357 SimulatePmts();
00358 SimulateElectronics();
00359 SimulateTrigger();
00360 CompileStats();
00361 }
00362
00363 int SimDetector::GetNumberOfDigits(void)
00364 {
00365 return fDigits.size();
00366 }
00367
00368
00369 SimDigit* SimDetector::GetSimDigit(UInt_t ihit)
00370 {
00371 if(ihit<fDigits.size())
00372 return &(fDigits[ihit]);
00373 else return NULL;
00374 }
00375
00376 void SimDetector::Print(Option_t* option) const
00377 {
00378 std::string opt = option;
00379 Bool_t verbose = (opt.find("v") != std::string::npos);;
00380 Bool_t showpmts = (opt.find("p") != std::string::npos);;
00381 Bool_t showdigits = (opt.find("d") != std::string::npos);;
00382 Bool_t showsnarldigits = (opt.find("s") != std::string::npos);;
00383
00384 if(verbose) {
00385 showpmts = showdigits = showsnarldigits = true;
00386 }
00387
00388 printf("SimDetector:");
00389 printf("Current context: %s\n",fContext.AsString());
00390 printf("---------Config------------------------------\n");
00391 printf("PMT sim: M16Model %s\n",fM16Model.c_str());
00392 printf(" M64Model %s\n",fM64Model.c_str());
00393 SimPmt::PrintConfig();
00394 if(fFarElectronics) fFarElectronics->Print();
00395 if(fNearElectronics) fNearElectronics->Print();
00396 printf("Triggers: fDaqTriggerMask 0x%x\n",fDaqTriggerMask);
00397 printf(" fDaqTrigTimingMethod %s\n",
00398 (fDaqTrigTimingMethod==SimDaqTrigger::kGap)?"Gap":"Window");
00399 printf(" fDaqTrigTimeGap %f ns\n",fDaqTrigTimeGap/Munits::ns);
00400 printf(" fDaqTrigTimeWindow %f ns\n",fDaqTrigTimeWindow/Munits::ns);
00401 printf(" fDaqTrigReadoutWindowStart %f ns\n",fDaqTrigReadoutWindowStart/Munits::ns);
00402 printf(" fDaqTrigReadoutWindowStop %f ns\n",fDaqTrigReadoutWindowStop/Munits::ns);
00403
00404 for(int itrig=0;itrig<kSimMaxTriggers;itrig++) {
00405 if(fDaqTriggers[itrig]) {
00406 printf(" -- Trigger %2d: --\n",itrig);
00407 fDaqTriggers[itrig]->Print(option);
00408 }
00409 }
00410 printf("---------PMTS------------------------------------\n");
00411 printf(" Total PMTS in memory: %d Active PMTs: %d\n", (int)fPmts.size(),(int)fActivePmts.size());
00412 SimPmtList::iterator it;
00413 if(showpmts)
00414 for(it = fActivePmts.begin(); it!= fActivePmts.end(); it++) {
00415 SimPmt* pmt = it->second;
00416 if(pmt){
00417 pmt->Print(option);
00418 }
00419 }
00420
00421 printf("---------Digits----------------------------------\n");
00422 printf(" Total digits: %d\n",(int)fDigits.size());
00423 if(showdigits)
00424 for(UInt_t i = 0; i<fDigits.size(); i++) {
00425 printf(" Digit %3d: %s\n",i,fDigits[i].AsString());
00426 }
00427 for(UInt_t j=0; j < fSnarls.size(); j++ ) {
00428 printf("---------Snarl %d\n",j);
00429 printf(" Digits: %d\n",(int)fSnarls[j].size());
00430 printf(" Trigger time: %f ns\n",fSnarls[j].GetTriggerTime()/Munits::ns);
00431 printf(" Trigger Source: 0x%08X\n",fSnarls[j].GetTriggerSource());
00432 if(fSnarls[j].Size()>0) {
00433 printf(" Start time: %f ns\n",fSnarls[j].GetDigit(0)->GetTime()/Munits::ns);
00434 printf(" Stop time: %f ns\n",fSnarls[j].GetDigit(fSnarls[j].Size()-1)->GetTime()/Munits::ns);
00435 }
00436 if(showsnarldigits)
00437 for(UInt_t i = 0; i<fSnarls[j].size(); i++) {
00438 printf(" Digit: %s\n",fSnarls[j][i].AsString());
00439 }
00440 }
00441
00442 printf("---------DAQ-------------------------------------\n");
00443 printf(" TriggerWord: 0x%08X\n",fTotalTriggerWord);
00444 printf(" TriggerMask: 0x%08X\n",fDaqTriggerMask);
00445 printf("--------SimEventResult---------------------------\n");
00446 fResult.Print();
00447 printf("-------------------------------------------------\n");
00448
00449
00450 }
00451
00452
00453
00454 void SimDetector::DistributePEs( void )
00455 {
00456 TObjArrayIter itr(fPeList);
00457 const DigiPE* digipe = NULL;
00458 double earlyTime = 1e10;
00459 while( (digipe = dynamic_cast<DigiPE*>(itr.Next()))!=0 ) {
00460 if(digipe->GetTime()<earlyTime) earlyTime = digipe->GetTime();
00461 }
00462
00463
00464 fTimeShift = 0;
00465 if(earlyTime<0) {
00466 while((earlyTime+fTimeShift)<0) fTimeShift+=100.*Munits::ns;
00467 MAXMSG("DetSim",Msg::kWarning,10) << "Negative times in PE list. Shifting all times forward by " << fTimeShift/Munits::ns << " ns" << endl;
00468 }
00469
00470
00471
00472
00473 itr.Reset();
00474 while( (digipe = dynamic_cast<DigiPE*>(itr.Next()))!=0 ) {
00475 if(fTimeShift>0) {
00476
00477 const_cast<DigiPE*>(digipe)->SetTime(digipe->GetTime() + fTimeShift);
00478 }
00479
00480
00481 this->SortDigiPE( digipe );
00482 }
00483
00484 }
00485
00486
00487
00488 void SimDetector::SortDigiPE( const DigiPE* digipe )
00489 {
00490 if(digipe==0) return;
00491 PlexPixelSpotId psid;
00492 PlexStripEndId seid;
00493
00494 const DigiScintHit* hit = digipe->GetHitPointer();
00495 psid = digipe->GetPixelSpotId();
00496 if(hit) seid = hit->StripEndId();
00497 Double_t time = digipe->GetTime();
00498
00499 if(!psid.IsValid()) {
00500 MSG("DetSim",Msg::kWarning) << "Invalid pixel spot on a DigiPE. Omitting. " << psid.AsString() << "\n";
00501 MSG("DetSim",Msg::kWarning) << "Time: " << time
00502 << " DarkNoise: " << ((digipe->IsDarkNoise())?"true":"false")
00503 << " FibreLight: " << ((digipe->IsFibreLight())?"true":"false")
00504 << " ScintHit: \n";
00505 if(hit)
00506 MSG("DetSim",Msg::kWarning) << hit->AsString() << endl;
00507
00508 return;
00509 }
00510 if (psid.GetDetector()==Detector::kUnknown) {
00511 MSG("DetSim",Msg::kWarning) << "Bad pixel spot on a DigiPE (unknown detector). Omitting.\n";
00512 return;
00513 }
00514
00515
00516 SimPmt* pmt = 0;
00517 int tube = GetTubeIndex(psid);
00518 SimPmtList::iterator it = fPmts.find(tube);
00519 pmt = it->second;
00520
00521
00522 if(it == fPmts.end()) {
00523 SimPmt::Pmt_t type = SimPmt::kM16;
00524
00525 if(psid.GetElecType() == ElecType::kQIE) type = SimPmt::kM64;
00526
00527 std::string modelName;
00528 if( type == SimPmt::kM16 ) modelName = fM16Model;
00529 else modelName = fM64Model;
00530
00531 pmt = SimPmtMaker::Create(modelName,psid,fContext,fRandom);
00532
00533 if(!pmt) {
00534 MSG("DetSim",Msg::kError) << "SimDetector: Failed to create new "
00535 << "pmt of type " << modelName << endl;
00536 return;
00537 }
00538
00539
00540 pmt->Reset(fContext);
00541
00542 MSG("DetSim",Msg::kDebug) << "SimDetector: Adding new PMT "
00543 << pmt->GetTubeId().AsString()
00544 << " type: " << pmt->GetType()
00545 << " at: " << tube
00546 << endl;
00547 fPmts[tube] = pmt;
00548 }
00549
00550
00551 MSG("DetSim",Msg::kVerbose) << "SimDetector::AddDigiPE "
00552 << psid.AsString() << " "
00553 << 1.0 << "pe "
00554 << time << "ns"
00555 << endl;
00556
00557
00558 fPmts[tube]->AddDigiPE(digipe);
00559
00560
00561 fActivePmts[tube] = fPmts[tube];
00562 }
00563
00564
00565
00566 void SimDetector::SimulatePmts( void )
00567 {
00573 SimPmtList::iterator it;
00574
00575
00576 for(it = fActivePmts.begin(); it!= fActivePmts.end(); it++) {
00577 SimPmt* pmt = it->second;
00578 if(pmt){
00579
00580 MSG("DetSim",Msg::kDebug) << "Simulating PMT "
00581 << pmt->GetTubeId().AsString()
00582 << endl;
00583 pmt->SimulatePmt();}
00584 }
00585 }
00586
00587
00588 void SimDetector::SimulateElectronics( void )
00589 {
00594 fDigits.clear();
00595
00596
00597 if(fFarElectronics)
00598 fFarElectronics->ReadoutDetector(fActivePmts);
00599
00600
00601 fDigits.AddList(fFarElectronics->GetDigits());
00602
00603
00604 if(fNearElectronics)
00605 fNearElectronics->ReadoutDetector(fActivePmts);
00606
00607
00608 fDigits.AddList(fNearElectronics->GetDigits());
00609
00610 for(UInt_t i = 0; i<fDigits.size(); i++) {
00611 MSG("DetSim",Msg::kVerbose)
00612 << "SimDetector read out digit: "
00613 << fDigits[i].AsString() << std::endl;;
00614 }
00615
00616 }
00617
00618 void SimDetector::SimulateTrigger( void )
00619 {
00624
00625
00626 fTotalTriggerWord = 0;
00627 fBiggestSnarl = 0;
00628 fBiggestSnarlSize = -1;
00629
00630
00631 fDigits.Sort();
00632
00633 bool dotrigger = (fApplyTrigger>0);
00634 static bool donemessage = false;
00635 if(fApplyTrigger==3) {
00636
00637 if(fContext.GetDetector()==Detector::kFar) {
00638 if(!donemessage) MSG("DetSim",Msg::kWarning)
00639 << "This is the far detector, so I'm assuming you want DAQ triggers on. Use applytrigger=0 to turn them off." << endl;
00640 dotrigger = true;
00641 }
00642 else if(fContext.GetDetector()==Detector::kNear) {
00643 if(!donemessage) MSG("DetSim",Msg::kWarning)
00644 << "This is the near detector, so I'm assuming you want DAQ triggers off. Use applytrigger=1 to turn them on." << endl;
00645 dotrigger = false;
00646 }
00647 else if(fContext.GetDetector()==Detector::kCalDet) {
00648 if(!donemessage) MSG("DetSim",Msg::kWarning)
00649 << "This is the caldet detector, so I'm assuming you want DAQ triggers off. Use applytrigger=1 to turn them on." << endl;
00650 dotrigger = false;
00651 }
00652 donemessage = true;
00653 };
00654
00655 if(!dotrigger) {
00656
00657
00658 Int_t triggerWord = 0;
00659
00660 for(int itrig=0;itrig<kSimMaxTriggers;itrig++) {
00661 int triggerbit = (1<<itrig);
00662
00663 if(fDaqTriggers[itrig]) {
00664 bool result = fDaqTriggers[itrig]->ApplyTriggerAt(fPlex,
00665 fDigits,
00666 0,
00667 fDigits.size()
00668 );
00669 if(result) triggerWord |= triggerbit;
00670 }
00671 }
00672
00673
00674 if(fContext.GetDetector() == Detector::kFar) {
00675 triggerWord |= 0x20000;
00676 } else
00677 if(fContext.GetDetector() == Detector::kNear) {
00678 triggerWord |= 0x10000;
00679 }
00680
00681
00682 double snarltime = 0;
00683 if(fDigits.size()>0) snarltime = fDigits[0].GetTime();
00684 SimSnarl snarl(triggerWord,snarltime);
00685 fTotalTriggerWord = triggerWord;
00686
00687
00688 snarl.AddList(fDigits);
00689
00690
00691 fSnarls.push_back(snarl);
00692 fBiggestSnarlSize = snarl.Size();
00693 return;
00694 }
00695
00696
00697
00698
00699
00700
00701 UInt_t startdigit = 0;
00702
00703 while(startdigit<fDigits.size()) {
00704 int digitsInBurst = 0;
00705 switch(fDaqTrigTimingMethod) {
00706 case SimDaqTrigger::kNone:
00707 digitsInBurst=fDigits.size();
00708 MSG("DetSim",Msg::kDebug) << "Trigger: NULL trigger, triggering all digits." << endl;
00709 break;
00710 case SimDaqTrigger::kWindow:
00711 digitsInBurst = IsWindowBurst(fDigits,startdigit);
00712 if(digitsInBurst) MSG("DetSim",Msg::kDebug) << "Trigger: Window trigger fired with " << digitsInBurst << " digits." << endl;
00713 break;
00714 case SimDaqTrigger::kGap:
00715 digitsInBurst = IsGapBurst(fDigits,startdigit);
00716 if(digitsInBurst) MSG("DetSim",Msg::kDebug) << "Trigger: Gap trigger fired with " << digitsInBurst << " digits." << endl; break;
00717 default:
00718 MSG("DetSim",Msg::kError) << "Unknown DAQ trigger window method " << fDaqTrigTimingMethod << endl;
00719 break;
00720 }
00721
00722 if(digitsInBurst>0) {
00723
00724
00725 Int_t triggerWord = 0;
00726
00727 for(int itrig=0;itrig<kSimMaxTriggers;itrig++) {
00728 int triggerbit = (1<<itrig);
00729
00730 if(fDaqTriggers[itrig]) {
00731 bool result = fDaqTriggers[itrig]->ApplyTriggerAt(fPlex,
00732 fDigits,
00733 startdigit,
00734 startdigit+digitsInBurst
00735 );
00736 if(result) triggerWord |= triggerbit;
00737 }
00738 }
00739 MSG("DetSim",Msg::kDebug) << "Burst digits " << startdigit
00740 << " to " << startdigit+digitsInBurst - 1
00741 << " fired triggers: " << triggerWord << endl;
00742
00743 if(triggerWord != 0){
00744
00745
00746 fTotalTriggerWord |= triggerWord;
00747
00748
00749 SimSnarl snarl(triggerWord,fDigits[startdigit].GetTime());
00750
00751
00752 Double_t burst_start = fDigits[startdigit].GetTime();
00753 Double_t burst_stop = fDigits[startdigit+digitsInBurst-1].GetTime();
00754 Double_t window_open = burst_start - fDaqTrigReadoutWindowStart;
00755 Double_t window_close = burst_stop + fDaqTrigReadoutWindowStop;
00756
00757 UInt_t lastdigit = 0;
00758 for(UInt_t i=0; i<fDigits.size(); i++) {
00759 if(( fDigits[i].GetTime()>=window_open ) &&
00760 ( fDigits[i].GetTime()<=window_close ) ) {
00761 snarl.push_back(fDigits[i]);
00762 if(i>lastdigit) lastdigit=i;
00763 }
00764 }
00765
00766
00767
00768 fSnarls.push_back(snarl);
00769 if((Int_t)snarl.Size() > fBiggestSnarlSize) {
00770 fBiggestSnarlSize = snarl.size();;
00771 fBiggestSnarl = fSnarls.size() -1;
00772 }
00773
00774
00775 startdigit += lastdigit;
00776 }
00777 }
00778 startdigit++;
00779 }
00780 }
00781
00782 void SimDetector::CompileStats()
00783 {
00784 fResult.Reset();
00785
00786
00787 SimPmtList::iterator it;
00788 for(it = fActivePmts.begin(); it!= fActivePmts.end(); it++) {
00789 SimPmt* pmt = it->second;
00790 if(pmt){
00791 fResult.totalPe += pmt->GetTotalPe();
00792 fResult.hitPixels += pmt->GetTotalHitPixels(false);
00793 fResult.hitPixelsWithXtalk += pmt->GetTotalHitPixels(true);
00794 fResult.totalCharge += pmt->GetTotalCharge();
00795 }
00796 }
00797
00798
00799 if(fFarElectronics) {
00800 fResult.digitsAfterFETrigger+=( fFarElectronics->GetDigitsAfterFETrigger() );
00801 fResult.adcsAfterFETrigger+=( fFarElectronics-> GetAdcsAfterFETrigger() );
00802 fResult.digitsAfterSpars+=( fFarElectronics->GetDigitsAfterSpars() );
00803 fResult.adcsAfterSpars+=( fFarElectronics->GetAdcsAfterSpars() );
00804 }
00805
00806
00807 if(fNearElectronics) {
00808 fResult.digitsAfterFETrigger+=( fNearElectronics->GetDigitsAfterFETrigger() );
00809 fResult.adcsAfterFETrigger+=( fNearElectronics-> GetAdcsAfterFETrigger() );
00810 fResult.digitsAfterSpars+=( fNearElectronics->GetDigitsAfterSpars() );
00811 fResult.adcsAfterSpars+=( fNearElectronics->GetAdcsAfterSpars() );
00812 }
00813
00814
00815 fResult.snarls = GetNumberOfSnarls();
00816
00817
00818 fResult.snarl_digits = new Int_t[ fResult.snarls ];
00819 fResult.snarl_trigger = new Int_t[ fResult.snarls ];
00820 fResult.snarl_adcs = new Float_t[ fResult.snarls ];
00821
00822 fResult.bigSnarl= GetBiggestSnarl();
00823
00824
00825 for(UInt_t isnarl = 0; isnarl < fSnarls.size(); isnarl++) {
00826 Float_t adctot = 0;
00827 for(UInt_t i=0; i<fSnarls[isnarl].size(); i++) {
00828 SimDigit& simdigit = fSnarls[isnarl][i];
00829
00830 adctot+= simdigit.GetADC() ;
00831 }
00832
00833
00834 fResult.digitsAfterDaqTrigger+=( fSnarls[isnarl].Size() );
00835 fResult.adcsAfterDaqTrigger+=( adctot );
00836
00837 fResult.snarl_digits[isnarl] = fSnarls[isnarl].Size();
00838 fResult.snarl_trigger[isnarl] = fSnarls[isnarl].GetTriggerSource();
00839 fResult.snarl_adcs[isnarl] = adctot;
00840 }
00841
00842 fResult.timeShift = fTimeShift;
00843
00844 }
00845
00846
00847 Int_t SimDetector::IsWindowBurst(SimDigitList& digitList,
00848 UInt_t startdigit)
00849 {
00850
00851
00852
00853
00854 Double_t t_start = digitList[startdigit].GetTime();
00855 Double_t t_stop = t_start + fDaqTrigTimeWindow;
00856
00857 Int_t ndigs = 1;
00858 while(startdigit+ndigs < digitList.GoodSize()) {
00859 Double_t t = fDigits[startdigit+ndigs-1].GetTime();
00860 if(t>t_stop) break;
00861 ndigs++;
00862 }
00863 return ndigs;
00864 }
00865
00866
00867 Int_t SimDetector::IsGapBurst(SimDigitList& digitList,
00868 UInt_t startdigit)
00869 {
00870
00871
00872
00873
00874 if(startdigit!=0) {
00875 Double_t t1 = fDigits[startdigit-1].GetTime();
00876 Double_t t2 = fDigits[startdigit].GetTime();
00877 if (t2-t1 < fDaqTrigTimeGap)
00878 return 0;
00879 }
00880
00881
00882 Int_t ndigs = 1;
00883 while(startdigit+ndigs < digitList.GoodSize()) {
00884 Double_t t1 = fDigits[startdigit+ndigs-1].GetTime();
00885 Double_t t2 = fDigits[startdigit+ndigs].GetTime();
00886 if(t2-t1 >= fDaqTrigTimeGap) return ndigs;
00887 ndigs++;
00888 }
00889 return ndigs;
00890
00891 }