All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BNBRetriever_module.cc
Go to the documentation of this file.
1 /** ********************************************************************
2  * @file BNBRetriever_module.cc
3  * @date Wed April 9 2021
4  * @author J. Zennamo (FNAL)
5  *
6  * Based heavily on code by Z. Pavlovic written for MicroBooNE
7  * Based heavily on code by NOvA collaboration (Thanks NOvA!):
8  * https://cdcvs.fnal.gov/redmine/projects/novaart/repository/entry/trunk/IFDBSpillInfo/BNBInfo_module.cc
9  */
10 
11 #include "art/Framework/Core/EDProducer.h"
12 #include "art/Framework/Core/ModuleMacros.h"
13 #include "art/Framework/Principal/Event.h"
14 #include "art/Framework/Principal/Handle.h"
15 #include "art/Framework/Principal/Run.h"
16 #include "art/Framework/Principal/SubRun.h"
17 #include "canvas/Utilities/InputTag.h"
18 #include "fhiclcpp/types/Atom.h"
19 #include "messagefacility/MessageLogger/MessageLogger.h"
21 
22 #include "artdaq-core/Data/Fragment.hh"
23 #include "sbndaq-artdaq-core/Overlays/ICARUS/ICARUSTriggerV2Fragment.hh"
24 
26 
27 #include "ifdh_art/IFBeamService/IFBeam_service.h"
28 #include "ifbeam_c.h"
29 #include "MWRData.h"
30 
31 #include <memory>
32 #include <vector>
33 #include <cassert>
34 
35 namespace sbn {
36  class BNBRetriever;
37 }
38 
39 class sbn::BNBRetriever : public art::EDProducer {
40 public:
41 
42  struct Config {
43 
44  using Name = fhicl::Name;
45  using Comment = fhicl::Comment;
46 
47  fhicl::Atom<double> TimePadding {
48  Name{ "TimePadding" },
49  Comment{ "extension to the time window considered when collecting spills [seconds]" },
50  0.0333 // default
51  };
52 
53  fhicl::Atom<std::string> RawDataLabel {
54  Name{ "raw_data_label" },
55  Comment{ "art data product instance name for trigger information (product label is 'daq')" }
56  };
57 
58  fhicl::Atom<std::string> DeviceUsedForTiming {
59  Name{ "DeviceUsedForTiming" },
60  Comment{ "name in the IFBeam database of the device used to extract spill times" }
61  };
62 
63  fhicl::Atom<std::string> URL {
64  Name{ "URL" },
65  Comment{ "IFBeam database access URL" }
66  };
67 
68  fhicl::Atom<std::string> Bundle {
69  Name{ "Bundle" },
70  Comment{ "" } // explain what this is and which database/table it's looking for
71  };
72 
73  fhicl::Atom<double> TimeWindow {
74  Name{ "TimeWindow" },
75  Comment{ "" } // explain what this is, what's for and its unit
76  };
77 
78  fhicl::Atom<std::string> MultiWireBundle {
79  Name{ "MultiWireBundle" },
80  Comment{ "" } // explain what this is and which database/table it's looking for
81  };
82 
83  fhicl::Atom<double> MWR_TimeWindow {
84  Name{ "MWR_TimeWindow" },
85  Comment{ "" } // explain what this is, what's for and its unit
86  };
87 
88  }; // Config
89 
90  using Parameters = art::EDProducer::Table<Config>;
91 
92 
93  explicit BNBRetriever(Parameters const& params);
94  // The compiler-generated destructor is fine for non-base
95  // classes without bare pointers or other resource use.
96 
97  // Plugins should not be copied or assigned.
98  BNBRetriever(BNBRetriever const&) = delete;
99  BNBRetriever(BNBRetriever&&) = delete;
100  BNBRetriever& operator=(BNBRetriever const&) = delete;
101  BNBRetriever& operator=(BNBRetriever&&) = delete;
102 
103  // Required functions.
104  void produce(art::Event& e) override;
105  void beginSubRun(art::SubRun& sr) override;
106  void endSubRun(art::SubRun& sr) override;
107 
108 private:
109  // input labels
110  std::vector< sbn::BNBSpillInfo > fOutbeamInfos;
111  double fTimePad;
112  std::string fURL;
114  std::string raw_data_label;
115  std::string fDeviceUsedForTiming;
116  unsigned int TotalBeamSpills;
117  //
118  art::ServiceHandle<ifbeam_ns::IFBeam> ifbeam_handle;
119  std::unique_ptr<ifbeam_ns::BeamFolder> bfp;
120  std::unique_ptr<ifbeam_ns::BeamFolder> bfp_mwr;
121 
122  struct TriggerInfo_t {
123  int gate_type = 0; ///< Source of the spill: `1`: BNB, `2`: NuMI
124  double t_current_event = 0;
125  double t_previous_event = 0;
126  unsigned int number_of_gates_since_previous_event = 0; // FIXME needs to be integral type
127  };
128 
129  struct MWRdata_t {
130  std::vector< std::vector<double> > MWR_times;
131  std::vector< std::vector< std::vector< int > > > unpacked_MWR;
132  };
133 
134 
135  static constexpr double MWRtoroidDelay = -0.035; ///< the same time point is measured _t_ by MWR and _t + MWRtoroidDelay`_ by the toroid [ms]
136 
137  /// Returns the information of the trigger in the current event.
138  TriggerInfo_t extractTriggerInfo(art::Event const& e) const;
139 
140  /**
141  * @brief Determines spill times and extracts data based on multiwire devices.
142  * @param triggerInfo information from the trigger of this event
143  * @return times and unpacked data, per device (`"M875BB"`, `"M876BB"`, `"MMBTBB"`)
144  */
145  MWRdata_t extractSpillTimes(TriggerInfo_t const& triggerInfo) const;
146 
147  /**
148  * @brief Matches spill times with multiwire chamber data from the database.
149  * @param eventID ID of the event the information is associated to
150  * @param triggerInfo information from the trigger of this event
151  * @param MWRdata data from multiwire chambers
152  * @param isFirstEventInRun whether we are processing the first event of the run
153  * @param[out] beamInfos container to _add_ spill information records to
154  * @return count of matched spills
155  */
156  int matchMultiWireData(
157  art::EventID const& eventID,
158  TriggerInfo_t const& triggerInfo,
159  MWRdata_t const& MWRdata, bool isFirstEventInRun,
160  std::vector< sbn::BNBSpillInfo >& beamInfos
161  ) const;
162 
163  /**
164  * @brief Assembles and returns a spill information record.
165  * @param eventID ID of the event the information is associated to
166  * @param time time of the spill
167  * @param MWRdata all extracted data from multiwire chambers
168  * @param matched_MWR data from multiwire chambers matched with the time
169  * @return a `sbn::BNBSpillInfo` object with information on the spill at `time`
170  */
172  (art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector<int> const& matched_MWR) const;
173 
174 };
175 
177  : EDProducer{params},
178  fTimePad(params().TimePadding()),
179  raw_data_label(params().RawDataLabel()),
180  fDeviceUsedForTiming(params().DeviceUsedForTiming()),
181  bfp( ifbeam_handle->getBeamFolder(params().Bundle(), params().URL(), params().TimeWindow())),
182  bfp_mwr( ifbeam_handle->getBeamFolder(params().MultiWireBundle(), params().URL(), params().MWR_TimeWindow()))
183 {
184 
185  // Check fTimePad is positive
186  if (fTimePad < 0) {
187  throw art::Exception(art::errors::Configuration)
188  << "Parameter `TimePadding` must be non-negative (" << fTimePad << " was specified).\n";
189  }//End Time check
190 
191  // how close in time does the spill time have to be from the DAQ time (in seconds).
192  // If these are too large then it fails to capture the device
193  // If these are too small then the time jitter in devices means we miss good data
194  //
195  // These values should likely not be changed unless authors of the IFBeam API are consulted
196  //
197  bfp->set_epsilon(0.02); //20 ms, this was tuned by hand and compared to IFBeamDB times
198  bfp_mwr->set_epsilon(0.5);
199 
200  //bfp_mwr->setValidWindow(86400);
201  bfp_mwr->setValidWindow(3605);
202  produces< std::vector< sbn::BNBSpillInfo >, art::InSubRun >();
203  TotalBeamSpills = 0;
204 }
205 
206 
207 void sbn::BNBRetriever::produce(art::Event& e)
208 {
209 
210  // If this is the first event in the run, then ignore it
211  // We do not currently have the ability to figure out the first
212  // spill that the DAQ was sensitive to, so don't try to save any
213  // spill information
214  //
215  // TODO: long-term goal -- can we fix this?
216  if (e.event() == 1) return;
217 
218  TriggerInfo_t const triggerInfo = extractTriggerInfo(e);
219 
220  //We only want to process BNB gates, i.e. type 1
221  if(triggerInfo.gate_type != 1) return;
222  // Keep track of the number of beam gates the DAQ thinks
223  // are in this job
224  TotalBeamSpills += triggerInfo.number_of_gates_since_previous_event;
225 
226 
227  MWRdata_t const MWRdata = extractSpillTimes(triggerInfo);
228 
229 
230  int const spill_count = matchMultiWireData(e.id(), triggerInfo, MWRdata, e.event() == 1, fOutbeamInfos);
231 
232 
233  if(spill_count > int(triggerInfo.number_of_gates_since_previous_event))
234  mf::LogDebug("BNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << " \t \t ::: WRONG!"<< std::endl;
235  else
236  mf::LogDebug("BNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << std::endl;
237 
238 }//end iteration over art::Events
239 
240 
242 
243  //Here we read in the artdaq Fragments and extract three pieces of information:
244  // 1. The time of the current event, t_current_event
245  // 2. the time of the previously triggered event, t_previous_event (NOTE: Events are non-sequential!)
246  // 3. the number of beam spills since the previously triggered event, number_of_gates_since_previous_event
247 
248  auto const & raw_data = e.getProduct< std::vector<artdaq::Fragment> >({ raw_data_label, "ICARUSTriggerV2" });
249 
250  TriggerInfo_t triggerInfo;
251 
252  for(auto raw_datum : raw_data){
253 
254  uint64_t artdaq_ts = raw_datum.timestamp();
255  icarus::ICARUSTriggerV2Fragment frag(raw_datum);
256  std::string data = frag.GetDataString();
257  char *buffer = const_cast<char*>(data.c_str());
258  icarus::ICARUSTriggerInfo datastream_info = icarus::parse_ICARUSTriggerV2String(buffer);
259  triggerInfo.gate_type = datastream_info.gate_type;
260  triggerInfo.number_of_gates_since_previous_event = frag.getDeltaGatesBNB();
261 
262  triggerInfo.t_current_event = static_cast<double>(artdaq_ts)/(1000000000.0); //check this offset...
263  if(triggerInfo.gate_type == 1)
264  triggerInfo.t_previous_event = (static_cast<double>(frag.getLastTimestampBNB()))/(1e9);
265  else
266  triggerInfo.t_previous_event = (static_cast<double>(frag.getLastTimestampOther()))/(1000000000.0);
267 
268  }
269 
270  mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Previous : " << triggerInfo.t_previous_event << ", Current : " << triggerInfo.t_current_event << std::endl;
271 
272  return triggerInfo;
273 }
274 
275 
277 
278  // These lines get everything primed within the IFBeamDB
279  // They seem redundant but they are needed
280  try{auto cur_vec_temp = bfp->GetNamedVector((triggerInfo.t_previous_event)-fTimePad,"E:THCURR");} catch (WebAPIException &we) {}
281  try{auto packed_M876BB_temp = bfp_mwr->GetNamedVector((triggerInfo.t_current_event)+fTimePad,"E:M875BB{4440:888}.RAW");} catch (WebAPIException &we) {}
282 
283 
284  //The multiwire chambers provide their
285  // data in a vector format but we'll have
286  // to sort through it in std::string format
287  // to correctly unpack it
288  std::vector< std::vector< std::vector< int > > > unpacked_MWR;
289  std::vector< std::vector< double> > MWR_times;
290  unpacked_MWR.resize(3);
291  MWR_times.resize(3);
292  std::string packed_data_str;
293 
294  //Create a list of all the MWR devices with their different
295  // memory buffer increments
296  // generally in the format: "E:<Device>.{Memory Block}"
297  std::vector<std::string> vars = bfp_mwr->GetDeviceList();
298  mf::LogDebug("BNBRetriever") << " Number of MWR Device Blocks Found : " << vars.size() << std::endl;
299  // Tracking the time from the IFBeamDB
300  double time_for_mwr;
301 
302  // this is an iterator to track which of the
303  // three devices we will be working with
304  int dev = 0;
305 
306  // The MWR devices are annoying and have confusing buffer
307  // what we'll do is sort through all of them first and then
308  // match them to the closest spills in time
309  //
310 
311  // int t_steps = int(((triggerInfo.t_previous_event - fTimePad) - (triggerInfo.t_current_event + fTimePad))/0.5)+25;
312  int t_steps = int(((triggerInfo.t_current_event + fTimePad) - (triggerInfo.t_previous_event - fTimePad - 20.))/0.5)+25;
313  mf::LogDebug("BNBRetriever") << " t_steps " << t_steps << std::endl;
314 
315  for(int t = 0; t < t_steps; t++){//Iterate through time increments
316  for (std::string const& var : vars) {// Iterate through the devices
317 
318  //Make sure we have a device
319  if(var.empty()){
320  mf::LogDebug("BNBRetriever") << " NO MWR DEVICES?!" << std::endl;
321  continue;
322  }
323  /// Check the device name and interate the double-vector index
324  if(var.find("M875BB") != std::string::npos ) dev = 0;
325  else if(var.find("M876BB") != std::string::npos ) dev = 1;
326  else if(var.find("MMBTBB") != std::string::npos ) dev = 2;
327  else{
328  mf::LogDebug("BNBRetriever") << " NOT matched to a MWR DEVICES?!" << var << std::endl;
329  continue;}
330 
331  time_for_mwr = 0;
332 
333  try{
334  //Pull the MWR data for the device
335  // these data are "packed"
336  std::vector<double> packed_MWR = bfp_mwr->GetNamedVector((triggerInfo.t_previous_event)-20.-fTimePad+double(0.5*t),var,&time_for_mwr);
337 
338  //We'll convert this into a format
339  // that we can unpack doubles >> strings
340  //
341  packed_data_str.clear();
342  packed_data_str += std::to_string(int(time_for_mwr));
343  packed_data_str.append(",");
344  packed_data_str.append(var);
345  packed_data_str.append(",,");
346 
347  /* for(auto const value: packed_MWR){
348  packed_data_str += ',';
349  packed_data_str += std::to_string(int(value));
350  }*/
351  for(int j = 0; j < int(packed_MWR.size()); j++){
352  packed_data_str += std::to_string(int(packed_MWR[j]));
353  if(j < int(packed_MWR.size())-1)
354  packed_data_str.append(",");
355  }
356 
357  // Use Zarko's unpacking function to turn this into consumeable data
358  std::vector<double> MWR_times_temp;
359 
360  // There is a 35 ms offset between the toriod and the MWR times
361  // we'll just remove that here to match to the spill times
362  std::vector< std::vector< int > > unpacked_MWR_temp = mwrdata.unpackMWR(packed_data_str,MWR_times_temp,MWRtoroidDelay);
363 
364  //There are four events that are packed into one MWR IFBeam entry
365  for(std::size_t s: util::counter(unpacked_MWR_temp.size())){
366 
367  // If this entry has a unique time them store it for later
368  if(std::find(MWR_times[dev].begin(), MWR_times[dev].end(), MWR_times_temp[s]) == MWR_times[dev].end()){
369  unpacked_MWR[dev].push_back(unpacked_MWR_temp[s]);
370  MWR_times[dev].push_back(MWR_times_temp[s]);
371  }//check for unique time
372  }//Iterate through the unpacked events
373  }//try
374  catch (WebAPIException &we) {
375  //Ignore when we can't find the MWR devices
376  // they don't always report and the timing of them can be annoying
377 
378  }//catch
379  }// Iterate over all the multiwire devices
380  }// Iterate over all times
381 
382  mf::LogDebug("BNBRetriever") << " Number of MWR[0] times : " << MWR_times[0].size() << std::endl;
383  mf::LogDebug("BNBRetriever") << " Number of MWR[0]s : " << unpacked_MWR[0].size() << std::endl;
384  mf::LogDebug("BNBRetriever") << " Number of MWR[1] times : " << MWR_times[1].size() << std::endl;
385  mf::LogDebug("BNBRetriever") << " Number of MWR[1]s : " << unpacked_MWR[1].size() << std::endl;
386  mf::LogDebug("BNBRetriever") << " Number of MWR[2] times : " << MWR_times[2].size() << std::endl;
387  mf::LogDebug("BNBRetriever") << " Number of MWR[2]s : " << unpacked_MWR[2].size() << std::endl;
388 
389  return { std::move(MWR_times), std::move(unpacked_MWR) };
390 }
391 
392 
394  art::EventID const& eventID,
395  TriggerInfo_t const& triggerInfo,
396  MWRdata_t const& MWRdata, bool isFirstEventInRun,
397  std::vector< sbn::BNBSpillInfo >& beamInfos
398 ) const {
399 
400  auto const& [ MWR_times, unpacked_MWR ] = MWRdata; // alias
401 
402  //Here we will start collecting all the other beamline devices
403  // First we get the times that the beamline device fired
404  // we have to pick a specific variable to use
405  std::vector<double> times_temps = bfp->GetTimeList(fDeviceUsedForTiming);
406 
407  // We'll keep track of how many of these spills match to our
408  // DAQ trigger times
409  int spill_count = 0;
410  std::vector<int> matched_MWR;
411  matched_MWR.resize(3);
412 
413 
414  // NOTE: for now, this is dead code because we don't
415  // do anything for the first event in a run. We may want to revisit
416  // this later to understand if there is a way we can do the POT
417  // accounting in the first event.
418  //
419  // Need to handle the first event in a run differently
420  if(isFirstEventInRun){
421 
422  //We'll remove the spills after our event
423  int spills_after_our_target = 0;
424  // iterate through all the spills to find the
425  // spills that are after our triggered event
426  for (size_t i = 0; i < times_temps.size(); i++) {
427  if(times_temps[i] > (triggerInfo.t_current_event+fTimePad)){
428  spills_after_our_target++;
429  }
430  }//end loop through spill times
431 
432  // Remove the spills after our trigger
433  times_temps.erase(times_temps.end()-spills_after_our_target,times_temps.end());
434 
435  // Remove the spills before the start of our Run
436  times_temps.erase(times_temps.begin(), times_temps.end() - std::min(int(triggerInfo.number_of_gates_since_previous_event), int(times_temps.size())));
437 
438  }//end fix for "first event"
439 
440  // Iterating through each of the beamline times
441  for (size_t i = 0; i < times_temps.size(); i++) {
442 
443  // Only continue if these times are matched to our DAQ time
444 
445  if(!isFirstEventInRun){//We already addressed the "first event" above
446  if(times_temps[i] > (triggerInfo.t_current_event)){continue;}
447  if(times_temps[i] <= (triggerInfo.t_previous_event)){continue;}
448  }
449 
450 
451  //Great we found a matched spill! Let's count it
452  spill_count++;
453 
454  //Loop through the multiwire devices:
455 
456  for(int dev = 0; dev < int(MWR_times.size()); dev++){
457 
458  //Loop through the multiwire times:
459  double Tdiff = 1000000000.;
460  matched_MWR[dev] = 0;
461 
462  for(int mwrt = 0; mwrt < int(MWR_times[dev].size()); mwrt++){
463 
464  //found a candidate match!
465  if(fabs((MWR_times[dev][mwrt] - times_temps[i])) >= Tdiff){continue;}
466 
467  bool best_match = true;
468 
469  //Check for a better match...
470  for (size_t j = 0; j < times_temps.size(); j++) {
471  if( j == i) continue;
472  if(times_temps[j] > (triggerInfo.t_current_event+fTimePad)){continue;}
473  if(times_temps[j] <= (triggerInfo.t_previous_event-fTimePad)){continue;}
474 
475  //is there a better match later in the spill sequence
476  if(fabs((MWR_times[dev][mwrt] - times_temps[j])) <
477  fabs((MWR_times[dev][mwrt] - times_temps[i]))){
478  //we can have patience...
479  best_match = false;
480  break;
481  }
482  }//end better match check
483 
484  //Verified best match!
485  if(best_match == true){
486  matched_MWR[dev] = mwrt;
487  Tdiff = fabs((MWR_times[dev][mwrt] - times_temps[i]));
488  }
489 
490  }//end loop over MWR times
491 
492  }//end loop over MWR devices
493 
494  sbn::BNBSpillInfo spillInfo = makeBNBSpillInfo(eventID, times_temps[i], MWRdata, matched_MWR);
495 
496  beamInfos.push_back(std::move(spillInfo));
497 
498  // We do not write these to the art::Events because
499  // we can filter events but want to keep all the POT
500  // information, so we'll write it to the SubRun
501 
502  }//end iteration over beam device times
503 
504  return spill_count;
505 }
506 
507 
509  (art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector<int> const& matched_MWR) const
510 {
511 
512  auto const& [ MWR_times, unpacked_MWR ] = MWRdata; // alias
513 
514  // initializing all of our device carriers
515  // device definitions can be found in BNBSpillInfo.h
516 
517  double TOR860 = 0; // units e12 protons
518  double TOR875 = 0; // units e12 protons
519  double LM875A = 0; // units R/s
520  double LM875B = 0; // units R/s
521  double LM875C = 0; // units R/s
522  double HP875 = 0; // units mm
523  double VP875 = 0; // units mm
524  double HPTG1 = 0; // units mm
525  double VPTG1 = 0; // units mm
526  double HPTG2 = 0; // units mm
527  double VPTG2 = 0; // units mm
528  double BTJT2 = 0; // units Deg C
529  double THCURR = 0; // units kiloAmps
530 
531  double TOR860_time = 0; // units s
532 
533  // Here we request all the devices
534  // since sometimes devices fail to report we'll
535  // allow each to throw an exception but still move forward
536  // interpreting these failures will be part of the beam quality analyses
537  try{bfp->GetNamedData(time, "E:TOR860@",&TOR860,&TOR860_time);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
538  try{bfp->GetNamedData(time, "E:TOR875",&TOR875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
539  try{bfp->GetNamedData(time, "E:LM875A",&LM875A);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
540  try{bfp->GetNamedData(time, "E:LM875B",&LM875B);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
541  try{bfp->GetNamedData(time, "E:LM875C",&LM875C);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
542  try{bfp->GetNamedData(time, "E:HP875",&HP875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
543  try{bfp->GetNamedData(time, "E:VP875",&VP875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
544  try{bfp->GetNamedData(time, "E:HPTG1",&HPTG1);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
545  try{bfp->GetNamedData(time, "E:VPTG1",&VPTG1);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
546  try{bfp->GetNamedData(time, "E:HPTG2",&HPTG2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
547  try{bfp->GetNamedData(time, "E:VPTG2",&VPTG2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
548  try{bfp->GetNamedData(time, "E:BTJT2",&BTJT2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
549  try{bfp->GetNamedData(time, "E:THCURR",&THCURR);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";}
550 
551  //crunch the times
552  unsigned long int time_closest_int = (int) TOR860_time;
553  double time_closest_ns = (TOR860_time - time_closest_int)*1e9;
554 
555  //Store everything in our data-product
556  sbn::BNBSpillInfo beamInfo;
557  beamInfo.TOR860 = TOR860*1e12; //add in factor of 1e12 protons to get correct POT units
558  beamInfo.TOR875 = TOR875*1e12; //add in factor of 1e12 protons to get correct POT units
559  beamInfo.LM875A = LM875A;
560  beamInfo.LM875B = LM875B;
561  beamInfo.LM875C = LM875C;
562  beamInfo.HP875 = HP875;
563  beamInfo.VP875 = VP875;
564  beamInfo.HPTG1 = HPTG1;
565  beamInfo.VPTG1 = VPTG1;
566  beamInfo.HPTG2 = HPTG2;
567  beamInfo.VPTG2 = VPTG2;
568  beamInfo.BTJT2 = BTJT2;
569  beamInfo.THCURR = THCURR;
570  beamInfo.spill_time_s = time_closest_int;
571  beamInfo.spill_time_ns = time_closest_ns;
572 
573  for(auto const& MWRdata: unpacked_MWR){
574  std::ignore = MWRdata;
575  assert(!MWRdata.empty());
576  }
577 
578  if(unpacked_MWR[0].empty()){
579  beamInfo.M875BB.clear();
580  beamInfo.M875BB_spill_time_diff = -999;//units in seconds
581  }
582  else{
583  beamInfo.M875BB = unpacked_MWR[0][matched_MWR[0]];
584  beamInfo.M875BB_spill_time_diff = (MWR_times[0][matched_MWR[0]] - time);
585  }
586 
587  if(unpacked_MWR[1].empty()){
588  beamInfo.M876BB.clear();
589  beamInfo.M876BB_spill_time_diff = -999;//units in seconds
590  }
591  else{
592  beamInfo.M876BB = unpacked_MWR[1][matched_MWR[1]];
593  beamInfo.M876BB_spill_time_diff = (MWR_times[1][matched_MWR[1]] - time);
594  }
595 
596  if(unpacked_MWR[2].empty()){
597  beamInfo.MMBTBB.clear();
598  beamInfo.MMBTBB_spill_time_diff = -999;//units in seconds
599  }
600  else{
601  beamInfo.MMBTBB = unpacked_MWR[2][matched_MWR[2]];
602  beamInfo.MMBTBB_spill_time_diff = (MWR_times[2][matched_MWR[2]] - time);
603  }
604  // We do not write these to the art::Events because
605  // we can filter events but want to keep all the POT
606  // information, so we'll write it to the SubRun
607 
608  beamInfo.event = eventID.event(); // the rest of ID is known by art::SubRun
609 
610  return beamInfo;
611 }
612 
613 
614 void sbn::BNBRetriever::beginSubRun(art::SubRun& sr)
615 {
616  return;
617 }
618 
619 //____________________________________________________________________________
620 void sbn::BNBRetriever::endSubRun(art::SubRun& sr)
621 {
622  // We will add all of the BNBSpillInfo data-products to the
623  // art::SubRun so it persists
624  // currently this is ~2.7 kB/event or ~0.07 kB/spill
625 
626 mf::LogDebug("BNBRetriever")<< "Total number of DAQ Spills : " << TotalBeamSpills << std::endl;
627 mf::LogDebug("BNBRetriever")<< "Total number of Selected Spills : " << fOutbeamInfos.size() << std::endl;
628 
629  auto p = std::make_unique< std::vector< sbn::BNBSpillInfo > >();
630  std::swap(*p, fOutbeamInfos);
631 
632  sr.put(std::move(p), art::subRunFragment());
633 
634  return;
635 }
636 
637 DEFINE_ART_MODULE(sbn::BNBRetriever)
float M876BB_spill_time_diff
the time difference between M876BB and the matched spill
Definition: BNBSpillInfo.h:50
std::vector< int > M876BB
Multiwire station after Mag 875...?
Definition: BNBSpillInfo.h:46
void produce(art::Event &e) override
std::string fDeviceUsedForTiming
float LM875C
Loss Monitor after the RWM, unit R/s.
Definition: BNBSpillInfo.h:30
float VPTG2
Horizontal Position Monitor at Target Station 2, closest to target, units mm.
Definition: BNBSpillInfo.h:38
int gate_type
Source of the spill: 1: BNB, 2: NuMI.
pdgs p
Definition: selectors.fcl:22
float VPTG1
Horizontal Position Monitor at Target Station 1, units mm.
Definition: BNBSpillInfo.h:35
unsigned long int spill_time_ns
The IFDB Beam Spill Time, unit nsec.
Definition: BNBSpillInfo.h:18
fhicl::Atom< std::string > Bundle
MWRdata_t extractSpillTimes(TriggerInfo_t const &triggerInfo) const
Determines spill times and extracts data based on multiwire devices.
BNBRetriever(Parameters const &params)
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
TriggerInfo_t extractTriggerInfo(art::Event const &e) const
Returns the information of the trigger in the current event.
float MMBTBB_spill_time_diff
the time difference between MMBTBB and the matched spill
Definition: BNBSpillInfo.h:51
fhicl::Atom< double > TimePadding fhicl::Atom< std::string > RawDataLabel
float TOR875
Toroid after Mag 875, units e12 Protons.
Definition: BNBSpillInfo.h:26
unsigned int TotalBeamSpills
float LM875A
Loss Monitor before the RWM, unit R/s.
Definition: BNBSpillInfo.h:28
std::unique_ptr< ifbeam_ns::BeamFolder > bfp
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
std::vector< sbn::BNBSpillInfo > fOutbeamInfos
float BTJT2
Temperature of air exiting target, units Deg C.
Definition: BNBSpillInfo.h:40
fhicl::Atom< std::string > URL
void beginSubRun(art::SubRun &sr) override
std::vector< int > MMBTBB
Multiwire station at the target station,.
Definition: BNBSpillInfo.h:47
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
fhicl::Atom< std::string > DeviceUsedForTiming
std::unique_ptr< ifbeam_ns::BeamFolder > bfp_mwr
BEGIN_PROLOG vertical distance to the surface Name
Test of util::counter and support utilities.
art::EDProducer::Table< Config > Parameters
float HP875
Horizontal Position Monitor after Mag 875, units mm.
Definition: BNBSpillInfo.h:31
int matchMultiWireData(art::EventID const &eventID, TriggerInfo_t const &triggerInfo, MWRdata_t const &MWRdata, bool isFirstEventInRun, std::vector< sbn::BNBSpillInfo > &beamInfos) const
Matches spill times with multiwire chamber data from the database.
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
std::vector< std::vector< double > > MWR_times
float HPTG2
Horizontal Position Monitor at Target Station 2, closest to target, units mm.
Definition: BNBSpillInfo.h:37
float THCURR
Current applied to Horn, units kiloAmperes.
Definition: BNBSpillInfo.h:42
fhicl::Atom< double > MWR_TimeWindow
unsigned long int spill_time_s
The IFDB Beam Spill Time, unit sec.
Definition: BNBSpillInfo.h:17
std::string to_string(WindowPattern const &pattern)
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
sbn::BNBSpillInfo makeBNBSpillInfo(art::EventID const &eventID, double time, MWRdata_t const &MWRdata, std::vector< int > const &matched_MWR) const
Assembles and returns a spill information record.
float VP875
Verticle Position Monitor after Mag 875, units mm.
Definition: BNBSpillInfo.h:32
do i e
unsigned int event
Definition: BNBSpillInfo.h:20
void endSubRun(art::SubRun &sr) override
float TOR860
Toroid before Mag 875, units e12 Protons.
Definition: BNBSpillInfo.h:25
BNBRetriever & operator=(BNBRetriever const &)=delete
std::vector< int > M875BB
Multiwire station before Mag 875...?
Definition: BNBSpillInfo.h:45
float LM875B
Loss Monitor after the RWM, unit R/s.
Definition: BNBSpillInfo.h:29
std::vector< std::vector< std::vector< int > > > unpacked_MWR
fhicl::Atom< double > TimeWindow
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
static constexpr double MWRtoroidDelay
the same time point is measured t by MWR and _t + MWRtoroidDelay`_ by the toroid [ms] ...
art::ServiceHandle< ifbeam_ns::IFBeam > ifbeam_handle
float M875BB_spill_time_diff
the time difference between M875BB and the matched spill
Definition: BNBSpillInfo.h:49
float HPTG1
Horizontal Position Monitor at Target Station 1, units mm.
Definition: BNBSpillInfo.h:34
fhicl::Atom< std::string > MultiWireBundle