All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CAFMaker_module.cc
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////
2 // \file CAFMaker_module.cc
3 /// \brief This module creates Common Analysis Files.
4 // Inspired by the NOvA CAFMaker package
5 // \author $Author: psihas@fnal.gov
6 //////////////////////////////////////////////////////////////////
7 
8 // ---------------- TO DO ----------------
9 //
10 // - Add in cycle and batch to params
11 // - Move this list some place useful
12 // - Add reco.CRT branch
13 // ---------------------------------------
14 
15 
22 #include "sbncode/CAFMaker/Utils.h"
23 
24 // C/C++ includes
25 #include <fenv.h>
26 #include <time.h>
27 #include <algorithm>
28 #include <cmath>
29 #include <iomanip>
30 #include <iostream>
31 #include <iterator>
32 #include <map>
33 #include <sstream>
34 #include <string>
35 #include <vector>
36 #include <array>
37 
38 #ifdef DARWINBUILD
39 #include <libgen.h>
40 #endif
41 
42 #include "ifdh_art/IFDHService/IFDH_service.h"
43 
44 // ROOT includes
45 #include "TFile.h"
46 #include "TH1D.h"
47 #include "TTree.h"
48 #include "TMath.h"
49 #include "TTimeStamp.h"
50 #include "TRandomGen.h"
51 #include "TObjString.h"
52 
53 // Framework includes
54 #include "art/Framework/Core/EDProducer.h"
55 #include "art/Framework/Core/FileBlock.h"
56 #include "art/Framework/Core/ModuleMacros.h"
57 #include "art/Framework/Principal/Event.h"
58 #include "art/Framework/Principal/Handle.h"
59 #include "art/Framework/Principal/SubRun.h"
60 #include "art/Framework/Services/Registry/ServiceHandle.h"
61 #include "art/Framework/Services/System/TriggerNamesService.h"
62 #include "nurandom/RandomUtils/NuRandomService.h"
67 
68 #include "art_root_io/TFileService.h"
69 
70 #include "canvas/Persistency/Common/FindMany.h"
71 #include "canvas/Persistency/Common/FindManyP.h"
72 #include "canvas/Persistency/Common/FindOne.h"
73 #include "canvas/Persistency/Common/FindOneP.h"
74 #include "canvas/Persistency/Common/Ptr.h"
75 #include "canvas/Persistency/Common/PtrVector.h"
76 
77 #include "cetlib_except/exception.h"
78 #include "cetlib_except/demangle.h"
79 
80 #include "fhiclcpp/ParameterSet.h"
81 
82 #include "messagefacility/MessageLogger/MessageLogger.h"
83 
84 // LArSoft includes
91 
92 #include "nusimdata/SimulationBase/MCFlux.h"
93 #include "nusimdata/SimulationBase/MCTruth.h"
94 #include "nusimdata/SimulationBase/MCNeutrino.h"
95 #include "nusimdata/SimulationBase/GTruth.h"
96 
97 #include "fhiclcpp/ParameterSetRegistry.h"
98 
110 
111 
112 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
114 
115 // StandardRecord
118 
119 #include "sbnanaobj/StandardRecord/Flat/FlatRecord.h"
122 
123 // // CAFMaker
125 // #include "sbncode/CAFMaker/Blinding.h"
126 
127 // Metadata
129 
130 namespace sbn{
131  namespace evwgh{
132  std::ostream& operator<<(std::ostream& os, const sbn::evwgh::EventWeightParameterSet& p)
133  {
134  // TODO proper implementation of this should be added in sbnobj
135  os << p.fName << " " << p.fRWType << std::endl;
136  for(const auto& it: p.fParameterMap){
137  os << it.first.fName << " " << it.first.fMean << " " << it.first.fWidth << std::endl << " ";
138  for(float v: it.second) os << " " << v;
139  os << std::endl;
140  }
141  return os;
142  }
143  }
144 }
145 
146 namespace caf {
147 
148 /// Module to create Common Analysis Files from ART files
149 class CAFMaker : public art::EDProducer {
150  public:
151  // Allows 'nova --print-description' to work
152  using Parameters = art::EDProducer::Table<CAFMakerParams>;
153 
154  explicit CAFMaker(const Parameters& params);
155  virtual ~CAFMaker();
156 
157  void produce(art::Event& evt) noexcept;
158 
159  void respondToOpenInputFile(const art::FileBlock& fb);
160 
161  void beginJob();
162  void endJob();
163  virtual void beginRun(art::Run& r);
164  virtual void beginSubRun(art::SubRun& sr);
165  virtual void endSubRun(art::SubRun& sr);
166 
167  protected:
169 
170  std::string fCafFilename;
171  std::string fCafBlindFilename;
172  std::string fCafPrescaleFilename;
173 
174  std::string fFlatCafFilename;
177 
183  double fTotalPOT;
184  double fSubRunPOT;
186  double fTotalEvents;
187  double fBlindEvents;
189  std::vector<caf::SRBNBInfo> fBNBInfo; ///< Store detailed BNB info to save into the first StandardRecord of the output file
190  std::vector<caf::SRNuMIInfo> fNuMIInfo; ///< Store detailed NuMI info to save into the first StandardRecord of the output file
191  std::vector<caf::SRTrigger> fSRTrigger; ///< Store trigger and beam gate information
192 
193  // int fCycle;
194  // int fBatch;
195 
196  TFile* fFile = 0;
197  TFile* fFileb = 0;
198  TFile* fFilep = 0;
199 
200  TTree* fRecTree = 0;
201  TTree* fRecTreeb = 0;
202  TTree* fRecTreep = 0;
203 
204  TFile* fFlatFile = 0;
205  TFile* fFlatFileb = 0;
206  TFile* fFlatFilep = 0;
207 
208  TTree* fFlatTree = 0;
209  TTree* fFlatTreeb = 0;
210  TTree* fFlatTreep = 0;
211 
212  flat::Flat<caf::StandardRecord>* fFlatRecord = 0;
213  flat::Flat<caf::StandardRecord>* fFlatRecordb = 0;
214  flat::Flat<caf::StandardRecord>* fFlatRecordp = 0;
215 
216  Det_t fDet; ///< Detector ID in caf namespace typedef
217 
218  // volumes
219  std::vector<std::vector<geo::BoxBoundedGeo>> fTPCVolumes;
220  std::vector<geo::BoxBoundedGeo> fActiveVolumes;
221 
222  // random number generator for fake reco
224 
225  // random number generator for prescaling
226  TRandom *fBlindTRandom;
227 
228  /// What position in the vector each parameter set take
229  std::map<std::string, unsigned int> fWeightPSetIndex;
230  /// Map from parameter labels to previously seen parameter set configuration
231  std::map<std::string, std::vector<sbn::evwgh::EventWeightParameterSet>> fPrevWeightPSet;
232 
233  std::string DeriveFilename(const std::string& inname,
234  const std::string& ext) const;
235 
236  void AddEnvToFile(TFile* f);
237  void AddMetadataToFile(TFile* f,
238  const std::map<std::string, std::string>& metadata);
239  void AddGlobalTreeToFile(TFile* outfile, caf::SRGlobal& global) const;
240  void AddHistogramsToFile(TFile* outfile,bool isBlindPOT, bool isPrescalePOT) const;
241 
242  void InitializeOutfiles();
243 
245  double GetBlindPOTScale() const;
246 
247  void InitVolumes(); ///< Initialize volumes from Gemotry service
248 
249  /// Equivalent of FindManyP except a return that is !isValid() prints a
250  /// messsage and aborts if StrictMode is true.
251  template <class T, class U>
252  art::FindManyP<T> FindManyPStrict(const U& from, const art::Event& evt,
253  const art::InputTag& label) const;
254 
255  template <class T, class D, class U>
256  art::FindManyP<T, D> FindManyPDStrict(const U& from,
257  const art::Event& evt,
258  const art::InputTag& tag) const;
259 
260  /// Equivalent of FindOneP except a return that is !isValid() prints a
261  /// messsage and aborts if StrictMode is true.
262  template <class T, class U>
263  art::FindOneP<T> FindOnePStrict(const U& from, const art::Event& evt,
264  const art::InputTag& label) const;
265 
266 
267  /// \brief Retrieve an object from an association, with error handling
268  ///
269  /// This can go wrong in two ways: either the FindManyP itself is
270  /// invalid, or the result for the requested index is empty. In most
271  /// cases these have the same response, so conflating them here
272  /// saves redundancy elsewhere.
273  ///
274  /// \param fm The FindManyP object describing the association
275  /// \param idx Which element of the FindManyP to look it
276  /// \param[out] ret The product retrieved
277  /// \return Whether \a ret was filled
278  template <class T>
279  bool GetAssociatedProduct(const art::FindManyP<T>& fm, int idx, T& ret) const;
280 
281  /// Equivalent of evt.getByLabel(label, handle) except failedToGet
282  /// prints a message and aborts if StrictMode is true.
283  template <class EvtT, class T>
284  void GetByLabelStrict(const EvtT& evt, const std::string& label,
285  art::Handle<T>& handle) const;
286 
287  /// Equivalent of evt.getByLabel(label, handle) except failedToGet
288  /// prints a message.
289  template <class T>
290  void GetByLabelIfExists(const art::Event& evt, const std::string& label,
291  art::Handle<T>& handle) const;
292 
293  /// \param pset The parameter set
294  /// \param name Pass "foo.bar.baz" as {"foo", "bar", "baz"}
295  /// \param[out] ret Value of the key, not set if we return false
296  /// \return Whether the key was found
297  template <class T>
298  bool GetPsetParameter(const fhicl::ParameterSet& pset,
299  const std::vector<std::string>& name, T& ret) const;
300 
301  static bool EssentiallyEqual(double a, double b, double precision = 0.0001) {
302  return a <= (b + precision) && a >= (b - precision);
303  }
304 
305  static bool sortRBTrkLength(const art::Ptr<recob::Track>& a,
306  const art::Ptr<recob::Track>& b) {
307  return a->Length() > b->Length();
308  }
309  // static bool sortTrackLength(const SRTrack& a, const SRTrack& b) {
310  // return a.len > b.len;
311  // }
312 //.......................................................................
313 }; //Producer
314 
315 //.......................................................................
316 
318  : art::EDProducer{params},
319  fParams(params()), fFile(0)
320  {
321  // Note: we will define isRealData on a per event basis in produce function [using event.isRealData()], at least for now.
322 
323  fCafFilename = fParams.CAFFilename();
324  fFlatCafFilename = fParams.FlatCAFFilename();
325 
326  // Normally CAFMaker is run wit no output ART stream, so these go
327  // nowhere, but can be occasionally useful for filtering in ART
328 
329  produces<std::vector<caf::StandardRecord>>();
330  //produces<art::Assns<caf::StandardRecord, recob::Slice>>();
331 
332  // setup volume definitions
333  InitVolumes();
334 
335  // setup random number generators
336  fFakeRecoTRandom = new TRandomMT64(art::ServiceHandle<rndm::NuRandomService>()->getSeed());
337  if (fParams.CreateBlindedCAF()) {
338  fBlindTRandom = new TRandomMT64(art::ServiceHandle<rndm::NuRandomService>()->getSeed());
339  }
340 }
341 
342 //......................................................................
343  double CAFMaker::GetBlindPOTScale() const {
344  std::string bstring = std::to_string(fParams.POTBlindSeed());
345  int slen = bstring.length();
346  std::string s1 = bstring.substr(0,int(slen/2));
347  std::string s2 = bstring.substr(int(slen/2));
348  double rat = stod(s1)/stod(s2);
349  while (abs(rat)>1){
350  rat = -1 * (abs(rat) - 1);
351  }
352  return 1 + rat*0.3;
353 
354  }
355 //......................................................................
357 
358  //simple cuts for trk and shower variables
359  //blind events with a potential lepton with momentum > 0.6 that starts in fiducial volume
360  for (caf::SRTrack& trk: brec->reco.trk) {
361  const caf::SRVector3D start = trk.start;
362  if ( ((start.x < -71.1 - 25 && start.x > -369.33 + 25 ) ||
363  (start.x > 71.1 + 25 && start.x < 369.33 - 25 )) &&
364  (start.y > -181.7 + 25 && start.y < 134.8 - 25 ) &&
365  (start.z > -895.95 + 30 && start.z < 895.95 - 50)) {
366 
367  if (trk.mcsP.fwdP_muon > 0.6) {
368  trk.mcsP.fwdP_muon = TMath::QuietNaN();
369  }
370  if (trk.rangeP.p_muon > 0.6) {
371  trk.rangeP.p_muon = TMath::QuietNaN();
372  }
373  }
374  }
375 
376  //Note shower energy may not be currently very functional
377  for (caf::SRShower& shw: brec->reco.shw) {
378  const caf::SRVector3D start = shw.start;
379  if ( ((start.x < -71.1 - 25 && start.x > -369.33 + 25 ) ||
380  (start.x > 71.1 + 25 && start.x < 369.33 - 25 )) &&
381  (start.y > -181.7 + 25 && start.y < 134.8 - 25 ) &&
382  (start.z > -895.95 + 30 && start.z < 895.95 - 50)) {
383  if (shw.bestplane_energy > 0.6) {
384  shw.bestplane_energy = TMath::QuietNaN();
385  shw.plane[0].energy = TMath::QuietNaN();
386  shw.plane[1].energy = TMath::QuietNaN();
387  shw.plane[2].energy = TMath::QuietNaN();
388  }
389  }
390  }
391 
392  // And for slices, check vertex in FV and then check tracks and showers
393  for (caf::SRSlice& slc: brec->slc) {
394  const caf::SRVector3D vtx = slc.vertex;
395  if ( ((vtx.x < -71.1 - 25 && vtx.x > -369.33 + 25 ) ||
396  (vtx.x > 71.1 + 25 && vtx.x < 369.33 - 25 )) &&
397  (vtx.y > -181.7 + 25 && vtx.y < 134.8 - 25 ) &&
398  (vtx.z > -895.95 + 30 && vtx.z < 895.95 - 50)) {
399 
400  for (caf::SRTrack& trk: slc.reco.trk) {
401  if (trk.mcsP.fwdP_muon > 0.6) {
402  trk.mcsP.fwdP_muon = TMath::QuietNaN();
403  }
404  if (trk.rangeP.p_muon > 0.6) {
405  trk.rangeP.p_muon = TMath::QuietNaN();
406  }
407  }
408  for (caf::SRShower& shw: slc.reco.shw) {
409  if (shw.bestplane_energy > 0.6) {
410  shw.bestplane_energy = TMath::QuietNaN();
411  shw.plane[0].energy = TMath::QuietNaN();
412  shw.plane[1].energy = TMath::QuietNaN();
413  shw.plane[2].energy = TMath::QuietNaN();
414  }
415  }
416  }
417  }
418 }
419 
421  const geo::GeometryCore *geometry = lar::providerFrom<geo::Geometry>();
422 
423  // first the TPC volumes
424  for (auto const &cryo: geometry->IterateCryostats()) {
425  geo::GeometryCore::TPC_iterator iTPC = geometry->begin_TPC(cryo.ID()),
426  tend = geometry->end_TPC(cryo.ID());
427  std::vector<geo::BoxBoundedGeo> this_tpc_volumes;
428  while (iTPC != tend) {
429  geo::TPCGeo const& TPC = *iTPC;
430  this_tpc_volumes.push_back(TPC.ActiveBoundingBox());
431  iTPC++;
432  }
433  fTPCVolumes.push_back(std::move(this_tpc_volumes));
434  }
435 
436  // then combine them into active volumes
437  for (const std::vector<geo::BoxBoundedGeo> &tpcs: fTPCVolumes) {
438  double XMin = std::min_element(tpcs.begin(), tpcs.end(), [](auto &lhs, auto &rhs) { return lhs.MinX() < rhs.MinX(); })->MinX();
439  double YMin = std::min_element(tpcs.begin(), tpcs.end(), [](auto &lhs, auto &rhs) { return lhs.MinY() < rhs.MinY(); })->MinY();
440  double ZMin = std::min_element(tpcs.begin(), tpcs.end(), [](auto &lhs, auto &rhs) { return lhs.MinZ() < rhs.MinZ(); })->MinZ();
441 
442  double XMax = std::max_element(tpcs.begin(), tpcs.end(), [](auto &lhs, auto &rhs) { return lhs.MaxX() < rhs.MaxX(); })->MaxX();
443  double YMax = std::max_element(tpcs.begin(), tpcs.end(), [](auto &lhs, auto &rhs) { return lhs.MaxY() < rhs.MaxY(); })->MaxY();
444  double ZMax = std::max_element(tpcs.begin(), tpcs.end(), [](auto &lhs, auto &rhs) { return lhs.MaxZ() < rhs.MaxZ(); })->MaxZ();
445 
446  fActiveVolumes.emplace_back(XMin, XMax, YMin, YMax, ZMin, ZMax);
447  }
448 }
449 
450 //......................................................................
452 {
453  delete fRecTree;
454  delete fFile;
455 
456  delete fFlatRecord;
457  delete fFlatTree;
458  delete fFlatFile;
459 
460  if (fParams.CreateBlindedCAF()) {
461  delete fRecTreeb;
462  delete fRecTreep;
463  delete fFileb;
464  delete fFilep;
465  delete fFlatRecordb;
466  delete fFlatRecordp;
467  delete fFlatTreeb;
468  delete fFlatTreep;
469  delete fFlatFileb;
470  delete fFlatFilep;
471  delete fBlindTRandom;
472  }
473 
474  delete fFakeRecoTRandom;
475 
476 }
477 
478 //......................................................................
479 std::string CAFMaker::DeriveFilename(const std::string& inname,
480  const std::string& ext) const
481 {
482  char* temp = new char[inname.size()+1];
483  std::strcpy(temp, inname.c_str());
484  std::string ret = basename(temp);
485  delete[] temp;
486  const size_t dotpos = ret.rfind('.'); // Find last dot
487  assert(dotpos != std::string::npos); // Must have a dot, surely?
488  ret.resize(dotpos); // Truncate everything after dot
489  ret += ext;
490  return ret;
491 }
492 
493 //......................................................................
494 void CAFMaker::respondToOpenInputFile(const art::FileBlock& fb) {
495  if ((fParams.CreateCAF() && !fFile) ||
496  (fParams.CreateFlatCAF() && !fFlatFile) ||
497  (fParams.CreateBlindedCAF() && (!fFileb || !fFilep))) {
498  // If Filename wasn't set in the FCL, and this is the
499  // first file we've seen
500  if(fParams.CreateCAF() && fCafFilename.empty()){
501  if (fParams.CreateBlindedCAF()){
505  fCafBlindFilename = DeriveFilename(fCafBlindFilename, fParams.FileExtension());
507  fCafPrescaleFilename = DeriveFilename(fCafPrescaleFilename, fParams.FileExtension());
508  }
509  else {
510  fCafFilename = DeriveFilename(fb.fileName(), fParams.FileExtension());
511  }
512  }
513  if(fParams.CreateFlatCAF() && fFlatCafFilename.empty()){
514  if (fParams.CreateBlindedCAF()){
518  fFlatCafBlindFilename = DeriveFilename(fFlatCafBlindFilename, fParams.FlatCAFFileExtension());
520  fFlatCafPrescaleFilename = DeriveFilename(fFlatCafPrescaleFilename, fParams.FlatCAFFileExtension());
521  }
522  else {
524  }
525  }
526  if (fParams.CreateBlindedCAF() && fCafBlindFilename.empty()) {
527  const std::string basename = fCafFilename;
529  fCafBlindFilename = DeriveFilename(fCafBlindFilename, fParams.FileExtension());
531  fCafPrescaleFilename = DeriveFilename(fCafPrescaleFilename, fParams.FileExtension());
532  }
534  const std::string basename = fFlatCafFilename;
538  fFlatCafPrescaleFilename = DeriveFilename(fFlatCafPrescaleFilename, fParams.FlatCAFFileExtension());
539  }
541  }
542 
543  fFileNumber ++;
544  fFirstInFile = true;
545  fFirstBlindInFile = true;
546  fFirstPrescaleInFile = true;
547 
548 }
549 
550 //......................................................................
552 {
553 }
554 
555 //......................................................................
556 void CAFMaker::AddGlobalTreeToFile(TFile* outfile, caf::SRGlobal& global) const
557 {
558  outfile->cd();
559 
560  TTree* globalTree = new TTree("globalTree", "globalTree");
561  SRGlobal* pglobal = &global;
562  TBranch* br = globalTree->Branch("global", "caf::SRGlobal", &pglobal);
563  if(!br) abort();
564  globalTree->Fill();
565  globalTree->Write();
566 }
567 
568 //......................................................................
569 void CAFMaker::beginRun(art::Run& run) {
570  fDet = kUNKNOWN;
571 
572  caf::Det_t override = kUNKNOWN;
573  if(fParams.DetectorOverride() == "sbnd") override = kSBND;
574  if(fParams.DetectorOverride() == "icarus") override = kICARUS;
575  if(!fParams.DetectorOverride().empty() && override == kUNKNOWN){
576  std::cout << "CAFMaker: unrecognized value for DetectorOverride parameter: '" << fParams.DetectorOverride() << "'" << std::endl;
577  abort();
578  }
579 
580  // Heuristic method to determine the detector ID
581  const geo::GeometryCore* geom = lar::providerFrom<geo::Geometry>();
582 
583  std::string gdml = geom->GDMLFile();
584  gdml = basename(gdml.c_str()); // strip directory part
585  std::cout << "CAFMaker: Attempting to deduce detector from GDML file name: '" << gdml
586  << "' and configured detector name: '" << geom->DetectorName() << "'. ";
587  // Lowercase filename, in case it contains "SBND" or "Icarus" etc
588  for(unsigned int i = 0; i < gdml.size(); ++i) gdml[i] = std::tolower(gdml[i]);
589  // Do we find the string in either of the names?
590  const bool hasSBND = ((gdml.find("sbnd") != std::string::npos) ||
591  (geom->DetectorName().find("sbnd") != std::string::npos));
592  const bool hasIcarus = ((gdml.find("icarus") != std::string::npos) ||
593  (geom->DetectorName().find("icarus") != std::string::npos));
594 
595  // Either no evidence, or ambiguous evidence
596  if(hasSBND == hasIcarus){
597  std::cout << "Unable to automatically determine detector!" << std::endl;
598  if(override == kUNKNOWN) abort();
599  }
600  // Now must be one or the other
601  if(hasSBND){
602  fDet = kSBND;
603  std::cout << "Detected SBND" << std::endl;
604  }
605  if(hasIcarus){
606  fDet = kICARUS;
607  std::cout << "Detected Icarus" << std::endl;
608  }
609 
610  if(override != kUNKNOWN){
611  std::cout << "Detector set to ";
612  std::cout << ((override == kSBND) ? "SBND" : "Icarus");
613  std::cout << " based on user configuration." << std::endl;
614  if(fDet == override){
615  std::cout << " This was redundant with the auto-detection. Suggest to not specify DetectorOverride" << std::endl;
616  }
617  else if(fDet != kUNKNOWN){
618  std::cout << " This OVERRODE the auto-detection. Are you sure this is what you wanted?" << std::endl;
619  }
620  fDet = override;
621  }
622 
623 
624  if(fParams.SystWeightLabels().empty()) return; // no need for globalTree
625 
626  SRGlobal global;
627 
628  for(const std::string& label: fParams.SystWeightLabels()){
629  art::Handle<std::vector<sbn::evwgh::EventWeightParameterSet>> wgt_params;
630  GetByLabelStrict(run, label, wgt_params);
631 
632  if(fPrevWeightPSet.count(label)){
633  if(fPrevWeightPSet[label] != *wgt_params){
634  std::cout << "CAFMaker: Run-level EventWeightParameterSet mismatch."
635  << std::endl;
636  std::cout << "Previous parameter sets:";
638  std::cout << p << std::endl;
639  }
640  std::cout << "\nNew parameter sets:";
641  for(const sbn::evwgh::EventWeightParameterSet& p: *wgt_params){
642  std::cout << p << std::endl;
643  }
644  abort();
645  }
646  return; // Match, no need to refill into tree
647  }
648 
649  // If there were no weights available, return
650  if (!wgt_params.isValid()){
651  std::cout << "CAFMaker: no EventWeightParameterSet found under label '" << label << "'" << std::endl;
652  return;
653  }
654 
655  fPrevWeightPSet[label] = *wgt_params;
656 
657  for(const sbn::evwgh::EventWeightParameterSet& pset: *wgt_params){
658  FillSRGlobal(pset, global, fWeightPSetIndex);
659  } // end for pset
660  } // end for label
661 
662  if(fFile) AddGlobalTreeToFile(fFile, global);
668 }
669 
670 //......................................................................
671 void CAFMaker::beginSubRun(art::SubRun& sr) {
672 
673  // get POT information
674  fBNBInfo.clear();
675  fNuMIInfo.clear();
676  fSubRunPOT = 0;
677 
678  if(auto bnb_spill = sr.getHandle<std::vector<sbn::BNBSpillInfo>>(fParams.BNBPOTDataLabel())){
679  FillExposure(*bnb_spill, fBNBInfo, fSubRunPOT);
681  }
682  else if (auto numi_spill = sr.getHandle<std::vector<sbn::NuMISpillInfo>>(fParams.NuMIPOTDataLabel())) {
683  FillExposureNuMI(*numi_spill, fNuMIInfo, fSubRunPOT);
685  }
686  else if(auto pot_handle = sr.getHandle<sumdata::POTSummary>(fParams.GenLabel())){
687  fSubRunPOT = pot_handle->totgoodpot;
689  }
690  else{
691  if(!fParams.BNBPOTDataLabel().empty() || !fParams.GenLabel().empty() || !fParams.NuMIPOTDataLabel().empty()){
692  std::cout << "Found neither BNB data POT info under '"
694  << "' not NuMIdata POT info under '"
696  << "' nor MC POT info under '"
697  << fParams.GenLabel() << "'"
698  << std::endl;
699  if(fParams.StrictMode()) abort();
700  }
701 
702  // Otherwise, if one label is blank, maybe no POT was the expected result
703  }
704 
705  std::cout << "POT: " << fSubRunPOT << std::endl;
706 
707  fFirstInSubRun = true;
708 }
709 
710 //......................................................................
711 void CAFMaker::AddEnvToFile(TFile* outfile)
712 {
713  // Global information about the processing details:
714  std::map<std::string, std::string> envmap;
715 
716  // Environ comes from unistd.h
717  // environ is not present on OSX for some reason, so just use getenv to
718  // grab the variables we care about.
719 #ifdef DARWINBUILD
720  std::set<TString> variables;
721  variables.insert("USER");
722  variables.insert("HOSTNAME");
723  variables.insert("PWD");
724  for (auto var : variables) if(getenv(var)) envmap[var] = getenv(var);
725 #else
726  for (char** penv = environ; *penv; ++penv) {
727  const std::string pair = *penv;
728  const size_t split = pair.find("=");
729  if(split == std::string::npos) continue; // Huh?
730  const std::string key = pair.substr(0, split);
731  const std::string value = pair.substr(split + 1);
732  envmap[key] = value;
733  }
734 #endif
735 
736  // Default constructor is "now"
737  envmap["date"] = TTimeStamp().AsString();
738  envmap["output"] = fCafFilename;
739 
740  // Get the command-line we were invoked with. What I'd really like is
741  // just the fcl script and list of input filenames in a less hacky
742  // fashion. I'm not sure that's actually possible in ART.
743  // TODO: ask the artists.
744  FILE* cmdline = fopen("/proc/self/cmdline", "rb");
745  char* arg = 0;
746  size_t size = 0;
747  std::string cmd;
748  while (getdelim(&arg, &size, 0, cmdline) != -1) {
749  cmd += arg;
750  cmd += " ";
751  }
752  free(arg);
753  fclose(cmdline);
754 
755  envmap["cmd"] = cmd;
756 
757  outfile->mkdir("env")->cd();
758 
759  TTree* trenv = new TTree("envtree", "envtree");
760  std::string key, value;
761  trenv->Branch("key", &key);
762  trenv->Branch("value", &value);
763  for(const auto& keyval: envmap){
764  key = keyval.first;
765  value = keyval.second;
766  trenv->Fill();
767  }
768  trenv->Write();
769 }
770 
771 //......................................................................
772 void CAFMaker::AddMetadataToFile(TFile* outfile, const std::map<std::string, std::string>& metadata)
773 {
774  outfile->mkdir("metadata")->cd();
775 
776  TTree* trmeta = new TTree("metatree", "metatree");
777  std::string key, value;
778  trmeta->Branch("key", &key);
779  trmeta->Branch("value", &value);
780  for(const auto& keyval: metadata){
781  key = keyval.first;
782  value = keyval.second;
783  trmeta->Fill();
784  }
785  trmeta->Write();
786 }
787 
788 //......................................................................
790 {
791  if(fParams.CreateCAF()){
792 
793  mf::LogInfo("CAFMaker") << "Output filename is " << fCafFilename;
794 
795  fFile = new TFile(fCafFilename.c_str(), "RECREATE");
796 
797  fRecTree = new TTree("recTree", "records");
798 
799  // Tell the tree it's expecting StandardRecord objects
800  StandardRecord* rec = 0;
801  fRecTree->Branch("rec", "caf::StandardRecord", &rec);
802 
804 
805  if (fParams.CreateBlindedCAF()) {
806  mf::LogInfo("CAFMaker") << "Blinded output filenames are " << fCafBlindFilename << ", and " << fCafPrescaleFilename;
807  fFileb = new TFile(fCafBlindFilename.c_str(), "RECREATE");
808  fRecTreeb = new TTree("recTree", "records");
809  fRecTreeb->Branch("rec", "caf::StandardRecord", &rec);
810 
811  fFilep = new TFile(fCafPrescaleFilename.c_str(), "RECREATE");
812  fRecTreep = new TTree("recTree", "records");
813  fRecTreep->Branch("rec", "caf::StandardRecord", &rec);
814 
817  }
818 
819  }
820 
821  if(fParams.CreateFlatCAF()){
822  mf::LogInfo("CAFMaker") << "Output flat filename is " << fFlatCafFilename;
823 
824  // LZ4 is the fastest format to decompress. I get 3x faster loading with
825  // this compared to the default, and the files are only slightly larger.
826  fFlatFile = new TFile(fFlatCafFilename.c_str(), "RECREATE", "",
827  ROOT::CompressionSettings(ROOT::kLZ4, 1));
828 
829  fFlatTree = new TTree("recTree", "recTree");
830 
831  fFlatRecord = new flat::Flat<caf::StandardRecord>(fFlatTree, "rec", "", 0);
832 
834 
835  if (fParams.CreateBlindedCAF()) {
836 
837  mf::LogInfo("CAFMaker") << "Blinded output flat filename are " << fFlatCafBlindFilename << ", and " << fFlatCafPrescaleFilename;
838 
839  // LZ4 is the fastest format to decompress. I get 3x faster loading with
840  // this compared to the default, and the files are only slightly larger.
841  fFlatFileb = new TFile(fFlatCafBlindFilename.c_str(), "RECREATE", "",
842  ROOT::CompressionSettings(ROOT::kLZ4, 1));
843 
844  fFlatFilep = new TFile(fFlatCafPrescaleFilename.c_str(), "RECREATE", "",
845  ROOT::CompressionSettings(ROOT::kLZ4, 1));
846 
847  fFlatTreeb = new TTree("recTree", "recTree");
848  fFlatTreep = new TTree("recTree", "recTree");
849 
850  fFlatRecordb = new flat::Flat<caf::StandardRecord>(fFlatTreeb, "rec", "", 0);
851  fFlatRecordp = new flat::Flat<caf::StandardRecord>(fFlatTreep, "rec", "", 0);
852 
854  AddEnvToFile(fFlatFilep);
855  }
856 
857  }
858 
859  fFileNumber = -1;
860  fTotalPOT = 0;
861  fSubRunPOT = 0;
862  fTotalSinglePOT = 0;
863  fTotalEvents = 0;
864  fBlindEvents = 0;
865  fPrescaleEvents = 0;
866  fFirstInFile = false;
867  fFirstInSubRun = false;
868  // fCycle = -5;
869  // fBatch = -5;
870 }
871 
872 
873 //......................................................................
874 template <class T, class U>
875 art::FindManyP<T> CAFMaker::FindManyPStrict(const U& from,
876  const art::Event& evt,
877  const art::InputTag& tag) const {
878  art::FindManyP<T> ret(from, evt, tag);
879 
880  if (!tag.label().empty() && !ret.isValid() && fParams.StrictMode()) {
881  std::cout << "CAFMaker: No Assn from '"
882  << cet::demangle_symbol(typeid(from).name()) << "' to '"
883  << cet::demangle_symbol(typeid(T).name())
884  << "' found under label '" << tag << "'. "
885  << "Set 'StrictMode: false' to continue anyway." << std::endl;
886  abort();
887  }
888 
889  return ret;
890 }
891 
892 //......................................................................
893 template <class T, class D, class U>
894 art::FindManyP<T, D> CAFMaker::FindManyPDStrict(const U& from,
895  const art::Event& evt,
896  const art::InputTag& tag) const {
897  art::FindManyP<T, D> ret(from, evt, tag);
898 
899  if (!tag.label().empty() && !ret.isValid() && fParams.StrictMode()) {
900  std::cout << "CAFMaker: No Assn from '"
901  << cet::demangle_symbol(typeid(from).name()) << "' to '"
902  << cet::demangle_symbol(typeid(T).name())
903  << "' found under label '" << tag << "'. "
904  << "Set 'StrictMode: false' to continue anyway." << std::endl;
905  abort();
906  }
907 
908  return ret;
909 }
910 
911 //......................................................................
912 template <class T, class U>
913 art::FindOneP<T> CAFMaker::FindOnePStrict(const U& from,
914  const art::Event& evt,
915  const art::InputTag& tag) const {
916  art::FindOneP<T> ret(from, evt, tag);
917 
918  if (!tag.label().empty() && !ret.isValid() && fParams.StrictMode()) {
919  std::cout << "CAFMaker: No Assn from '"
920  << cet::demangle_symbol(typeid(from).name()) << "' to '"
921  << cet::demangle_symbol(typeid(T).name())
922  << "' found under label '" << tag << "'. "
923  << "Set 'StrictMode: false' to continue anyway." << std::endl;
924  abort();
925  }
926 
927  return ret;
928 }
929 
930 //......................................................................
931 template <class T>
932 bool CAFMaker::GetAssociatedProduct(const art::FindManyP<T>& fm, int idx,
933  T& ret) const {
934  if (!fm.isValid()) return false;
935 
936  const std::vector<art::Ptr<T>> prods = fm.at(idx);
937 
938  if (prods.empty()) return false;
939 
940  ret = *prods[0];
941 
942  return true;
943 }
944 
945 //......................................................................
946 template <class EvtT, class T>
947 void CAFMaker::GetByLabelStrict(const EvtT& evt, const std::string& label,
948  art::Handle<T>& handle) const {
949  evt.getByLabel(label, handle);
950  if (!label.empty() && handle.failedToGet() && fParams.StrictMode()) {
951  std::cout << "CAFMaker: No product of type '"
952  << cet::demangle_symbol(typeid(*handle).name())
953  << "' found under label '" << label << "'. "
954  << "Set 'StrictMode: false' to continue anyway." << std::endl;
955  abort();
956  }
957 }
958 
959 //......................................................................
960 template <class T>
961 void CAFMaker::GetByLabelIfExists(const art::Event& evt,
962  const std::string& label,
963  art::Handle<T>& handle) const {
964  evt.getByLabel(label, handle);
965  if (!label.empty() && handle.failedToGet() && fParams.StrictMode()) {
966  std::cout << "CAFMaker: No product of type '"
967  << cet::demangle_symbol(typeid(*handle).name())
968  << "' found under label '" << label << "'. "
969  << "Continuing without it." << std::endl;
970  }
971 }
972 
973 //......................................................................
974 template <class T>
975 bool CAFMaker::GetPsetParameter(const fhicl::ParameterSet& pset,
976  const std::vector<std::string>& name,
977  T& ret) const {
978  fhicl::ParameterSet p = pset;
979  for (unsigned int i = 0; i < name.size() - 1; ++i) {
980  if (!p.has_key(name[i])) return false;
981  p = p.get<fhicl::ParameterSet>(name[i]);
982  }
983  if (!p.has_key(name.back())) return false;
984  ret = p.get<T>(name.back());
985  return true;
986 }
987 
988 //......................................................................
989 void CAFMaker::produce(art::Event& evt) noexcept {
990 
991  // is this event real data?
992  bool isRealData = evt.isRealData();
993 
994  std::unique_ptr<std::vector<caf::StandardRecord>> srcol(
995  new std::vector<caf::StandardRecord>);
996 
997  std::unique_ptr<art::Assns<caf::StandardRecord, recob::Slice>> srAssn(
998  new art::Assns<caf::StandardRecord, recob::Slice>);
999 
1000  fTotalEvents += 1;
1001 
1002  // get all the truth's
1003  art::Handle<std::vector<simb::MCTruth>> mctruth_handle;
1004  GetByLabelStrict(evt, fParams.GenLabel(), mctruth_handle);
1005 
1006  std::vector<art::Ptr<simb::MCTruth>> mctruths;
1007  if (mctruth_handle.isValid()) {
1008  art::fill_ptr_vector(mctruths, mctruth_handle);
1009  }
1010 
1011  // And associated GTruth objects
1012  art::FindManyP<simb::GTruth> fmp_gtruth = FindManyPStrict<simb::GTruth>(mctruths, evt, fParams.GenLabel());
1013 
1014  art::Handle<std::vector<simb::MCTruth>> cosmic_mctruth_handle;
1015  evt.getByLabel(fParams.CosmicGenLabel(), cosmic_mctruth_handle);
1016 
1017  art::Handle<std::vector<simb::MCTruth>> pgun_mctruth_handle;
1018  evt.getByLabel(fParams.ParticleGunGenLabel(), pgun_mctruth_handle);
1019 
1020  // use the MCTruth to determine the simulation type
1021  caf::MCType_t mctype = caf::kMCUnknown;
1022  if (mctruth_handle.isValid() && cosmic_mctruth_handle.isValid()) {
1023  mctype = caf::kMCOverlay;
1024  }
1025  else if (mctruth_handle.isValid()) {
1026  mctype = caf::kMCNeutrino;
1027  }
1028  else if (cosmic_mctruth_handle.isValid()) {
1029  mctype = caf::kMCCosmic;
1030  }
1031  else if (pgun_mctruth_handle.isValid()) {
1032  mctype = caf::kMCParticleGun;
1033  }
1034 
1035  // Lookup the MeV-Portal info if it is there
1036  //
1037  // Don't be "strict" because this will only be true for a subset of MC
1038  art::Handle<std::vector<evgen::ldm::MeVPrtlTruth>> mevprtltruth_handle;
1039  evt.getByLabel(fParams.GenLabel(), mevprtltruth_handle);
1040 
1041  std::vector<art::Ptr<evgen::ldm::MeVPrtlTruth>> mevprtl_truths;
1042  if (mevprtltruth_handle.isValid()) art::fill_ptr_vector(mevprtl_truths, mevprtltruth_handle);
1043 
1044  // prepare map of track ID's to energy depositions
1045  art::Handle<std::vector<sim::SimChannel>> simchannel_handle;
1046  GetByLabelStrict(evt, fParams.SimChannelLabel(), simchannel_handle);
1047 
1048  std::vector<art::Ptr<sim::SimChannel>> simchannels;
1049  if (simchannel_handle.isValid()) {
1050  art::fill_ptr_vector(simchannels, simchannel_handle);
1051  }
1052 
1053  art::Handle<std::vector<simb::MCFlux>> mcflux_handle;
1054  GetByLabelStrict(evt, "generator", mcflux_handle);
1055 
1056  std::vector<art::Ptr<simb::MCFlux>> mcfluxes;
1057  if (mcflux_handle.isValid()) {
1058  art::fill_ptr_vector(mcfluxes, mcflux_handle);
1059  }
1060 
1061  // get the MCReco for the fake-reco
1062  art::Handle<std::vector<sim::MCTrack>> mctrack_handle;
1063  GetByLabelStrict(evt, "mcreco", mctrack_handle);
1064  std::vector<art::Ptr<sim::MCTrack>> mctracks;
1065  if (mctrack_handle.isValid()) {
1066  art::fill_ptr_vector(mctracks, mctrack_handle);
1067  }
1068 
1069  // get all of the true particles from G4
1070  std::vector<caf::SRTrueParticle> true_particles;
1071  art::Handle<std::vector<simb::MCParticle>> mc_particles;
1072  GetByLabelStrict(evt, fParams.G4Label(), mc_particles);
1073 
1074  // collect services
1075  // Moved ParticleInventory and BackTracker services definition as needed elsewhere (BH)
1076  auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
1077  auto const dprop =
1078  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clock_data);
1079  const geo::GeometryCore *geometry = lar::providerFrom<geo::Geometry>();
1080 
1081  // Collect the input TPC reco tags
1082  std::vector<std::string> pandora_tag_suffixes;
1083  fParams.PandoraTagSuffixes(pandora_tag_suffixes);
1084  if (pandora_tag_suffixes.size() == 0) pandora_tag_suffixes.push_back("");
1085 
1086  // collect the TPC hits
1087  std::vector<art::Ptr<recob::Hit>> hits;
1088  for (unsigned i_tag = 0; i_tag < pandora_tag_suffixes.size(); i_tag++) {
1089  const std::string &pandora_tag_suffix = pandora_tag_suffixes[i_tag];
1090  art::Handle<std::vector<recob::Hit>> thisHits;
1091  GetByLabelStrict(evt, fParams.HitLabel() + pandora_tag_suffix, thisHits);
1092  if (thisHits.isValid()) {
1093  art::fill_ptr_vector(hits, thisHits);
1094  }
1095  }
1096 
1097  // Prep truth-to-reco-matching info
1098  std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE*>>> id_to_ide_map;
1099  std::map<int, std::vector<art::Ptr<recob::Hit>>> id_to_truehit_map;
1100  std::map<int, caf::HitsEnergy> id_to_hit_energy_map;
1101 
1102  if ( !isRealData ) {
1103  art::ServiceHandle<cheat::BackTrackerService> bt_serv;
1104 
1105  id_to_ide_map = PrepSimChannels(simchannels, *geometry);
1106  id_to_truehit_map = PrepTrueHits(hits, clock_data, *bt_serv);
1107  id_to_hit_energy_map = SetupIDHitEnergyMap(hits, clock_data, *bt_serv);
1108  }
1109 
1110  //#######################################################
1111  // Fill truths & fake reco
1112  //#######################################################
1113 
1114  caf::SRTruthBranch srtruthbranch;
1115 
1116  if (mc_particles.isValid()) {
1117  art::ServiceHandle<cheat::ParticleInventoryService> pi_serv;
1118  art::ServiceHandle<cheat::BackTrackerService> bt_serv;
1119 
1120  for (const simb::MCParticle part: *mc_particles) {
1121  true_particles.emplace_back();
1122 
1123  FillTrueG4Particle(part,
1124  fActiveVolumes,
1125  fTPCVolumes,
1126  id_to_ide_map,
1127  id_to_truehit_map,
1128  *bt_serv,
1129  *pi_serv,
1130  mctruths,
1131  true_particles.back());
1132  }
1133  }
1134 
1135  std::vector<art::FindManyP<sbn::evwgh::EventWeightMap>> fmpewm;
1136 
1137  // holder for invalid MCFlux
1138  simb::MCFlux badflux; // default constructor gives nonsense values
1139 
1140  for (size_t i=0; i<mctruths.size(); i++) {
1141  auto const& mctruth = mctruths.at(i);
1142  const simb::MCFlux &mcflux = (mcfluxes.size()) ? *mcfluxes.at(i) : badflux;
1143 
1144  simb::GTruth gtruth;
1145  bool ok = GetAssociatedProduct(fmp_gtruth, i, gtruth);
1146  if(!ok){
1147  std::cout << "Failed to get GTruth object!" << std::endl;
1148  }
1149 
1150  srtruthbranch.nu.push_back(SRTrueInteraction());
1151  srtruthbranch.nnu ++;
1152 
1153  if ( !isRealData ) FillTrueNeutrino(mctruth, mcflux, gtruth, true_particles, id_to_truehit_map, srtruthbranch.nu.back(), i, fActiveVolumes);
1154 
1155  // Don't check for syst weight assocations until we have something (MCTruth
1156  // corresponding to a neutrino) that could plausibly be reweighted. This
1157  // avoids the need for special configuration for cosmics or single particle
1158  // simulation, and real data.
1159  if(fmpewm.empty() && mctruth->NeutrinoSet()){
1160  for(const std::string& label: fParams.SystWeightLabels()){
1161  fmpewm.push_back(FindManyPStrict<sbn::evwgh::EventWeightMap>(mctruths, evt, label));
1162  }
1163  }
1164 
1165  // For each of the sources of systematic weights
1166  for(auto& fm: fmpewm){
1167  if (!fm.isValid()) continue; // Don't crash if StrictMode==false
1168 
1169  // Find the weights associated with this particular interaction
1170  const std::vector<art::Ptr<sbn::evwgh::EventWeightMap>> wgts = fm.at(i);
1171 
1172  // For all the weights associated with this MCTruth
1173  for(const art::Ptr<sbn::evwgh::EventWeightMap>& wgtmap: wgts){
1174  FillEventWeight(*wgtmap, srtruthbranch.nu.back(), fWeightPSetIndex);
1175  } // end for wgtmap
1176  } // end for fm
1177  } // end for i (mctruths)
1178 
1179  // get the number of events generated in the gen stage
1180  unsigned n_gen_evt = 0;
1181  for (const art::ProcessConfiguration &process: evt.processHistory()) {
1182  fhicl::ParameterSet gen_config;
1183  bool success = evt.getProcessParameterSet(process.processName(), gen_config);
1184  if (success && gen_config.has_key("source") && gen_config.has_key("source.maxEvents") && gen_config.has_key("source.module_type") ) {
1185  int max_events = gen_config.get<int>("source.maxEvents");
1186  std::string module_type = gen_config.get<std::string>("source.module_type");
1187  if (module_type == "EmptyEvent") {
1188  n_gen_evt += max_events;
1189  }
1190  }
1191  }
1192 
1193  std::vector<caf::SRFakeReco> srfakereco;
1194  FillFakeReco(mctruths, true_particles, mctracks, fActiveVolumes, *fFakeRecoTRandom, srfakereco);
1195 
1196  // Fill the MeVPrtl stuff
1197  for (unsigned i_prtl = 0; i_prtl < mevprtl_truths.size(); i_prtl++) {
1198  srtruthbranch.prtl.emplace_back();
1199  FillMeVPrtlTruth(*mevprtl_truths[i_prtl], fActiveVolumes, srtruthbranch.prtl.back());
1200  srtruthbranch.nprtl = srtruthbranch.prtl.size();
1201  }
1202 
1203  //#######################################################
1204  // Fill detector & reco
1205  //#######################################################
1206 
1207  //Beam gate and Trigger info
1208  fSRTrigger.clear();
1209  if(isRealData)
1210  {
1211  const auto& addltrig = evt.getProduct<sbn::ExtraTriggerInfo>(fParams.TriggerLabel());
1212  const auto& trig = evt.getProduct<std::vector<raw::Trigger>>(fParams.TriggerLabel());
1213  if(trig.size()==1)
1214  {
1215  FillTrigger(addltrig, trig, fSRTrigger);
1216  }
1217  }
1218 
1219  // try to find the result of the Flash trigger if it was run
1220  bool pass_flash_trig = false;
1221  art::Handle<bool> flashtrig_handle;
1222  GetByLabelStrict(evt, fParams.FlashTrigLabel(), flashtrig_handle);
1223 
1224  if (flashtrig_handle.isValid()) {
1225  pass_flash_trig = *flashtrig_handle;
1226  }
1227 
1228  // Fill various detector information associated with the event
1229  //
1230  // Get all of the CRT hits
1231  std::vector<caf::SRCRTHit> srcrthits;
1232 
1233  art::Handle<std::vector<sbn::crt::CRTHit>> crthits_handle;
1234  GetByLabelStrict(evt, fParams.CRTHitLabel(), crthits_handle);
1235  // fill into event
1236  if (crthits_handle.isValid()) {
1237 
1238  //==== gate start time
1239  //==== 03/31/22 : 1600000 ns = 1.6 ms is the default T0Offset in MC
1240  //==== https://github.com/SBNSoftware/icaruscode/blob/v09_37_02_01/icaruscode/CRT/crtsimmodules_icarus.fcl#L11
1241  uint64_t m_gate_start_timestamp = fParams.CRTSimT0Offset(); // ns
1242  if(isRealData){
1243 
1244  art::Handle< std::vector<raw::ExternalTrigger> > externalTrigger_handle;
1245  evt.getByLabel( fParams.TriggerLabel(), externalTrigger_handle );
1246  const std::vector<raw::ExternalTrigger> &externalTrgs = *externalTrigger_handle;
1247 
1248  art::Handle< std::vector<raw::Trigger> > trigger_handle;
1249  evt.getByLabel( fParams.TriggerLabel(), trigger_handle );
1250  const std::vector<raw::Trigger> &trgs = *trigger_handle;
1251 
1252  if(externalTrgs.size()==1 && trgs.size()==1){
1253  long long TriggerAbsoluteTime = externalTrgs[0].GetTrigTime(); // Absolute time of trigger
1254  double BeamGateRelativeTime = trgs[0].BeamGateTime(); // BeamGate time w.r.t. electronics clock T0 in us
1255  double TriggerRelativeTime = trgs[0].TriggerTime(); // Trigger time w.r.t. electronics clock T0 in us
1256  m_gate_start_timestamp = TriggerAbsoluteTime + (int)(BeamGateRelativeTime*1000-TriggerRelativeTime*1000);
1257  }
1258  else{
1259  std::cout << "Unexpected in " << evt.id() << ": there are " << trgs.size()
1260  << " triggers in '" << fParams.TriggerLabel().encode() << "' data product."
1261  << " Please contact CAFmaker maintainer." << std::endl;
1262  abort();
1263  }
1264  }
1265 
1266  const std::vector<sbn::crt::CRTHit> &crthits = *crthits_handle;
1267  for (unsigned i = 0; i < crthits.size(); i++) {
1268  srcrthits.emplace_back();
1269  FillCRTHit(crthits[i], m_gate_start_timestamp, fParams.CRTUseTS0(), srcrthits.back());
1270  }
1271  }
1272 
1273  // Get all of the CRT Tracks
1274  std::vector<caf::SRCRTTrack> srcrttracks;
1275 
1276  art::Handle<std::vector<sbn::crt::CRTTrack>> crttracks_handle;
1277  GetByLabelStrict(evt, fParams.CRTTrackLabel(), crttracks_handle);
1278  // fill into event
1279  if (crttracks_handle.isValid()) {
1280  const std::vector<sbn::crt::CRTTrack> &crttracks = *crttracks_handle;
1281  for (unsigned i = 0; i < crttracks.size(); i++) {
1282  srcrttracks.emplace_back();
1283  FillCRTTrack(crttracks[i], fParams.CRTUseTS0(), srcrttracks.back());
1284  }
1285  }
1286 
1287  // Get all of the OpFlashes
1288  std::vector<caf::SROpFlash> srflashes;
1289 
1290  for (const std::string& pandora_tag_suffix : pandora_tag_suffixes) {
1291  art::Handle<std::vector<recob::OpFlash>> flashes_handle;
1292  GetByLabelStrict(evt, fParams.OpFlashLabel() + pandora_tag_suffix, flashes_handle);
1293  // fill into event
1294  if (flashes_handle.isValid()) {
1295  const std::vector<recob::OpFlash> &opflashes = *flashes_handle;
1296  int cryostat = ( pandora_tag_suffix.find("W") != std::string::npos ) ? 1 : 0;
1297  for (const recob::OpFlash& flash : opflashes) {
1298  srflashes.emplace_back();
1299  FillOpFlash(flash, cryostat, srflashes.back());
1300  }
1301  }
1302  }
1303 
1304  // collect the TPC slices
1305  std::vector<art::Ptr<recob::Slice>> slices;
1306  std::vector<std::string> slice_tag_suffixes;
1307  std::vector<unsigned> slice_tag_indices;
1308  for (unsigned i_tag = 0; i_tag < pandora_tag_suffixes.size(); i_tag++) {
1309  const std::string &pandora_tag_suffix = pandora_tag_suffixes[i_tag];
1310  // Get a handle on the slices
1311  art::Handle<std::vector<recob::Slice>> thisSlices;
1312  GetByLabelStrict(evt, fParams.PFParticleLabel() + pandora_tag_suffix, thisSlices);
1313  if (thisSlices.isValid()) {
1314  art::fill_ptr_vector(slices, thisSlices);
1315  for (unsigned i = 0; i < thisSlices->size(); i++) {
1316  slice_tag_suffixes.push_back(pandora_tag_suffix);
1317  slice_tag_indices.push_back(i_tag);
1318  }
1319  }
1320  }
1321 
1322  // The Standard Record
1323  // Branch entry definition -- contains list of slices, CRT information, and truth information
1324  StandardRecord rec;
1325 
1326  //#######################################################
1327  // Loop over slices
1328  //#######################################################
1329  for (unsigned sliceID = 0; sliceID < slices.size(); sliceID++) {
1330  // Holder for information on this slice
1331  caf::SRSlice recslc;
1332  recslc.truth.det = fDet;
1333 
1334  art::Ptr<recob::Slice> slice = slices[sliceID];
1335  const std::string &slice_tag_suff = slice_tag_suffixes[sliceID];
1336  unsigned producer = slice_tag_indices[sliceID];
1337 
1338  // Get tracks & showers here
1339  std::vector<art::Ptr<recob::Slice>> sliceList {slice};
1340  art::FindManyP<recob::PFParticle> findManyPFParts =
1341  FindManyPStrict<recob::PFParticle>(sliceList, evt, fParams.PFParticleLabel() + slice_tag_suff);
1342 
1343  std::vector<art::Ptr<recob::PFParticle>> fmPFPart;
1344  if (findManyPFParts.isValid()) {
1345  fmPFPart = findManyPFParts.at(0);
1346  }
1347 
1348  art::FindManyP<recob::Hit> fmSlcHits =
1349  FindManyPStrict<recob::Hit>(sliceList, evt, fParams.PFParticleLabel() + slice_tag_suff);
1350 
1351  std::vector<art::Ptr<recob::Hit>> slcHits;
1352  if (fmSlcHits.isValid()) {
1353  slcHits = fmSlcHits.at(0);
1354  }
1355 
1356  art::FindOneP<sbn::CRUMBSResult> foSlcCRUMBS =
1357  FindOnePStrict<sbn::CRUMBSResult>(sliceList, evt,
1358  fParams.CRUMBSLabel() + slice_tag_suff);
1359  const sbn::CRUMBSResult *slcCRUMBS = nullptr;
1360  if (foSlcCRUMBS.isValid()) {
1361  slcCRUMBS = foSlcCRUMBS.at(0).get();
1362  }
1363 
1364  art::FindManyP<sbn::SimpleFlashMatch> fm_sFM =
1365  FindManyPStrict<sbn::SimpleFlashMatch>(fmPFPart, evt,
1366  fParams.FlashMatchLabel() + slice_tag_suff);
1367 
1368  art::FindManyP<larpandoraobj::PFParticleMetadata> fmPFPMeta =
1369  FindManyPStrict<larpandoraobj::PFParticleMetadata>(fmPFPart, evt,
1370  fParams.PFParticleLabel() + slice_tag_suff);
1371 
1372  art::FindManyP<recob::SpacePoint> fmSpacePoint =
1373  FindManyPStrict<recob::SpacePoint>(slcHits, evt, fParams.PFParticleLabel() + slice_tag_suff);
1374 
1375  std::vector<art::Ptr<recob::SpacePoint>> slcSpacePoints;
1376  if (fmSpacePoint.isValid()) {
1377  for (unsigned i = 0; i < fmSpacePoint.size(); i++) {
1378  const std::vector<art::Ptr<recob::SpacePoint>> &thisSpacePoints = fmSpacePoint.at(i);
1379  if (thisSpacePoints.size() == 0) {
1380  slcSpacePoints.emplace_back(); // nullptr
1381  }
1382  else if (thisSpacePoints.size() == 1) {
1383  slcSpacePoints.push_back(fmSpacePoint.at(i).at(0));
1384  }
1385  else abort();
1386  }
1387  }
1388 
1389  art::FindManyP<recob::PFParticle> fmSpacePointPFPs =
1390  FindManyPStrict<recob::PFParticle>(slcSpacePoints, evt, fParams.PFParticleLabel() + slice_tag_suff);
1391 
1392  art::FindManyP<recob::Shower> fmShower =
1393  FindManyPStrict<recob::Shower>(fmPFPart, evt, fParams.RecoShowerLabel() + slice_tag_suff);
1394 
1395  // make Ptr's to showers for shower -> other object associations
1396  std::vector<art::Ptr<recob::Shower>> slcShowers;
1397  if (fmShower.isValid()) {
1398  for (unsigned i = 0; i < fmShower.size(); i++) {
1399  const std::vector<art::Ptr<recob::Shower>> &thisShowers = fmShower.at(i);
1400  if (thisShowers.size() == 0) {
1401  slcShowers.emplace_back(); // nullptr
1402  }
1403  else if (thisShowers.size() == 1) {
1404  slcShowers.push_back(fmShower.at(i).at(0));
1405  }
1406  else assert(false); // bad
1407  }
1408  }
1409 
1410  art::FindManyP<float> fmShowerCosmicDist =
1411  FindManyPStrict<float>(slcShowers, evt, fParams.ShowerCosmicDistLabel() + slice_tag_suff);
1412 
1413  art::FindManyP<float> fmShowerResiduals =
1414  FindManyPStrict<float>(slcShowers, evt, fParams.RecoShowerSelectionLabel() + slice_tag_suff);
1415 
1416  art::FindManyP<sbn::ShowerTrackFit> fmShowerTrackFit =
1417  FindManyPStrict<sbn::ShowerTrackFit>(slcShowers, evt, fParams.RecoShowerSelectionLabel() + slice_tag_suff);
1418 
1419  art::FindManyP<sbn::ShowerDensityFit> fmShowerDensityFit =
1420  FindManyPStrict<sbn::ShowerDensityFit>(slcShowers, evt, fParams.RecoShowerSelectionLabel() + slice_tag_suff);
1421 
1422  art::FindManyP<recob::Track> fmTrack =
1423  FindManyPStrict<recob::Track>(fmPFPart, evt,
1424  fParams.RecoTrackLabel() + slice_tag_suff);
1425 
1426  // make Ptr's to tracks for track -> other object associations
1427  std::vector<art::Ptr<recob::Track>> slcTracks;
1428  if (fmTrack.isValid()) {
1429  for (unsigned i = 0; i < fmTrack.size(); i++) {
1430  const std::vector<art::Ptr<recob::Track>> &thisTracks = fmTrack.at(i);
1431  if (thisTracks.size() == 0) {
1432  slcTracks.emplace_back(); // nullptr
1433  }
1434  else if (thisTracks.size() == 1) {
1435  slcTracks.push_back(fmTrack.at(i).at(0));
1436  }
1437  else assert(false); // bad
1438  }
1439  }
1440 
1441  // Get the stubs!
1442  art::FindManyP<sbn::Stub> fmSlcStubs =
1443  FindManyPStrict<sbn::Stub>(sliceList, evt,
1444  fParams.StubLabel() + slice_tag_suff);
1445 
1446  std::vector<art::Ptr<sbn::Stub>> fmStubs;
1447  if (fmSlcStubs.isValid()) {
1448  fmStubs = fmSlcStubs.at(0);
1449  }
1450 
1451  // Lookup stubs to overlaid PFP
1452  art::FindManyP<recob::PFParticle> fmStubPFPs =
1453  FindManyPStrict<recob::PFParticle>(fmStubs, evt,
1454  fParams.StubLabel() + slice_tag_suff);
1455  // and get the stub hits for truth matching
1456  art::FindManyP<recob::Hit> fmStubHits =
1457  FindManyPStrict<recob::Hit>(fmStubs, evt,
1458  fParams.StubLabel() + slice_tag_suff);
1459 
1460  art::FindManyP<anab::Calorimetry> fmCalo =
1461  FindManyPStrict<anab::Calorimetry>(slcTracks, evt,
1462  fParams.TrackCaloLabel() + slice_tag_suff);
1463 
1464  art::FindManyP<anab::ParticleID> fmChi2PID =
1465  FindManyPStrict<anab::ParticleID>(slcTracks, evt,
1466  fParams.TrackChi2PidLabel() + slice_tag_suff);
1467 
1468  art::FindManyP<sbn::ScatterClosestApproach> fmScatterClosestApproach =
1469  FindManyPStrict<sbn::ScatterClosestApproach>(slcTracks, evt,
1470  fParams.TrackScatterClosestApproachLabel() + slice_tag_suff);
1471 
1472  art::FindManyP<sbn::StoppingChi2Fit> fmStoppingChi2Fit =
1473  FindManyPStrict<sbn::StoppingChi2Fit>(slcTracks, evt,
1474  fParams.TrackStoppingChi2FitLabel() + slice_tag_suff);
1475 
1476  art::FindManyP<sbn::MVAPID> fmTrackDazzle =
1477  FindManyPStrict<sbn::MVAPID>(slcTracks, evt,
1478  fParams.TrackDazzleLabel() + slice_tag_suff);
1479 
1480  art::FindManyP<sbn::MVAPID> fmShowerRazzle =
1481  FindManyPStrict<sbn::MVAPID>(slcShowers, evt,
1482  fParams.ShowerRazzleLabel() + slice_tag_suff);
1483 
1484  art::FindManyP<recob::Vertex> fmVertex =
1485  FindManyPStrict<recob::Vertex>(fmPFPart, evt,
1486  fParams.PFParticleLabel() + slice_tag_suff);
1487 
1488  art::FindManyP<recob::Hit> fmTrackHit =
1489  FindManyPStrict<recob::Hit>(slcTracks, evt,
1490  fParams.RecoTrackLabel() + slice_tag_suff);
1491 
1492  art::FindManyP<recob::Hit> fmShowerHit =
1493  FindManyPStrict<recob::Hit>(slcShowers, evt,
1494  fParams.RecoShowerLabel() + slice_tag_suff);
1495 
1496  // TODO: also save the sbn::crt::CRTHit in the matching so that CAFMaker has access to it
1497  art::FindManyP<anab::T0> fmCRTHitMatch =
1498  FindManyPStrict<anab::T0>(slcTracks, evt,
1499  fParams.CRTHitMatchLabel() + slice_tag_suff);
1500 
1501  // TODO: also save the sbn::crt::CRTTrack in the matching so that CAFMaker has access to it
1502  art::FindManyP<anab::T0> fmCRTTrackMatch =
1503  FindManyPStrict<anab::T0>(slcTracks, evt,
1504  fParams.CRTTrackMatchLabel() + slice_tag_suff);
1505 
1506  std::vector<art::FindManyP<recob::MCSFitResult>> fmMCSs;
1507  static const std::vector<std::string> PIDnames {"muon", "pion", "kaon", "proton"};
1508  for (std::string pid: PIDnames) {
1509  art::InputTag tag(fParams.TrackMCSLabel() + slice_tag_suff, pid);
1510  fmMCSs.push_back(FindManyPStrict<recob::MCSFitResult>(slcTracks, evt, tag));
1511  }
1512 
1513  std::vector<art::FindManyP<sbn::RangeP>> fmRanges;
1514  static const std::vector<std::string> rangePIDnames {"muon", "pion", "proton"};
1515  for (std::string pid: rangePIDnames) {
1516  art::InputTag tag(fParams.TrackRangeLabel() + slice_tag_suff, pid);
1517  fmRanges.push_back(FindManyPStrict<sbn::RangeP>(slcTracks, evt, tag));
1518  }
1519 
1520  // if (slice.IsNoise() || slice.NCell() == 0) continue;
1521  // Because we don't care about the noise slice and slices with no hits.
1522 
1523  // get the primary particle
1524  size_t iPart;
1525  for (iPart = 0; iPart < fmPFPart.size(); ++iPart ) {
1526  const recob::PFParticle &thisParticle = *fmPFPart[iPart];
1527  if (thisParticle.IsPrimary()) break;
1528  }
1529  // primary particle and meta-data
1530  const recob::PFParticle *primary = (iPart == fmPFPart.size()) ? NULL : fmPFPart[iPart].get();
1531  const larpandoraobj::PFParticleMetadata *primary_meta = (iPart == fmPFPart.size()) ? NULL : fmPFPMeta.at(iPart).at(0).get();
1532  // get the flash match
1533  const sbn::SimpleFlashMatch* fmatch = nullptr;
1534  if (fm_sFM.isValid() && primary != NULL) {
1535  std::vector<art::Ptr<sbn::SimpleFlashMatch>> fmatches = fm_sFM.at(iPart);
1536  if (fmatches.size() != 0) {
1537  assert(fmatches.size() == 1);
1538  fmatch = fmatches[0].get();
1539  }
1540  }
1541  // get the primary vertex
1542  const recob::Vertex *vertex = (iPart == fmPFPart.size() || !fmVertex.at(iPart).size()) ? NULL : fmVertex.at(iPart).at(0).get();
1543 
1544  //#######################################################
1545  // Add slice info.
1546  //#######################################################
1547  FillSliceVars(*slice, primary, producer, recslc);
1548  FillSliceMetadata(primary_meta, recslc);
1549  FillSliceFlashMatch(fmatch, recslc);
1550  FillSliceFlashMatchA(fmatch, recslc);
1551  FillSliceVertex(vertex, recslc);
1552  FillSliceCRUMBS(slcCRUMBS, recslc);
1553 
1554  // select slice
1555  if (!SelectSlice(recslc, fParams.CutClearCosmic())) continue;
1556 
1557  // Whether Pandora thinks this slice is a neutrino
1558  //
1559  // This requirement is used to determine whether to save additional
1560  // per-hit information about the slice.
1561  bool NeutrinoSlice = !recslc.is_clear_cosmic;
1562 
1563  // Fill truth info after decision on selection is made
1564  if ( !isRealData ) {
1565  art::ServiceHandle<cheat::ParticleInventoryService> pi_serv;
1566 
1567  FillSliceTruth(slcHits, mctruths, srtruthbranch,
1568  *pi_serv, clock_data, recslc);
1569 
1570  FillSliceFakeReco(slcHits, mctruths, srtruthbranch,
1571  *pi_serv, clock_data, recslc, true_particles, mctracks,
1572  fActiveVolumes, *fFakeRecoTRandom);
1573  }
1574 
1575  //#######################################################
1576  // Add detector dependent slice info.
1577  //#######################################################
1578  // if (fDet == kSBND) {
1579  // rec.sel.contain.nplanestofront = rec.slc.firstplane - (plnfirst - 1);
1580  // rec.sel.contain.nplanestoback = (plnlast) - 1 - rec.slc.lastplane;
1581  // }
1582 
1583  //#######################################################
1584  // Add stub reconstructed objects.
1585  //#######################################################
1586  for (size_t iStub = 0; iStub < fmStubs.size(); iStub++) {
1587  const sbn::Stub &thisStub = *fmStubs[iStub];
1588 
1589  art::Ptr<recob::PFParticle> thisStubPFP;
1590  if (!fmStubPFPs.at(iStub).empty()) thisStubPFP = fmStubPFPs.at(iStub).at(0);
1591 
1592  rec.reco.stub.emplace_back();
1593  FillStubVars(thisStub, thisStubPFP, rec.reco.stub.back());
1594  if ( !isRealData ) FillStubTruth(fmStubHits.at(iStub), id_to_hit_energy_map, true_particles, clock_data, rec.reco.stub.back());
1595  rec.reco.nstub = rec.reco.stub.size();
1596 
1597  // Duplicate stub reco info in the srslice
1598  recslc.reco.stub.push_back(rec.reco.stub.back());
1599  recslc.reco.nstub = recslc.reco.stub.size();
1600  }
1601 
1602  if (fParams.FillHits()) {
1603  for ( size_t iHit = 0; iHit < slcHits.size(); ++iHit ) {
1604  const recob::Hit &thisHit = *slcHits[iHit];
1605 
1606  std::vector<art::Ptr<recob::PFParticle>> thisParticle;
1607  if (fmSpacePointPFPs.isValid()) {
1608  thisParticle = fmSpacePointPFPs.at(iHit);
1609  }
1610  std::vector<art::Ptr<recob::SpacePoint>> thisPoint;
1611  if (fmSpacePoint.isValid()) {
1612  thisPoint = fmSpacePoint.at(iHit);
1613  }
1614  if (!thisParticle.empty() && !thisPoint.empty()) {
1615  assert(thisParticle.size() == 1);
1616  assert(thisPoint.size() == 1);
1617  rec.reco.nhit++;
1618  rec.reco.hit.push_back(SRHit());
1619 
1620  FillHitVars(thisHit, producer, *thisPoint[0], *thisParticle[0], rec.reco.hit.back());
1621  recslc.reco.hit.push_back(rec.reco.hit.back());
1622  recslc.reco.nhit = recslc.reco.hit.size();
1623  }
1624  }
1625  }
1626 
1627  //#######################################################
1628  // Add track/shower reconstructed objects.
1629  //#######################################################
1630  // Reco objects have assns to the slice PFParticles
1631  // This depends on the findMany object created above.
1632  for ( size_t iPart = 0; iPart < fmPFPart.size(); ++iPart ) {
1633  const recob::PFParticle &thisParticle = *fmPFPart[iPart];
1634 
1635  std::vector<art::Ptr<recob::Track>> thisTrack;
1636  if (fmTrack.isValid()) {
1637  thisTrack = fmTrack.at(iPart);
1638  }
1639  std::vector<art::Ptr<recob::Shower>> thisShower;
1640  if (fmShower.isValid()) {
1641  thisShower = fmShower.at(iPart);
1642  }
1643  if (!thisTrack.empty()) { // it's a track!
1644  assert(thisTrack.size() == 1);
1645  assert(thisShower.size() == 0);
1646  rec.reco.ntrk ++;
1647  rec.reco.trk.push_back(SRTrack());
1648 
1649  // collect all the stuff
1650  std::array<std::vector<art::Ptr<recob::MCSFitResult>>, 4> trajectoryMCS;
1651  for (unsigned index = 0; index < 4; index++) {
1652  if (fmMCSs[index].isValid()) {
1653  trajectoryMCS[index] = fmMCSs[index].at(iPart);
1654  }
1655  else {
1656  trajectoryMCS[index] = std::vector<art::Ptr<recob::MCSFitResult>>();
1657  }
1658  }
1659 
1660  std::array<std::vector<art::Ptr<sbn::RangeP>>, 3> rangePs;
1661  for (unsigned index = 0; index < 3; index++) {
1662  if (fmRanges[index].isValid()) {
1663  rangePs[index] = fmRanges[index].at(iPart);
1664  }
1665  else {
1666  rangePs[index] = std::vector<art::Ptr<sbn::RangeP>>();
1667  }
1668  }
1669 
1670 
1671  // fill all the stuff
1672  FillTrackVars(*thisTrack[0], producer, rec.reco.trk.back());
1673  FillTrackMCS(*thisTrack[0], trajectoryMCS, rec.reco.trk.back());
1674  FillTrackRangeP(*thisTrack[0], rangePs, rec.reco.trk.back());
1675 
1676  const larpandoraobj::PFParticleMetadata *pfpMeta = (fmPFPMeta.at(iPart).empty()) ? NULL : fmPFPMeta.at(iPart).at(0).get();
1677  FillPFPVars(thisParticle, primary, pfpMeta, rec.reco.trk.back().pfp);
1678 
1679  if (fmChi2PID.isValid()) {
1680  FillTrackChi2PID(fmChi2PID.at(iPart), lar::providerFrom<geo::Geometry>(), rec.reco.trk.back());
1681  }
1682  if (fmScatterClosestApproach.isValid() && fmScatterClosestApproach.at(iPart).size()==1) {
1683  FillTrackScatterClosestApproach(fmScatterClosestApproach.at(iPart).front(), rec.reco.trk.back());
1684  }
1685  if (fmStoppingChi2Fit.isValid() && fmStoppingChi2Fit.at(iPart).size()==1) {
1686  FillTrackStoppingChi2Fit(fmStoppingChi2Fit.at(iPart).front(), rec.reco.trk.back());
1687  }
1688  if (fmTrackDazzle.isValid() && fmTrackDazzle.at(iPart).size()==1) {
1689  FillTrackDazzle(fmTrackDazzle.at(iPart).front(), rec.reco.trk.back());
1690  }
1691  if (fmCalo.isValid()) {
1692  FillTrackCalo(fmCalo.at(iPart), fmTrackHit.at(iPart),
1693  (fParams.FillHitsNeutrinoSlices() && NeutrinoSlice) || fParams.FillHitsAllSlices(),
1694  fParams.TrackHitFillRRStartCut(), fParams.TrackHitFillRREndCut(),
1695  lar::providerFrom<geo::Geometry>(), dprop, rec.reco.trk.back());
1696  }
1697  if (fmTrackHit.isValid()) {
1698  if ( !isRealData ) FillTrackTruth(fmTrackHit.at(iPart), id_to_hit_energy_map, true_particles, clock_data, rec.reco.trk.back());
1699  }
1700  // NOTE: SEE TODO's AT fmCRTHitMatch and fmCRTTrackMatch
1701  if (fmCRTHitMatch.isValid()) {
1702  FillTrackCRTHit(fmCRTHitMatch.at(iPart), rec.reco.trk.back());
1703  }
1704  if (fmCRTTrackMatch.isValid()) {
1705  FillTrackCRTTrack(fmCRTTrackMatch.at(iPart), rec.reco.trk.back());
1706  }
1707  // Duplicate track reco info in the srslice
1708  recslc.reco.trk.push_back(rec.reco.trk.back());
1709  recslc.reco.ntrk = recslc.reco.trk.size();
1710  } // thisTrack exists
1711 
1712  else if (!thisShower.empty()) { // it's a shower!
1713  assert(thisTrack.size() == 0);
1714  assert(thisShower.size() == 1);
1715  rec.reco.nshw ++;
1716  rec.reco.shw.push_back(SRShower());
1717  FillShowerVars(*thisShower[0], vertex, fmShowerHit.at(iPart), lar::providerFrom<geo::Geometry>(), producer, rec.reco.shw.back());
1718 
1719  const larpandoraobj::PFParticleMetadata *pfpMeta = (iPart == fmPFPart.size()) ? NULL : fmPFPMeta.at(iPart).at(0).get();
1720  FillPFPVars(thisParticle, primary, pfpMeta, rec.reco.shw.back().pfp);
1721 
1722  // We may have many residuals per shower depending on how many showers ar in the slice
1723 
1724  if (fmShowerRazzle.isValid() && fmShowerRazzle.at(iPart).size()==1) {
1725  FillShowerRazzle(fmShowerRazzle.at(iPart).front(), rec.reco.shw.back());
1726  }
1727  if (fmShowerCosmicDist.isValid() && fmShowerCosmicDist.at(iPart).size() != 0) {
1728  FillShowerCosmicDist(fmShowerCosmicDist.at(iPart), rec.reco.shw.back());
1729  }
1730  if (fmShowerResiduals.isValid() && fmShowerResiduals.at(iPart).size() != 0) {
1731  FillShowerResiduals(fmShowerResiduals.at(iPart), rec.reco.shw.back());
1732  }
1733  if (fmShowerTrackFit.isValid() && fmShowerTrackFit.at(iPart).size() == 1) {
1734  FillShowerTrackFit(*fmShowerTrackFit.at(iPart).front(), rec.reco.shw.back());
1735  }
1736  if (fmShowerDensityFit.isValid() && fmShowerDensityFit.at(iPart).size() == 1) {
1737  FillShowerDensityFit(*fmShowerDensityFit.at(iPart).front(), rec.reco.shw.back());
1738  }
1739  if (fmShowerHit.isValid()) {
1740  if ( !isRealData ) FillShowerTruth(fmShowerHit.at(iPart), id_to_hit_energy_map, true_particles, clock_data, rec.reco.shw.back());
1741  }
1742  // Duplicate track reco info in the srslice
1743  recslc.reco.shw.push_back(rec.reco.shw.back());
1744  recslc.reco.nshw = recslc.reco.shw.size();
1745 
1746  } // thisShower exists
1747 
1748  else {}
1749 
1750  }// end for pfparts
1751 
1752 
1753 
1754  //#######################################################
1755  // Fill slice in rec tree
1756  //#######################################################
1757 
1758  // // Set mc branch values to default
1759  // rec.mc.setDefault();
1760  // if (fParams.EnableBlindness()) BlindThisRecord(&rec);
1761  //util::CreateAssn(*this, evt, *srcol, art::Ptr<recob::Slice>(slices, sliceID),
1762  // *srAssn);
1763 
1764  rec.slc.push_back(recslc);
1765 
1766  } // end loop over slices
1767 
1768  //#######################################################
1769  // Fill rec Tree
1770  //#######################################################
1771  rec.nslc = rec.slc.size();
1772  rec.mc = srtruthbranch;
1773  rec.fake_reco = srfakereco;
1774  rec.nfake_reco = srfakereco.size();
1775  rec.pass_flashtrig = pass_flash_trig; // trigger result
1776  rec.crt_hits = srcrthits;
1777  rec.ncrt_hits = srcrthits.size();
1778  rec.crt_tracks = srcrttracks;
1779  rec.ncrt_tracks = srcrttracks.size();
1780  rec.opflashes = srflashes;
1781  rec.nopflashes = srflashes.size();
1782  if (fParams.FillTrueParticles()) {
1783  rec.true_particles = true_particles;
1784  }
1785  rec.ntrue_particles = true_particles.size();
1786 
1787  // Get metadata information for header
1788  unsigned int run = evt.run();
1789  unsigned int subrun = evt.subRun();
1790  unsigned int evtID = evt.event();
1791  // unsigned int spillNum = evt.id().event();
1792 
1793  rec.hdr = SRHeader();
1794 
1795  // Get the Process and Cluser number
1796  const char *process_str = std::getenv("PROCESS");
1797  if (process_str) {
1798  try {
1799  rec.hdr.proc = std::stoi(process_str);
1800  }
1801  catch (...) {}
1802  }
1803 
1804  const char *cluster_str = std::getenv("CLUSTER");
1805  if (cluster_str) {
1806  try {
1807  rec.hdr.cluster = std::stoi(cluster_str);
1808  }
1809  catch (...) {}
1810  }
1811 
1812  rec.hdr.run = run;
1813  rec.hdr.subrun = subrun;
1814  rec.hdr.evt = evtID;
1815  // rec.hdr.subevt = sliceID;
1816  rec.hdr.ismc = !isRealData;
1817  rec.hdr.det = fDet;
1818  rec.hdr.fno = fFileNumber;
1819  if(fFirstInFile)
1820  {
1821  rec.hdr.nbnbinfo = fBNBInfo.size();
1822  rec.hdr.bnbinfo = fBNBInfo;
1823  rec.hdr.nnumiinfo = fNuMIInfo.size();
1824  rec.hdr.numiinfo = fNuMIInfo;
1825  rec.hdr.pot = fSubRunPOT;
1826  }
1827 
1828  rec.hdr.ngenevt = n_gen_evt;
1829  rec.hdr.mctype = mctype;
1830  rec.hdr.first_in_file = fFirstInFile;
1831  rec.hdr.first_in_subrun = fFirstInSubRun;
1832  rec.hdr.triggerinfo = fSRTrigger;
1833  rec.hdr.ntriggerinfo = fSRTrigger.size();
1834  // rec.hdr.cycle = fCycle;
1835  // rec.hdr.batch = fBatch;
1836  // rec.hdr.blind = 0;
1837  // rec.hdr.filt = rb::IsFiltered(evt, slices, sliceID);
1838 
1839 
1840  if(fRecTree){
1841  // Save the standard-record
1842  StandardRecord* prec = &rec;
1843  fRecTree->SetBranchAddress("rec", &prec);
1844  fRecTree->Fill();
1845 
1846  if(fFlatTree){
1847  fFlatRecord->Clear();
1848  fFlatRecord->Fill(rec);
1849  fFlatTree->Fill();
1850  }
1851 
1852  //Generate random number to decide if event is saved in prescale or blinded file
1853  if (fParams.CreateBlindedCAF()) {
1854  const bool keepprescale = fBlindTRandom->Uniform() < 1/fParams.PrescaleFactor();
1855  rec.hdr.evt = 0;
1856  if (keepprescale) {
1857  StandardRecord* precp = new StandardRecord (*prec);
1858  if (fFirstPrescaleInFile) {
1859  precp->hdr.pot = fSubRunPOT*(1/fParams.PrescaleFactor());
1860  precp->hdr.first_in_file = true;
1861  precp->hdr.first_in_subrun = true;
1862  precp->hdr.nbnbinfo = fBNBInfo.size()*(1/fParams.PrescaleFactor());
1863  precp->hdr.nnumiinfo = fNuMIInfo.size()*(1/fParams.PrescaleFactor());
1864  }
1865  precp->hdr.ngenevt = n_gen_evt*(1/fParams.PrescaleFactor());
1866  precp->hdr.evt = evtID;
1867  fRecTreep->SetBranchAddress("rec", &precp);
1868  fRecTreep->Fill();
1869  fPrescaleEvents += 1;
1870  if (fFlatTree) {
1871  fFlatRecordp->Clear();
1872  fFlatRecordp->Fill(*precp);
1873  fFlatTreep->Fill();
1874  }
1875  fFirstPrescaleInFile = false;
1876  }
1877  else {
1878  StandardRecord* precb = new StandardRecord (*prec);
1879  BlindEnergyParameters(precb);
1880  if (fFirstBlindInFile) {
1881  precb->hdr.pot = fSubRunPOT*(1-(1/fParams.PrescaleFactor()))*GetBlindPOTScale();
1882  precb->hdr.first_in_file = true;
1883  precb->hdr.first_in_subrun = true;
1884  precb->hdr.nbnbinfo = fBNBInfo.size()*(1 - (1/fParams.PrescaleFactor()));
1885  precb->hdr.nnumiinfo = fNuMIInfo.size()*(1-(1/fParams.PrescaleFactor()));
1886  }
1887  precb->hdr.ngenevt = n_gen_evt*(1 - (1/fParams.PrescaleFactor()));
1888  precb->hdr.evt = evtID;
1889  fRecTreeb->SetBranchAddress("rec", &precb);
1890  fRecTreeb->Fill();
1891  fBlindEvents += 1;
1892  if (fFlatTree) {
1893  fFlatRecordb->Clear();
1894  fFlatRecordb->Fill(*precb);
1895  fFlatTreeb->Fill();
1896  }
1897  fFirstBlindInFile = false;
1898  }
1899  }
1900  }
1901 
1902 // reset
1903  fFirstInFile = false;
1904  fFirstInSubRun = false;
1905  srcol->push_back(rec);
1906  evt.put(std::move(srcol));
1907 
1908  fBNBInfo.clear();
1909  fNuMIInfo.clear();
1910  fSRTrigger.clear();
1911  rec.hdr.pot = 0;
1912 }
1913 
1914 void CAFMaker::endSubRun(art::SubRun& sr) {
1915 
1916 }
1917 
1918 //......................................................................
1919  void CAFMaker::AddHistogramsToFile(TFile* outfile,bool isBlindPOT = false, bool isPrescalePOT = false) const
1920 {
1921 
1922  outfile->cd();
1923 
1924  TH1* hPOT = new TH1D("TotalPOT", "TotalPOT;; POT", 1, 0, 1);
1925  TH1* hEvents = new TH1D("TotalEvents", "TotalEvents;; Events", 1, 0, 1);
1926 
1927  if (isBlindPOT) {
1928  hPOT->Fill(0.5,fTotalPOT*(1-(1/fParams.PrescaleFactor()))*GetBlindPOTScale());
1929  }
1930  else if (isPrescalePOT) {
1931  hPOT->Fill(0.5,fTotalPOT*(1/fParams.PrescaleFactor()));
1932  }
1933  else {
1934  hPOT->Fill(0.5,fTotalPOT);
1935  }
1936  hEvents->Fill(0.5,fTotalEvents);
1937 
1938  hPOT->Write();
1939  hEvents->Write();
1940 
1941  if (fParams.CreateBlindedCAF()) {
1942  TH1*hBlindEvents = new TH1D("BlindEvents", "BlindEvents;; Events", 1, 0, 1);
1943  TH1* hPrescaleEvents = new TH1D("PrescaleEvents", "PrescaleEvents;; Events", 1, 0, 1);
1944  hBlindEvents->Fill(0.5, fBlindEvents);
1945  hPrescaleEvents->Fill(0.5, fPrescaleEvents);
1946  hBlindEvents->Write();
1947  hPrescaleEvents->Write();
1948  }
1949 }
1950 
1951 //......................................................................
1953  if (fTotalEvents == 0) {
1954 
1955  std::cerr << "No events processed in this file. Aborting rather than "
1956  "produce an empty CAF."
1957  << std::endl;
1958  // n.b. changed abort() to return so that eny exceptions thrown during startup
1959  // still get printed to the user by art
1960  return;
1961  }
1962 
1963 
1964 
1965  if(fFile){
1967  fRecTree->SetDirectory(fFile);
1968  fFlatTree->SetDirectory(fFlatFile);
1969  if (fParams.CreateBlindedCAF()) {
1970  fRecTreeb->SetDirectory(fFileb);
1971  fRecTreep->SetDirectory(fFilep);
1972  }
1973  if (fParams.CreateBlindedCAF() && fFlatFileb) {
1974  fFlatTreeb->SetDirectory(fFlatFileb);
1975  fFlatTreep->SetDirectory(fFlatFilep);
1976  }
1977 
1978  fFile->cd();
1979  fFile->Write();
1980  if (fParams.CreateBlindedCAF()) {
1981  AddHistogramsToFile(fFileb,true,false);
1982  AddHistogramsToFile(fFilep,false,true);
1983  fFileb->cd();
1984  fFileb->Write();
1985  fFilep->cd();
1986  fFilep->Write();
1987  }
1988 
1989  }
1990 
1991  if(fFlatFile){
1993  fFlatFile->Write();
1994 
1995  if (fParams.CreateBlindedCAF()) {
1996  AddHistogramsToFile(fFlatFileb,true,false);
1997  AddHistogramsToFile(fFlatFilep,false,true);
1998  fFlatFileb->Write();
1999  fFlatFilep->Write();
2000  }
2001  }
2002 
2003  std::map<std::string, std::string> metamap;
2004 
2005  try{
2006  art::ServiceHandle<util::MetadataSBN> meta;
2007 
2008  std::map<std::string, std::string> strs;
2009  std::map<std::string, int> ints;
2010  std::map<std::string, double> doubles;
2011  std::map<std::string, std::string> objs;
2012  meta->GetMetadataMaps(strs, ints, doubles, objs);
2013 
2014  for(auto it: strs) metamap[it.first] = "\""+it.second+"\"";
2015  for(auto it: ints) metamap[it.first] = std::to_string(it.second);
2016  for(auto it: doubles) metamap[it.first] = std::to_string(it.second);
2017  for(auto it: objs) metamap[it.first] = it.second;
2018  }
2019  catch(art::Exception& e){//(art::errors::ServiceNotFound)
2020  // I don't know any way to detect this apart from an exception, unfortunately
2021  std::cout << "\n\nCAFMaker: TFileMetadataSBN service not configured -- this CAF will not have any metadata saved.\n" << std::endl;
2022  }
2023 
2024  if(fFile) AddMetadataToFile(fFile, metamap);
2027  if(fFlatFile) AddMetadataToFile(fFlatFile, metamap);
2030 }
2031 
2032 
2033 } // end namespace caf
2034 DEFINE_ART_MODULE(caf::CAFMaker)
2035 ////////////////////////////////////////////////////////////////////////
void FillHitVars(const recob::Hit &hit, unsigned producer, const recob::SpacePoint &spacepoint, const recob::PFParticle &particle, caf::SRHit &srhit, bool allowEmpty)
Definition: FillReco.cxx:738
void FillSliceVertex(const recob::Vertex *vertex, caf::SRSlice &slice, bool allowEmpty)
Definition: FillReco.cxx:334
unsigned int fno
Index of file processed by CAFMaker.
Definition: SRHeader.h:31
Det_t det
Detector, SBND=1 ICARUS=2.
Definition: SRHeader.h:35
process_name vertex
Definition: cheaterreco.fcl:51
int ncrt_tracks
Number of CRT tracks in event.
Unknown detector.
Definition: SREnums.h:9
void FillCRTHit(const sbn::crt::CRTHit &hit, uint64_t gate_start_timestamp, bool use_ts0, caf::SRCRTHit &srhit, bool allowEmpty)
Definition: FillReco.cxx:63
Atom< string > UnblindFileExtension
void FillShowerRazzle(const art::Ptr< sbn::MVAPID > razzle, caf::SRShower &srshower, bool allowEmpty)
Definition: FillReco.cxx:226
void BlindEnergyParameters(StandardRecord *brec)
Det_t
Which SBN detector?
Definition: SREnums.h:7
std::map< int, std::vector< std::pair< geo::WireID, const sim::IDE * > > > PrepSimChannels(const std::vector< art::Ptr< sim::SimChannel >> &simchannels, const geo::GeometryCore &geo)
Definition: FillTrue.cxx:685
std::map< std::string, std::vector< sbn::evwgh::EventWeightParameterSet > > fPrevWeightPSet
Map from parameter labels to previously seen parameter set configuration.
Atom< string > FileExtension
Atom< bool > StrictMode
void FillTrackCRTHit(const std::vector< art::Ptr< anab::T0 >> &t0match, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:379
size_t nnumiinfo
Number of NuMIInfo objects.
Definition: SRHeader.h:43
std::vector< caf::SRBNBInfo > bnbinfo
storing beam information per subrun
Definition: SRHeader.h:42
A 3-vector with more efficient storage than TVector3.
Definition: SRVector3D.h:16
Utilities related to art service access.
void FillShowerResiduals(const std::vector< art::Ptr< float > > &residuals, caf::SRShower &srshower)
Definition: FillReco.cxx:247
SRHeader hdr
Header branch: run, subrun, etc.
unsigned int subrun
subrun number
Definition: SRHeader.h:25
Atom< string > PrescaleFileExtension
std::vector< caf::SRNuMIInfo > fNuMIInfo
Store detailed NuMI info to save into the first StandardRecord of the output file.
std::vector< SRMeVPrtl > prtl
If present – information on decay of MeV &quot;Portal&quot; particle.
Definition: SRTruthBranch.h:24
void FillSliceVars(const recob::Slice &slice, const recob::PFParticle *primary, unsigned producer, caf::SRSlice &srslice, bool allowEmpty)
Definition: FillReco.cxx:269
int nfake_reco
Number of Fake-Reco&#39;s in list.
const geo::GeometryCore * geometry
std::string DeriveFilename(const std::string &inname, const std::string &ext) const
BEGIN_PROLOG could also be cerr
void FillTrackRangeP(const recob::Track &track, const std::array< std::vector< art::Ptr< sbn::RangeP >>, 3 > &range_results, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:456
void FillTrueNeutrino(const art::Ptr< simb::MCTruth > mctruth, const simb::MCFlux &mcflux, const simb::GTruth &gtruth, const std::vector< caf::SRTrueParticle > &srparticles, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &id_to_truehit_map, caf::SRTrueInteraction &srneutrino, size_t i, const std::vector< geo::BoxBoundedGeo > &active_volumes)
Definition: FillTrue.cxx:258
void InitVolumes()
Initialize volumes from Gemotry service.
std::vector< caf::SRBNBInfo > fBNBInfo
Store detailed BNB info to save into the first StandardRecord of the output file. ...
void FillStubTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRStub &srstub, bool allowEmpty)
Definition: FillTrue.cxx:147
TRandom * fFakeRecoTRandom
virtual ~CAFMaker()
Far Detector.
Definition: SREnums.h:11
The SRTrueInteraction is a representation of neutrino interaction information.
int nslc
Number of slices in list.
std::string fFlatCafFilename
static bool sortRBTrkLength(const art::Ptr< recob::Track > &a, const art::Ptr< recob::Track > &b)
Module to create Common Analysis Files from ART files.
std::vector< SRShower > shw
Vector of trac showers.
std::vector< SRHit > hit
Vector of hits.
void GetByLabelIfExists(const art::Event &evt, const std::string &label, art::Handle< T > &handle) const
void FillShowerDensityFit(const sbn::ShowerDensityFit &densityFit, caf::SRShower &srshower)
Definition: FillReco.cxx:262
pdgs p
Definition: selectors.fcl:22
SRVector3D vertex
Candidate neutrino vertex in local detector coordinates [cm].
Definition: SRSlice.h:34
Geometry information for a single TPC.
Definition: TPCGeo.h:38
std::vector< caf::SRTrigger > triggerinfo
storing trigger information per event
Definition: SRHeader.h:46
virtual void endSubRun(art::SubRun &sr)
Atom< string > BlindFileExtension
geo::BoxBoundedGeo const & ActiveBoundingBox() const
Returns the box of the active volume of this TPC.
Definition: TPCGeo.h:320
unsigned int run
run number
Definition: SRHeader.h:24
Atom< std::string > DetectorOverride
SRTrueInteraction truth
Truth information on the slice.
Definition: SRSlice.h:36
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
std::vector< SRSlice > slc
Slice branch.
void FillTrackCalo(const std::vector< art::Ptr< anab::Calorimetry >> &calos, const std::vector< art::Ptr< recob::Hit >> &hits, bool fill_calo_points, float fillhit_rrstart, float fillhit_rrend, const geo::GeometryCore *geom, const detinfo::DetectorPropertiesData &dprop, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:630
void FillTrackScatterClosestApproach(const art::Ptr< sbn::ScatterClosestApproach > closestapproach, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:599
bool first_in_file
Whether this event is there first in the input file.
Definition: SRHeader.h:37
flat::Flat< caf::StandardRecord > * fFlatRecord
bool ismc
data or MC? True if MC
Definition: SRHeader.h:30
void FillShowerVars(const recob::Shower &shower, const recob::Vertex *vertex, const std::vector< art::Ptr< recob::Hit >> &hits, const geo::GeometryCore *geom, unsigned producer, caf::SRShower &srshower, bool allowEmpty)
Definition: FillReco.cxx:161
void FillStubVars(const sbn::Stub &stub, const art::Ptr< recob::PFParticle > stubpfp, caf::SRStub &srstub, bool allowEmpty)
Definition: FillReco.cxx:19
Atom< int > POTBlindSeed
size_t nshw
Number of trac showers.
std::string fCafFilename
void FillSliceTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srmc, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData, caf::SRSlice &srslice, bool allowEmpty)
Definition: FillTrue.cxx:160
Atom< bool > CreateCAF
SRShowerPlaneInfo plane[3]
Definition: SRShower.h:40
void FillExposure(const std::vector< sbn::BNBSpillInfo > &bnb_spill_info, std::vector< caf::SRBNBInfo > &BNBInfo, double &subRunPOT)
Atom< string > GenLabel
art::EDProducer::Table< CAFMakerParams > Parameters
void FillSliceFlashMatchA(const sbn::SimpleFlashMatch *fmatch, caf::SRSlice &srslice, bool allowEmpty)
Definition of vertex object for LArSoft.
Definition: Vertex.h:35
MCType_t
Which type of MC?
Definition: SREnums.h:34
Det_t fDet
Detector ID in caf namespace typedef.
art::FindManyP< T > FindManyPStrict(const U &from, const art::Event &evt, const art::InputTag &label) const
BEGIN_PROLOG TPC
flat::Flat< caf::StandardRecord > * fFlatRecordb
Representation of a rb::Hit, knows hit amplitude and integral, geometric IDs, and time...
Definition: SRHit.h:27
size_t nprtl
Number of portals.
Definition: SRTruthBranch.h:25
std::map< int, caf::HitsEnergy > SetupIDHitEnergyMap(const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
Definition: FillTrue.cxx:657
void FillTrackCRTTrack(const std::vector< art::Ptr< anab::T0 >> &t0match, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:399
void InitializeOutfiles()
unsigned int evt
ART event number, indexes trigger windows.
Definition: SRHeader.h:28
Math::BigFloat precision(-16)
TPC_iterator begin_TPC() const
Returns an iterator pointing to the first TPC in the detector.
int ncrt_hits
Number of CRT hits in event.
Atom< string > FlatCAFFileExtension
process_name gaushit a
bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic)
Definition: FillReco.cxx:14
MCType_t mctype
Type of Monte Carlo used to generate this record.
Definition: SRHeader.h:34
std::string fFlatCafPrescaleFilename
std::string GDMLFile() const
Returns the full directory path to the GDML file source.
size_t ntriggerinfo
Number of Trigger objects.
Definition: SRHeader.h:45
T abs(T value)
std::vector< SRTrueInteraction > nu
Vector of true nu or cosmic.
Definition: SRTruthBranch.h:21
ReweightType fRWType
Type of throws (the same for all parameters in a set)
void FillTrackVars(const recob::Track &track, unsigned producer, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:668
size_t nhit
Number of hits.
std::vector< SROpFlash > opflashes
List of OpFlashes in spill.
bool GetPsetParameter(const fhicl::ParameterSet &pset, const std::vector< std::string > &name, T &ret) const
void FillShowerTrackFit(const sbn::ShowerTrackFit &trackFit, caf::SRShower &srshower)
Definition: FillReco.cxx:255
void FillSliceCRUMBS(const sbn::CRUMBSResult *crumbs, caf::SRSlice &slice, bool allowEmpty)
Definition: FillReco.cxx:345
void FillTrackChi2PID(const std::vector< art::Ptr< anab::ParticleID >> particleIDs, const geo::GeometryCore *geom, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:518
void FillSliceFlashMatch(const sbn::SimpleFlashMatch *fmatch, caf::SRSlice &srslice, bool allowEmpty)
void FillShowerTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRShower &srshower, bool allowEmpty)
Definition: FillTrue.cxx:134
Metadata associated to PFParticles.
std::string fCafBlindFilename
Additional information on trigger.
size_t nstub
Number of stubs.
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
bool first_in_subrun
Whether this event is the first in the subrun.
Definition: SRHeader.h:36
Atom< float > PrescaleFactor
float fwdP_muon
Momentum from start-&gt;end fit for muon [GeV/c].
Definition: SRTrkMCS.h:18
bool is_clear_cosmic
Whether pandora marks the slice as a &quot;clear&quot; cosmic.
Definition: SRSlice.h:46
virtual void beginRun(art::Run &r)
std::vector< SRCRTHit > crt_hits
CRT hits in event.
float pot
POT of the subrun associated with this record.
Definition: SRHeader.h:33
Container for a set of reweightable parameters.
Atom< bool > CreateFlatCAF
size_t ntrk
Number of panora tracks.
unsigned int ngenevt
Number of events generated in input file associated with this record (before any filters) ...
Definition: SRHeader.h:32
SRSliceRecoBranch reco
TPC reco information for the slice.
Definition: SRSlice.h:56
std::vector< SRTrueParticle > true_particles
True particles in spill.
SRVector3D start
Start point of track.
Definition: SRTrack.h:43
SRTrkMCS mcsP
Definition: SRTrack.h:51
void FillTrackStoppingChi2Fit(const art::Ptr< sbn::StoppingChi2Fit > stoppingChi2, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:608
std::vector< SRTrack > trk
Vector of pandora tracks.
std::map< EventWeightParameter, std::vector< float > > fParameterMap
Mapping of definitions to the set of values.
void respondToOpenInputFile(const art::FileBlock &fb)
bool IsPrimary() const
Returns whether the particle is the root of the flow.
Definition: PFParticle.h:86
void FillFakeReco(const std::vector< art::Ptr< simb::MCTruth >> &mctruths, const std::vector< caf::SRTrueParticle > &srparticles, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, std::vector< caf::SRFakeReco > &srfakereco)
Definition: FillTrue.cxx:636
void AddMetadataToFile(TFile *f, const std::map< std::string, std::string > &metadata)
void FillMeVPrtlTruth(const evgen::ldm::MeVPrtlTruth &truth, const std::vector< geo::BoxBoundedGeo > &active_volumes, caf::SRMeVPrtl &srtruth)
Definition: FillTrue.cxx:182
void AddEnvToFile(TFile *f)
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch fmatch
Definition: reco_sbnd.fcl:182
bool pass_flashtrig
Whether this Record passed the Flash Trigger requirement.
Description of geometry of one entire detector.
SRVector3D start
shower start point in detector coordinates [cm]
Definition: SRShower.h:42
An SRSlice contains overarching information for a slice.
Definition: SRSlice.h:24
void FillCRTTrack(const sbn::crt::CRTTrack &track, bool use_ts0, caf::SRCRTTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:86
std::vector< SRCRTTrack > crt_tracks
CRT tracks in event.
Atom< string > BNBPOTDataLabel
double GetBlindPOTScale() const
TRandom * fBlindTRandom
Provides recob::Track data product.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
void FillTrueG4Particle(const simb::MCParticle &particle, const std::vector< geo::BoxBoundedGeo > &active_volumes, const std::vector< std::vector< geo::BoxBoundedGeo >> &tpc_volumes, const std::map< int, std::vector< std::pair< geo::WireID, const sim::IDE * >>> &id_to_ide_map, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &id_to_truehit_map, const cheat::BackTrackerService &backtracker, const cheat::ParticleInventoryService &inventory_service, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, caf::SRTrueParticle &srparticle)
Definition: FillTrue.cxx:434
void FillOpFlash(const recob::OpFlash &flash, int cryo, caf::SROpFlash &srflash, bool allowEmpty)
Definition: FillReco.cxx:114
float p_muon
momentum estimate from trk range (muon hypothesis)
Definition: SRTrkRange.h:17
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
int ntrue_particles
Number of true particles in list.
CAFMaker(const Parameters &params)
void AddHistogramsToFile(TFile *outfile, bool isBlindPOT, bool isPrescalePOT) const
void FillSliceMetadata(const larpandoraobj::PFParticleMetadata *primary_meta, caf::SRSlice &srslice, bool allowEmpty)
Definition: FillReco.cxx:292
The StandardRecord is the primary top-level object in the Common Analysis File trees.
std::ostream & operator<<(std::ostream &os, const sbn::evwgh::EventWeightParameterSet &p)
Atom< string > NuMIPOTDataLabel
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
BEGIN_PROLOG triggeremu_data_config_icarus settings PMTADCthresholds sequence::icarus_stage0_multiTPC_TPC physics sequence::icarus_stage0_EastHits_TPC physics sequence::icarus_stage0_WestHits_TPC physics producers purityana0 module_type
bool GetAssociatedProduct(const art::FindManyP< T > &fm, int idx, T &ret) const
Retrieve an object from an association, with error handling.
int prec
std::vector< std::vector< geo::BoxBoundedGeo > > fTPCVolumes
void FillTrackTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillTrue.cxx:118
void FillSliceFakeReco(const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srmc, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData, caf::SRSlice &srslice, const std::vector< caf::SRTrueParticle > &srparticles, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand)
Definition: FillTrue.cxx:238
void produce(art::Event &evt) noexcept
std::vector< SRFakeReco > fake_reco
List of fake-reco slices.
CAFMakerParams fParams
art::FindManyP< T, D > FindManyPDStrict(const U &from, const art::Event &evt, const art::InputTag &tag) const
void FillPFPVars(const recob::PFParticle &particle, const recob::PFParticle *primary, const larpandoraobj::PFParticleMetadata *pfpMeta, caf::SRPFP &srpfp, bool allowEmpty)
Definition: FillReco.cxx:698
void FillTrackDazzle(const art::Ptr< sbn::MVAPID > dazzle, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:617
size_t nnu
Number of true nu or cosmic.
Definition: SRTruthBranch.h:22
std::string to_string(WindowPattern const &pattern)
Header representing overview information for the current event/slice.
Definition: SRHeader.h:18
std::map< int, std::vector< art::Ptr< recob::Hit > > > PrepTrueHits(const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
Definition: FillTrue.cxx:674
SRSliceRecoBranch reco
Slice reco branch: tracks, showers, etc.
void FillTrigger(const sbn::ExtraTriggerInfo &addltrig_info, const std::vector< raw::Trigger > &trig_info, std::vector< caf::SRTrigger > &triggerInfo)
Definition: FillTrigger.cxx:6
void FillShowerCosmicDist(const std::vector< art::Ptr< float > > &cosmicDistVec, caf::SRShower &srshower)
Definition: FillReco.cxx:239
Vectors of reconstructed vertices found by various algorithms.
Definition: SRTruthBranch.h:15
SRTrkRange rangeP
Definition: SRTrack.h:52
do i e
std::vector< geo::BoxBoundedGeo > fActiveVolumes
float bestplane_energy
shower energy at best plane [GeV]
Definition: SRShower.h:35
size_t nbnbinfo
Number of BNBInfo objects.
Definition: SRHeader.h:41
std::string fName
Name of the parameter set.
void AddGlobalTreeToFile(TFile *outfile, caf::SRGlobal &global) const
SRTruthBranch mc
Truth branch for all interactions.
Near Detector.
Definition: SREnums.h:10
then echo fcl name
Data product holding additional trigger information.
temporary value
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
Atom< bool > CreateBlindedCAF
void FillExposureNuMI(const std::vector< sbn::NuMISpillInfo > &numi_spill_info, std::vector< caf::SRNuMIInfo > &NuMIInfo, double &subRunPOT)
TCEvent evt
Definition: DataStructs.cxx:8
art::FindOneP< T > FindOnePStrict(const U &from, const art::Event &evt, const art::InputTag &label) const
std::vector< caf::SRNuMIInfo > numiinfo
storing beam information per subrun
Definition: SRHeader.h:44
std::vector< caf::SRTrigger > fSRTrigger
Store trigger and beam gate information.
Definition: Stub.h:16
virtual void beginSubRun(art::SubRun &sr)
Forward iterator browsing all geometry elements in the detector.
Definition: GeometryCore.h:727
float energy
shower calculated energy for this plane [GeV]
Definition: SRShower.h:21
void FillEventWeight(const sbn::evwgh::EventWeightMap &wgtmap, caf::SRTrueInteraction &srint, const std::map< std::string, unsigned int > &weightPSetIndex)
Definition: FillTrue.cxx:414
int nopflashes
Number of OpFlashes in spill.
esac echo uname r
std::string fFlatCafBlindFilename
void FillSRGlobal(const sbn::evwgh::EventWeightParameterSet &pset, caf::SRGlobal &srglobal, std::map< std::string, unsigned int > &weightPSetIndex)
Definition: FillTrue.cxx:89
static bool EssentiallyEqual(double a, double b, double precision=0.0001)
void GetByLabelStrict(const EvtT &evt, const std::string &label, art::Handle< T > &handle) const
Sequence< std::string > SystWeightLabels
std::string fCafPrescaleFilename
flat::Flat< caf::StandardRecord > * fFlatRecordp
BEGIN_PROLOG could also be cout
std::vector< SRStub > stub
Vector of stubs.
TPC_iterator end_TPC() const
Returns an iterator pointing after the last TPC in the detector.
std::map< std::string, unsigned int > fWeightPSetIndex
What position in the vector each parameter set take.
void FillTrackMCS(const recob::Track &track, const std::array< std::vector< art::Ptr< recob::MCSFitResult >>, 4 > &mcs_results, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillReco.cxx:413