CRTSim_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CRTSim
3 // Plugin Type: producer (art v2_10_03)
4 // File: CRTSim_module.cc
5 //
6 // Generated at Wed Jun 27 04:09:39 2018 by Andrew Olivier using cetskelgen
7 // from cetlib version v3_02_00.
8 ////////////////////////////////////////////////////////////////////////
9 
10 // An ART module to simulate how the ProtoDUNE-SP Cosmic Ray Tagger (CRT) system
11 //responds to energy deposits. Starts with sim::AuxDetSimChannel, loops over SimChannels
12 //produced for CRT volumes, groups energy deposits across SimChannels into "readout packets",
13 //and produces one CRT::Hit for each (group? Need more information about board) sim::AuxDetIDE
14 //within a "readout packet".
15 //
16 // According to Matt Strait and Vishvas, the CRT boards already do some hit reconstruction for us.
17 //This module should apply any energy deposit-level physics (like Birks' Law and Poisson fluctuations
18 //in number of photons?), apply detector response (from an as-yet-unavailable MySQL database), then
19 //do the same reconstruction steps as the CRT boards. Each CRT board is responsible for an entire
20 //module's channels. A board only reads out when it finds a "hit" with an energy deposit above some
21 //threshold. Then, it reads out the "hit"s on ALL of its' channels in one "packet" that becomes a
22 //single artdaq::Fragment.
23 
24 //TODO: art::Assns<sim::AuxDetSimChannel, std::vector<CRT::Hit>> for backtracking?
25 //TODO: Associate CRT::Hits from a readout window? Seems possible to do this in "real data".
26 //TODO: Produce and associate to raw::ExternalTriggers?
27 
28 //Framework includes
36 #include "fhiclcpp/ParameterSet.h"
41 
42 //LArSoft includes
45 
46 //local includes
47 //#include "CRTTrigger.h"
49 
50 //c++ includes
51 #include <memory>
52 #include <algorithm>
53 
54 namespace CRT {
55  class CRTSim;
56 }
57 
58 class CRT::CRTSim : public art::EDProducer {
59 public:
60  explicit CRTSim(fhicl::ParameterSet const & p);
61  // The compiler-generated destructor is fine for non-base
62  // classes without bare pointers or other resource use.
63 
64  // Plugins should not be copied or assigned.
65  CRTSim(CRTSim const &) = delete;
66  CRTSim(CRTSim &&) = delete;
67  CRTSim & operator = (CRTSim const &) = delete;
68  CRTSim & operator = (CRTSim &&) = delete;
69 
70  // Required functions.
71  void produce(art::Event & e) override;
72 
73  // Selected optional functions.
74  //void beginJob() override;
75  /*void beginRun(art::Run & r) override;
76  void beginSubRun(art::SubRun & sr) override;
77  void endJob() override;
78  void endRun(art::Run & r) override;
79  void endSubRun(art::SubRun & sr) override;
80  void respondToCloseInputFile(art::FileBlock const & fb) override;
81  void respondToCloseOutputFiles(art::FileBlock const & fb) override;
82  void respondToOpenInputFile(art::FileBlock const & fb) override;
83  void respondToOpenOutputFiles(art::FileBlock const & fb) override;*/
84 
85 private:
86 
87  //The formats for time and ADC value I will use throughout this module. If I want to change it later, I only have to change it in one place.
88  typedef long long int time;
89  typedef unsigned short adc_t;
90 
91  // Member data
92  art::InputTag fSimLabel; //The label of the module that produced sim::AuxDetSimChannels
93 
94  //Parameters I could probably get from calibration + electronics documentation to make this simulation more realistic.
95  //Decided that I am more interested in speed for now.
96  /*double fScintillationYield; //The converion from GeV to energy to photons
97  double fQuantumEff; //The conversion from photons to photo-electrons leaving the photocathode
98  double fDummyGain; //Dummy conversion of photo-electrons leaving the photocathode to voltage entering the MAROC2 chip.
99  double fResistanceBeforeMAROC; //Resistance converting current after gain to voltage entering MAROC2 */
100 
101  //Simple parameterization in lieu of complicated information above. I can probably still get this from the calibration output.
102  double fGeVToADC; //Conversion from GeV in detector to ADC counts output by MAROC2.
103 
104  //Parameterization for algorithm that takes voltage entering MAROC2 and converts it to ADC hits. If I ultimately decide I want to
105  //study impact of more detailed simulation, factor this out into an algorithm for simulating MAROC2 that probably takes continuous
106  //voltage signal as input anyway.
107  time fIntegrationTime; //The time in ns over which charge is integrated in the CRT electronics before being sent to the DAC comparator
108  size_t fReadoutWindowSize; //The time in fIntegrationTimes during which activity in a CRT channel is sent to an ADC if the board has
109  //already decided to trigger
110  size_t fDeadtime; //The dead time in fIntegrationTimes after readout during which no energy deposits are processed by CRT boards.
111  adc_t fDACThreshold; //DAC threshold for triggering readout for any CRT strip.
112  //In GeV for now, but needs to become ADC counts one day.
113  //Should be replaced by either a lookup in a hardware database or
114  //some constant value one day.
115 };
116 
117 
119  /*fScintillationYield(p.get<double>("ScintillationYield")),
120  fQuantumEff(p.get<double>("QuantumEff")),
121  fDummyGain(p.get<double>("DummyGain")),*/
122  fGeVToADC(p.get<double>("GeVToADC")),
123  fIntegrationTime(p.get<time>("IntegrationTime")),
124  fReadoutWindowSize(p.get<size_t>("ReadoutWindowSize")),
125  fDeadtime(p.get<size_t>("Deadtime")),
126  fDACThreshold(p.get<adc_t>("DACThreshold"))
127 {
128  //Tell ART that I convert std::vector<AuxDetSimChannel> to CRT::Hits associated with raw::ExternalTriggers
129  produces<std::vector<CRT::Trigger>>();
130  produces<art::Assns<sim::AuxDetSimChannel, CRT::Trigger>>();
131  consumes<std::vector<sim::AuxDetSimChannel>>(fSimLabel);
132 }
133 
134 //Turn sim::AuxDetSimChannels into CRT::Hits.
136 {
137  //Get collection of AuxDetSimChannel as input
138  auto channels = e.getValidHandle<std::vector<sim::AuxDetSimChannel>>(fSimLabel);
139 
140  //Collections of CRT::Trigger and AuxDetSimChannel-CRT::Trigger associations that I will std::move() into e at the end of produce
141  auto trigCol = std::make_unique<std::vector<CRT::Trigger>>();
142  auto simToTrigger = std::make_unique<art::Assns<sim::AuxDetSimChannel, CRT::Trigger>>();
143 
144  //Utilities to go along with making Assns
146  art::PtrMaker<CRT::Trigger> makeTrigPtr(e);
147 
148  //Get access to geometry for each event (TODO: -> subrun?) in case CRTs move later
150 
151  //Group AuxDetSimChannels by module they came from for easier access later. Storing AuxDetSimChannels as art::Ptrs so I can make Assns later.
152  //TODO: I'm spending a lot of effort and confusing code on keeping track of sim::AuxDetSimChannels for Assns at the end of this module.
153  // Are raw -> simulation Assns worth this much trouble? Can I restructure my logic somehow to make this association more natural?
154  std::map<uint32_t, art::PtrVector<sim::AuxDetSimChannel>> moduleToChannels;
155  for(size_t channelPos = 0; channelPos < channels->size(); ++channelPos)
156  {
157  const auto id = (*channels)[channelPos].AuxDetID();
158  const auto& det = geom->AuxDet(id);
159  if(det.Name().find("CRT") != std::string::npos) //If this is a CRT AuxDet
160  {
161  moduleToChannels[id].push_back(makeSimPtr(channelPos));
162  } //End if this is a CRT AuxDet
163  } //End for each simulated sensitive volume -> CRT strip
164 
165  MF_LOG_DEBUG("moduleToChannels") << "Got " << moduleToChannels.size() << " modules to process in detector simulation.\n";
166 
167  //For each CRT module
168  for(auto& pair: moduleToChannels)
169  {
170  auto& module = pair.second;
171 
172  //Probably a good idea to write a function/algorithm class for each of these
173  //TODO: Any leftover physics like Birks' Law? I can handle Birks' Law more accurately if I
174  // can get access to individual Geant steps.
175  //TODO: Read detector response from MariaDB database on DAQ machine?
176  //TODO: Simulate detector response with quantum efficiency and detection efficiency?
177  //TODO: simulate time -> timestamp. Check out how 35t example in dunetpc/dunesim/DetSim does this.
178 
179  //Integrate "energy deposited" over time, then form a time-ordered sparse-vector (=std::map) of CRT::Hits
180  //associated with the art::Ptr that produced each hit. Associating each hit with a time value gives me the
181  //option to skip over dead time later. Each time bin contains up to one hit per channel.
182  MF_LOG_DEBUG("moduleToChannels") << "Processing " << module.size() << " channels in module " << pair.first << "\n";
183  std::map<time, std::vector<std::pair<CRT::Hit, art::Ptr<sim::AuxDetSimChannel>>>>timeToHits; //Mapping from integration time bin to list of hit-Ptr pairs
184  for(const auto& channel: module)
185  {
186  MF_LOG_DEBUG("channels") << "Processing channel " << channel->AuxDetSensitiveID() << "\n";
187  const auto& ides = channel->AuxDetIDEs();
188  for(const auto& eDep: ides)
189  {
190  const size_t tAvg = (eDep.exitT+eDep.entryT)/2.;
191  timeToHits[tAvg/fIntegrationTime].emplace_back(CRT::Hit(channel->AuxDetSensitiveID(), eDep.energyDeposited*fGeVToADC), channel);
192  MF_LOG_DEBUG("TrueTimes") << "Assigned true hit at time " << tAvg << " to bin " << tAvg/fIntegrationTime << ".\n";
193  }
194  }
195  //std::map<time, std::vector<std::pair<CRT::Hit, art::Ptr<sim::AuxDetSimChannel>>>> oldWindow;
196  std::stringstream ss;
197  auto lastTimeStamp=time(0);
198  int i=0;
199  for(auto window : timeToHits)
200  {
201  if (i!=0 && (time(fDeadtime)+lastTimeStamp)>window.first && lastTimeStamp<window.first) continue;
202  i++;
203  const auto& hitsInWindow = window.second;
204  const auto aboveThresh = std::find_if(hitsInWindow.begin(), hitsInWindow.end(),
205  [this](const auto& hitPair) { return hitPair.first.ADC() > fDACThreshold; });
206 
207 
208 if(aboveThresh != hitsInWindow.end()){
209 
210  std::vector<CRT::Hit> hits;
211  const time timestamp = window.first; //Set timestamp before window is changed.
212  const time end = (timestamp+fReadoutWindowSize);
213  std::set<uint32_t> channelBusy; //A std::set contains only unique elements. This set stores channels that have already been read out in
214  //this readout window and so are "busy" and cannot contribute any more hits.
215  for(auto busyCheckWindow : timeToHits){
216  if (time(busyCheckWindow.first)<timestamp || time(busyCheckWindow.first)>end) continue;
217  for(const auto& hitPair: window.second)
218  {
219  const auto channel = hitPair.first.Channel(); //TODO: Get channel number back without needing art::Ptr here.
220  // Maybe store crt::Hits.
221  if(channelBusy.insert(channel).second) //If this channel hasn't already contributed to this readout window
222  {
223  hits.push_back(hitPair.first);
224  simToTrigger->addSingle(hitPair.second, makeTrigPtr(trigCol->size()-1));
225  }
226  }
227  }
228  //std::cout<<"Hits Generated:"<<hits.size()<<std::endl;
229  lastTimeStamp=window.first;
230 
231  MF_LOG_DEBUG("CreateTrigger") << "Creating CRT::Trigger...\n";
232  trigCol->emplace_back(pair.first, timestamp*fIntegrationTime, std::move(hits));
233  } // For each readout with a triggerable hit
234  } // For each time window
235 
236  } //For each CRT module
237 
238  //Put Triggers and Assns into the event
239  MF_LOG_DEBUG("CreateTrigger") << "Putting " << trigCol->size() << " CRT::Triggers into the event at the end of analyze().\n";
240  e.put(std::move(trigCol));
241  e.put(std::move(simToTrigger));
242 }
243 
244 
size_t fDeadtime
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
double fGeVToADC
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
time fIntegrationTime
uint8_t channel
Definition: CRTFragment.hh:201
art framework interface to geometry description
unsigned short adc_t
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
def move(depos, offset)
Definition: depos.py:107
adc_t fDACThreshold
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
long long int time
art::InputTag fSimLabel
AuxDetGeo const & AuxDet(unsigned int const ad=0) const
Returns the specified auxiliary detector.
size_t fReadoutWindowSize
#define MF_LOG_DEBUG(id)
void produce(art::Event &e) override
CRTSim & operator=(CRTSim const &)=delete
CRTSim(fhicl::ParameterSet const &p)