SimCounter35t_module.cc
Go to the documentation of this file.
1 // SimCounter35t_module.cc
2 //
3 // Matthew Thiesse
4 // March 2015
5 //
6 // This producer module is use in 35t simulation to convert sim IDEs
7 // in muon counters to raw::ExternalTrigger data products in the same
8 // format created by the data splitter
9 
10 // workaround for Mac build problem
11 #define BOOST_SYSTEM_NO_DEPRICATED
18 #include "art_root_io/TFileService.h"
20 #include "fhiclcpp/ParameterSet.h"
22 #include "nurandom/RandomUtils/NuRandomService.h"
23 
25 #include "lardataobj/RawData/raw.h"
30 
31 #include "CLHEP/Random/RandFlat.h"
32 
33 #include <memory>
34 #include <iostream>
35 #include <sstream>
36 
37 #include "TTree.h"
38 
39 namespace detsim {
40  class SimCounter35t;
41 }
42 
44 public:
45  explicit SimCounter35t(fhicl::ParameterSet const & p);
46  // The destructor generated by the compiler is fine for classes
47  // without bare pointers or other resource use.
48 
49  // Plugins should not be copied or assigned.
50  SimCounter35t(SimCounter35t const &) = delete;
51  SimCounter35t(SimCounter35t &&) = delete;
52  SimCounter35t & operator = (SimCounter35t const &) = delete;
54 
55  // Required functions.
56  void produce(art::Event & e) override;
57 
58  // Selected optional functions.
59  void beginJob() override;
60 
61 private:
62 
63  // chanTick represents a single time "tick" for a single counter.
64  // multiple hits during the same time window on the same counter are possible.
65  // using this struct is an alternative to initializing an array of 50000 values for
66  // each AuxDetSimChannel where most of the entries are zero. This way, information is
67  // stored only if there is nonzero energy deposition.
68  struct chanTick {
69  unsigned int tick;
70  double eDep;
71  unsigned int auxDetID;
72  int numHits;
73 
74  chanTick(int t, int adid, double ed)
75  : tick(t), eDep(ed), auxDetID(adid), numHits(1) {
76  }
77 
78  void Add(double ed) {
79  eDep += ed;
80  ++numHits;
81  }
82  };
83 
84  // container to hold info for ticks with nonzero energy deposition
85  std::vector<chanTick> tickv;
86 
87  // fhicl parameters
89  bool fMakeTree;
90  double fBSUTriggerThreshold; // MeV
91  double fTSUTriggerThreshold; // MeV
94  unsigned int fCombinedTimeDelay; // ns
95 
96  // Tree containing aux det hit info. copied from dune/LArG4/CheckAuxDet_module.cc
97  TTree *fTree;
98  int run;
99  int subrun;
100  int event;
101  int nauxdets;
103  int ntrkids;
104  double entryx;
105  double entryy;
106  double entryz;
107  double entryt;
108  double exitx;
109  double exity;
110  double exitz;
111  double exitt;
112  double exitpx;
113  double exitpy;
114  double exitpz;
115  int trackid;
116  double energy;
117 
118  CLHEP::RandFlat fFlat;
119 };
120 
121 /////////////////////////////////////////////////////////////////////////////////
122 
124  :
125  EDProducer{p},
126  fLArG4ModuleLabel(p.get<std::string>("LArGeantModuleLabel", "largeant")),
127  fMakeTree(p.get<bool>("MakeTree",false)),
128  fBSUTriggerThreshold(p.get<double>("BSUTriggerThreshold",0.5)),// MeV
129  fTSUTriggerThreshold(p.get<double>("TSUTriggerThreshold",0.25)),// MeV
130  fTriggerEfficiency(p.get<double>("TriggerEfficiency",1.)),
131  fClockSpeedCounter(p.get<double>("ClockSpeedCounter",64)), // MHz
132  fCombinedTimeDelay(p.get<double>("CombinedTimeDelay",160)), // ns
133  fFlat(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "rand"), 0, 1)
134 {
135  produces< std::vector< raw::ExternalTrigger > >();
136 }
137 
138 /////////////////////////////////////////////////////////////////////////////////
139 
141 {
142  int skippedHitsIneff = 0;
143  int skippedHitsOutRange = 0;
144 
145  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
146  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e, clockData);
147 
148  // make unique_ptr that allows ownership of the produced triggers to be transferred to the art::Event after the put statement below
149  std::unique_ptr<std::vector<raw::ExternalTrigger>> trigcol(new std::vector<raw::ExternalTrigger>);
150 
151  run = e.run();
152  subrun = e.subRun();
153  event = e.id().event();
154 
155  // get all auzDetSimChannel information containing AuxDetIDEs
156  std::vector<const sim::AuxDetSimChannel*> fAuxDetSimChannels;
157  e.getView(fLArG4ModuleLabel, fAuxDetSimChannels);
158 
159  nauxdets = fAuxDetSimChannels.size();
160 
161  // loop over all AuxDetSimChannels
162  for (size_t i=0; i<fAuxDetSimChannels.size(); ++i) {
163  const sim::AuxDetSimChannel* c = fAuxDetSimChannels[i];
164  auxdetid = c->AuxDetID();
165 
166  // get AuxDetIDEs associated with sim channel
167  const std::vector<sim::AuxDetIDE>& setOfIDEs = c->AuxDetIDEs();
168  ntrkids = setOfIDEs.size();
169  // if (ntrkids>0) std::cout << auxdetid << " " << ntrkids << std::endl;
170 
171  // loop over all AuxDetIDEs
172  for (size_t j=0; j<setOfIDEs.size(); ++j) {
173 
174  // fill tree
175  if (fMakeTree) {
176  entryx = setOfIDEs[j].entryX;
177  entryy = setOfIDEs[j].entryY;
178  entryz = setOfIDEs[j].entryZ;
179  entryt = setOfIDEs[j].entryT;
180  exitx = setOfIDEs[j].exitX;
181  exity = setOfIDEs[j].exitY;
182  exitz = setOfIDEs[j].exitZ;
183  exitt = setOfIDEs[j].exitT;
184  exitpx = setOfIDEs[j].exitMomentumX;
185  exitpy = setOfIDEs[j].exitMomentumY;
186  exitpz = setOfIDEs[j].exitMomentumZ;
187  energy = setOfIDEs[j].energyDeposited;
188  trackid = setOfIDEs[j].trackID;
189  fTree->Fill();
190  }
191 
192  double randEff = fFlat.fire();
193  if (randEff > fTriggerEfficiency) {
194  ++skippedHitsIneff;
195  continue;
196  }
197 
198  // calculate the time length of one window
199  double triggerOffsetTPC = clockData.TriggerOffsetTPC()*1.e3; // ns
200  double readoutWindowSizeTPC = detProp.ReadOutWindowSize(); // tpc ticks
201  double clockSpeedTPC = clockData.TPCClock().Frequency(); // MHz
202  double windowLength = readoutWindowSizeTPC/clockSpeedTPC; // us
203 
204  // get information from AuxDetIDE
205  double time = setOfIDEs[j].entryT+fCombinedTimeDelay-triggerOffsetTPC; // ns
206  if (time<0 || time>windowLength*1000) {
207  ++skippedHitsOutRange;
208  continue;
209  }
210  uint32_t tickIDE = time*fClockSpeedCounter/1000; // PTB ticks
211  double edepIDE = setOfIDEs[j].energyDeposited*1000;//MeV
212 
213  // loop over tickv to add eDep
215  for (it = tickv.begin(); it != tickv.end(); ++it) {
216  chanTick* ct = &*it;
217  if (ct->tick == tickIDE && ct->auxDetID == auxdetid) {
218  ct->Add(edepIDE);
219  break;
220  }
221  }
222 
223  // if the chanTick doesn't exist already, make one
224  if (it==tickv.end()) {
225  // initialise chanTick with IDE values
226  tickv.push_back(chanTick(tickIDE,auxdetid,edepIDE));
227  }
228  }
229  }
230 
231  // std::cout << "how many? " << tickv.size() << std::endl;
232 
233  // fill collection of raw::ExternalTriggers, if eDep is above threshold
234  std::map<int, int >trigmap;
236  int icount= 0;
237  if (tickv.size()>1) {
238  //std::vector<chanTick>::iterator myend=tickv.end()--;
239  for (it = tickv.begin(); it != tickv.end(); ++it) {
240  chanTick ct = *it;
241 
242  // for c2: auxDetID is always >= 0
243  //if ( (ct.auxDetID >= 44 && ct.auxDetID <= 91 && ct.eDep > fBSUTriggerThreshold) ||
244  // (ct.auxDetID >= 0 && ct.auxDetID <=43 && ct.eDep > fTSUTriggerThreshold) ||
245  if ( (ct.auxDetID >= 44 && ct.auxDetID <= 91 && ct.eDep > fBSUTriggerThreshold) ||
246  (ct.auxDetID <=43 && ct.eDep > fTSUTriggerThreshold) ||
247  (ct.auxDetID >= 92 && ct.eDep > 1.e-6) )
248  {
249  icount++;
250  // std::cout << "hit " << icount << " " << ct.auxDetID << " " <<
251  // ct.tick << " " << ct.eDep << std::endl;
252  // Build triggers from individual hits
253  unsigned int iRM=0; unsigned int iCL=0; unsigned int iNU=0; unsigned int iNL=0;
254  unsigned int iSU=0; unsigned int iSL=0; unsigned int iWU=0; unsigned int iEL=0;
255  trigcol->push_back(raw::ExternalTrigger(ct.auxDetID,ct.tick));
256  if (ct.auxDetID<6) iSL=ct.tick;
257  if (ct.auxDetID>5 && ct.auxDetID<16) iEL=ct.tick;
258  if (ct.auxDetID>15 && ct.auxDetID<22) iNL=ct.tick;
259  if (ct.auxDetID>21 && ct.auxDetID<28) iNU=ct.tick;
260  if (ct.auxDetID>27 && ct.auxDetID<38) iWU=ct.tick;
261  if (ct.auxDetID>37 && ct.auxDetID<44) iSU=ct.tick;
262  if (ct.auxDetID>43 && ct.auxDetID<57) iCL=ct.tick;
263  if (ct.auxDetID>66 && ct.auxDetID<83) iRM=ct.tick;
264  // std::cout << "here 2" << std::endl;
266  if (start != tickv.end()) {
267  for (it2 = start; it2 != tickv.end(); ++it2) {
268  chanTick ct2 = *it2;
269  // for c2: auxDetID is always >= 0
270  //if ( (ct2.auxDetID >= 44 && ct2.auxDetID <= 91
271  //&& ct2.eDep > fBSUTriggerThreshold)
272  // || (ct2.auxDetID >= 0 && ct2.auxDetID <=43
273  if ( (ct2.auxDetID >= 44 && ct2.auxDetID <= 91
274  && ct2.eDep > fBSUTriggerThreshold)
275  || (ct2.auxDetID <=43
276  && ct2.eDep > fTSUTriggerThreshold) ||
277  (ct2.auxDetID >= 92 && ct2.eDep > 1.e-6) ) {
278  float t1 = ct.tick; float t2=ct2.tick;
279  // std::cout << "times " << ct.auxDetID << " " << t1 << " " <<
280  // ct2.auxDetID << " " << t2 << std::endl;
281  float diff = t2-t1; //std::cout << "diff " << fabs(diff) << std::endl;
282  if (fabs(diff)<5) {
283  if (ct2.auxDetID<6) iSL=ct2.tick;
284  if (ct2.auxDetID>5 && ct2.auxDetID<16) iEL=ct2.tick;
285  if (ct2.auxDetID>15 && ct2.auxDetID<22) iNL=ct2.tick;
286  if (ct2.auxDetID>21 && ct2.auxDetID<28) iNU=ct2.tick;
287  if (ct2.auxDetID>27 && ct2.auxDetID<38) iWU=ct2.tick;
288  if (ct2.auxDetID>37 && ct2.auxDetID<44) iSU=ct2.tick;
289  if (ct2.auxDetID>43 && ct2.auxDetID<57) iCL=ct2.tick;
290  if (ct2.auxDetID>66 && ct2.auxDetID<83) iRM=ct2.tick;
291  }
292  }
293  }
294  }
295  float ttime; int trigtick;
296  // std::cout << "NL " << iNL << " SU " << iSU << " NU " << iNU << " SL " << iSL << std::endl;
297  if (iRM>0 && iCL>0) { ttime=0.5*(iRM+iCL)+0.5; trigtick=int(ttime);
298  if (trigmap[trigtick]==0) {trigmap[trigtick]++;trigmap[trigtick+1]++;
299  trigmap[trigtick+2]++;trigmap[trigtick-1]++;trigmap[trigtick-2]++;
300  trigcol->push_back(raw::ExternalTrigger(110,trigtick));
301  // std::cout << "good trig " ;
302  }
303  // std::cout << "RM+CL trigger " << trigtick << std::endl;
304  }
305  if (iEL>0 && iWU>0) { ttime=0.5*(iEL+iWU)+0.5; trigtick=int(ttime);
306  if (trigmap[trigtick]==0) {trigmap[trigtick]++;trigmap[trigtick+1]++;
307  trigmap[trigtick+2]++;trigmap[trigtick-1]++;trigmap[trigtick-2]++;
308  trigcol->push_back(raw::ExternalTrigger(111,trigtick));
309  // std::cout << "good trig " ;
310  }
311  // std::cout << "WU+EL trigger " << trigtick << std::endl;
312  }
313  if (iNU>0 && iSL>0) { ttime=0.5*(iNU+iSL)+0.5; trigtick=int(ttime);
314  if (trigmap[trigtick]==0) {trigmap[trigtick]++;trigmap[trigtick+1]++;
315  trigmap[trigtick+2]++;trigmap[trigtick-1]++;trigmap[trigtick-2]++;
316  trigcol->push_back(raw::ExternalTrigger(112,trigtick));
317  // std::cout << "good trig " ;
318  }
319  // std::cout << "NU+SL trigger " << trigtick << std::endl;
320  }
321  if (iSU>0 && iNL>0) { ttime=0.5*(iSU+iNL)+0.5; trigtick=int(ttime);
322  if (trigmap[trigtick]==0) {trigmap[trigtick]++;trigmap[trigtick+1]++;
323  trigmap[trigtick+2]++;trigmap[trigtick-1]++;trigmap[trigtick-2]++;
324  trigcol->push_back(raw::ExternalTrigger(113,trigtick));
325  // std::cout << "good trig " ;
326  }
327  // std::cout << "SU+NL trigger " << trigtick << std::endl;
328  }
329  }
330  }
331 
332  }// if more than one counter hit
333  // put ExternalTrigger collection into event record
334  e.put(std::move(trigcol));
335 
336 
337  // output hit information for event
338  std::ostringstream out;
339  for (std::vector<chanTick>::iterator it = tickv.begin(); it != tickv.end(); ++it) {
340  chanTick ct = *it;
341  // for c2: auxDetID is always >= 0
342  //if ( (ct.auxDetID >= 44 && ct.auxDetID <= 91 && ct.eDep > fBSUTriggerThreshold) ||
343  // (ct.auxDetID >= 0 && ct.auxDetID <=43 && ct.eDep > fTSUTriggerThreshold) ||
344  if ( (ct.auxDetID >= 44 && ct.auxDetID <= 91 && ct.eDep > fBSUTriggerThreshold) ||
345  (ct.auxDetID <=43 && ct.eDep > fTSUTriggerThreshold) ||
346  (ct.auxDetID >= 92 && ct.eDep > 1.e-6) )
347  out << "AuxDet " << ct.auxDetID << " had " << ct.numHits << " hits at readout tick " << ct.tick << ". Total eDep = " << ct.eDep << " MeV.\n";
348  }
349  if (skippedHitsIneff) out << skippedHitsIneff << " hits were skipped due to counter inefficiency.\n";
350  if (skippedHitsOutRange) out << skippedHitsOutRange << " hits were skipped for being out of TPC window range.\n";
351  mf::LogInfo("SimCounter35t") << out.str();
352 
353  tickv.clear();
354 
355 }
356 
357 /////////////////////////////////////////////////////////////////////////////////
358 
360 {
361  // Implementation of optional member function here.
363  if (fMakeTree) {
364  fTree = tfs->make<TTree>("SimCounter35t","SimCounter35t");
365  fTree->Branch("run",&run,"run/I");
366  fTree->Branch("subrun",&subrun,"subrun/I");
367  fTree->Branch("event",&event,"event/I");
368  fTree->Branch("nauxdets",&nauxdets,"nauxdets/I");
369  fTree->Branch("auxdetid",&auxdetid,"auxdetid/I");
370  fTree->Branch("ntrkids",&ntrkids,"ntrkids/I");
371  fTree->Branch("entryx",&entryx,"entryx/D");
372  fTree->Branch("entryy",&entryy,"entryy/D");
373  fTree->Branch("entryz",&entryz,"entryz/D");
374  fTree->Branch("entryt",&entryt,"entryt/D");
375  fTree->Branch("exitx",&exitx,"exitx/D");
376  fTree->Branch("exity",&exity,"exity/D");
377  fTree->Branch("exitz",&exitz,"exitz/D");
378  fTree->Branch("exitt",&exitt,"exitt/D");
379  fTree->Branch("exitpx",&exitpx,"exitpx/D");
380  fTree->Branch("exitpy",&exitpy,"exitpy/D");
381  fTree->Branch("exitpz",&exitpz,"exitpz/D");
382  fTree->Branch("trackid",&trackid,"trackid/D");
383  fTree->Branch("energy",&energy,"energy/D");
384  }
385 }
386 
intermediate_table::iterator iterator
base_engine_t & createEngine(seed_t seed)
SimCounter35t & operator=(SimCounter35t const &)=delete
Utilities related to art service access.
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
chanTick(int t, int adid, double ed)
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
Detector simulation of raw signals on wires.
SimCounter35t(fhicl::ParameterSet const &p)
std::vector< chanTick > tickv
Collection of particles crossing one auxiliary detector cell.
void produce(art::Event &e) override
object containing MC truth information necessary for making RawDigits and doing back tracking ...
const double e
uint32_t AuxDetID() const
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:69
unsigned int uint32_t
Definition: stdint.h:126
def move(depos, offset)
Definition: depos.py:107
Collect all the RawData header files together.
std::vector< sim::AuxDetIDE > const & AuxDetIDEs() const
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:89
RunNumber_t run() const
Definition: DataViewImpl.cc:82
p
Definition: test.py:223
EventNumber_t event() const
Definition: EventID.h:116
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
Definition: DataViewImpl.h:565
ProductID put(std::unique_ptr< PROD > &&edp, FullSemantic< Level::Run > const semantic)
Definition: DataViewImpl.h:730
EventID id() const
Definition: Event.cc:37
Event finding and building.