ProtoDUNEBeam_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: ProtoDUNEBeam
3 // Module Type: producer
4 // File: ProtoDUNEBeam_module.cc
5 //
6 // Generated at Thu Nov 17 11:20:31 2016 by Leigh Howard Whitehead,42 3-039,+41227672470, using artmod
7 // from cetpkgsupport v1_11_00.
8 ////////////////////////////////////////////////////////////////////////
9 // Modified by Caroline Zhang with inputs from Karl Wharburton
10 // August 2017 for beam simulation storage
11 // Email: carolineligezhang@gmail.com
12 ////////////////////////////////////////////////////////////////////////
13 // Modified by Pablo and Leigh H. Whitehead
14 // July 2018 for redoing beam simulation storage and definition of
15 // absent Cherenkov detectors
16 // Email: pablo.fer@cern.ch
17 ////////////////////////////////////////////////////////////////////////
18 
27 #include "fhiclcpp/ParameterSet.h"
29 #include "cetlib_except/exception.h"
34 #include <memory>
35 #include <string>
36 #include <map>
37 #include <utility>
38 #include <vector>
39 // Added for ProtoDUNE beam simulation storage
40 //#include "lardataobj/Simulation/ProtoDUNEbeamsim.h"
48 //#include "dunesim/EventGenerator/ProtoDUNEbeamTPCmatching/ProtoDUNEbeammatch.h"
49 //#include "dunesim/EventGenerator/ProtoDUNEbeamTPCmatching/ProtoDUNEBeamToF.h"
51 // art extensions
52 #include "nurandom/RandomUtils/NuRandomService.h"
53 #include "art_root_io/TFileService.h"
54 #include <TFile.h>
55 #include <TTree.h>
56 #include <TVector3.h>
57 #include <TLorentzVector.h>
58 #include <TDatabasePDG.h>
59 #include <TParticlePDG.h>
60 #include "TSystem.h"
61 #include "CLHEP/Random/RandFlat.h"
62 #include "ifdh.h"
63 #include <sys/stat.h>
64 
65 namespace evgen{
66 
67  class ProtoDUNEBeam;
68 
69  class ProtoDUNEBeam : public art::EDProducer {
70  public:
71  explicit ProtoDUNEBeam(fhicl::ParameterSet const & p);
72  // The destructor generated by the compiler is fine for classes
73  // without bare pointers or other resource use.
75 
76  // Plugins should not be copied or assigned.
77  ProtoDUNEBeam(ProtoDUNEBeam const &) = delete;
78  ProtoDUNEBeam(ProtoDUNEBeam &&) = delete;
79  ProtoDUNEBeam & operator = (ProtoDUNEBeam const &) = delete;
81 
82  // Required functions.
83  void produce(art::Event & e) override;
84  void beginJob() override;
85  void beginRun(art::Run& run) override;
86  void endJob() override;
87 
88 
89  // Convenience struct to encapsulate each spill
90  // Contains the good particle and all backgrounds
91  struct ProtoFullSpill {
92 
93  ProtoFullSpill(int event, int track, float time, int id){
94  fGoodEvent = event;
95  fGoodTrack = track;
96  fGoodTime = time;
97  fGoodIndex = id;
98  };
99 
100  // Good particle information
101  int fGoodEvent; // Beam simulation event number
102  int fGoodTrack; // Beam simulation track number
103  float fGoodTime; // Time of beam event
104  int fGoodIndex; // Index of the good particle in the good particle tree
105 
106  // All of the beam events and tracks
107  std::map<int,std::vector<int> > fAllSpillTracks;
108  };
109 
110  private:
111 
112  std::vector<ProtoFullSpill> fAllSpills;
113 
114  // A list of good events and an index for it.
115  unsigned int fCurrentGoodEvent;
116  std::vector<int> fGoodEventList;
117 
118  // Calculate how many overlay events we need.
119  void CalculateNOverlays();
120 
121  // Check if a given beam event is close enough to a good particle event to be useful.
122  int IsOverlayEvent(int event, int nOverlay);
123  std::vector<int> GetAllOverlays(int event, int nOverlay);
124 
125  // Fill the above maps and vector.
126  void FillParticleMaps();
127 
128  // Generate a true event based on a single entry from the input tree.
129  void GenerateTrueEvent(simb::MCTruth &mcTruth, std::vector<sim::ProtoDUNEbeamsim> &beamsimcol, beam::ProtoDUNEBeamEvent & beamEvent);
130 
131  // Handle root files from beam instrumentation group
132  void OpenInputFile();
133 
134  // Generate a TLorentzVector for position making sure we get the
135  // coordinates as we need them.
136  TLorentzVector ConvertCoordinates(float x, float y, float z, float t);
137 
138  // Make the momentum vector, rotating as required.
139  TLorentzVector MakeMomentumVector(float px, float py, float pz, int pdg, bool shifts);
140  TLorentzVector MakeMomentumVector(const TVector3 &mom, int pdg, bool shifts);
141 
142  // We need to rotate the beam monitor coordinates into the detector frame
143  TLorentzVector ConvertBeamMonitorCoordinates(float x, float y, float z, float t, float offset);
144 
145  //New for making tracks
146  TVector3 ConvertProfCoordinates(double x, double y, double z, double zOffset);
147  TVector3 ProjectToTPC(TVector3 firstPoint, TVector3 secondPoint);
148  double GetPosition( short fiber );
149  void MakeTracks( beam::ProtoDUNEBeamEvent & beamEvent );
151  double MomentumCosTheta( double, double, double );
152 
153 
154  TVector3 ConvertBeamMonitorMomentumVec(float px, float py, float pz);
155  // Setup the beam monitor basis vectors in detector coordinates
157  // Apply the rotation
158  void RotateMonitorVector(TVector3 &vec);
159 
160  void SetBeamEvent(beam::ProtoDUNEBeamEvent & beamevt);
161  beam::FBM MakeFiberMonitor( float pos );
162 
163 
164  // Background particles need to be fired from an upstream position
165  TVector3 GetBackgroundPosition(float x, float y, float z, float px, float py, float pz);
166 
167  CLHEP::RandFlat fFlatRnd;
168 
172 
173  // The current event number. Ideally this could be an unsigned int,
174  // but we will need to compare it to some ints later on.
176 
177  // Let the user define the event to start at
179 
180  TFile* fInputFile;
181  // Input file provides a TTree that we need to read.
184 
185  // To make sure we can fire the GoodParticles from the correct place
196 
197  // For the TOF part
198  Float_t fGoodTOF1_x;
199  Float_t fGoodTOF1_y;
200  Float_t fGoodTOF1_z;
201  Float_t fGoodTOF1_t;
202  Float_t fGoodTOF1_Px;
203  Float_t fGoodTOF1_Py;
204  Float_t fGoodTOF1_Pz;
208 
209  //For the TRIG part
210  Float_t fGoodTRIG1_x;
211  Float_t fGoodTRIG1_y;
212  Float_t fGoodTRIG1_z;
213  Float_t fGoodTRIG1_t;
214  Float_t fGoodTRIG1_Px;
215  Float_t fGoodTRIG1_Py;
216  Float_t fGoodTRIG1_Pz;
220 
221  Float_t fGoodTRIG2_x;
222  Float_t fGoodTRIG2_y;
223  Float_t fGoodTRIG2_z;
224  Float_t fGoodTRIG2_t;
225  Float_t fGoodTRIG2_Px;
226  Float_t fGoodTRIG2_Py;
227  Float_t fGoodTRIG2_Pz;
231 
232  //For the BPROF part
233  Float_t fGoodBPROF1_x;
234  Float_t fGoodBPROF1_y;
235  Float_t fGoodBPROF1_z;
236  Float_t fGoodBPROF1_t;
237  Float_t fGoodBPROF1_Px;
238  Float_t fGoodBPROF1_Py;
239  Float_t fGoodBPROF1_Pz;
243 
244  Float_t fGoodBPROF2_x;
245  Float_t fGoodBPROF2_y;
246  Float_t fGoodBPROF2_z;
247  Float_t fGoodBPROF2_t;
248  Float_t fGoodBPROF2_Px;
249  Float_t fGoodBPROF2_Py;
250  Float_t fGoodBPROF2_Pz;
254 
255  Float_t fGoodBPROF3_x;
256  Float_t fGoodBPROF3_y;
257  Float_t fGoodBPROF3_z;
258  Float_t fGoodBPROF3_t;
259  Float_t fGoodBPROF3_Px;
260  Float_t fGoodBPROF3_Py;
261  Float_t fGoodBPROF3_Pz;
265 
266  Float_t fGoodBPROF4_x;
267  Float_t fGoodBPROF4_y;
268  Float_t fGoodBPROF4_z;
269  Float_t fGoodBPROF4_t;
270  Float_t fGoodBPROF4_Px;
271  Float_t fGoodBPROF4_Py;
272  Float_t fGoodBPROF4_Pz;
276 
287 
288  TTree * fRecoTree;
289  float fXBPF697_x;
290  float fXBPF701_x;
291  float fXBPF702_x;
292 
293  float fXBPF697_rx;
294  float fXBPF701_rx;
295  float fXBPF702_rx;
296 
297  float fXBPF697_p;
298  float fXBPF701_p;
299  float fXBPF702_p;
300 
301  float fXBPF697_f;
302  float fXBPF701_f;
303  float fXBPF702_f;
304  float fReco_p;
305 
306  float fReco_tof;
307 
310 
311  float fXBPF716_x;
312  float fXBPF717_y;
313  float fXBPF707_x;
314  float fXBPF708_y;
315 
316  float fXBPF716_rx;
317  float fXBPF717_ry;
318  float fXBPF707_rx;
319  float fXBPF708_ry;
320 
321  float fXBPF716_f;
322  float fXBPF717_f;
323  float fXBPF707_f;
324  float fXBPF708_f;
325 
329 
333 
337 
338  // Members we need to extract from the tree
339  float fX, fY, fZ;
340  float fPx, fPy, fPz;
341  float fPDG; // Input tree has all floats
342 
343  int fTrueID;
344 
345  // Event and TrackID for good particle tree
346 // float fBeamEvent;
347 // float fTrackID;
348 
349  // Same for all particles
350  float fAllEventID;
351  float fAllTrackID;
353 
354  // We need two times: the trigger time, and the time at the entry point
355  // to the TPC where we generate the event.
356  float fEntryT;
357 
358  // Define the coordinate transform from the beam frame to the detector frame
359  float fBeamX;
360  float fBeamY;
361  float fBeamZ;
364  float fRotateXZ;
365  float fRotateYZ;
366  // Rotate the beam monitor coordinate system (those after the last bending magnet)
369  // The three beam monitor basis vectors in the detector coordinate system
370  TVector3 fBMBasisX;
371  TVector3 fBMBasisY;
372  TVector3 fBMBasisZ;
373  // The z positions of the important elements along the beam direction
375  float fBPROF4Pos;
377 
378  // Parameters from the .fcl file to deal with overlaying events
379  float fIntensity; // Number of interactions on the secondary target per SPS spill
380  float fReadoutWindow; // Readout window (needs to match the values used in the simulation) in milliseconds
381  float fBeamSpillLength; // The SPS spill length in seconds
382 
383 // Beam monitors resolutions
387 
388  float fLB;
389 /*
390  float fMagP1;
391  float fMagP3;
392  float fMagP4;
393  float fCurrent;
394 */
395  float fL1;
396  float fL2;
397  float fL3;
398  float fBeamBend;
399 
400  float fLMag;
401  float fNominalP;
402  float fB;
403 
405 
406 
407  // Number of beam interactions to overlay.
409 
410  ifdh_ns::ifdh* fIFDH;
411  };
412 }
413 
414 // Create the random number generator
415 namespace {
416  std::string const instanceName = "protoDUNEBeam";
417 }
418 
419 
420 //---------------------------------------------------------------------------------
421 //----------------------------------------constructors-----------------------------
423  : EDProducer{pset}
424  // now create the engine (for example, use art); seed will be set
425  // by calling declareEngine
426  , fFlatRnd(createEngine(art::ServiceHandle<rndm::NuRandomService>{}->declareEngine(instanceName),
427  "HepJamesRandom", instanceName))
428 {
429  // Call appropriate produces<>() functions here.
430  produces< std::vector<simb::MCTruth> >();
431  produces<std::vector<sim::ProtoDUNEbeamsim>>();
432  produces< sumdata::RunData, art::InRun >();
433  produces< std::vector< beam::ProtoDUNEBeamEvent > >();
434  //produces< art::Assns<sim::ProtoDUNEbeamsim, simb::MCTruth>>();
435  // File reading variable initialisations
436  fFileName = pset.get< std::string>("FileName");
437  fGoodParticleTreeName = pset.get< std::string>("GoodParticleTreeName");
438  fAllParticlesTreeName = pset.get< std::string>("AllParticlesTreeName");
439  std::cout << "All particles tree name = " << fAllParticlesTreeName << std::endl;
440  // Intensity variables
441  fIntensity = pset.get<float>("Intensity");
442  fReadoutWindow = pset.get<float>("ReadoutWindow");
443  fBeamSpillLength = pset.get<float>("BeamSpillLength");
444 
445 // Beam monitors resolutions
446  fT_Resolution = pset.get<float>("T_Resolution");
447  fPos_Resolution = pset.get<float>("Pos_Resolution");
448  fCh_Efficiency = pset.get<float>("Ch_Efficiency");
449 
450  // See if the user wants to start at an event other than zero.
451  fStartEvent = pset.get<int>("StartEvent");
452 
453  // Or maybe there was --nskip specified in the command line or skipEvents in FHiCL?
454  for (auto const & p : fhicl::ParameterSetRegistry::get())
455  {
456  auto const& ps = p.second;
457  if (ps.has_key("source") && ps.has_key("source.skipEvents"))
458  {
459  fStartEvent += ps.get<int>("source.skipEvents");
460  break; // take the first occurence
461  } // no "else", if parameter not found, then just don't change anything
462  }
463  // ...and if there is -e option or firstEvent in FHiCL, this add up to the no. of events to skip.
464  for (auto const & p : fhicl::ParameterSetRegistry::get())
465  {
466  auto const& ps = p.second;
467  if (ps.has_key("source") && ps.has_key("source.firstEvent"))
468  {
469  int fe = ps.get<int>("source.firstEvent") - 1; // events base index is 1
470  if (fe > 0) fStartEvent += fe;
471  break; // take the first occurence
472  } // no "else", if parameter not found, then just don't change anything
473  }
474  mf::LogInfo("ProtoDUNEBeam") << "Skip " << fStartEvent << " first events from the input file.";
475 
476  fEventNumber = 0;
477 
478  // Coordinate transform
479  fBeamX = pset.get<float>("BeamX");
480  fBeamY = pset.get<float>("BeamY");
481  fBeamZ = pset.get<float>("BeamZ");
482  fBeamThetaShift = pset.get<float>("BeamThetaShift",0.0);
483  fBeamPhiShift = pset.get<float>("BeamPhiShift",0.0);
484  fRotateXZ = pset.get<float>("RotateXZ"); // Only use rotation if the above aren't defined
485  fRotateYZ = pset.get<float>("RotateYZ");
486 
487  fRotateMonitorXZ = pset.get<float>("RotateMonitorXZ");
488  fRotateMonitorYZ = pset.get<float>("RotateMonitorYZ");
489  fBPROFEXTPos = pset.get<float>("BPROFEXTPosZ");
490  fBPROF4Pos = pset.get<float>("BPROF4PosZ");
491  fNP04frontPos = pset.get<float>("NP04frontPosZ");
492  // Setup the beam monitor basis vectors
494 
495  // Initialise the input file and tree to be null.
496  fInputFile = 0x0;
497  fGoodParticleTree = 0x0;
498  fAllParticlesTree = 0x0;
499  fIFDH = 0;
500 
501  fCurrentGoodEvent = 0;
502 
503  // For momentum spectrometer
504 /*
505  fCurrent = pset.get<float>("Current");
506  fMagP1 = pset.get<float>("MagP1");
507  fMagP3 = pset.get<float>("MagP3");
508  fMagP4 = pset.get<float>("MagP4");
509 */
510  fL1 = pset.get<float>("L1");
511  fL2 = pset.get<float>("L2");
512  fL3 = pset.get<float>("L3");
513  fBeamBend = pset.get<float>("BeamBend");
514 
515  //New values for momentum spectrometer
516  fLMag = pset.get<float>("LMag");
517  fB = pset.get<float>("B");
518  fNominalP = pset.get<float>("NominalP");
519 
520 
521 /*
522  fLB = fMagP1*fabs(fCurrent);
523  float deltaI = fabs(fCurrent) - fMagP4;
524  if(deltaI>0) fLB += fMagP3*deltaI*deltaI;
525 
526  std::cout << "Old LB: " << fLB << std::endl;
527 */
528  fLB = fB * fLMag * fNominalP / 7.;
529 // std::cout << "New LB: " << fLB << std::endl;
530 
531  fSaveRecoTree = pset.get<bool>("SaveRecoTree");
532 
533 
534  // Make sure we use ifdh to open the beam input file.
535  OpenInputFile();
536 }
537 
538 
539 
540 //-----------------------------default destructor----------------------------------
541 //------------------------------------------------------------------------------------
543 {
544  fIFDH->cleanup();
545 
546 }
547 
548 //-------------------------------------------------------------------------------------
550 
552 
553  fInputFile = new TFile(fFileName.c_str(),"READ");
554  // Check we have the file
555  if(fInputFile == 0x0){
556  throw cet::exception("ProtoDUNEBeam") << "Input file " << fFileName << " cannot be read.\n";
557  }
558 
559  fGoodParticleTree = (TTree*)fInputFile->Get(fGoodParticleTreeName.c_str());
560  // Check we have the tree
561  if(fGoodParticleTree == 0x0){
562  throw cet::exception("ProtoDUNEBeam") << "Input tree " << fGoodParticleTreeName << " cannot be read.\n";
563  }
564 
565  fAllParticlesTree = (TTree*)fInputFile->Get(fAllParticlesTreeName.c_str());
566  // Check we have the tree
567  if(fAllParticlesTree == 0x0){
568  throw cet::exception("ProtoDUNEBeam") << "Input tree " << fAllParticlesTreeName << " cannot be read.\n";
569  }
570  std::cout << "All particle tree " << fAllParticlesTreeName << " has " << fAllParticlesTree->GetEntries() << " entries" << std::endl;
571 
572  // We need different bits of information for different particles.
573  // The GoodParticles should be fired from the detector front (NP04front)
574  // Background particles should be fired from the first monitor after the final bending magnet in order
575  // to ensure those that should hit the CRT will do so (BPROFEXT)
576 
577  // Since this is technically an ntuple, all objects are floats
578  // Position four-vector components
579  fAllParticlesTree->SetBranchAddress("x",&fX);
580  fAllParticlesTree->SetBranchAddress("y",&fY);
581  fAllParticlesTree->SetBranchAddress("z",&fZ);
582  fAllParticlesTree->SetBranchAddress("t",&fEntryT);
583  // Momentum components
584  fAllParticlesTree->SetBranchAddress("Px",&fPx);
585  fAllParticlesTree->SetBranchAddress("Py",&fPy);
586  fAllParticlesTree->SetBranchAddress("Pz",&fPz);
587  // PDG code
588  fAllParticlesTree->SetBranchAddress("PDGid",&fPDG);
589  // Event and track number
590  fAllParticlesTree->SetBranchAddress("EventID",&fAllEventID);
591  fAllParticlesTree->SetBranchAddress("TrackID",&fAllTrackID);
592  fAllParticlesTree->SetBranchAddress("ParentID", &fAllParentID);
593 
594  // We only need the trigger time and event number from the good particle tree.
595  // The good particle tree variable should match the names of the other trees
596  std::string namePrefix = fAllParticlesTreeName.substr(fAllParticlesTreeName.find_last_of("\\/")+1,std::string::npos);
597 
598  std::cout << "Name prefix for good particle tree = " << namePrefix << std::endl;
599 
600 // fGoodParticleTree->SetBranchAddress((namePrefix+"_EventID").c_str(),&fBeamEvent);
601 // fGoodParticleTree->SetBranchAddress((namePrefix+"_TrackID").c_str(),&fTrackID);
602 
603  ////////************added by Caroline for beam simulation storage for good particles ***************//////////////
604  fGoodParticleTree->SetBranchAddress("NP04front_x",&fGoodNP04front_x);
605  fGoodParticleTree->SetBranchAddress("NP04front_y",&fGoodNP04front_y);
606  fGoodParticleTree->SetBranchAddress("NP04front_z",&fGoodNP04front_z);
607  fGoodParticleTree->SetBranchAddress("NP04front_t",&fGoodNP04front_t);
608  fGoodParticleTree->SetBranchAddress("NP04front_Px",&fGoodNP04front_Px);
609  fGoodParticleTree->SetBranchAddress("NP04front_Py",&fGoodNP04front_Py);
610  fGoodParticleTree->SetBranchAddress("NP04front_Pz",&fGoodNP04front_Pz);
611  fGoodParticleTree->SetBranchAddress("NP04front_PDGid",&fGoodNP04front_PDGid);
612  fGoodParticleTree->SetBranchAddress("NP04front_EventID",&fGoodNP04front_EventID);
613  fGoodParticleTree->SetBranchAddress("NP04front_TrackID",&fGoodNP04front_TrackID);
614 
615  // add more lines for the TOF part
616  fGoodParticleTree->SetBranchAddress("TOF1_x",&fGoodTOF1_x);
617  fGoodParticleTree->SetBranchAddress("TOF1_y",&fGoodTOF1_y);
618  fGoodParticleTree->SetBranchAddress("TOF1_z",&fGoodTOF1_z);
619  fGoodParticleTree->SetBranchAddress("TOF1_t",&fGoodTOF1_t);
620  fGoodParticleTree->SetBranchAddress("TOF1_Px",&fGoodTOF1_Px);
621  fGoodParticleTree->SetBranchAddress("TOF1_Py",&fGoodTOF1_Py);
622  fGoodParticleTree->SetBranchAddress("TOF1_Pz",&fGoodTOF1_Pz);
623  fGoodParticleTree->SetBranchAddress("TOF1_PDGid",&fGoodTOF1_PDGid);
624  fGoodParticleTree->SetBranchAddress("TOF1_EventID",&fGoodTOF1_EventID);
625  fGoodParticleTree->SetBranchAddress("TOF1_TrackID",&fGoodTOF1_TrackID);
626 
627  // add more lines for the TRIG part
628  fGoodParticleTree->SetBranchAddress("TRIG1_x",&fGoodTRIG2_x);
629  fGoodParticleTree->SetBranchAddress("TRIG1_y",&fGoodTRIG2_y);
630  fGoodParticleTree->SetBranchAddress("TRIG1_z",&fGoodTRIG2_z);
631  fGoodParticleTree->SetBranchAddress("TRIG1_t",&fGoodTRIG2_t);
632  fGoodParticleTree->SetBranchAddress("TRIG1_Px",&fGoodTRIG2_Px);
633  fGoodParticleTree->SetBranchAddress("TRIG1_Py",&fGoodTRIG2_Py);
634  fGoodParticleTree->SetBranchAddress("TRIG1_Pz",&fGoodTRIG2_Pz);
635  fGoodParticleTree->SetBranchAddress("TRIG1_PDGid",&fGoodTRIG2_PDGid);
636  fGoodParticleTree->SetBranchAddress("TRIG1_EventID",&fGoodTRIG2_EventID);
637  fGoodParticleTree->SetBranchAddress("TRIG1_TrackID",&fGoodTRIG2_TrackID);
638 
639  fGoodParticleTree->SetBranchAddress("TRIG2_x",&fGoodTRIG2_x);
640  fGoodParticleTree->SetBranchAddress("TRIG2_y",&fGoodTRIG2_y);
641  fGoodParticleTree->SetBranchAddress("TRIG2_z",&fGoodTRIG2_z);
642  fGoodParticleTree->SetBranchAddress("TRIG2_t",&fGoodTRIG2_t);
643  fGoodParticleTree->SetBranchAddress("TRIG2_Px",&fGoodTRIG2_Px);
644  fGoodParticleTree->SetBranchAddress("TRIG2_Py",&fGoodTRIG2_Py);
645  fGoodParticleTree->SetBranchAddress("TRIG2_Pz",&fGoodTRIG2_Pz);
646  fGoodParticleTree->SetBranchAddress("TRIG2_PDGid",&fGoodTRIG2_PDGid);
647  fGoodParticleTree->SetBranchAddress("TRIG2_EventID",&fGoodTRIG2_EventID);
648  fGoodParticleTree->SetBranchAddress("TRIG2_TrackID",&fGoodTRIG2_TrackID);
649 
650  //add more lines for the BPROF part
651  fGoodParticleTree->SetBranchAddress("BPROF1_x",&fGoodBPROF1_x);
652  fGoodParticleTree->SetBranchAddress("BPROF1_y",&fGoodBPROF1_y);
653  fGoodParticleTree->SetBranchAddress("BPROF1_z",&fGoodBPROF1_z);
654  fGoodParticleTree->SetBranchAddress("BPROF1_t",&fGoodBPROF1_t);
655  fGoodParticleTree->SetBranchAddress("BPROF1_Px",&fGoodBPROF1_Px);
656  fGoodParticleTree->SetBranchAddress("BPROF1_Py",&fGoodBPROF1_Py);
657  fGoodParticleTree->SetBranchAddress("BPROF1_Pz",&fGoodBPROF1_Pz);
658  fGoodParticleTree->SetBranchAddress("BPROF1_PDGid",&fGoodBPROF1_PDGid);
659  fGoodParticleTree->SetBranchAddress("BPROF1_EventID",&fGoodBPROF1_EventID);
660  fGoodParticleTree->SetBranchAddress("BPROF1_TrackID",&fGoodBPROF1_TrackID);
661 
662  fGoodParticleTree->SetBranchAddress("BPROF2_x",&fGoodBPROF2_x);
663  fGoodParticleTree->SetBranchAddress("BPROF2_y",&fGoodBPROF2_y);
664  fGoodParticleTree->SetBranchAddress("BPROF2_z",&fGoodBPROF2_z);
665  fGoodParticleTree->SetBranchAddress("BPROF2_t",&fGoodBPROF2_t);
666  fGoodParticleTree->SetBranchAddress("BPROF2_Px",&fGoodBPROF2_Px);
667  fGoodParticleTree->SetBranchAddress("BPROF2_Py",&fGoodBPROF2_Py);
668  fGoodParticleTree->SetBranchAddress("BPROF2_Pz",&fGoodBPROF2_Pz);
669  fGoodParticleTree->SetBranchAddress("BPROF2_PDGid",&fGoodBPROF2_PDGid);
670  fGoodParticleTree->SetBranchAddress("BPROF2_EventID",&fGoodBPROF2_EventID);
671  fGoodParticleTree->SetBranchAddress("BPROF2_TrackID",&fGoodBPROF2_TrackID);
672 
673  fGoodParticleTree->SetBranchAddress("BPROF3_x",&fGoodBPROF3_x);
674  fGoodParticleTree->SetBranchAddress("BPROF3_y",&fGoodBPROF3_y);
675  fGoodParticleTree->SetBranchAddress("BPROF3_z",&fGoodBPROF3_z);
676  fGoodParticleTree->SetBranchAddress("BPROF3_t",&fGoodBPROF3_t);
677  fGoodParticleTree->SetBranchAddress("BPROF3_Px",&fGoodBPROF3_Px);
678  fGoodParticleTree->SetBranchAddress("BPROF3_Py",&fGoodBPROF3_Py);
679  fGoodParticleTree->SetBranchAddress("BPROF3_Pz",&fGoodBPROF3_Pz);
680  fGoodParticleTree->SetBranchAddress("BPROF3_PDGid",&fGoodBPROF3_PDGid);
681  fGoodParticleTree->SetBranchAddress("BPROF3_EventID",&fGoodBPROF3_EventID);
682  fGoodParticleTree->SetBranchAddress("BPROF3_TrackID",&fGoodBPROF3_TrackID);
683 
684  fGoodParticleTree->SetBranchAddress("BPROF4_x",&fGoodBPROF4_x);
685  fGoodParticleTree->SetBranchAddress("BPROF4_y",&fGoodBPROF4_y);
686  fGoodParticleTree->SetBranchAddress("BPROF4_z",&fGoodBPROF4_z);
687  fGoodParticleTree->SetBranchAddress("BPROF4_t",&fGoodBPROF4_t);
688  fGoodParticleTree->SetBranchAddress("BPROF4_Px",&fGoodBPROF4_Px);
689  fGoodParticleTree->SetBranchAddress("BPROF4_Py",&fGoodBPROF4_Py);
690  fGoodParticleTree->SetBranchAddress("BPROF4_Pz",&fGoodBPROF4_Pz);
691  fGoodParticleTree->SetBranchAddress("BPROF4_PDGid",&fGoodBPROF4_PDGid);
692  fGoodParticleTree->SetBranchAddress("BPROF4_EventID",&fGoodBPROF4_EventID);
693  fGoodParticleTree->SetBranchAddress("BPROF4_TrackID",&fGoodBPROF4_TrackID);
694 
695  fGoodParticleTree->SetBranchAddress("BPROFEXT_x",&fGoodBPROFEXT_x);
696  fGoodParticleTree->SetBranchAddress("BPROFEXT_y",&fGoodBPROFEXT_y);
697  fGoodParticleTree->SetBranchAddress("BPROFEXT_z",&fGoodBPROFEXT_z);
698  fGoodParticleTree->SetBranchAddress("BPROFEXT_t",&fGoodBPROFEXT_t);
699  fGoodParticleTree->SetBranchAddress("BPROFEXT_Px",&fGoodBPROFEXT_Px);
700  fGoodParticleTree->SetBranchAddress("BPROFEXT_Py",&fGoodBPROFEXT_Py);
701  fGoodParticleTree->SetBranchAddress("BPROFEXT_Pz",&fGoodBPROFEXT_Pz);
702  fGoodParticleTree->SetBranchAddress("BPROFEXT_PDGid",&fGoodBPROFEXT_PDGid);
703  fGoodParticleTree->SetBranchAddress("BPROFEXT_EventID",&fGoodBPROFEXT_EventID);
704  fGoodParticleTree->SetBranchAddress("BPROFEXT_TrackID",&fGoodBPROFEXT_TrackID);
705 
706  // Calculate the number of events to overlay
708 
709  // Now we need to fill the particle map
711 
712 
713  if( fSaveRecoTree ){
714  fRecoTree = tfs->make<TTree>("tree", "");
715  fRecoTree->Branch( "XBPF697_p", &fXBPF697_p );
716  fRecoTree->Branch( "XBPF701_p", &fXBPF701_p );
717  fRecoTree->Branch( "XBPF702_p", &fXBPF702_p );
718 
719  fRecoTree->Branch( "XBPF697_f", &fXBPF697_f );
720  fRecoTree->Branch( "XBPF701_f", &fXBPF701_f );
721  fRecoTree->Branch( "XBPF702_f", &fXBPF702_f );
722 
723  fRecoTree->Branch( "XBPF697_x", &fXBPF697_x );
724  fRecoTree->Branch( "XBPF701_x", &fXBPF701_x );
725  fRecoTree->Branch( "XBPF702_x", &fXBPF702_x );
726 
727  fRecoTree->Branch( "XBPF697_rx", &fXBPF697_rx );
728  fRecoTree->Branch( "XBPF701_rx", &fXBPF701_rx );
729  fRecoTree->Branch( "XBPF702_rx", &fXBPF702_rx );
730 
731  fRecoTree->Branch( "Reco_p", &fReco_p );
732  fRecoTree->Branch( "Reco_tof", &fReco_tof );
733  fRecoTree->Branch( "NP04front_p", &fNP04front_p );
734 
735  fRecoTree->Branch( "NP04_PDG", &fNP04_PDG );
736 
737  fRecoTree->Branch( "XBPF707_x", &fXBPF707_x );
738  fRecoTree->Branch( "XBPF707_f", &fXBPF707_f );
739  fRecoTree->Branch( "XBPF708_y", &fXBPF708_y );
740  fRecoTree->Branch( "XBPF708_f", &fXBPF708_f );
741  fRecoTree->Branch( "XBPF716_x", &fXBPF716_x );
742  fRecoTree->Branch( "XBPF716_f", &fXBPF716_f );
743  fRecoTree->Branch( "XBPF717_y", &fXBPF717_y );
744  fRecoTree->Branch( "XBPF717_f", &fXBPF717_f );
745 
746  fRecoTree->Branch( "XBPF707_rx", &fXBPF707_rx );
747  fRecoTree->Branch( "XBPF708_ry", &fXBPF708_ry );
748  fRecoTree->Branch( "XBPF716_rx", &fXBPF716_rx );
749  fRecoTree->Branch( "XBPF717_ry", &fXBPF717_ry );
750 
751  fRecoTree->Branch( "TrueFront_x", &fTrueFront_x );
752  fRecoTree->Branch( "TrueFront_y", &fTrueFront_y );
753  fRecoTree->Branch( "TrueFront_z", &fTrueFront_z );
754 
755  fRecoTree->Branch( "TrueFront_Px", &fTrueFront_Px );
756  fRecoTree->Branch( "TrueFront_Py", &fTrueFront_Py );
757  fRecoTree->Branch( "TrueFront_Pz", &fTrueFront_Pz );
758 
759  fRecoTree->Branch( "RecoFront_x", &fRecoFront_x );
760  fRecoTree->Branch( "RecoFront_y", &fRecoFront_y );
761  fRecoTree->Branch( "RecoFront_z", &fRecoFront_z );
762  fRecoTree->Branch("TrueID", &fTrueID);
763 
764  }
765 }
766 
767 //----------------------------------------------------------------------------------------
768 
770 {
771  // Grab the geometry object to see what geometry we are using
773  std::unique_ptr<sumdata::RunData> runcol(new sumdata::RunData(geo->DetectorName()));
774  run.put(std::move(runcol));
775 }
776 
777 //--------------------------------------------------------------------------------------------
778 
780  fInputFile->Close();
781 }
782 
783 
784 //--------------------------------------------------------------------------------------------
786 {
787 
788  // Define the truth collection for this event.
789  auto truthcol = std::make_unique< std::vector<simb::MCTruth> >();
790 
791  //------------ Added by Caroline for beam simulation storage----------------------------
792  std::unique_ptr<std::vector<sim::ProtoDUNEbeamsim>> beamsimcol (new std::vector<sim::ProtoDUNEbeamsim>);
793  std::unique_ptr<std::vector<beam::ProtoDUNEBeamEvent> > beamData(new std::vector<beam::ProtoDUNEBeamEvent>);
794  //std::unique_ptr<art::Assns<sim::ProtoDUNEbeamsim, simb::MCTruth> > beamsimassn (new art::Assns<sim::ProtoDUNEbeamsim, simb::MCTruth>);
795  simb::MCTruth truth;
796  beam::ProtoDUNEBeamEvent beamEvent;
797 
798  // Fill the MCTruth object
799  GenerateTrueEvent(truth, (*beamsimcol), beamEvent ); // Add a reference for ProtoDUNEBeamEvent
800 
801  // Add the MCTruth to the vector
802  truthcol->push_back(truth);
803 
804  //Make the assn
805  // util::CreateAssn(*this, e, *beamsimcol, truth, *beamsimassn);
806  // Finally, add the MCTruth to the event
807  e.put(std::move(truthcol));
808  e.put(std::move(beamsimcol));
809 
810  beamData->push_back( beamEvent );
811  e.put( std::move( beamData ) );
812 
813  //puts the vector object on to each event
814  // We have made our event, increment the event number.
815  ++fEventNumber;
816 }
817 //--------------------------------------------------------------------------------------
818 
819 // Fill the particle maps using the input files. This links the events of interest
820 // to the entry number in fAllParticlesTree.
822 
823  // First off, loop over the good particles tree.
824  int goodEventCounter = 0;
825  for(int i = 0; i < fGoodParticleTree->GetEntries(); ++i){
826  // If we want to skip some events, make sure we don't bother reading them in.
827  if(fStartEvent > goodEventCounter){
828  ++goodEventCounter;
829  continue;
830  }
831  else{
832  ++goodEventCounter;
833  }
834 
835  fGoodParticleTree->GetEntry(i);
836 
837 // std::cout << "Tree entry " << i << " corresponds to event " << fGoodBPROFEXT_EventID << std::endl;
838 
839  // Make sure we didn't have two good particles in one event
840  if(std::find(fGoodEventList.begin(),fGoodEventList.end(),(int)fGoodBPROFEXT_EventID)!=fGoodEventList.end()) continue;
841 
842  // NEW APPROACH - construct a ProtoFullSpill object
844  fAllSpills.push_back(newSpill);
845 
847 
848  }
849 
850  // Print a message in case a user starts thinking something has broken.
851  mf::LogInfo("ProtoDUNEBeam") << "About to loop over the beam simulation tree, this could take some time.";
852 
853  // Now we need to loop over the main particle tree
854  for(int i = 0; i < fAllParticlesTree->GetEntries(); ++i){
855  fAllParticlesTree->GetEntry(i);
856 
857  if (i%100000==0) std::cout << "Looking at entry " << i << std::endl;
858 
859  int event = int(fAllEventID);
860 
861  // Look at which good events this should be overlaid with
862  std::vector<int> goodEventList = GetAllOverlays(event,fOverlays);
863 
864  unsigned int nMatches = 0;
865  for(auto &spill : fAllSpills){
866  // Stop looking if we have found all of our matches
867  if(nMatches == goodEventList.size()) break;
868 
869  // Is this a spill of interest?
870  if(std::find(goodEventList.begin(),goodEventList.end(),spill.fGoodEvent) == goodEventList.end()) continue;
871 
872  // Yes, so add this track to the spill
873  spill.fAllSpillTracks[event].push_back(i);
874  ++nMatches;
875  }
876 
877  } // End loop over the main tree.
878 
879  mf::LogInfo("ProtoDUNEBeam") << "Found " << fGoodEventList.size() << " good events containing " << goodEventCounter << " good particles.";
880  mf::LogInfo("ProtoDUNEBeam") << "Built " << fAllSpills.size() << " beam spills.";
881  mf::LogInfo("ProtoDUNEBeam") << "All maps built, beginning event generation.";
882 
883 }
884 
885 
886 
887 //-------------------------------------------------------------------------------------------------
888 //modified by Caroline for beam sim storage
889 void evgen::ProtoDUNEBeam::GenerateTrueEvent(simb::MCTruth &mcTruth, std::vector<sim::ProtoDUNEbeamsim> &beamsimcol, beam::ProtoDUNEBeamEvent & beamEvent){
890  // std::unique_ptr<std::vector<sim::ProtoDUNEbeamsim>> beamsimcol
891  // Check we haven't exceeded the length of the input tree
892  if(fEventNumber >= (int)fGoodEventList.size()){
893  throw cet::exception("ProtoDUNEBeam") << "Requested entry " << fEventNumber
894  << " but tree only has entries 0 to "
895  << fGoodEventList.size() - 1 << std::endl;
896  } //end of if statement
897 
898  size_t nBeamEvents = 0;
899 
900  // Get the list of entries for the current event
901 // int beamEvent = fGoodEventList[fCurrentGoodEvent];
902 
903  // A single particle seems the most accurate description.
905 
906  // NEW APPROACH
908 // std::cout << "This spill has " << spill.fAllSpillTracks.size() << " contributing events" << std::endl;
909 
910  // Find the entries that we are interested in.
911  //std::cout << "Finding all particles associated with good particle event " << std::endl;
912  for(auto const & event : spill.fAllSpillTracks){
913 
914  //std::cout << " - This event has " << event.second.size() << " contributing tracks" << std::endl;
915 
916  // Is this the event we would have triggered on?
917  bool trigEvent = (event.first == spill.fGoodEvent);
918  float baseTime;
919  if(trigEvent){
920  // Set the base time for the triggered event equal to the negative of the good particle time.
921  // This will be corrected later on to set the time to zero, but keep time offsets within the event.
922  baseTime = -1.0 * spill.fGoodTime;
923  }
924  else{
925  // Get a random time from -fReadoutWindow to +fReadoutWindow in ns (fReadoutWindow value is in ms).
926  baseTime = (fFlatRnd.fire() - 0.5)*2.0*(fReadoutWindow*1000.*1000.);
927  }
928  for(auto const t : event.second){
929  // Get the entry from the tree for this event and track.
930  fAllParticlesTree->GetEntry(t);
931 
932  //std::cout << fAllEventID << ", " << fAllTrackID << ", " << spill.fGoodEvent << ", " << spill.fGoodTrack << std::endl;
933 
934  // Convert the pdgCode to an int
935  int intPDG = (int)fPDG;
936  // We need to ignore nuclei for now...
937  if(intPDG > 100000){
938  //std::cout << "Skipping nuc" << std::endl;
939  continue;
940  }
941 
942  // Check to see if this should be a primary beam particle (good particle) or beam background
943  std::string process="primaryBackground";
944 
945  TLorentzVector pos;
946  TLorentzVector mom;
947  // If this track is a "good particle", use the usual "primary" tag
948  /*
949  std::cout << "Trig: " << trigEvent << std::endl;
950  std::cout << "SpillGoodEvent: " << spill.fGoodEvent << std::endl;
951  std::cout << "SpillTrack: " << spill.fGoodTrack << std::endl;
952  std::cout << "AllTrack: " << (int)fAllTrackID << std::endl;
953  std::cout << "t: " << t << std::endl;
954  */
955  if(trigEvent && (spill.fGoodTrack == (int)fAllTrackID)){
956  process="primary";
957  // We also need to build the momentum vector using the correct good particle information
958  fGoodParticleTree->GetEntry(spill.fGoodIndex);
961  if (fSaveRecoTree) {
962  fTrueFront_x = pos.X();
963  fTrueFront_y = pos.Y();
964  fTrueFront_z = pos.Z();
965 
966  fTrueFront_Px = mom.X();
967  fTrueFront_Py = mom.Y();
968  fTrueFront_Pz = mom.Z();
969  }
970 
971  SetBeamEvent(beamEvent);
972  ++nBeamEvents;
973  }
974  else{
975  // We just need to shift our background particles upstream to BPROFEXT so they will hit the CRTs
976  TVector3 tempPos = GetBackgroundPosition(fX,fY,fZ,fPx,fPy,fPz);
977  // At this step the position and momentum matches the GoodPartcle coordinates so apply the same functions
978  pos = ConvertCoordinates(tempPos.X()/10.,tempPos.Y()/10.,tempPos.Z()/10.,baseTime+fEntryT);
979  mom = MakeMomentumVector(fPx/1000.,fPy/1000.,fPz/1000.,intPDG,false);
980  fGoodParticleTree->GetEntry(spill.fGoodIndex);
981  std::cout << "SpillGoodTrack: " << spill.fGoodTrack << " " << (int)fGoodNP04front_PDGid << std::endl;
982  std::cout << "ParentID: " << (int)fAllParentID << " " << (int)fPDG << std::endl;
983  std::cout << "TrackID: " << (int)fAllTrackID<< std::endl;
984  std::cout << "GoodEvent: " << spill.fGoodEvent << std::endl;
985 // if(fabs(intPDG) == 13){
986 // std::cout << "Found a " << process << " muon at time = " << baseTime+fEntryT << ":" << std::endl;
987 // std::cout << fX/10. << ", " << fY/10. << ", " << fZ/10. << std::endl;
988 // pos.Print();
989 // mom.Vect().Unit().Print();
990 // }
991  }
992 
993 // std::cout << "Information for particle " << intPDG << " with process " << process << std::endl;
994 // pos.Print();
995 // mom.Print();
996 // mom.Vect().Unit().Print();
997 
998  // Track ID needs to be negative for primaries
999  int trackID = -1*(mcTruth.NParticles() + 1); //g4trkid in larsoft
1000  if (fSaveRecoTree)
1001  fTrueID = trackID;
1002 
1003  // Create the particle and add the starting position and momentum
1004  //std::cout << "Adding particle with process " << process
1005  // << " and PDG " << intPDG << std::endl;
1006  simb::MCParticle newParticle(trackID,intPDG,process);
1007  newParticle.AddTrajectoryPoint(pos,mom);
1008 
1009  // Add the MCParticle to the MCTruth for the event.
1010  mcTruth.Add(newParticle);
1011 
1012  // We want to save extra information from the beam monitors for the Good Particle
1013  if(trigEvent && (spill.fGoodTrack == (int)fAllTrackID)){
1014 
1015  fGoodParticleTree->GetEntry(spill.fGoodIndex);
1016 
1019 
1020  // For BPROF4 we want to rotate the coordinates into the detector frame
1023  sim::ProtoDUNEBeamInstrument bprof4("BPROF4",bprof4Pos.X(),bprof4Pos.Y(),bprof4Pos.Z(),fGoodBPROF4_t,bprof4Mom.X(),bprof4Mom.Y(),bprof4Mom.Z(),fGoodBPROF4_PDGid,fGoodBPROF4_EventID,fGoodBPROF4_TrackID,fPos_Resolution);
1024 
1025  // Same for BPROFEXT
1028  sim::ProtoDUNEBeamInstrument bprofext("BPROFEXT",bprofextPos.X(),bprofextPos.Y(),bprofextPos.Z(),fGoodBPROFEXT_t,bprofextMom.X(),bprofextMom.Y(),bprofextMom.Z(),fGoodBPROFEXT_PDGid,fGoodBPROFEXT_EventID,fGoodBPROFEXT_TrackID,fPos_Resolution);
1029 
1030 // std::cout << "Predicted detector position" << std::endl;
1031 // TVector3 predDir = (bprof4Pos.Vect()-bprofextPos.Vect()).Unit();
1032 // float projDist = (fNP04frontPos - fBPROF4Pos) + fabs(fBeamZ*10./fBMBasisZ.Z());
1033 // (bprof4Pos.Vect() + projDist*predDir).Print();
1034 
1039 
1040 // Adding Cherenkovs with same variables as BPROFEXT except for their response
1043 
1044 
1046  temp.AddInstrument(tof1);
1047  temp.AddInstrument(trig2);
1048  temp.AddInstrument(bprof4);
1049  temp.AddInstrument(bprofext);
1050  temp.AddInstrument(trig1);
1051  temp.AddInstrument(bprof3);
1052  temp.AddInstrument(bprof2);
1053  temp.AddInstrument(bprof1);
1054  temp.AddInstrument(cherenkov1);
1055  temp.AddInstrument(cherenkov2);
1056 
1057 // std::cout << "ProtoDUNEbeamsim object has " << temp.NInstruments() << " beam instruments" << std::endl;
1058 //std::cout << "TOF1 resolution: " << fT_Resolution << std::endl;
1059 
1060  beamsimcol.push_back(temp);
1061 // std::cout<< beamsimcol.size() << std::endl;
1062  // std::cout<<" test value beam profile monitor: TTREE "<<fGoodBPROF4_x<<std::endl;
1063 // std::cout<<"From TTree TRIG2_TRACKID: "<<fGoodTRIG2_TrackID<<std::endl;
1064 // std::cout<<"From ProtoDUNEBeamInstrument: "<<tof1.GetT()<<std::endl;
1065 // std::cout<<"From ProtoDUNEBeamInstrument: "<<tof1.GetSmearedVar1()<<std::endl;
1066 
1067 
1068  // std::cout<<"the testing for beam profile monitor information: "<<fGoodBPROF4_z<<std::endl;
1069 
1070 
1071 // std::cout<< "From the data product: TRIG2TRACKID: "<<temp.get_TRIG2_TrackID()<<std::endl;
1072  //check the last index of the vector
1073  sim::ProtoDUNEbeamsim lastelement = beamsimcol.back();
1074 
1075 // std::cout<<"From the vector TRIG2_TRACKID: "<<lastelement.get_TRIG2_TrackID()<<std::endl;
1076 
1077 
1078  //Make the assn
1079  //util::CreateAssn(*this, e, *beamsimcol, newParticle, *beamsimassn)
1080 
1081 
1082  } // End beam instrumentation section
1083 
1084  } // End loop over interesting tracks for each event
1085  } // End loop over the vector of interesting events
1086 
1087  mf::LogInfo("ProtoDUNEBeam") << "Got " << nBeamEvents << " beam events";
1088  mf::LogInfo("ProtoDUNEBeam") << "Created event with " << mcTruth.NParticles() << " particles.";
1089 
1090  // Move on the good event iterator
1092 }
1093 
1094 //---------------------------------------------------------------------------------------
1095 
1096 // Function written in similar way as "openDBs()" in CORSIKAGen_module.cc
1098 {
1099  // Setup ifdh object
1100  if (!fIFDH)
1101  {
1102  fIFDH = new ifdh_ns::ifdh;
1103  }
1104 
1105  const char* ifdh_debug_env = std::getenv("IFDH_DEBUG_LEVEL");
1106  if ( ifdh_debug_env )
1107  {
1108  mf::LogInfo("ProtoDUNEBeam") << "IFDH_DEBUG_LEVEL: " << ifdh_debug_env<<"\n";
1109  fIFDH->set_debug(ifdh_debug_env);
1110  }
1111 
1112  std::string path(gSystem->DirName(fFileName.c_str()));
1113  std::string pattern(gSystem->BaseName(fFileName.c_str()));
1114 
1115  auto flist = fIFDH->findMatchingFiles(path,pattern);
1116  if (flist.empty())
1117  {
1118  struct stat buffer;
1119  if (stat(fFileName.c_str(), &buffer) != 0)
1120  {
1121  throw cet::exception("ProtoDUNEBeam") << "No files returned for path:pattern: "<<path<<":"<<pattern<<std::endl;
1122  }
1123  else
1124  {
1125  mf::LogInfo("ProtoDUNEBeam") << "For "<< fFileName <<"\n";
1126  }
1127  }
1128  else
1129  {
1130  std::pair<std::string, long> f = flist.front();
1131 
1132  mf::LogInfo("ProtoDUNEBeam") << "For "<< fFileName <<"\n";
1133 
1134  // Do the fetching, store local filepaths in locallist
1135 
1136  mf::LogInfo("ProtoDUNEBeam")
1137  << "Fetching: " << f.first << " " << f.second <<"\n";
1138  std::string fetchedfile(fIFDH->fetchInput(f.first));
1139  MF_LOG_DEBUG("ProtoDUNEBeam") << " Fetched; local path: " << fetchedfile;
1140 
1141  fFileName = fetchedfile;
1142  }
1143 }
1144 
1145 
1146 //----------------------------------------------------------------------------------
1147 
1148 TLorentzVector evgen::ProtoDUNEBeam::ConvertCoordinates(float x, float y, float z, float t){
1149 
1150  float finalX = x + fBeamX;
1151  float finalY = y + fBeamY;
1152 // float finalZ = (z - z) + fBeamZ; // Just use the z position
1153  float finalZ = z + fBeamZ; // Just use the z position
1154 
1155  TLorentzVector newPos(finalX,finalY,finalZ,t);
1156  return newPos;
1157 }
1158 
1159 //--------------------------------------------------------------------------------
1160 
1161 TLorentzVector evgen::ProtoDUNEBeam::MakeMomentumVector(float px, float py, float pz, int pdg, bool shifts){
1162 
1163  //float rotationXZ = fRotateXZ;
1164  //float rotationYZ = fRotateYZ;
1165 
1166  // Make the momentum vector and rotate it
1167  TVector3 momVec(px,py,pz);
1168 
1169  if(shifts){
1170  // Shift theta and phi first, and only rotate if we should
1171  if(fabs(fBeamThetaShift) > 1.e-10 && fabs(fBeamPhiShift) > 1.e-10){
1172  //std::cout << "Shifted momentum vector from " << momVec.Theta() << ", " << momVec.Phi() << " ";
1173  momVec.SetTheta(momVec.Theta() + fBeamThetaShift);
1174  momVec.SetPhi(momVec.Phi() + fBeamPhiShift);
1175  //std::cout << "to " << momVec.Theta() << ", " << momVec.Phi() << std::endl;
1176  }
1177  else{
1178  momVec.RotateY(fRotateXZ/*rotationXZ*/ * TMath::Pi() / 180.);
1179  momVec.RotateX(fRotateYZ/*rotationYZ*/ * TMath::Pi() / 180.);
1180  }
1181  }
1182 
1183  // Find the particle mass so we can form the energy
1184  const TDatabasePDG* databasePDG = TDatabasePDG::Instance();
1185  const TParticlePDG* definition = databasePDG->GetParticle(pdg);
1186  float mass = definition->Mass();
1187 
1188  float energy = sqrt(mass*mass + momVec.Mag2());
1189 
1190  TLorentzVector newMom(momVec,energy);
1191  return newMom;
1192 }
1193 
1194 TLorentzVector evgen::ProtoDUNEBeam::MakeMomentumVector(const TVector3 &mom, int pdg, bool shifts){
1195 
1196  return MakeMomentumVector(mom.X(),mom.Y(),mom.Z(),pdg,shifts);
1197 
1198 }
1199 
1200 //-----------------------------------------------------------------------------
1201 
1203 
1204  // The number of events to overlay is as follows:
1205  // N = Intensity * 2.0 * ReadoutWindow / BeamSpillLength
1206  fOverlays = fIntensity * (2.0 * fReadoutWindow / 1000.) / fBeamSpillLength;
1207  std::cout << "Number of overlays = " << fOverlays << std::endl;
1208 }
1209 
1210 
1211 //-------------------------------------------------------------------------------
1213 
1214  // Check if this event lies within nOverlay/2 of each
1215  for(auto const e : fGoodEventList){
1216  if(fabs(event - e) < nOverlay/2){
1217  return e;
1218  }
1219  }
1220  return -1;
1221 }
1222 
1223 
1224 //---------------------------------------------------------------------------------
1225 std::vector<int> evgen::ProtoDUNEBeam::GetAllOverlays(int event, int nOverlay){
1226 
1227  std::vector<int> nMatches;
1228  for(auto const e : fGoodEventList){
1229  if(fabs(event - e) < nOverlay/2){
1230  nMatches.push_back(e);
1231  }
1232  }
1233  return nMatches;
1234 
1235 }
1236 //----------------------------------------------------------------------------------
1237 
1238 // We need to rotate the beam monitor coordinates into the detector frame (matching NP04front)
1239 // This means they can later be treated in the same way as the standard NP04front positions
1240 TLorentzVector evgen::ProtoDUNEBeam::ConvertBeamMonitorCoordinates(float x, float y, float z, float t, float zOffset){
1241 
1242  float off = fNP04frontPos - zOffset;
1243 
1244  TLorentzVector old(x,y,z,t);
1245 
1246  // Convert the coordinates using the rotated basis vectors
1247  float newX = x*fBMBasisX.X() + y*fBMBasisY.X() + (z-zOffset)*fBMBasisZ.X() + off*fabs(fBMBasisZ.X());
1248  float newY = x*fBMBasisX.Y() + y*fBMBasisY.Y() + (z-zOffset)*fBMBasisZ.Y() + off*fabs(fBMBasisZ.Y());
1249  float newZ = x*fBMBasisX.Z() + y*fBMBasisY.Z() + (z-zOffset) - off*fabs(fBMBasisZ.Z());
1250 
1251  // Account for the small differences between NP04front and the detector coordinates
1252  newX += fBeamX*10.;
1253  newY += fBeamY*10.;
1254  newZ += fBeamZ*10.;
1255 
1256  // Make our new beam monitor position in the detector coordinate system
1257  TLorentzVector result(newX,newY,newZ,t);
1258 
1259 // std::cout << "Coordinate transform..." << std::endl;
1260 // old.Print();
1261 // result.Print();
1262 
1263  return result;
1264 }
1265 
1266 TVector3 evgen::ProtoDUNEBeam::ConvertProfCoordinates(double x, double y, double z, double zOffset){
1267  double off = fNP04frontPos - zOffset;
1268 
1269  TVector3 old(x,y,z);
1270 
1271  double newX = x*fBMBasisX.X() + y*fBMBasisY.X() + /*(z-zOffset)*fBMBasisZ.X()*/ + off*fabs(fBMBasisZ.X());
1272  double newY = x*fBMBasisX.Y() + y*fBMBasisY.Y() + /*(z-zOffset)*fBMBasisZ.Y()*/ + off*fabs(fBMBasisZ.Y());
1273  double newZ = x*fBMBasisX.Z() + y*fBMBasisY.Z() + /*(z-zOffset) */ - off*fabs(fBMBasisZ.Z());
1274 
1275  newX += fBeamX*10.;
1276  newY += fBeamY*10.;
1277  newZ += fBeamZ*10.;
1278 
1279  TVector3 result(newX/10., newY/10., newZ/10.);
1280  return result;
1281 }
1282 
1284 
1285  TVector3 newMom(px,py,pz);
1286 // std::cout << "Momentum transform..." << std::endl;
1287 // newMom.Unit().Print();
1288  RotateMonitorVector(newMom);
1289 // newMom.Unit().Print();
1290  return newMom;
1291 }
1292 
1294 
1295  fBMBasisX = TVector3(1.,0.,0.);
1296  fBMBasisY = TVector3(0.,1.,0.);
1297  fBMBasisZ = TVector3(0.,0.,1.);
1301 
1302 }
1303 
1305 
1306  // Note: reordering how these are done in order to keep the basis
1307  // vectors of the monitors parallel to the ground.
1308  vec.RotateX( fRotateMonitorYZ * TMath::Pi() / 180. );
1309  vec.RotateY( fRotateMonitorXZ * TMath::Pi() / 180. );
1310 
1311 }
1312 
1313 TVector3 evgen::ProtoDUNEBeam::GetBackgroundPosition(float x, float y, float z, float px, float py, float pz){
1314 
1315  TVector3 pos(x,y,z);
1316  TVector3 dir = TVector3(px,py,pz).Unit();
1317 
1318  // Want to move the position upstream by a distance equal to fNP04frontPos - fBPROFEXTPos
1319  // This length is in the beam direction frame unless we account for it
1320  float shiftLength = (fNP04frontPos - fBPROFEXTPos)/fBMBasisZ.Z();
1321 
1322  return pos - shiftLength*dir;
1323 }
1324 
1325 
1327  //This will just use the class members
1328 
1329  beamevt.SetTOFs( std::vector<double>{ fGoodTRIG2_t - fGoodTOF1_t } );
1330  beamevt.SetTOFChans( std::vector<int>{ 0 } );
1331  beamevt.SetUpstreamTriggers( std::vector<size_t>{0} );
1332  beamevt.SetDownstreamTriggers( std::vector<size_t>{0} );
1333  beamevt.SetCalibrations( 0., 0., 0., 0. );
1334  beamevt.DecodeTOF();
1335 
1336  beamevt.SetMagnetCurrent( 0. );
1337  beamevt.SetTimingTrigger( 12 );
1338 
1339  beam::CKov dummy;
1340  dummy.trigger = 0;
1341  dummy.pressure = 0.;
1342  dummy.timeStamp = 0.;
1343  beamevt.SetCKov0( dummy );
1344  beamevt.SetCKov1( dummy );
1345 
1346  beamevt.SetActiveTrigger(0);
1347  beamevt.SetT0( std::make_pair(0.,0.) );
1348 
1349  beamevt.SetFBMTrigger( "XBPF022697", MakeFiberMonitor( fGoodBPROF1_x ) );
1350  beamevt.SetFBMTrigger( "XBPF022698", MakeFiberMonitor( fGoodBPROF1_y ) );
1351  beamevt.SetFBMTrigger( "XBPF022701", MakeFiberMonitor( fGoodBPROF2_x ) );
1352  beamevt.SetFBMTrigger( "XBPF022702", MakeFiberMonitor( fGoodBPROF3_x ) );
1353 
1354  beamevt.SetFBMTrigger( "XBPF022707", MakeFiberMonitor( fGoodBPROFEXT_x ) );
1355  beamevt.SetFBMTrigger( "XBPF022708", MakeFiberMonitor( fGoodBPROFEXT_y ) );
1356 
1357  beamevt.SetFBMTrigger( "XBPF022716", MakeFiberMonitor( fGoodBPROF4_x ) );
1358  beamevt.SetFBMTrigger( "XBPF022717", MakeFiberMonitor( fGoodBPROF4_y ) );
1359 
1360  MakeTracks( beamevt );
1361  MomentumSpectrometer( beamevt );
1362 
1363 
1364  if( fSaveRecoTree ){
1365  fReco_p = beamevt.GetRecoBeamMomentum(0);
1366  fReco_tof = beamevt.GetTOF();
1367  std::cout << "TOF: " << beamevt.GetTOFs()[0] << " " << beamevt.GetTOF() << std::endl;
1369 
1373 
1377 
1381 
1388 
1393 
1394 
1395  fXBPF697_f = beamevt.GetFBM( "XBPF022697" ).active[0];
1396  fXBPF701_f = beamevt.GetFBM( "XBPF022701" ).active[0];
1397  fXBPF702_f = beamevt.GetFBM( "XBPF022702" ).active[0];
1398 
1399  fXBPF707_f = beamevt.GetFBM( "XBPF022707" ).active[0];
1400  fXBPF708_f = beamevt.GetFBM( "XBPF022708" ).active[0];
1401  fXBPF716_f = beamevt.GetFBM( "XBPF022716" ).active[0];
1402  fXBPF717_f = beamevt.GetFBM( "XBPF022717" ).active[0];
1403 
1407 
1412 
1413  //fTrueFront_x = fGoodNP04front_x + fBeamX;
1414  //fTrueFront_y = fGoodNP04front_y + fBeamY;
1415  //fTrueFront_z = fGoodNP04front_z + fBeamZ;
1416 
1417  fRecoFront_x = beamevt.GetBeamTrack(0).End().X();
1418  fRecoFront_y = beamevt.GetBeamTrack(0).End().Y();
1419  fRecoFront_z = beamevt.GetBeamTrack(0).End().Z();
1420 
1421  fRecoTree->Fill();
1422  }
1423 }
1424 
1426  beam::FBM theFBM;
1427 
1428  //I should probably just make this into
1429  //a constructor for the FBM...
1430  theFBM.ID = -1;
1431  theFBM.glitch_mask = {};
1432  std::uninitialized_fill( std::begin(theFBM.fiberData), std::end(theFBM.fiberData), 0. );
1433  std::uninitialized_fill( std::begin(theFBM.timeData), std::end(theFBM.timeData), 0. );
1434  theFBM.timeStamp = 0.;
1435 
1436  short f = 96 - short( floor(pos) ) - 1;
1437  theFBM.fibers[f] = 1;
1438  theFBM.active.push_back(f);
1439  theFBM.decoded = true;
1440 
1441  return theFBM;
1442 }
1443 
1445  return ((96 - fiber) - .5);
1446 }
1447 
1449 
1450  //We should only have one active fiber at a time
1451  //
1452  //Might need to ask Leigh, etc. if it's possible
1453  //to have multiple particles going through at the
1454  //same time. In which case -- try to implement it
1455 
1456  short fx1 = beamEvent.GetFBM( "XBPF022707" ).active[0];
1457  short fy1 = beamEvent.GetFBM( "XBPF022708" ).active[0];
1458 
1459  double x1 = GetPosition( fx1 );
1460  double y1 = GetPosition( fy1 );
1461 
1462  TVector3 pos1 = ConvertProfCoordinates( x1, y1, 0., fBPROFEXTPos );
1463 
1464  short fx2 = beamEvent.GetFBM( "XBPF022716" ).active[0];
1465  short fy2 = beamEvent.GetFBM( "XBPF022717" ).active[0];
1466 
1467  double x2 = GetPosition( fx2 );
1468  double y2 = GetPosition( fy2 );
1469 
1470  TVector3 pos2 = ConvertProfCoordinates( x2, y2, 0., fBPROF4Pos );
1471 
1472  std::vector< TVector3 > thePoints = { pos1, pos2, ProjectToTPC( pos1, pos2 ) };
1473  std::vector< TVector3 > theMomenta = {
1474  ( pos2 - pos1 ).Unit(),
1475  ( pos2 - pos1 ).Unit(),
1476  ( pos2 - pos1 ).Unit()
1477  };
1478 
1479  beamEvent.AddBeamTrack(
1480  recob::Track(
1483  recob::Track::Flags_t( thePoints.size() ),
1484  false ),
1486  )
1487  );
1488 
1489 }
1490 
1491 TVector3 evgen::ProtoDUNEBeam::ProjectToTPC(TVector3 firstPoint, TVector3 secondPoint){
1492  TVector3 dR = (secondPoint - firstPoint);
1493 
1494  double deltaZ = -1.*secondPoint.Z();
1495  double deltaX = deltaZ * (dR.X() / dR.Z());
1496  double deltaY = deltaZ * (dR.Y() / dR.Z());
1497 
1498  TVector3 lastPoint = secondPoint + TVector3(deltaX, deltaY, deltaZ);
1499  return lastPoint;
1500 }
1501 
1503 
1504  short f1 = beamEvent.GetFBM( "XBPF022697" ).active[0];
1505  short f2 = beamEvent.GetFBM( "XBPF022701" ).active[0];
1506  short f3 = beamEvent.GetFBM( "XBPF022702" ).active[0];
1507 
1508  double x1 = -1.e-3 * GetPosition( f1 );
1509  double x2 = -1.e-3 * GetPosition( f2 );
1510  double x3 = -1.e-3 * GetPosition( f3 );
1511 
1512  double cos_theta = MomentumCosTheta( x1, x2, x3 );
1513  double momentum = 299792458*fLB/(1.E9 * acos(cos_theta));
1514  beamEvent.AddRecoBeamMomentum( momentum );
1515 
1516 }
1517 
1518 double evgen::ProtoDUNEBeam::MomentumCosTheta(double x1, double x2, double x3){
1519  double a = (x2*fL3 - x3*fL2)*cos(fBeamBend)/(fL3-fL2);
1520 
1521 
1522  double numTerm = (a - x1)*( (fL3 - fL2)*tan(fBeamBend) + (x3 - x2)*cos(fBeamBend) ) + fL1*( fL3 - fL2 );
1523 
1524  double denomTerm1, denomTerm2, denom;
1525  denomTerm1 = sqrt( fL1*fL1 + (a - x1)*(a - x1) );
1526  denomTerm2 = sqrt( TMath::Power( ( (fL3 - fL2)*tan(fBeamBend) + (x3 - x2)*cos(fBeamBend) ),2)
1527  + TMath::Power( ( (fL3 - fL2) ),2) );
1528  denom = denomTerm1 * denomTerm2;
1529 
1530  double cosTheta = numTerm/denom;
1531  return cosTheta;
1532 }
1533 
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
base_engine_t & createEngine(seed_t seed)
const FBM & GetFBM(std::string) const
beam::FBM MakeFiberMonitor(float pos)
void MakeTracks(beam::ProtoDUNEBeamEvent &beamEvent)
double GetPosition(short fiber)
const recob::Track & GetBeamTrack(size_t i) const
const std::vector< double > & GetTOFs() const
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
Definition: MCParticle.h:257
static QCString result
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:82
std::string string
Definition: nybbler.cc:12
ROOT::Math::SMatrix< Double32_t, 5, 5, ROOT::Math::MatRepSym< Double32_t, 5 > > SMatrixSym55
Definition: TrackingTypes.h:85
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< Vector_t > convertCollToVector(std::vector< Vector > const &coll)
Definition: TrackingTypes.h:58
void SetTimingTrigger(int theTrigger)
ProtoDUNEBeam & operator=(ProtoDUNEBeam const &)=delete
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
static collection_type const & get() noexcept
TrackTrajectory::Flags_t Flags_t
Definition: Track.h:68
int NParticles() const
Definition: MCTruth.h:75
string dir
Particle class.
std::map< int, std::vector< int > > fAllSpillTracks
std::vector< short > active
art framework interface to geometry description
Definition: Run.h:17
void SetFBMTrigger(std::string, FBM)
void SetCKov0(CKov theCKov)
def process(f, kind)
Definition: search.py:254
TVector3 ConvertProfCoordinates(double x, double y, double z, double zOffset)
ProtoFullSpill(int event, int track, float time, int id)
const double e
int IsOverlayEvent(int event, int nOverlay)
std::vector< int > GetAllOverlays(int event, int nOverlay)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void SetMagnetCurrent(double theMagnetCurrent)
void GenerateTrueEvent(simb::MCTruth &mcTruth, std::vector< sim::ProtoDUNEbeamsim > &beamsimcol, beam::ProtoDUNEBeamEvent &beamEvent)
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
A trajectory in space reconstructed from hits.
single particles thrown at the detector
Definition: MCTruth.h:26
const double a
const double & GetTOF() const
std::string getenv(std::string const &name)
Definition: getenv.cc:15
def move(depos, offset)
Definition: depos.py:107
std::vector< int > fGoodEventList
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
std::vector< Point_t > convertCollToPoint(std::vector< Point > const &coll)
Definition: TrackingTypes.h:55
TVector3 GetBackgroundPosition(float x, float y, float z, float px, float py, float pz)
void RotateMonitorVector(TVector3 &vec)
static constexpr double ps
Definition: Units.h:99
void AddBeamTrack(recob::Track theTrack)
double MomentumCosTheta(double, double, double)
TLorentzVector ConvertBeamMonitorCoordinates(float x, float y, float z, float t, float offset)
void MomentumSpectrometer(beam::ProtoDUNEBeamEvent &beamEvent)
void AddRecoBeamMomentum(double theMomentum)
std::array< short, 192 > fibers
void Add(simb::MCParticle const &part)
Definition: MCTruth.h:80
void produce(art::Event &e) override
std::string pattern
Definition: regex_t.cc:35
void SetDownstreamTriggers(std::vector< size_t > theContent)
#define MF_LOG_DEBUG(id)
Provides recob::Track data product.
void SetUpstreamTriggers(std::vector< size_t > theContent)
std::vector< ProtoFullSpill > fAllSpills
TVector3 ProjectToTPC(TVector3 firstPoint, TVector3 secondPoint)
std::array< short, 192 > glitch_mask
cet::LibraryManager dummy("noplugin")
Point_t const & End() const
Definition: Track.h:125
list x
Definition: train.py:276
void SetT0(std::pair< double, double > theT0)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
void SetCKov1(CKov theCKov)
double fiberData[6]
Event generator information.
Definition: MCTruth.h:32
def momentum(x1, x2, x3, scale=1.)
LArSoft geometry interface.
Definition: ChannelGeo.h:16
const double & GetRecoBeamMomentum(size_t i) const
Event Generation using GENIE, cosmics or single particles.
void SetTOFs(std::vector< double > theContent)
double timeData[4]
void SetBeamEvent(beam::ProtoDUNEBeamEvent &beamevt)
TLorentzVector ConvertCoordinates(float x, float y, float z, float t)
void SetCalibrations(double TOFCalAA, double TOFCalBA, double TOFCalAB, double TOFCalBB)
TVector3 ConvertBeamMonitorMomentumVec(float px, float py, float pz)
ProtoDUNEBeam(fhicl::ParameterSet const &p)
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void AddInstrument(ProtoDUNEBeamInstrument newInst)
void SetTOFChans(std::vector< int > theContent)
void beginRun(art::Run &run) override
QTextStream & endl(QTextStream &s)
Event finding and building.
TLorentzVector MakeMomentumVector(float px, float py, float pz, int pdg, bool shifts)
void SetActiveTrigger(size_t theTrigger)