WCSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WCSimWCDigitizer.cc
Go to the documentation of this file.
1 #include "WCSimWCDigitizer.hh"
2 #include "G4EventManager.hh"
3 #include "G4DigiManager.hh"
4 
5 // for memset
6 
7 //Use this and one/two of below to debug hit information
8 //#define WCSIMWCDIGITIZER_VERBOSE
9 //Print out hits with PMT IDs up to N
10 #define NPMTS_VERBOSE -1
11 //And/Or a specific PMT ID
12 #define VERBOSE_PMT -1
13 
14 #ifndef HYPER_VERBOSITY
15 // #define HYPER_VERBOSITY
16 #endif
17 
18 // *******************************************
19 // BASE CLASS
20 // *******************************************
21 
23  WCSimDetectorConstruction* inDetector,
24  WCSimWCDAQMessenger* myMessenger,
25  DigitizerType_t digitype,
26  G4String detectorElement)
27  :G4VDigitizerModule(name), myDetector(inDetector), DAQMessenger(myMessenger), DigitizerType(digitype),DigitizerClassName(""), detectorElement(detectorElement)
28 {
29  // G4String colName = "WCDigitizedStoreCollection";
30  G4String colName;
31  if(detectorElement=="tank") colName = "WCDigitizedStoreCollection";
32  else if(detectorElement=="OD") colName = "WCDigitizedStoreCollection_OD";
33  collectionName.push_back(colName);
34  ReInitialize();
35 
36 #ifdef HYPER_VERBOSITY
37  if(detectorElement=="OD")G4cout<<"WCSimWCDigitizerBase::WCSimWCDigitizerBase ☆ recording collection name "<<colName<<" for "<<detectorElement<<G4endl;
38 #endif
39 
40  if(DAQMessenger == NULL) {
41  G4cerr << "WCSimWCDAQMessenger pointer is NULL when passed to WCSimWCDigitizerBase constructor. Exiting..."
42  << G4endl;
43  exit(-1);
44  }
45 }
46 
48 }
49 
51 {
52  //set the options to digitizer-specific defaults
57 
58  //read the .mac file to override them
59  if(DAQMessenger != NULL) {
62  }
63  else {
64  G4cerr << "WCSimWCDAQMessenger pointer is NULL when used in WCSimWCDigitizerBase::GetVariables(). Exiting..."
65  << G4endl;
66  exit(-1);
67  }
68 
69  G4cout << "Using digitizer deadtime " << DigitizerDeadTime << " ns" << G4endl;
70  G4cout << "Using digitizer integration window " << DigitizerIntegrationWindow << " ns" << G4endl;
71  G4cout << "Using digitizer time resolution " << DigitizerTimingPrecision << " ns" << G4endl;
72  G4cout << "Using digitizer charge resolution " << DigitizerPEPrecision << " p.e." << G4endl;
73 }
74 
76 {
77  //Input is WCSimWCDigitsCollection with raw PMT hits (photon + dark noise)
78  //Output is WCSimWCDigitsCollection with digitied PMT hits
79 
80  //Clear the DigiStoreHitMap
81  ReInitialize();
82 
83  //Temporary Storage of Digitized hits which is passed to the trigger
84  DigiStore = new WCSimWCDigitsCollection(collectionName[0],collectionName[0]);
85 
86  G4DigiManager* DigiMan = G4DigiManager::GetDMpointer();
87 
88  // Get the PMT collection ID
89  // G4int WCHCID = DigiMan->GetDigiCollectionID("WCRawPMTSignalCollection");
90 
91  G4String rawcollectionName;
92  if(detectorElement=="tank") rawcollectionName = "WCRawPMTSignalCollection";
93  else if(detectorElement=="OD") rawcollectionName = "WCRawPMTSignalCollection_OD";
94  G4int WCHCID = DigiMan->GetDigiCollectionID(rawcollectionName);
95 
96  // Get the PMT Digits collection
97  WCSimWCDigitsCollection* WCHCPMT =
98  (WCSimWCDigitsCollection*)(DigiMan->GetDigiCollection(WCHCID));
99 
100 #ifdef HYPER_VERBOSITY
101  if(detectorElement=="OD"){
102  G4cout << "WCSimWCDigitizerBase::Digitize ☆ making digits collection (WCSimWCDigitsCollection*)"<<collectionName[0]
103  << " for "<<detectorElement<<" and calling DigitizeHits on "<<rawcollectionName<<" to fill it"<<G4endl;}
104 #endif
105 
106  if (WCHCPMT) {
107  DigitizeHits(WCHCPMT);
108  } else {
109  G4cout << "WCSimWCDigitizerBase::Digitize didn't find hit collection for " << detectorElement << G4endl;
110  }
111 
112  StoreDigiCollection(DigiStore);
113 
114 }
115 
116 bool WCSimWCDigitizerBase::AddNewDigit(int tube, int gate, double digihittime, double peSmeared, std::vector<int> digi_comp)
117 {
118  //digitised hit information does not have infinite precision
119  //so need to round the charge and time information
120  double digihittime_d = Truncate(digihittime, DigitizerTimingPrecision);
121  double peSmeared_d = Truncate(peSmeared, DigitizerPEPrecision);
122 
123  //gate is not a trigger, but just the position of the digit in the array
124  //inside the WCSimWCDigi object
125 #ifdef WCSIMWCDIGITIZER_VERBOSE
126  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT) {
127  G4cout<<"Adding hit "<<gate<<" in tube "<<tube
128  << " with time " << digihittime_d << " charge " << peSmeared_d
129  << " (truncated from t: " << digihittime << " q: " << peSmeared << ")"
130  << " (made of " << digi_comp.size() << " raw hits with IDs ";
131  for(unsigned int iv = 0; iv < digi_comp.size(); iv++)
132  G4cout << " " << digi_comp[iv] << ",";
133  G4cout << ")";
134  }
135 #endif
136 
137  //use un-truncated peSmeared here, so that truncation does not affect the test
138  if (peSmeared > 0.0) {
139  if ( DigiStoreHitMap[tube] == 0) {
140  WCSimWCDigi* Digi = new WCSimWCDigi();
141  Digi->SetTubeID(tube);
142  Digi->SetPe(gate,peSmeared_d);
143  Digi->AddPe(digihittime_d);
144  Digi->SetTime(gate,digihittime_d);
145  Digi->AddDigiCompositionInfo(digi_comp);
146  DigiStoreHitMap[tube] = DigiStore->insert(Digi);
147 #ifdef WCSIMWCDIGITIZER_VERBOSE
148  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
149  G4cout << " NEW HIT" << G4endl;
150 #endif
151  }
152  else {
153  (*DigiStore)[DigiStoreHitMap[tube]-1]->SetPe(gate,peSmeared_d);
154  (*DigiStore)[DigiStoreHitMap[tube]-1]->SetTime(gate,digihittime_d);
155  (*DigiStore)[DigiStoreHitMap[tube]-1]->AddPe(digihittime_d);
156  (*DigiStore)[DigiStoreHitMap[tube]-1]->AddDigiCompositionInfo(digi_comp);
157 #ifdef WCSIMWCDIGITIZER_VERBOSE
158  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
159  G4cout << " DEJA VU" << G4endl;
160 #endif
161  }
162  return true;
163  }//peSmeared > 0
164  else {
165 #ifdef WCSIMWCDIGITIZER_VERBOSE
166  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
167  G4cout << "DIGIT REJECTED with charge " << peSmeared_d
168  << " time " << digihittime_d << G4endl;
169 #endif
170  return false;
171  }
172 }
173 
175 {
181 }
182 
183 
184 // *******************************************
185 // DERIVED CLASS
186 // *******************************************
187 
189  WCSimDetectorConstruction* myDetector,
190  WCSimWCDAQMessenger* myMessenger,
191  G4String detectorElement)
192  : WCSimWCDigitizerBase(name, myDetector, myMessenger, kDigitizerSKI, detectorElement)
193 {
194  DigitizerClassName = "SKI";
195  GetVariables();
196 }
197 
199 }
200 
202 
203  if(detectorElement=="tank") G4cout << "TANK # ";
204  if(detectorElement=="OD") G4cout << "OD # ";
205  G4cout << "WCSimWCDigitizerSKI::DigitizeHits START WCHCPMT->entries() = " << WCHCPMT->entries() << G4endl;
206 
207  //Get the PMT info for hit time smearing
208  G4String WCIDCollectionName = myDetector->GetIDCollectionName();
209  WCSimPMTObject * PMT = myDetector->GetPMTPointer(WCIDCollectionName);
210 
211  // G. Pronost 2019/09/09:
212  // Hit need to be sorted! (This is done no where!)
213  std::sort(WCHCPMT->GetVector()->begin(), WCHCPMT->GetVector()->end(), WCSimWCDigi::SortFunctor_Hit());
214 
215  //loop over entires in WCHCPMT, each entry corresponds to
216  //the photons on one PMT
217  for (G4int i = 0 ; i < WCHCPMT->entries() ; i++)
218  {
219 
220  //We must first sort hits by PMT in time. This is very important as the code
221  //assumes that each hit is in time order from lowest to highest.
222  (*WCHCPMT)[i]->SortArrayByHitTime();
223  int tube = (*WCHCPMT)[i]->GetTubeID();
224 #ifdef WCSIMWCDIGITIZER_VERBOSE
225  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT) {
226  G4cout << "tube " << tube
227  << " totalpe = " << (*WCHCPMT)[i]->GetTotalPe()
228  << " times";
229  for(int ip = 0; ip < (*WCHCPMT)[i]->GetTotalPe(); ip++)
230  G4cout << " " << (*WCHCPMT)[i]->GetTime(ip);
231  /*
232  G4cout<<" parents =\t";
233  for( G4int ip = 0 ; ip < (*WCHCPMT)[i]->GetTotalPe() ; ip++)
234  G4cout << " " << (*WCHCPMT)[i]->GetParentID(ip);
235  */
236  G4cout <<G4endl;
237  }
238 #endif
239 
240  //Sorting done. Now we integrate the charge on each PMT.
241  // Integration occurs for DigitizerIntegrationWindow ns (user set)
242  // Digitizer is then dead for DigitizerDeadTime ns (user set)
243 
244  //look over all hits on the PMT
245  //integrate charge and start digitizing
246  double intgr_start=0;
247  double upperlimit=0;
248  G4double efficiency = 0.985; // with skrn1pe (AP tuning) & 30% QE increase in stacking action
249 
250  // Variables to store photon uniqueid that make up a digit
251  int digi_unique_id = 0;
252  int photon_unique_id = 0;
253  std::vector<int> digi_comp;
254 
255  //loop over the hits on this PMT
256  for( G4int ip = 0 ; ip < (*WCHCPMT)[i]->GetTotalPe() ; ip++)
257  {
258  double time = (*WCHCPMT)[i]->GetTime(ip);
259  double pe = (*WCHCPMT)[i]->GetPe(ip);
260 
261  //start the integration time as the time of the first hit
262  //Hits must be sorted in time
263  if(ip==0) {
264  intgr_start=time;
265  peSmeared = 0;
266  //Set the limits of the integration window [intgr_start,upperlimit]
267  upperlimit = intgr_start + DigitizerIntegrationWindow;
268  }
269 
270 #ifdef WCSIMWCDIGITIZER_VERBOSE
271  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
272  G4cout << "ip " << ip
273  << " pe " << pe
274  << " time " << time
275  << " intgr_start " << intgr_start
276  << " upperlimit " << upperlimit
277  << G4endl;
278 #endif
279 
280  bool MakeDigit = false;
281  if(time >= intgr_start && time <= upperlimit) {
282  peSmeared += pe;
283  photon_unique_id = ip;
284  digi_comp.push_back(photon_unique_id);
285 
286 #ifdef WCSIMWCDIGITIZER_VERBOSE
287  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
288  G4cout<<"INFO: time "<<time<<" digi_id "<<digi_unique_id<<" p_id "<<photon_unique_id<<G4endl;
289 #endif
290  //if this is the last digit, make sure to make the digit
291  if(ip + 1 == (*WCHCPMT)[i]->GetTotalPe()){
292  MakeDigit = true;
293  }
294 
295  }
296  //if ensures we don't append the same digit multiple times while in the integration window
297  else if(digi_comp.size()) {
298  //this hit is outside the integration time window.
299  //Charge integration is over. The is now a DigitizerDeadTime ns dead
300  //time period where no hits can be recorded
301  MakeDigit = true;
302  }
303 
304  //Make digit here
305  if(MakeDigit) {
306  int iflag;
308 
309  //Check if previous hit passed the threshold. If so we will digitize the hit
310  if(iflag == 0) {
311  //apply time smearing
312  double Q = (peSmeared > 0.5) ? peSmeared : 0.5;
313  //digitize hit
314  peSmeared *= efficiency;
315  bool accepted = WCSimWCDigitizerBase::AddNewDigit(tube, digi_unique_id,
316  intgr_start + PMT->HitTimeSmearing(Q),
317  peSmeared, digi_comp);
318  if(accepted) {
319  digi_unique_id++;
320  }
321  assert(digi_comp.size());
322  digi_comp.clear();
323  }
324  else {
325  //reject hit
326 #ifdef WCSIMWCDIGITIZER_VERBOSE
327  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
328  G4cout << "DIGIT REJECTED with time " << intgr_start << G4endl;
329 #endif
330  digi_comp.clear();
331  }
332  }
333 
334  //Now try and deal with the next hit
335  if(time > upperlimit && time <= upperlimit + DigitizerDeadTime) {
336  //Now we need to reject hits that are after the integration
337  //period to the end of the veto signal
338  continue;
339  }
340  else if(time > upperlimit + DigitizerDeadTime){
341 #ifdef WCSIMWCDIGITIZER_VERBOSE
342  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
343  G4cout<<"*** PREPARING FOR >1 DIGI ***"<<G4endl;
344 #endif
345  //we now need to start integrating from the hit
346  intgr_start=time;
347  peSmeared = pe;
348  //Set the limits of the integration window [intgr_start,upperlimit]
349  upperlimit = intgr_start + DigitizerIntegrationWindow;
350 
351  //store the digi composition information
352  photon_unique_id = ip;
353  digi_comp.push_back(photon_unique_id);
354 
355  //if this is the last hit we must handle the creation of the digit
356  //as the loop will not evaluate again
357  if(ip+1 == (*WCHCPMT)[i]->GetTotalPe()) {
358  int iflag;
360  if(iflag == 0) {
361  //apply time smearing
362  double Q = (peSmeared > 0.5) ? peSmeared : 0.5;
363  //digitize hit
364  peSmeared *= efficiency;
365  bool accepted = WCSimWCDigitizerBase::AddNewDigit(tube, digi_unique_id,
366  intgr_start + PMT->HitTimeSmearing(Q),
367  peSmeared, digi_comp);
368  if(accepted) {
369  digi_unique_id++;
370  }
371  assert(digi_comp.size());
372  digi_comp.clear();
373  }
374  else {
375  //reject hit
376 #ifdef WCSIMWCDIGITIZER_VERBOSE
377  if(tube < NPMTS_VERBOSE || tube == VERBOSE_PMT)
378  G4cout << "DIGIT REJECTED with time " << intgr_start << G4endl;
379 #endif
380  digi_comp.clear();
381  }
382  }
383  }
384  }//ip (totalpe)
385  }//i (WCHCPMT->entries())
386  G4cout<<"WCSimWCDigitizerSKI::DigitizeHits END DigiStore->entries() " << DigiStore->entries() << "\n";
387 
388 #ifdef WCSIMWCDIGITIZER_VERBOSE
389  G4cout<<"\n\n\nCHECK DIGI COMP:"<<G4endl;
390  for (G4int idigi = 0 ; idigi < DigiStore->entries() ; idigi++){
391  int tubeid = (*DigiStore)[idigi]->GetTubeID();
392  if(tubeid < NPMTS_VERBOSE) {
393  std::map< int, std::vector<int> > comp = (*DigiStore)[idigi]->GetDigiCompositionInfo();
394  for(size_t i = 0; i < comp.size(); i++){
395  G4cout << "tube " << tubeid
396  << " gate " << i << " p_id";
397  for(size_t iv = 0; iv < comp[i].size(); iv++) {
398  G4cout << " " << comp[i][iv];
399  }//iv
400  G4cout << G4endl;
401  }//i
402  }
403  }//idigi
404 #endif
405 }
406 
WCSimDetectorConstruction * myDetector
Get the geometry information.
#define VERBOSE_PMT
WCSimWCDAQMessenger * DAQMessenger
Get the /DAQ/ .mac options.
double DigitizerPEPrecision
Digitizer charge precision (p.e.)
double Truncate(double value, double precision)
Override the default digitizer charge resolution (p.e.)
void SetDigitizerIntegrationWindow(int iDigitizerIntegrationWindow)
virtual double GetDefaultPEPrecision()=0
Set the default digitizer-specific charge resolution (in p.e.) (overridden by .mac) ...
void SetDigitizerTimingPrecision(double iDigitizerTimingPrecision)
static void Threshold(double &pe, int &iflag)
void SetTubeID(G4int tube)
Definition: WCSimWCDigi.hh:85
WCSimWCDigitizerBase(G4String name, WCSimDetectorConstruction *, WCSimWCDAQMessenger *, DigitizerType_t, G4String detectorElement)
WCSimPMTObject * GetPMTPointer(G4String CollectionName)
virtual int GetDefaultIntegrationWindow()=0
Set the default digitizer-specific integration window (in ns) (overridden by .mac) ...
bool AddNewDigit(int tube, int gate, double digihittime, double peSmeared, std::vector< int > digi_comp)
void SetPe(G4int gate, G4double Q)
Definition: WCSimWCDigi.hh:87
WCSimWCDigitsCollection * DigiStore
G4TDigiCollection< WCSimWCDigi > WCSimWCDigitsCollection
Definition: WCSimWCDigi.hh:214
void SetDigitizerDeadTime(int iDigitizerDeadTime)
enum EDigitizerType DigitizerType_t
virtual double GetDefaultTimingPrecision()=0
Set the default digitizer-specific timing resolution (in ns) (overridden by .mac) ...
void AddDigiCompositionInfo(std::vector< int > &digi_comp)
Definition: WCSimWCDigi.hh:97
double DigitizerTimingPrecision
Digitizer time precision (ns)
virtual int GetDefaultDeadTime()=0
Set the default digitizer-specific deadtime (in ns) (overridden by .mac)
std::map< int, int > DigiStoreHitMap
Used to check if a digit has already been created on a PMT.
virtual double HitTimeSmearing(double)=0
int DigitizerIntegrationWindow
Digitizer integration window (ns)
void SaveOptionsToOutput(WCSimRootOptions *wcopt)
Save current values of options.
int DigitizerDeadTime
Digitizer deadtime (ns)
void GetVariables()
Get the default deadtime, etc. from the derived class, and override with read from the ...
int tubeid[MAX_N_ACTIVE_TUBES]
Definition: jhfNtuple.h:41
void SetDigitizerClassName(string iDigitizerClassName)
void AddPe(G4double hitTime)
Definition: WCSimWCDigi.hh:128
#define NPMTS_VERBOSE
void SetDigitizerPEPrecision(double iDigitizerPEPrecision)
void SetTime(G4int gate, G4double T)
Definition: WCSimWCDigi.hh:88
G4String DigitizerClassName
Name of the digitizer class being run.
virtual void DigitizeHits(WCSimWCDigitsCollection *WCHCPMT)=0
WCSimWCDigitizerSKI(G4String name, WCSimDetectorConstruction *, WCSimWCDAQMessenger *, G4String detectorElement)
void TellMeAboutTheDigitizer(WCSimWCDigitizerBase *digitizer)
void DigitizeHits(WCSimWCDigitsCollection *WCHCPMT)