All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NuMIRetriever_module.cc
Go to the documentation of this file.
1 /*
2  * NuMI Beam Spill Info Retriever module for ICARUS
3  * Based heavily on code by Z. Pavlovic written for MicroBooNE
4  * Based heavily on code by NOvA collaboration (Thanks NOvA!)
5 */
6 
7 #include "art/Framework/Core/EDProducer.h"
8 #include "art/Framework/Core/ModuleMacros.h"
9 #include "art/Framework/Principal/Event.h"
10 #include "art/Framework/Principal/Handle.h"
11 #include "art/Framework/Principal/Run.h"
12 #include "art/Framework/Principal/SubRun.h"
13 #include "canvas/Utilities/InputTag.h"
14 #include "fhiclcpp/ParameterSet.h"
15 #include "messagefacility/MessageLogger/MessageLogger.h"
20 
21 #include "artdaq-core/Data/Fragment.hh"
22 #include "sbndaq-artdaq-core/Overlays/ICARUS/ICARUSTriggerV2Fragment.hh"
23 
27 
28 #include "ifdh_art/IFBeamService/IFBeam_service.h"
29 #include "ifbeam_c.h"
30 //#include "MWRData.h"
31 
32 #include <memory>
33 #include <optional>
34 #include <vector>
35 
36 namespace sbn {
37  class NuMIRetriever;
38 }
39 
40 class sbn::NuMIRetriever : public art::EDProducer {
41 public:
42  explicit NuMIRetriever(fhicl::ParameterSet const &p);
43  NuMIRetriever(NuMIRetriever const&) = delete;
44  NuMIRetriever(NuMIRetriever &&) = delete;
45  NuMIRetriever& operator=(NuMIRetriever const&) = delete;
47 
48  // Required functions.
49  void produce(art::Event& e) override;
50  void beginSubRun(art::SubRun& sr) override;
51  void endSubRun(art::SubRun& sr) override;
52 
53 private:
54  // input labels
55  std::vector< sbn::NuMISpillInfo > fOutbeamInfos;
56  double fTimePad;
57  double fBFPEpsilion;
58  std::string fURL;
59  //MWRData mwrdata;
60  std::string raw_data_label_;
61  std::string fDeviceUsedForTiming;
63  art::ServiceHandle<ifbeam_ns::IFBeam> ifbeam_handle;
64  std::unique_ptr<ifbeam_ns::BeamFolder> bfp;
65 };
66 
67 sbn::NuMIRetriever::NuMIRetriever(fhicl::ParameterSet const& p)
68  : EDProducer{p},
69  fTimePad(p.get<double>("TimePadding", 0.5)), //epsilon in seconds, buffer time to look for spills
70  fBFPEpsilion(p.get<double>("BFPEpsilon", 0.02)), // 20 ms, tuned for BNB, check for NuMI here might need to be larger
71  raw_data_label_(p.get<std::string>("raw_data_label")),
72  fDeviceUsedForTiming(p.get<std::string>("DeviceUsedForTiming")),
73  bfp(ifbeam_handle->getBeamFolder(p.get<std::string>("Bundle"), p.get<std::string>("URL"), p.get<double>("TimeWindow")))
74 {
75 
76  bfp->set_epsilon(fBFPEpsilion);
77  bfp->setValidWindow(500.);
78  produces<std::vector<sbn::NuMISpillInfo>, art::InSubRun>();
79  TotalBeamSpills = 0;
80 }
81 
82 void sbn::NuMIRetriever::produce(art::Event &e)
83 {
84 
85  // If this is the first event in the run, then ignore it
86  // We do not currently have the ability to figure out the first
87  // spill that the DAQ was sensitive to, so don't try to save any
88  // spill information
89  //
90  // TODO: long-term goal -- can we fix this?
91  if (e.event() == 1) return;
92 
93  int gate_type = 0;
94  art::Handle< std::vector<artdaq::Fragment> > raw_data_ptr;
95  e.getByLabel(raw_data_label_, "ICARUSTriggerV2", raw_data_ptr);
96  auto const & raw_data = (*raw_data_ptr);
97 
98  double t_current_event = 0;
99  double t_previous_event = 0;
100  double number_of_gates_since_previous_event = 0;
101 
102  for(auto raw_datum : raw_data){
103 
104  uint64_t artdaq_ts = raw_datum.timestamp();
105  icarus::ICARUSTriggerV2Fragment frag(raw_datum);
106  std::string data = frag.GetDataString();
107  char *buffer = const_cast<char*>(data.c_str());
108  icarus::ICARUSTriggerInfo datastream_info = icarus::parse_ICARUSTriggerV2String(buffer);
109  gate_type = datastream_info.gate_type;
110  number_of_gates_since_previous_event = frag.getDeltaGatesNuMI();
111 
112  t_current_event = static_cast<double>(artdaq_ts)/(1000000000.); //check this offset...
113  if(gate_type == 2)
114  t_previous_event = (static_cast<double>(frag.getLastTimestampNuMI()))/(1000000000.);
115  else
116  t_previous_event = (static_cast<double>(frag.getLastTimestampOther()))/(1000000000.);
117 
118  }
119 
120  std::cout << std::setprecision(19) << "Previous : " << t_previous_event << ", Current : " << t_current_event << std::endl;
121  //We only want to process NuMI gates, i.e. type 2
122  if(gate_type == 2)
123  {
124  // Keep track of the number of beam gates the DAQ thinks
125  // are in this job
126  TotalBeamSpills += number_of_gates_since_previous_event;
127 
128  // These lines get everything primed within the IFBeamDB
129  // They seem redundant but they are needed
130  try{auto cur_vec_temp = bfp->GetNamedVector((t_previous_event)-fTimePad,"E:HP121[]");} catch (WebAPIException &we) {}
131 
132  try{auto cur_vec_temp_2 = bfp->GetNamedVector((t_current_event)+fTimePad,"E:VP121[]");} catch (WebAPIException &we) {}
133  try{auto packed_MTGTDS_temp = bfp->GetNamedVector((t_current_event)+fTimePad, "E:MTGTDS[]");} catch(WebAPIException &we) {}
134  std::vector<double> times_temps = bfp->GetTimeList(fDeviceUsedForTiming);
135 
136  int spill_count = 0;
137  // Iterating through each of the beamline times
138  for (size_t i = 0; i < times_temps.size(); i++) {
139 
140  // Only continue if these times are matched to our DAQ time
141  // plus or minus some time padding, currently using 3.3 ms
142  // which is half the Booster Rep Rate
143  if(e.event() != 1){//We already addressed the "first event" above
144  if(times_temps[i] > t_current_event){continue;}
145  if(times_temps[i] <= t_previous_event){continue;}
146  }
147 
148  //count found spills
149  spill_count++;
150 
151  //initialize all devices found in NuMISpillInfo.h in sbnobj
152  double HRNDIR = -1.;
153  double NSLINA = -1.;
154  double NSLINB = -1.;
155  double NSLINC = -1.;
156  double NSLIND = -1.;
157  double TOR101 = -1.;
158  double TORTGT = -1.;
159  double TR101D = -1.;
160  double TRTGTD = -1.;
161  std::vector< double > HP121;
162  std::vector< double > VP121;
163  std::vector< double > HPTGT;
164  std::vector< double > VPTGT;
165  std::vector< double > HITGT;
166  std::vector< double > VITGT;
167  std::vector< double > MTGTDS;
168  double TRTGTD_time = -1.;
169  std::cout << "Grabbing IFBeam info!" << std::endl;
170  try{bfp->GetNamedData(times_temps[i], "E:TRTGTD@",&TRTGTD,&TRTGTD_time);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
171  try{bfp->GetNamedData(times_temps[i], "E:TR101D",&TR101D);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
172  try{bfp->GetNamedData(times_temps[i], "E:HRNDIR",&HRNDIR);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
173  try{bfp->GetNamedData(times_temps[i], "E:NSLINA",&NSLINA);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
174  try{bfp->GetNamedData(times_temps[i], "E:NSLINB",&NSLINB);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
175  try{bfp->GetNamedData(times_temps[i], "E:NSLINC",&NSLINC);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
176  try{bfp->GetNamedData(times_temps[i], "E:NSLIND",&NSLIND);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
177  try{bfp->GetNamedData(times_temps[i], "E:TOR101",&TOR101);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
178  try{bfp->GetNamedData(times_temps[i], "E:TORTGT",&TORTGT);}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
179  // BPM Positions and Intensities - they each have 7 elements
180  // First is an average value of a few batches (often 2,3,4)
181  // used for auto-tuning, so we should disregard it
182 
183  try{HP121 = bfp->GetNamedVector(times_temps[i], "E:HP121[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " << "got exception: " << we.what() << "\n";}
184  try{VP121 = bfp->GetNamedVector(times_temps[i], "E:VP121[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " <<"got exception: " << we.what() << "\n";}
185  try{HPTGT = bfp->GetNamedVector(times_temps[i], "E:HPTGT[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " <<"got exception: " << we.what() << "\n";}
186  try{VPTGT = bfp->GetNamedVector(times_temps[i], "E:VPTGT[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " <<"got exception: " << we.what() << "\n";}
187  try{HITGT = bfp->GetNamedVector(times_temps[i], "E:HITGT[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " <<"got exception: " << we.what() << "\n";}
188  try{VITGT = bfp->GetNamedVector(times_temps[i], "E:VITGT[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " <<"got exception: " << we.what() << "\n";}
189  try{MTGTDS = bfp->GetNamedVector(times_temps[i], "E:MTGTDS[]");}catch (WebAPIException &we) {std::cout << "At time : " << times_temps[i] << " " <<"got exception: " << we.what() << "\n";}
190 
191  std::cout << "Finished getting IFBeam info" << std::endl;
192  std::cout << "BFP Time: " << times_temps[i] << " TOROID Time: " << TRTGTD_time << " TOROID COUNT: " << TRTGTD << std::endl;
193  unsigned long int time_closest_int = (int) TRTGTD_time;
194  double time_closest_ns = (TRTGTD_time - time_closest_int)*1000000000;
195 
196  sbn::NuMISpillInfo NuMIbeamInfo;
197  NuMIbeamInfo.TORTGT = TORTGT*1e12; //include factor of 1e12 protons in POT calculation
198  NuMIbeamInfo.TOR101 = TOR101*1e12; //include factor of 1e12 protons in POT calculation
199  NuMIbeamInfo.TRTGTD = TRTGTD*1e12; //include factor of 1e12 protons in POT calculation
200  NuMIbeamInfo.TR101D = TR101D*1e12; //include factor of 1e12 protons in POT calculation
201  NuMIbeamInfo.HRNDIR = HRNDIR;
202  NuMIbeamInfo.NSLINA = NSLINA;
203  NuMIbeamInfo.NSLINB = NSLINB;
204  NuMIbeamInfo.NSLINC = NSLINC;
205  NuMIbeamInfo.NSLIND = NSLIND;
206 
207  NuMIbeamInfo.HP121 = HP121;
208  NuMIbeamInfo.VP121 = VP121;
209  NuMIbeamInfo.HPTGT = HPTGT;
210  NuMIbeamInfo.VPTGT = VPTGT;
211  NuMIbeamInfo.HITGT = HITGT;
212  NuMIbeamInfo.VITGT = VITGT;
213  NuMIbeamInfo.MTGTDS = MTGTDS;
214 
215  NuMIbeamInfo.time = times_temps[i];
216  NuMIbeamInfo.event = e.event();
217  NuMIbeamInfo.spill_time_s = time_closest_int;
218  NuMIbeamInfo.spill_time_ns = time_closest_ns;
219  // Save the Number of DAQ Gates in the first saved spill
220  if (spill_count == 1) {
221  NuMIbeamInfo.daq_gates = number_of_gates_since_previous_event;
222  }
223  else {
224  NuMIbeamInfo.daq_gates = 0;
225  }
226 
227  fOutbeamInfos.push_back(NuMIbeamInfo);
228  }
229  if(spill_count > number_of_gates_since_previous_event)
230  std::cout << "Event Spills : " << spill_count << ", DAQ Spills : " << number_of_gates_since_previous_event << " \t \t ::: WRONG!"<< std::endl;
231  else
232  std::cout << "Event Spills : " << spill_count << ", DAQ Spills : " << number_of_gates_since_previous_event << std::endl;
233  }
234 }
235 
236 void sbn::NuMIRetriever::beginSubRun(art::SubRun& sr)
237 {
238  return;
239 }
240 
241 void sbn::NuMIRetriever::endSubRun(art::SubRun& sr)
242 {
243  // We will add all of the BNBSpillInfo data-products to the
244  // art::SubRun so it persists
245  // currently this is ~2.7 kB/event or ~0.07 kB/spill
246 
247  std::cout << "Total number of DAQ Spills : " << TotalBeamSpills << std::endl;
248  std::cout << "Total number of Selected Spills : " << fOutbeamInfos.size() << std::endl;
249 
250  auto p = std::make_unique< std::vector< sbn::NuMISpillInfo > >(fOutbeamInfos);
251 
252  sr.put(std::move(p), art::subRunFragment());
253 
254  // Clear the (now old) infos
255  fOutbeamInfos.clear();
256 
257  return;
258 }
259 
260 DEFINE_ART_MODULE(sbn::NuMIRetriever)
261 
262 
float TOR101
Other monitored POT at Start.
Definition: NuMISpillInfo.h:30
std::vector< double > HP121
List of Horizontal position at start per-bunch.
Definition: NuMISpillInfo.h:15
void beginSubRun(art::SubRun &sr) override
void endSubRun(art::SubRun &sr) override
NuMIRetriever(fhicl::ParameterSet const &p)
NuMIRetriever & operator=(NuMIRetriever const &)=delete
float TR101D
Best monitored POT at Start.
Definition: NuMISpillInfo.h:28
float TRTGTD
Best monitored POT at Target.
Definition: NuMISpillInfo.h:27
float time
Time of device used to lookup spill.
Definition: NuMISpillInfo.h:31
pdgs p
Definition: selectors.fcl:22
unsigned int daq_gates
Definition: NuMISpillInfo.h:37
std::vector< double > HPTGT
List of Horizontal position at target per-bunch.
Definition: NuMISpillInfo.h:17
std::unique_ptr< ifbeam_ns::BeamFolder > bfp
float TORTGT
Other monitored POT at Target.
Definition: NuMISpillInfo.h:29
Collection of exceptions for Geometry system.
unsigned long int spill_time_s
The IFDB Beam Spill Time, unit sec.
Definition: NuMISpillInfo.h:33
std::vector< double > VITGT
List of Vertical-Monitor intensity at tartget per bunch.
Definition: NuMISpillInfo.h:20
std::string fDeviceUsedForTiming
std::vector< double > MTGTDS
Definition: NuMISpillInfo.h:21
std::vector< double > HITGT
List of Horizontal-Monitor intensity at target per-bunch.
Definition: NuMISpillInfo.h:19
void produce(art::Event &e) override
do i e
unsigned long int spill_time_ns
The IFDB Beam Spill Time, unit nsec.
Definition: NuMISpillInfo.h:34
std::vector< sbn::NuMISpillInfo > fOutbeamInfos
unsigned int event
Definition: NuMISpillInfo.h:36
Class defining a sparse vector (holes are zeroes)
std::vector< double > VP121
List of Vertical position at start per-bunch.
Definition: NuMISpillInfo.h:16
std::vector< double > VPTGT
List of Vertical position at target per-bunch.
Definition: NuMISpillInfo.h:18
BEGIN_PROLOG could also be cout
art::ServiceHandle< ifbeam_ns::IFBeam > ifbeam_handle