ProtoDUNETriggeredBeam_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: ProtoDUNETriggeredBeam
3 // Module Type: producer
4 // File: ProtoDUNETriggeredBeam_module.cc
5 //
6 // Modified from the original ProtoDUNEBeam module to more accurately
7 // reflect what happens in reality. As such, it does not make use of
8 // the GoodParticle tree and uses the TRIG planes to work out which
9 // events are "Triggered" events
10 //
11 // Leigh Whitehead & Jake Calcutt
12 //
13 ////////////////////////////////////////////////////////////////////////
14 
23 #include "fhiclcpp/ParameterSet.h"
25 #include "cetlib_except/exception.h"
26 #include "cetlib/search_path.h"
27 #include "cetlib/filesystem.h"
32 #include <memory>
33 #include <string>
34 #include <map>
35 #include <utility>
36 #include <vector>
38 // art extensions
39 #include "nurandom/RandomUtils/NuRandomService.h"
40 #include "art_root_io/TFileService.h"
41 #include <TSystem.h>
42 #include <TFile.h>
43 #include <TTree.h>
44 #include <TGraph.h>
45 #include <TVector3.h>
46 #include "THnSparse.h"
47 #include "TH2D.h"
48 #include "TRandom3.h"
49 #include <TLorentzVector.h>
50 #include <TDatabasePDG.h>
51 #include <TParticlePDG.h>
52 #include "CLHEP/Random/RandFlat.h"
53 #include "ifdh.h"
54 #include <sys/stat.h>
55 
56 namespace evgen{
57 
58  class ProtoDUNETriggeredBeam;
59 
61  public:
63  // The destructor generated by the compiler is fine for classes
64  // without bare pointers or other resource use.
66 
67  // Plugins should not be copied or assigned.
72 
73  // Required functions.
74  void produce(art::Event & e) override;
75  void beginJob() override;
76  void beginRun(art::Run& run) override;
77  void endJob() override;
78 
79  // Simple struct to store the information for each particle at the front face
80  struct BeamParticle {
82  fTrackID=-999;
83  fPDG=-999;
84  fParentID=-999;
85  fPosX = -999;
86  fPosY = -999;
87  fPosZ = -999;
88  fPosT = -999;
89  fMomX = -999;
90  fMomY = -999;
91  fMomZ = -999;
92  };
93  BeamParticle(int trackid, int pdg, int parentid, float posX, float posY, float posZ, float posT,
94  float momX, float momY, float momZ){
95  fTrackID = trackid;
96  fPDG = pdg;
97  fParentID= parentid;
98  fPosX = posX;
99  fPosY = posY;
100  fPosZ = posZ;
101  fPosT = posT;
102  fMomX = momX;
103  fMomY = momY;
104  fMomZ = momZ;
105  };
106  void Print(){
107  std::cout << "Particle " << fPDG << ": (" << fPosX << "," << fPosY << "," << fPosZ << "," << fPosT << ") "
108  << ": (" << fMomX << "," << fMomY << "," << fMomZ << ") " << std::endl;
109  };
110  int fTrackID, fPDG, fParentID;
111  float fPosX, fPosY, fPosZ, fPosT;
112  float fMomX, fMomY, fMomZ;
113  };
114 
115  // Struct to contain the particles reaching the cryostat wall for each event
116  // in the beam simulation files
117  struct BeamEvent {
119  fEventID = -999;
120  fTriggerID = -999;
121  fHasInteracted = false;
122  }
123  BeamEvent(int eventid){
124  fEventID = eventid;
125  fTriggerID = -999;
126  fHasInteracted = false;
127  };
128 
129  void AddParticle(BeamParticle particle){
130  fParticlesFront.insert(std::make_pair(particle.fTrackID,particle));
131  };
132 
133  int fEventID;
134 
135  // Map of particles to the track ID
136  std::map<int,BeamParticle> fParticlesFront;
137 
139 
140  // We need information for each point in the beamline
141  std::map<std::string,BeamParticle> fTriggeredParticleInfo;
142 
143  // Some events can interact before between TRIG2 and NP04front
145  std::vector<int> fSecondaryTrackIDs;
146  };
147 
148  // Convenience struct to encapsulate all particles that would
149  // deposit energy within one readout window of the TPC
151 
152  OverlaidTriggerEvent(int trigID){
153  fTriggerEventID = trigID;
154  };
155 
156  void AddOverlay(int overlayID){
157  fOverlayEventIDs.push_back(overlayID);
158  };
159 
160  std::vector<int> fOverlayEventIDs;
162 
163  };
164 
165  private:
166 
167  // Calculate how many overlay events we need.
168  void CalculateNOverlays();
169 
170  // Fill the above maps and vector.
171  void FillParticleMaps(TTree *frontFaceTree);
172 
173  // Find trigger events
174  std::vector<int> FindTriggeredEvents(TTree *trig1Tree,TTree *trig2Tree);
175 
176  // Add the triggered particle information for a given instrument
177  void FillInstrumentInformation(std::vector<int> &eventIDs,TTree *instrumentTree);
178 
179  // Group the events to overlay a number of background events on each trigger event
180  OverlaidTriggerEvent GenerateOverlaidEvent(const int &trigEventID);
181 
182  // Generate a true event based on a single entry from the input tree.
183  void GenerateTrueEvent(simb::MCTruth &mcTruth, const OverlaidTriggerEvent &overlayEvent, beam::ProtoDUNEBeamEvent & beamEvent);
184 
185  // Convert our BeamParticle struct into a MCParticle object
186  simb::MCParticle BeamParticleToMCParticle(const BeamParticle &beamParticle, const int outputTrackID, const float triggerParticleTime, const int primaryStatus, const std::string process, const int motherID = -1);
187 
188  // Use DDMC to create a primary beam particle
190  const BeamParticle &beamParticle, const int outputTrackID,
191  const float triggerParticleTime,
192  beam::ProtoDUNEBeamEvent & beamEvent, const int primaryStatus, const std::string process);
193 
194  void SetDataDrivenPosMom(TLorentzVector & position,
195  TLorentzVector & momentum, double sampledHUp,
196  double sampledVUp, double sampledHDown,
197  double sampledVDown, double sampledMomentum,
198  int beamPDG);
199 
200  double UnsmearMomentum2D(double momentum, int pdg);
201 
203  beam::ProtoDUNEBeamEvent & beamEvent,
204  double sampledHUp, double sampledVUp, double sampledHDown,
205  double sampledVDown, double sampledMomentum);
206 
207  void ConvertSamplingPoint(double input_point[5],
208  std::vector<double> minima,
209  std::vector<double> maxima,
210  double output_point[5]);
211 
212  // Handle root files from beam instrumentation group
214 
215  // Convert to the detector coordinate frame
216  void ConvertCoordinates(float &x, float &y, float &z);
217 
218  // Convert the momentum to GeV and rotate as required.
219  void ConvertMomentum(float &px, float &py, float &pz);
220 
221  // We need to rotate the beam monitor coordinates into the detector frame
222  TLorentzVector ConvertBeamMonitorCoordinates(float x, float y, float z, float t, float offset);
223 
224  // Methods for making beam instrument tracks
225  TVector3 ConvertProfCoordinates(double x, double y, double z, double zOffset);
226  TVector3 ProjectToTPC(TVector3 firstPoint, TVector3 secondPoint);
227  double GetPosition( short fiber );
228  void MakeTracks( beam::ProtoDUNEBeamEvent & beamEvent );
230  double MomentumCosTheta( double, double, double );
232 
233  TVector3 ConvertBeamMonitorMomentumVec(float px, float py, float pz);
234  // Setup the beam monitor basis vectors in detector coordinates
236  // Apply the rotation
237  void RotateMonitorVector(TVector3 &vec);
238  // Fill all of the ProtoDUNEBeamEvent information from the beam simulation trigger event
239  void SetBeamEvent(beam::ProtoDUNEBeamEvent & beamevt, const BeamEvent &triggerEvent);
240  beam::FBM MakeFiberMonitor( float pos );
241 
242  // Background particles need to be fired from an upstream position
243  void SetBackgroundPosition(BeamParticle &particle);
244 
245  // Variables
246  CLHEP::RandFlat fFlatRnd;
247 
248  // Beam input file name and tree names (in beam order)
260 
261  // Variables for the beam simulation event building
262  std::vector<OverlaidTriggerEvent> fAllOverlaidTriggerEvents;
263  std::map<int,BeamEvent> fAllBeamEvents;
264  std::vector<int> fFinalTriggerEventIDs;
265 
266  // This event refers to the position in the list of beam simulation events
268 
269  // Let the user define the event to start at
271 
272  // An important feature is to be able to use a data-driven triggered particle
274 
275  // Define the coordinate transform from the beam frame to the detector frame
276  float fBeamX;
277  float fBeamY;
278  float fBeamZ;
281  // Rotate the beam monitor coordinate system (those after the last bending magnet)
284  // The three beam monitor basis vectors in the detector coordinate system
285  TVector3 fBMBasisX;
286  TVector3 fBMBasisY;
287  TVector3 fBMBasisZ;
288  // The z positions of the important elements along the beam direction
290  float fBPROF4Pos;
292  float fTRIG2Pos;
293 
294  // Parameters from the .fcl file to deal with overlaying events
295  float fIntensity; // Number of interactions on the secondary target per SPS spill
296  float fReadoutWindow; // Readout window (needs to match the values used in the simulation) in milliseconds
297  float fBeamSpillLength; // The SPS spill length in seconds
298 
299  float fLB;
300  float fL1;
301  float fL2;
302  float fL3;
303  float fBeamBend;
304 
305  float fLMag;
307  float fB;
308 
310 
311  TRandom3 fRNG;
313  std::vector<double> fMinima = {0.8, 0., 0., 0., 0.};
314  std::vector<double> fMaxima = {1.2, 192., 192., 192., 192.};
315  std::map<int, std::string> fPDGToName = {
316  {2212, "Protons"},
317  {211, "Pions"},
318  {-11, "Electrons"},
319  {-13, "Muons"},
320  {321, "Kaons"},
321  {-211, "Pions"},
322  {11, "Electrons"},
323  {13, "Muons"},
324  {-321, "Kaons"}
325  };
326 
329  TFile * fSamplingFile;
331  std::map<std::string, THnSparseD *> fPDFs;
332  std::map<std::string, TH2D *> fResolutionHists2D;
333  void Setup1GeV(); //Shared by 2GeV
334  void Setup3GeV();
335  void Setup6GeV(); //Shared by 7GeV
336 
337  void Scale2DRes();
338  void SetMinMax();
339 
340  std::string GetPrimaryEndProcess(const int &primary_pdg, const std::vector<int> & secondary_pdgs);
341  std::string GetSecondaryProcess(const int &primary_pdg, const int &secondary_pdg);
342 
344  TTree * fOutputTree;
345  TGraph * fTriggersGraph;
352 
354 
355  // Number of beam interactions to overlay.
357 
358  ifdh_ns::ifdh* fIFDH;
359  };
360 }
361 
362 // Create the random number generator
363 namespace {
364  std::string const instanceName = "protoDUNEBeam";
365 }
366 
367 
368 //---------------------------------------------------------------------------------
369 //----------------------------------------constructors-----------------------------
371  : EDProducer{pset}
372  // now create the engine (for example, use art); seed will be set
373  // by calling declareEngine
374  , fFlatRnd(createEngine(art::ServiceHandle<rndm::NuRandomService>{}->declareEngine(instanceName),
375  "HepJamesRandom", instanceName))
376 {
377  // Call appropriate produces<>() functions here.
378  produces< std::vector<simb::MCTruth> >();
379  produces< sumdata::RunData, art::InRun >();
380  produces< std::vector< beam::ProtoDUNEBeamEvent > >();
381  // File reading variable initialisations
382  fFileName = pset.get< std::string>("FileName");
383  fBaseFileName = fFileName.substr(fFileName.rfind("/")+1);
384 
385  // Tree names
386  fTOF1TreeName = pset.get<std::string>("TOF1TreeName");
387  fBPROF1TreeName = pset.get<std::string>("BPROF1TreeName");
388  fBPROF2TreeName = pset.get<std::string>("BPROF2TreeName");
389  fBPROF3TreeName = pset.get<std::string>("BPROF3TreeName");
390  fTRIG1TreeName = pset.get<std::string>("TRIG1TreeName");
391  fBPROFEXTTreeName = pset.get<std::string>("BPROFEXTTreeName");
392  fBPROF4TreeName = pset.get<std::string>("BPROF4TreeName");
393  fTRIG2TreeName = pset.get<std::string>("TRIG2TreeName");
394  fNP04frontTreeName = pset.get<std::string>("NP04frontTreeName");
395 
396  // Intensity variables
397  fIntensity = pset.get<float>("Intensity");
398  fReadoutWindow = pset.get<float>("ReadoutWindow");
399  fBeamSpillLength = pset.get<float>("BeamSpillLength");
400 
401  fUseDataDriven = pset.get<bool>("UseDataDrivenPrimary");
402  fReduceNP04frontArea = pset.get<bool>("ReduceNP04frontArea");
403 
404  // See if the user wants to start at an event other than zero.
405  fStartEvent = pset.get<int>("StartEvent");
406 
407  // Or maybe there was --nskip specified in the command line or skipEvents in FHiCL?
408  for (auto const & p : fhicl::ParameterSetRegistry::get())
409  {
410  if (p.second.has_key("source"))
411  {
412  // Need to add in another layer here because of some change (maybe in art?)
413  if (p.second.has_key("source.skipEvents"))
414  {
415  fStartEvent += p.second.get<int>("source.skipEvents");
416  break; // take the first occurence
417  }
418  } // no "else", if parameter not found, then just don't change anything
419  }
420  // ...and if there is -e option or firstEvent in FHiCL, this add up to the no. of events to skip.
421  for (auto const & p : fhicl::ParameterSetRegistry::get())
422  {
423  if (p.second.has_key("source"))
424  {
425  if (p.second.has_key("source.firstEvent"))
426  {
427  int fe = p.second.get<int>("source.firstEvent") - 1; // events base index is 1
428  if (fe > 0) fStartEvent += fe;
429  break; // take the first occurence
430  } // no "else", if parameter not found, then just don't change anything
431  }
432  }
433  mf::LogInfo("ProtoDUNETriggeredBeam") << "Skip " << fStartEvent << " first events from the input file.";
434 
436 
437  // Coordinate transform
438  fBeamX = pset.get<float>("BeamX");
439  fBeamY = pset.get<float>("BeamY");
440  fBeamZ = pset.get<float>("BeamZ");
441  fBeamThetaShift = pset.get<float>("BeamThetaShift",0.0);
442  fBeamPhiShift = pset.get<float>("BeamPhiShift",0.0);
443 
444 
445  fRotateMonitorXZ = pset.get<float>("RotateMonitorXZ");
446  fRotateMonitorYZ = pset.get<float>("RotateMonitorYZ");
447  fBPROFEXTPos = pset.get<float>("BPROFEXTPosZ");
448  fBPROF4Pos = pset.get<float>("BPROF4PosZ");
449  fTRIG2Pos = pset.get<float>("TRIG2PosZ");
450  fNP04frontPos = pset.get<float>("NP04frontPosZ");
451  // Setup the beam monitor basis vectors
453 
454  fIFDH = 0;
455 
456  fL1 = pset.get<float>("L1");
457  fL2 = pset.get<float>("L2");
458  fL3 = pset.get<float>("L3");
459  fBeamBend = pset.get<float>("BeamBend");
460 
461  //New values for momentum spectrometer
462  fLMag = pset.get<float>("LMag");
463  fB = pset.get<float>("B");
464  fNominalP = pset.get<std::string>("NominalP");
465  fLB = fB * fLMag * std::stod(fNominalP) / 7.;
466 
467  fMaxSamples = pset.get<int>("MaxSamples", 0);
468 
469  fRNG = TRandom3(pset.get<int>("Seed", 0));
470  fVerbose = pset.get<bool>("Verbose", false);
471  fIncludeAnti = pset.get<bool>("IncludeAnti", false);
472  fResolutionFileName = pset.get<std::string>("ResolutionFileName");
473  fSamplingFileName = pset.get<std::string>("SamplingFileName");
474 
475  fSaveOutputTree = pset.get<bool>("SaveOutputTree");
476 
477  // Make sure we use ifdh to open the beam input file.
478  OpenInputFile(fFileName);
479  if(fUseDataDriven){
480  //std::string found_sampling_file = FindFile(fSamplingFileName);
481  //OpenInputFile(found_sampling_file);
482 
483  //std::string found_res_file = FindFile(fResolutionFileName);
484  //OpenInputFile(found_res_file);
485 
486  fSamplingFileName = FindFile(fSamplingFileName);
487  OpenInputFile(fSamplingFileName);
488 
489  fResolutionFileName = FindFile(fResolutionFileName);
490  OpenInputFile(fResolutionFileName);
491  }
492 }
493 
494 
495 
496 //-----------------------------default destructor----------------------------------
497 //------------------------------------------------------------------------------------
499 {
500  fIFDH->cleanup();
501 }
502 
503 //-------------------------------------------------------------------------------------
505 
507 
508  TFile *inputFile = new TFile(fFileName.c_str(),"READ");
509  // Check we have the file
510  if(inputFile == 0x0){
511  throw cet::exception("ProtoDUNETriggeredBeam") << "Input file " << fFileName << " cannot be read.\n";
512  }
513 
514  TTree *frontFaceTree = (TTree*)inputFile->Get(fNP04frontTreeName.c_str());
515  // Check we have the tree
516  if(frontFaceTree == 0x0){
517  throw cet::exception("ProtoDUNETriggeredBeam") << "Input tree " << fNP04frontTreeName << " cannot be read.\n";
518  }
519  std::cout << "All particle tree " << fNP04frontTreeName << " has " << frontFaceTree->GetEntries() << " entries" << std::endl;
520 
521  // Calculate the number of events to overlay
523 
524  // Fill all potential events from the NP04front tree
525  FillParticleMaps(frontFaceTree);
526 
527  TTree *trig1Tree = (TTree*)inputFile->Get(fTRIG1TreeName.c_str());
528  TTree *trig2Tree = (TTree*)inputFile->Get(fTRIG2TreeName.c_str());
529 
530  // Now search for trigger events
531  std::vector<int> triggeredEventIDs = FindTriggeredEvents(trig1Tree,trig2Tree);
532  std::cout << "Proto trigger list has " << triggeredEventIDs.size() << " events" << std::endl;
533 
534  // For triggered events, we now need to attach the other instrument information
535  std::vector<std::string> otherInstrumentTreeNames;
536  otherInstrumentTreeNames.push_back(fTOF1TreeName.c_str());
537  otherInstrumentTreeNames.push_back(fBPROF1TreeName.c_str());
538  otherInstrumentTreeNames.push_back(fBPROF2TreeName.c_str());
539  otherInstrumentTreeNames.push_back(fBPROF3TreeName.c_str());
540  otherInstrumentTreeNames.push_back(fBPROFEXTTreeName.c_str());
541  otherInstrumentTreeNames.push_back(fBPROF4TreeName.c_str());
542 
543  for(const std::string treeName : otherInstrumentTreeNames){
544  TTree *instrumentTree = (TTree*)inputFile->Get(treeName.c_str());
545  FillInstrumentInformation(triggeredEventIDs,instrumentTree);
546  std::cout << " - Finished adding information from " << treeName << std::endl;
547  }
548  std::cout << "Final trigger list has " << triggeredEventIDs.size() << " events" << std::endl;
549  fFinalTriggerEventIDs = triggeredEventIDs;
550 
551  // We are done with the input file now
552  inputFile->Close();
553  delete inputFile;
554  inputFile = 0x0;
555 
556  // Data-driven file setup
557  if(fUseDataDriven){
558  fSamplingFile = new TFile(fSamplingFileName.c_str());
559  fResolutionFile = new TFile(fResolutionFileName.c_str());
560  if (fNominalP =="0.5") {
561  // This is the same function as for 1 GeV
562  Setup1GeV();
563  }
564  else if (fNominalP =="1") {
565  Setup1GeV();
566  }
567  else if (fNominalP =="2") {
568  // This is the same function as for 1 GeV
569  Setup1GeV();
570  }
571  else if (fNominalP =="3") {
572  Setup3GeV();
573  }
574  else if (fNominalP =="6") {
575  Setup6GeV();
576  }
577  else if (fNominalP =="7") {
578  // This is the same function as for 7 GeV
579  Setup6GeV();
580  }
581 
582  Scale2DRes();
583  SetMinMax();
584  }
585  if (fSaveOutputTree) {
586  fTriggersGraph = tfs->makeAndRegister<TGraph>("Triggers", fBaseFileName.c_str(), 1);
587  fTriggersGraph->SetPoint(0, 0., triggeredEventIDs.size());
588  if (fUseDataDriven) {
589  fOutputTree = tfs->make<TTree>("tree", "");
590  fOutputTree->Branch("PDG", &fOutputPDG);
591  fOutputTree->Branch("Event", &fOutputEvent);
592  fOutputTree->Branch("Momentum", &fOutputMomentum);
593  fOutputTree->Branch("UnsmearedMomentum", &fOutputUnsmearedMomentum);
594  fOutputTree->Branch("HUpstream", &fOutputHUpstream);
595  fOutputTree->Branch("VUpstream", &fOutputVUpstream);
596  fOutputTree->Branch("HDownstream", &fOutputHDownstream);
597  fOutputTree->Branch("VDownstream", &fOutputVDownstream);
598  }
599  }
600 }
601 
602 //----------------------------------------------------------------------------------------
603 
605 {
606  // Grab the geometry object to see what geometry we are using
608  std::unique_ptr<sumdata::RunData> runcol(new sumdata::RunData(geo->DetectorName()));
609  run.put(std::move(runcol));
610 }
611 
612 //--------------------------------------------------------------------------------------------
613 
615 
616 }
617 
618 
619 //--------------------------------------------------------------------------------------------
621 {
622  if(fEventNumber >= static_cast<int>(fFinalTriggerEventIDs.size())){
623  throw cet::exception("ProtoDUNETriggeredBeam") << "Requested entry " << fEventNumber
624  << " but tree only has entries 0 to "
625  << fFinalTriggerEventIDs.size() - 1 << std::endl;
626  }
627 
628  // Define the truth collection for this event.
629  auto truthcol = std::make_unique< std::vector<simb::MCTruth> >();
630 
631  std::unique_ptr<std::vector<beam::ProtoDUNEBeamEvent> > beamData(new std::vector<beam::ProtoDUNEBeamEvent>);
632 
633  simb::MCTruth truth;
634  beam::ProtoDUNEBeamEvent beamEvent;
635 
636  // Group the events together: a triggered event with fOverlay background events
638 
639  // Fill the MCTruth object
640  fOutputEvent = e.id().event();
641  GenerateTrueEvent(truth, overlayEvent, beamEvent);
642 
643  // Add the MCTruth to the vector
644  truthcol->push_back(truth);
645 
646  // Finally, add the MCTruth to the event
647  e.put(std::move(truthcol));
648 
649  beamData->push_back( beamEvent );
650  e.put( std::move( beamData ) );
651 
652  // We have made our event, increment the event number.
653  ++fEventNumber;
654 }
655 
656 //--------------------------------------------------------------------------------------
657 
658 // Fill the particle maps using the input files. This links the events of interest
659 // to the entry number in fAllParticlesTree.
661 
662  float eventID, trackID, pdgCode, parentID;
663  float posX, posY, posZ, posT;
664  float momX, momY, momZ;
665 
666  frontFaceTree->SetBranchAddress("EventID",&eventID);
667  frontFaceTree->SetBranchAddress("TrackID",&trackID);
668  frontFaceTree->SetBranchAddress("PDGid",&pdgCode);
669  frontFaceTree->SetBranchAddress("ParentID",&parentID);
670  frontFaceTree->SetBranchAddress("x",&posX);
671  frontFaceTree->SetBranchAddress("y",&posY);
672  frontFaceTree->SetBranchAddress("z",&posZ);
673  frontFaceTree->SetBranchAddress("t",&posT);
674  frontFaceTree->SetBranchAddress("Px",&momX);
675  frontFaceTree->SetBranchAddress("Py",&momY);
676  frontFaceTree->SetBranchAddress("Pz",&momZ);
677 
678  // Loop over all particles and group them by events
679  for(unsigned int p = 0; p < frontFaceTree->GetEntries(); ++p){
680 
681  frontFaceTree->GetEntry(p);
682 
683  // Don't consider nuclei here
684  const int intPdgCode = static_cast<int>(pdgCode);
685  if(intPdgCode > 10000) continue;
686 
687  // If this particle is travelling backwards then it won't hit the detector
688  if(momZ < 0) continue;
689 
690  // Convert to detector coordinate system
691  ConvertCoordinates(posX,posY,posZ);
692 
693  // Keep only those particles that might reach the detector
695  if(posX < -500 || posX > 500) continue;
696  if(posY < -150 || posY > 850) continue;
697  }
698 
699  // Convert momentum
700  ConvertMomentum(momX,momY,momZ);
701 
702  const int intEventID = static_cast<int>(eventID);
703  const int intTrackID = static_cast<int>(trackID);
704  const int intParentID= static_cast<int>(parentID);
705  BeamParticle newParticle(intTrackID, intPdgCode, intParentID,
706  posX, posY, posZ, posT, momX, momY, momZ);
707 
708  std::map<int,BeamEvent>::iterator evIter = fAllBeamEvents.find(intEventID);
709  if(evIter == fAllBeamEvents.end()){
710  BeamEvent newBeamEvent(intEventID);
711  newBeamEvent.AddParticle(newParticle);
712  fAllBeamEvents.insert(std::make_pair(intEventID,newBeamEvent));
713  }
714  else{
715  evIter->second.AddParticle(newParticle);
716  }
717 
718  }
719 
720  std::cout << "Found " << fAllBeamEvents.size() << " potential events" << std::endl;
721 
722  // Reset the branch addresses as the variables are going out of scope
723  frontFaceTree->ResetBranchAddresses();
724 }
725 
726 //---------------------------------------------------------------------------------------
727 
728 // Search for events that have particles in TRIG1 and TRIG2 planes
729 std::vector<int> evgen::ProtoDUNETriggeredBeam::FindTriggeredEvents(TTree *trig1Tree, TTree *trig2Tree){
730 
731  const std::vector<int> allowedPDGs = {11,-11,13,-13,211,-211,321,-321,2212};
732 
733  float eventID, trackID, pdgCode, parentID;
734  float posX, posY, posZ, posT;
735  float momX, momY, momZ;
736 
737  // Look at trigger two first to reduce computation
738  trig2Tree->SetBranchAddress("EventID",&eventID);
739  trig2Tree->SetBranchAddress("TrackID",&trackID);
740  trig2Tree->SetBranchAddress("PDGid",&pdgCode);
741  trig2Tree->SetBranchAddress("ParentID",&parentID);
742  trig2Tree->SetBranchAddress("x",&posX);
743  trig2Tree->SetBranchAddress("y",&posY);
744  trig2Tree->SetBranchAddress("z",&posZ);
745  trig2Tree->SetBranchAddress("t",&posT);
746  trig2Tree->SetBranchAddress("Px",&momX);
747  trig2Tree->SetBranchAddress("Py",&momY);
748  trig2Tree->SetBranchAddress("Pz",&momZ);
749 
750  // Temporarily store the particle for events with particle in TRIG2. Just store
751  // the first one if there are two
752  std::map<int,BeamParticle> trig2Particles;
753 
754  for(unsigned int p = 0; p < trig2Tree->GetEntries(); ++p){
755 
756  trig2Tree->GetEntry(p);
757 
758  const int intEventID = static_cast<int>(eventID);
759 
760  // If this event didn't have any particles at NP04front then move on
761  if(fAllBeamEvents.find(intEventID) == fAllBeamEvents.end()) continue;
762 
763  // Carry on if we already found a particle for this event
764  if(trig2Particles.find(intEventID) != trig2Particles.end()) continue;
765 
766  // If the particle isn't of the type we want then move on
767  if(std::find(allowedPDGs.begin(),allowedPDGs.end(),static_cast<int>(pdgCode))==allowedPDGs.end()) continue;
768 
769 
770  TVector3 det_pos = ConvertProfCoordinates(posX, posY, posZ, fTRIG2Pos);
771  BeamParticle particle(static_cast<int>(trackID), static_cast<int>(pdgCode), static_cast<int>(parentID),
772  det_pos.X(), det_pos.Y(), det_pos.Z(), posT, momX, momY, momZ);
773  //posX, posY, posZ, posT, momX, momY, momZ);
774  trig2Particles.insert(std::make_pair(intEventID,particle));
775  }
776 
777  trig2Tree->ResetBranchAddresses();
778 
779  // Now look at TRIG1
780  trig1Tree->SetBranchAddress("EventID",&eventID);
781  trig1Tree->SetBranchAddress("TrackID",&trackID);
782  trig1Tree->SetBranchAddress("PDGid",&pdgCode);
783  trig1Tree->SetBranchAddress("ParentID",&parentID);
784  trig1Tree->SetBranchAddress("x",&posX);
785  trig1Tree->SetBranchAddress("y",&posY);
786  trig1Tree->SetBranchAddress("z",&posZ);
787  trig1Tree->SetBranchAddress("t",&posT);
788  trig1Tree->SetBranchAddress("Px",&momX);
789  trig1Tree->SetBranchAddress("Py",&momY);
790  trig1Tree->SetBranchAddress("Pz",&momZ);
791 
792  std::map<int,BeamParticle> trig1Particles;
793  for(unsigned int p = 0; p < trig1Tree->GetEntries(); ++p){
794 
795  trig1Tree->GetEntry(p);
796  const int intEventID = static_cast<int>(eventID);
797 
798  // Move on if this event had no particle in TRIG2
799  if(trig2Particles.find(intEventID) == trig2Particles.end()) continue;
800 
801  if(std::find(allowedPDGs.begin(),allowedPDGs.end(),static_cast<int>(pdgCode))==allowedPDGs.end()) continue;
802 
803  BeamParticle particle(static_cast<int>(trackID), static_cast<int>(pdgCode), static_cast<int>(parentID),
804  posX, posY, posZ, posT, momX, momY, momZ);
805  trig1Particles.insert(std::make_pair(intEventID,particle));
806  }
807 
808  // Add the particle information at TRIG1 and TRIG2 to the triggered events
809  const std::string trig1TreeName = fTRIG1TreeName.substr(fTRIG1TreeName.find("/")+1);
810  const std::string trig2TreeName = fTRIG2TreeName.substr(fTRIG2TreeName.find("/")+1);
811 
812  std::vector<int> trigEventIDs;
813  for(auto const &element : trig1Particles){
814  BeamEvent &event = fAllBeamEvents.at(element.first);
815  // Check that this makes sense... the same particle or one particle is the parent of the other
816  if((element.second.fTrackID != trig2Particles.at(element.first).fTrackID) &&
817  (element.second.fTrackID != trig2Particles.at(element.first).fParentID)) continue;
818 
819  event.fTriggerID = trig2Particles.at(element.first).fTrackID;
820  event.fTriggeredParticleInfo.insert(std::make_pair(trig1TreeName,element.second));
821  event.fTriggeredParticleInfo.insert(std::make_pair(trig2TreeName,trig2Particles.at(element.first)));
822 
823  bool isTriggerEvent = false;
824  // There is a rare case where the TRIG2 particle can decay before NP04front
825  if(event.fParticlesFront.find(event.fTriggerID) == event.fParticlesFront.end()){
826  event.fHasInteracted = true;
827  // Find the child particle in the map
828  std::cout << "- Candidate event " << trigEventIDs.size() << " trigger particle of type " << trig2Particles.at(element.first).fPDG << " not at the front face... searching for children" << std::endl;
829  for(const std::pair<int,BeamParticle> &partPair : event.fParticlesFront){
830  if(partPair.second.fParentID == event.fTriggerID){
831  std::cout << " - Found child with PDG = " << partPair.second.fPDG << std::endl;
832  event.fSecondaryTrackIDs.push_back(partPair.first);
833  isTriggerEvent = true;
834  }
835  }
836  }
837  else{
838  isTriggerEvent = true;
839  }
840 
841  if(isTriggerEvent) trigEventIDs.push_back(element.first);
842  }
843 
844  trig1Tree->ResetBranchAddresses();
845 
846  return trigEventIDs;
847 }
848 
849 //---------------------------------------------------------------------------------------
850 
851 void evgen::ProtoDUNETriggeredBeam::FillInstrumentInformation(std::vector<int> &eventIDs, TTree *instrumentTree){
852 
853  float eventID, trackID, pdgCode, parentID;
854  float posX, posY, posZ, posT;
855  float momX, momY, momZ;
856 
857  instrumentTree->SetBranchAddress("EventID",&eventID);
858  instrumentTree->SetBranchAddress("TrackID",&trackID);
859  instrumentTree->SetBranchAddress("PDGid",&pdgCode);
860  instrumentTree->SetBranchAddress("ParentID",&parentID);
861  instrumentTree->SetBranchAddress("x",&posX);
862  instrumentTree->SetBranchAddress("y",&posY);
863  instrumentTree->SetBranchAddress("z",&posZ);
864  instrumentTree->SetBranchAddress("t",&posT);
865  instrumentTree->SetBranchAddress("Px",&momX);
866  instrumentTree->SetBranchAddress("Py",&momY);
867  instrumentTree->SetBranchAddress("Pz",&momZ);
868 
869  // Buffer all of the tree entries for trigger events
870  std::map<const int,std::vector<unsigned int>> triggerIndices;
871  std::map<const int,const bool> arePionDecays;
872  std::map<const int,const int> trig1TrackIDs;
873  std::map<const int,const int> trig2TrackIDs;
874  std::map<const int,bool> foundTrackInEvent;
875  for(const int &trigEventID : eventIDs){
876  BeamEvent &event = fAllBeamEvents.at(trigEventID);
877  const int trig1TrackID = event.fTriggeredParticleInfo.at("TRIG1").fTrackID;
878  const int trig2TrackID = event.fTriggeredParticleInfo.at("TRIG2").fTrackID;
879  const int trig1TrackPDG = event.fTriggeredParticleInfo.at("TRIG1").fPDG;
880  const int trig2TrackPDG = event.fTriggeredParticleInfo.at("TRIG2").fPDG;
881  const bool isPionDecay = ((trig1TrackPDG==211) && (trig2TrackPDG==-13)) ||
882  ((trig1TrackPDG==-211) && (trig2TrackPDG==13));
883 
884  arePionDecays.insert(std::make_pair(trigEventID,isPionDecay));
885  trig1TrackIDs.insert(std::make_pair(trigEventID,trig1TrackID));
886  trig2TrackIDs.insert(std::make_pair(trigEventID,trig2TrackID));
887  foundTrackInEvent.insert(std::make_pair(trigEventID,false));
888 
889  triggerIndices.insert(std::make_pair(trigEventID,std::vector<unsigned int>()));
890  }
891 
892  // Strip the first part of the tree name to get just the instrument name
893  std::string treeName = instrumentTree->GetName();
894  treeName = treeName.substr(treeName.find("/")+1);
895 
896  for(unsigned int p = 0; p < instrumentTree->GetEntries(); ++p){
897  instrumentTree->GetEntry(p);
898  // If this isn't a triggered event then move on
899  const int thisEvent = static_cast<int>(eventID);
900  if(std::find(eventIDs.begin(),eventIDs.end(),thisEvent)==eventIDs.end()) continue;
901 
902  triggerIndices.at(thisEvent).push_back(p);
903  const int thisParticle = static_cast<int>(trackID);
904  if(trig2TrackIDs.at(thisEvent) == thisParticle){
905  BeamParticle particle(static_cast<int>(trackID), static_cast<int>(pdgCode), static_cast<int>(parentID),
906  posX, posY, posZ, posT, momX, momY, momZ);
907  fAllBeamEvents.at(thisEvent).fTriggeredParticleInfo.insert(std::make_pair(treeName,particle));
908  foundTrackInEvent.at(thisEvent) = true;
909  }
910  }
911 
912 
913  for (auto it = eventIDs.begin(); it != eventIDs.end();) {
914  const int ev = *it;
915  if(foundTrackInEvent.at(ev)) {
916  ++it;
917  continue;
918  }
919 
920  // If we didn't find TRIG2 particle, then look for the TRIG1 one
921  for(const unsigned int index : triggerIndices.at(ev)){
922  instrumentTree->GetEntry(index);
923  const int thisEvent = static_cast<int>(eventID);
924  const int thisParticle = static_cast<int>(trackID);
925  if(trig1TrackIDs.at(thisEvent) == thisParticle){
926  BeamParticle particle(static_cast<int>(trackID), static_cast<int>(pdgCode), static_cast<int>(parentID),
927  posX, posY, posZ, posT, momX, momY, momZ);
928  fAllBeamEvents.at(thisEvent).fTriggeredParticleInfo.insert(std::make_pair(treeName,particle));
929  foundTrackInEvent.at(thisEvent) = true;
930  break;
931  }
932  }
933 
934 
935  if(foundTrackInEvent.at(ev)) {
936  ++it;
937  continue;
938  }
939  // In the rare case that we still don't have the particle, try the TRIG1 parent
940  const int parentTrack = fAllBeamEvents.at(ev).fTriggeredParticleInfo.at("TRIG1").fParentID;
941  for(const unsigned int index : triggerIndices.at(ev)){
942  instrumentTree->GetEntry(index);
943  const int thisEvent = static_cast<int>(eventID);
944  const int thisParticle = static_cast<int>(trackID);
945  if(parentTrack == thisParticle){
946  BeamParticle particle(static_cast<int>(trackID), static_cast<int>(pdgCode), static_cast<int>(parentID),
947  posX, posY, posZ, posT, momX, momY, momZ);
948  fAllBeamEvents.at(thisEvent).fTriggeredParticleInfo.insert(std::make_pair(treeName,particle));
949  foundTrackInEvent.at(thisEvent) = true;
950 
951  break;
952  }
953 
954  }
955 
956  if(foundTrackInEvent.at(ev) == false){
957  fAllBeamEvents.at(ev).fTriggerID = -999;
958  // Remove this event from the input vector
959  it = eventIDs.erase(it);
960  std::cout << "Issue found with event " << ev << ". Removing it from the trigger list - " << eventIDs.size() << " remain" << std::endl;
961  //std::cout << "We didn't find tracks " << trig2TrackIDs.at(ev) << " or " << trig1TrackIDs.at(ev) << " in " << treeName << std::endl;
962  //std::cout << " - PDGs: 1 = " << fAllBeamEvents.at(ev).fTriggeredParticleInfo.at("TRIG1").fPDG
963  // << " and 2 = " << fAllBeamEvents.at(ev).fTriggeredParticleInfo.at("TRIG2").fPDG << std::endl;
964  //for(const unsigned int index : triggerIndices.at(ev)){
965  // instrumentTree->GetEntry(index);
966  // std::cout << "- Choice = " << static_cast<int>(trackID) << " :: " << static_cast<int>(pdgCode) << std::endl;
967  //}
968  }
969  else {
970  ++it;
971  }
972  }
973 
974  instrumentTree->ResetBranchAddresses();
975 }
976 
977 //---------------------------------------------------------------------------------------
978 
979 // Group the events to overlay a number of background events on each trigger event
981 {
982  OverlaidTriggerEvent newTriggerEvent(trigEventID);
983  // Look to see if any of these neighbouring events had particles
984  for(int overlayID = trigEventID - (fOverlays / 2); overlayID < trigEventID + (fOverlays/2); ++overlayID){
985  if(fAllBeamEvents.find(overlayID) == fAllBeamEvents.end()) continue;
986 
987  newTriggerEvent.AddOverlay(overlayID);
988  }
989 
990  return newTriggerEvent;
991 }
992 
993 //-------------------------------------------------------------------------------------------------
994 
996 
997  // A single particle seems the most accurate description.
999 
1000  // Get the actual triggered event first and the beam particle
1001  const BeamEvent trigEvent = fAllBeamEvents.at(overlayEvent.fTriggerEventID);
1002 
1003  // We need to be slightly careful here... there are rare events where the pion decays between TRIG2 and NP04front
1004  BeamParticle trigParticle;
1005  int primaryStatus = 1; // 1 means track in G4, 0 means don't track
1006  if(!trigEvent.fHasInteracted){
1007  trigParticle = trigEvent.fParticlesFront.at(trigEvent.fTriggerID);
1008  }
1009  else{
1010  const std::string trig2Name = fTRIG2TreeName.substr(fTRIG2TreeName.find("/")+1);
1011  trigParticle = trigEvent.fTriggeredParticleInfo.at(trig2Name);
1012  primaryStatus = 0;
1013  }
1014 
1015  std::cout << "- Generating event with trigger particle type " << trigParticle.fPDG << std::endl;
1016 
1017  // Time of the triggered particle (will make all times relative to this)
1018  const float triggerParticleTime = trigParticle.fPosT;
1019 
1020  // The track ID for primary particles in LArSoft should be negative. This is -1 for our triggered particle
1021  int trigOutputTrackID = -1*(mcTruth.NParticles() + 1);
1022 
1023  simb::MCParticle triggerParticle;
1024  if(!fUseDataDriven || trigEvent.fHasInteracted){
1025  // Create the MCParticle for the triggered beam particle - NB the time offset sets T = 0 for this particle
1026  triggerParticle = BeamParticleToMCParticle(trigParticle, trigOutputTrackID, triggerParticleTime, primaryStatus, "primary");
1027 
1028  // Fill the ProtoDUNEBeamEvent here to store beamline information
1029  SetBeamEvent(beamEvent,trigEvent);
1030  std::cout << " - Created trigger particle using pure simulation" << std::endl;
1031  std::cout << " - Active? " << primaryStatus << std::endl;
1032  std::cout << " - Located at " << triggerParticle.EndX() << " " <<
1033  triggerParticle.EndY() << " " << triggerParticle.EndZ() <<
1034  std::endl;
1035  }
1036  else{
1037  triggerParticle = DataDrivenMCParticle(trigParticle, trigOutputTrackID, triggerParticleTime, beamEvent, primaryStatus, "primary");
1038  std::cout << " - Created trigger particle using data driven method" << std::endl;
1039  std::cout << " - Located at " << triggerParticle.EndX() << " " <<
1040  triggerParticle.EndY() << " " << triggerParticle.EndZ() <<
1041  std::endl;
1042  }
1043 
1044  //mcTruth.Add(triggerParticle);
1045 
1046  std::vector<simb::MCParticle> secondaries;
1047  std::vector<int> secondary_pdgs;
1048  // Now we can add any secondaries produced in the interaction before NP04front
1049  if(trigEvent.fHasInteracted){
1050  int count = mcTruth.NParticles();
1051  for(const int &id : trigEvent.fSecondaryTrackIDs){
1052  trigOutputTrackID = -1*(count + 2);
1053  BeamParticle secondary = trigEvent.fParticlesFront.at(id);
1054  simb::MCParticle secondaryParticle = BeamParticleToMCParticle(
1055  secondary, trigOutputTrackID, triggerParticleTime+secondary.fPosT, 1,
1056  GetSecondaryProcess(trigParticle.fPDG, secondary.fPDG), triggerParticle.TrackId());
1057  secondaries.push_back(secondaryParticle);
1058  triggerParticle.AddDaughter(trigOutputTrackID);
1059  secondary_pdgs.push_back(secondary.fPDG);
1060  //mcTruth.Add(secondaryParticle);
1061  ++count;
1062  }
1063  }
1064 
1065  if(!secondaries.empty()){
1066  std::cout << " - Trigger particle has daughters:";
1067  for (int i = 0; i < triggerParticle.NumberDaughters(); ++i) {
1068  std::cout << " " << triggerParticle.Daughter(i);
1069  }
1070  std::cout << std::endl;
1071  }
1072 
1073  // Add the trigger particle now that the hierarchy has been established
1074  if (trigEvent.fHasInteracted) {
1075  triggerParticle.SetEndProcess(
1076  GetPrimaryEndProcess(trigParticle.fPDG, secondary_pdgs));
1077  }
1078  mcTruth.Add(triggerParticle);
1079  // Now add all of the secondaries (if any)
1080  for (const simb::MCParticle & sec : secondaries) {
1081  mcTruth.Add(sec);
1082  std::cout << " - Added secondary " << sec.TrackId() <<
1083  " of type " << sec.PdgCode() << " with process " <<
1084  sec.Process() <<
1085  " from interacting primary " << triggerParticle.PdgCode() <<
1086  " " << triggerParticle.Mother() << std::endl;
1087  std::cout << " - Located at " << sec.EndX() << " " <<
1088  sec.EndY() << " " <<
1089  sec.EndZ() << std::endl;
1090  }
1091 
1092  // Now let's deal with all of the background events
1093  for(const int &eventID : overlayEvent.fOverlayEventIDs){
1094  // Each overlay event needs a base time within +/- fBeamWindow of the triggered beam event
1095  double baseTime = (fFlatRnd.fire() - 0.5)*2.0*(fReadoutWindow*1000.*1000.);
1096  // Special case for triggered event
1097  if(overlayEvent.fTriggerEventID == eventID) baseTime = triggerParticleTime;
1098 
1099  for (std::pair<int,BeamParticle> element : fAllBeamEvents.at(eventID).fParticlesFront){
1100  // Don't double count the trigger particle
1101  if(overlayEvent.fTriggerEventID == eventID && element.first == trigParticle.fTrackID) continue;
1102  BeamParticle particle = element.second;
1103 
1104  const int outputTrackID = -1*(mcTruth.NParticles() + 1);
1105  // For background particles we need to "back-strapolate" them to BPROFEXT so that they can hit the CRT
1106  SetBackgroundPosition(particle);
1107  simb::MCParticle backgroundParticle = BeamParticleToMCParticle(particle,outputTrackID,baseTime,1,"primaryBackground");
1108  mcTruth.Add(backgroundParticle);
1109  }
1110 
1111  }
1112 
1113  std::cout << "Created event with " << mcTruth.NParticles() << " particles." << std::endl;
1114 }
1115 
1116 //---------------------------------------------------------------------------------------
1117 
1118 simb::MCParticle evgen::ProtoDUNETriggeredBeam::BeamParticleToMCParticle(const BeamParticle &beamParticle, const int outputTrackID, const float timeOffset, const int primaryStatus, const std::string process, const int motherID){
1119 
1120  simb::MCParticle newParticle(outputTrackID,beamParticle.fPDG,process, motherID, -1.0, primaryStatus);
1121 
1122  // Get the position four-vector
1123  const TLorentzVector pos(beamParticle.fPosX,beamParticle.fPosY,beamParticle.fPosZ,beamParticle.fPosT - timeOffset);
1124 
1125  // Get the mass to calculate the momentum four-vector
1126  const TDatabasePDG* databasePDG = TDatabasePDG::Instance();
1127  const TParticlePDG* definition = databasePDG->GetParticle(beamParticle.fPDG);
1128  const float mass = definition->Mass();
1129  const float energy = sqrt(mass*mass + TVector3(beamParticle.fMomX,beamParticle.fMomY,beamParticle.fMomZ).Mag2());
1130 
1131  const TLorentzVector mom(beamParticle.fMomX,beamParticle.fMomY,beamParticle.fMomZ,energy);
1132 
1133  // Add the single trajectory point to the MCParticle
1134  newParticle.AddTrajectoryPoint(pos,mom);
1135  return newParticle;
1136 }
1137 
1138 //---------------------------------------------------------------------------------------
1139 
1141  const BeamParticle &beamParticle, const int outputTrackID,
1142  const float timeOffset, beam::ProtoDUNEBeamEvent & beamEvent, const int primaryStatus, const std::string process) {
1143 
1144  const int pdg = (fIncludeAnti ? beamParticle.fPDG : abs(beamParticle.fPDG));
1145  simb::MCParticle newParticle(outputTrackID, pdg, process, -1, -1.0, primaryStatus);
1146 
1147  double kin_samples[5]; //the point in phase space to check against pdf
1148  double pdf_check; //the number used for the checking
1149  bool sample_again = true;
1150 
1151  double sampled_momentum = 0.;
1152  double sampled_h_upstream = 0.;
1153  double sampled_v_upstream = 0.;
1154  double sampled_h_downstream = 0.;
1155  double sampled_v_downstream = 0.;
1156  int nSamples = 0;
1157  while (sample_again) {
1158  /*
1159  if (nSamples > fMaxSamples) {
1160  throw cet::exception("ProtoDUNETriggeredBeam") <<
1161  "Reached max samples. Exiting" << std::endl;
1162  }*/
1163  fRNG.RndmArray(5, &kin_samples[0]);
1164  pdf_check = fRNG.Rndm();
1165 
1166  //Need to convert the numbers sampled for the kinematics (0, 1)
1167  //to within the sampling range
1168  double kin_point[5];
1169  //Convert(kin_samples, minima, maxima, kin_point);
1170  ConvertSamplingPoint(kin_samples, fMinima, fMaxima, kin_point);
1171 
1172 
1173  //Find the bin in the THnSparseD. If the bin has a value of 0,
1174  //then it would not have been allocated to save on memory.
1175  //The false parameter prevents that bin from being allocated here,
1176  //to save memory
1177  const long long bin = fPDFs.at(fPDGToName.at(pdg))->GetBin(&kin_point[0],false);
1178  //The bin has no chance of being populated, move on
1179  if (bin == -1) continue;
1180 
1181  //Find how likely we are to populate this bin
1182  const double pdf_value = fPDFs.at(fPDGToName.at(pdg))->GetBinContent(bin);
1183 
1184  //If successful, save info and move on
1185  if (pdf_check <= pdf_value) {
1186  if (fVerbose) {
1187  std::cout << "bin: " << bin << " PDF val: " << pdf_value <<
1188  " Check: " << pdf_check << std::endl;
1189  std::cout << kin_samples[0] << " " << kin_samples[1] << " " <<
1190  kin_samples[2] << " " << kin_samples[3] << " " <<
1191  kin_samples[4] << std::endl;
1192  std::cout << kin_point[0] << " " << kin_point[1] << " " <<
1193  kin_point[2] << " " << kin_point[3] << " " <<
1194  kin_point[4] << std::endl;
1195  std::cout << "Will keep" << std::endl;
1196  }
1197 
1198  //diff
1199  sampled_momentum = kin_point[0];
1200  sampled_v_upstream = kin_point[1];
1201  sampled_h_upstream = kin_point[2];
1202  sampled_v_downstream = kin_point[3];
1203  sampled_h_downstream = kin_point[4];
1204 
1205  sample_again = false;
1206  }
1207  ++nSamples;
1208  }
1209 
1210  TLorentzVector position(0, 0, 0, 0);
1211  TLorentzVector momentum(0., 0., 0., 0.);
1212  SetDataDrivenPosMom(position, momentum, sampled_h_upstream,
1213  sampled_v_upstream, sampled_h_downstream,
1214  sampled_v_downstream, sampled_momentum,
1215  pdg);
1216  newParticle.AddTrajectoryPoint(position, momentum);
1217 
1218  SetDataDrivenBeamEvent(beamEvent, sampled_h_upstream,
1219  sampled_v_upstream, sampled_h_downstream,
1220  sampled_v_downstream, sampled_momentum);
1221 
1222  if (fSaveOutputTree) {
1223  fOutputPDG = pdg;
1224  fOutputMomentum = sampled_momentum;
1225  fOutputHUpstream = sampled_h_upstream;
1226  fOutputVUpstream = sampled_v_upstream;
1227  fOutputHDownstream = sampled_h_downstream;
1228  fOutputVDownstream = sampled_v_downstream;
1229  fOutputTree->Fill();
1230  }
1231 
1232  return newParticle;
1233 }
1234 
1235 //------------------------------------------------------------------------------------
1236 
1237 
1239  double input_point[5], std::vector<double> minima,
1240  std::vector<double> maxima, double output_point[5]) {
1241  for (int i = 0; i < 5; ++i) {
1242  const double delta = maxima[i] - minima[i];
1243  output_point[i] = minima[i] + delta * input_point[i];
1244  }
1245 }
1246 
1248  TLorentzVector & position, TLorentzVector & momentum, double sampledHUp,
1249  double sampledVUp, double sampledHDown, double sampledVDown,
1250  double sampledMomentum, int beamPDG) {
1251 
1252  const double upstreamX = 96. - sampledHUp;
1253  const double upstreamY = 96. - sampledVUp;
1254  const double downstreamX = 96. - sampledHDown;
1255  const double downstreamY = 96. - sampledVDown;
1256 
1257 
1258 //rename these
1259  TVector3 upstream_point = ConvertProfCoordinates(upstreamX, upstreamY, 0.,
1260  fBPROFEXTPos);
1261  TVector3 downstream_point = ConvertProfCoordinates(downstreamX, downstreamY, 0.,
1262  fBPROF4Pos);
1263  TVector3 dR = (downstream_point - upstream_point).Unit();
1264 
1265  //Project to generator point
1266  double deltaZ = (fBeamZ - downstream_point.Z());
1267  double deltaX = (dR.X() / dR.Z()) * deltaZ;
1268  double deltaY = (dR.Y() / dR.Z()) * deltaZ;
1269 
1270  TVector3 generator_point = downstream_point +
1271  TVector3(deltaX, deltaY, deltaZ);
1272  //Set the position 4-vector
1273  //Time = 0 for now?
1274  position = TLorentzVector(generator_point, 0.);
1275 
1276  //Prints out the projected position at the face of the TPC
1277  if (fVerbose) {
1278  deltaZ = (-1.*fBeamZ);
1279  deltaX = (dR.X() / dR.Z()) * deltaZ;
1280  deltaY = (dR.Y() / dR.Z()) * deltaZ;
1281 
1282  TVector3 last_point = generator_point +
1283  TVector3(deltaX, deltaY, deltaZ);
1284 
1285  std::cout << last_point.X() << " " << last_point.Y() << " " <<
1286  last_point.Z() << std::endl;
1287  }
1288 
1289  double unsmeared_momentum = 0.;
1290  /*switch (fUnsmearType) {
1291  case 1:
1292  unsmeared_momentum = UnsmearMomentum1D(sampledMomentum, beamPDG);
1293  break;
1294  case 2:*/
1295  unsmeared_momentum = UnsmearMomentum2D(sampledMomentum, beamPDG);
1296  //GetSystWeights();
1297  /*break;
1298  default:
1299  //Just do 1D
1300  unsmeared_momentum = UnsmearMomentum1D(sampledMomentum, beamPDG);
1301  break;
1302  }*/
1303 
1304  //TVector3 mom_vec = fRandMomentum[fCurrentEvent]*dR;
1305  //TVector3 mom_vec = unsmeared_momentum*dR;
1306  const TVector3 mom_vec = unsmeared_momentum*dR;
1307  fOutputUnsmearedMomentum = unsmeared_momentum;
1308 
1309  //Get the PDG and set the mass & energy accordingly
1310  const TDatabasePDG * dbPDG = TDatabasePDG::Instance();
1311  const TParticlePDG * def = dbPDG->GetParticle(beamPDG);
1312  const double mass = def->Mass();
1313  const double energy = sqrt(mass*mass + mom_vec.Mag2());
1314 
1315  //Set the momentum 4-vector
1316  momentum = TLorentzVector(mom_vec, energy);
1317 }
1318 
1319 /*
1320 double evgen::ProtoDUNETriggeredBeam::(double momentum, int pdg) {
1321  TF1 * res = fResolutions[fPDGToName[pdg]];
1322  double mean = res->GetParameter(1);
1323  double sigma = res->GetParameter(2);
1324  double t = fRNG.Gaus(mean, sigma); //random number from momentum resolution
1325  return (momentum/(t + 1.));
1326 }*/
1327 
1329 
1330  if (fVerbose) {
1331  std::cout << "Using 2D Unsmear method" << std::endl;
1332  }
1333 
1334  TH2D * res = fResolutionHists2D.at(fPDGToName.at(pdg));
1335 
1336  const int xBin = res->GetXaxis()->FindBin(momentum);
1337  if (fVerbose) {
1338  std::cout << "Momentum & bin: " << momentum << " " <<
1339  xBin << std::endl;
1340  }
1341 
1342  double true_min = res->GetYaxis()->GetXmin();
1343  double true_max = res->GetYaxis()->GetXmax();
1344  for (int i = 1; i <= res->GetNbinsY(); ++i) {
1345  if (res->GetBinContent(xBin, i) > 0.) {
1346  true_min = res->GetYaxis()->GetBinLowEdge(i);
1347  break;
1348  }
1349  }
1350  for (int i = res->GetNbinsY(); i >= 1; --i) {
1351  if (res->GetBinContent(xBin, i) > 0.) {
1352  true_max = res->GetYaxis()->GetBinUpEdge(i);
1353  break;
1354  }
1355  }
1356 
1357  if (fVerbose)
1358  std::cout << "True min and max: " << true_min << " " << true_max << std::endl;
1359 
1360  double unsmeared_momentum = 0.;
1361  while (true) {
1362  const double t = fRNG.Uniform(true_min, true_max);
1363  const double pdf_check = fRNG.Rndm(); //random number to check against PDF
1364 
1365  const int yBin = res->GetYaxis()->FindBin(t);
1366  const double pdf_value = res->GetBinContent(xBin, yBin);
1367  if (fVerbose) {
1368  std::cout << "True mom & bin: " << t << " " << yBin << std::endl;
1369  std::cout << "Check & val: " << pdf_check << " " << pdf_value <<
1370  std::endl;
1371  }
1372  if (pdf_check < pdf_value) {
1373  unsmeared_momentum = t;
1374  if (fVerbose) std::cout << "Setting momentum to " << t << std::endl;
1375  break;
1376  }
1377  }
1378 
1379  return unsmeared_momentum;
1380 }
1381 
1383  const int &primary_pdg, const std::vector<int> &secondary_pdgs) {
1384 
1385  if (primary_pdg == 2212) {
1386  return "protonInelastic";
1387  }
1388  else if (primary_pdg == 211) {
1389  if (std::find(secondary_pdgs.begin(), secondary_pdgs.end(), -13) !=
1390  secondary_pdgs.end()) {
1391  return "Decay";
1392  }
1393  else {
1394  return "pi+Inelastic";
1395  }
1396  }
1397  else if (primary_pdg == -211) {
1398  if (std::find(secondary_pdgs.begin(), secondary_pdgs.end(), 13) !=
1399  secondary_pdgs.end()) {
1400  return "Decay";
1401  }
1402  else {
1403  return "pi-Inelastic";
1404  }
1405  }
1406  else if (primary_pdg == 321) {
1407  return "Decay";
1408  }
1409 
1410  return "default";
1411 }
1412 
1414  const int &primary_pdg, const int &secondary_pdg) {
1415 
1416  std::string preamble = "primary:";
1417  if (primary_pdg == 2212) {
1418  return preamble + "protonInelastic";
1419  }
1420  else if (primary_pdg == 211) {
1421  if (secondary_pdg == -13) {
1422  return preamble + "Decay";
1423  }
1424  else if (secondary_pdg == 211 || secondary_pdg == -211 ||
1425  secondary_pdg == 2212 || secondary_pdg == 2112 ||
1426  secondary_pdg > 2212 || secondary_pdg == 22) {
1427  return preamble + "pi+Inelastic";
1428  }
1429  }
1430  else if (primary_pdg == -211) {
1431  if (secondary_pdg == 13) {
1432  return preamble + "Decay";
1433  }
1434  else if (secondary_pdg == 211 || secondary_pdg == -211 ||
1435  secondary_pdg == 2212 || secondary_pdg == 2112 ||
1436  secondary_pdg > 2212 || secondary_pdg == 22) {
1437  return preamble + "pi-Inelastic";
1438  }
1439  }
1440  else if (primary_pdg == 321) {
1441  return preamble + "Decay";
1442  }
1443 
1444  std::cout << "Notice! Unknown secondary option " << primary_pdg << " " <<
1445  secondary_pdg << std::endl;
1446  return preamble + "default";
1447 }
1448 
1450  if (fNominalP =="0.5") {
1451  fMinima[0] = 0.3;
1452  fMaxima[0] = 0.7;
1453  }
1454  else if (fNominalP =="2") {
1455  fMinima[0] = 1.6;
1456  fMaxima[0] = 2.4;
1457  }
1458  else if (fNominalP =="3") {
1459  fMinima[0] = 2.4;
1460  fMaxima[0] = 3.6;
1461  }
1462  else if (fNominalP =="6") {
1463  fMinima[0] = 5.0;
1464  fMaxima[0] = 7.0;
1465  }
1466  else if (fNominalP =="7") {
1467  fMinima[0] = 6.0;
1468  fMaxima[0] = 8.0;
1469  }
1470 }
1471 
1473  for (auto it = fResolutionHists2D.begin();
1474  it != fResolutionHists2D.end(); ++it) {
1475  TH2D * this_hist = it->second;
1476  for (int i = 1; i <= this_hist->GetNbinsX(); ++i) {
1477  const double integral = this_hist->TH1::Integral(i, i);
1478  double total = 0.;
1479  for (int j = 1; j <= this_hist->GetNbinsY(); ++j) {
1480  this_hist->SetBinContent(i, j,
1481  this_hist->GetBinContent(i, j) / integral);
1482  total += this_hist->GetBinContent(i, j);
1483  }
1484  }
1485  }
1486 
1487 /*
1488  for (auto it = fResolutionHists2DPlus.begin();
1489  it != fResolutionHists2DPlus.end(); ++it) {
1490  TH2D * this_hist = it->second;
1491  for (int i = 1; i <= this_hist->GetNbinsX(); ++i) {
1492  double integral = this_hist->Integral(i, i);
1493  double total = 0.;
1494  for (int j = 1; j <= this_hist->GetNbinsY(); ++j) {
1495  this_hist->SetBinContent(i, j,
1496  this_hist->GetBinContent(i, j) / integral);
1497  total += this_hist->GetBinContent(i, j);
1498  }
1499  }
1500 
1501  this_hist->Divide(fResolutionHists2D[it->first]);
1502  }
1503 
1504  for (auto it = fResolutionHists2DMinus.begin();
1505  it != fResolutionHists2DMinus.end(); ++it) {
1506  TH2D * this_hist = it->second;
1507  for (int i = 1; i <= this_hist->GetNbinsX(); ++i) {
1508  double integral = this_hist->Integral(i, i);
1509  double total = 0.;
1510  for (int j = 1; j <= this_hist->GetNbinsY(); ++j) {
1511  this_hist->SetBinContent(i, j,
1512  this_hist->GetBinContent(i, j) / integral);
1513  total += this_hist->GetBinContent(i, j);
1514  }
1515  }
1516 
1517  this_hist->Divide(fResolutionHists2D[it->first]);
1518  }
1519  */
1520 }
1521 
1523  std::vector<std::string> particle_types = {
1524  "Muons", "Pions", "Protons", "Electrons"
1525  };
1526  for (size_t i = 0; i < particle_types.size(); ++i) {
1527  const std::string part_type = particle_types[i];
1528  if (part_type == "Muons") {
1529  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get("Pions");
1530  }
1531  else {
1532  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get(part_type.c_str());
1533  }
1534 
1535  //Also get the resolutions
1536  std::string res_name = "";
1537  if (part_type == "Muons") {
1538  res_name = "hPionsRes";
1539  }
1540  else {
1541  res_name = "h" + part_type + "Res";
1542  }
1543 
1544  //fResolutionHists[part_type] = (TH1D*)fResolutionFile->Get(res_name.c_str());
1545 
1546  res_name += "2D";
1547  fResolutionHists2D[part_type] = (TH2D*)fResolutionFile->Get(res_name.c_str());
1548 
1549  /*
1550  std::string plus_name = res_name + "Plus";
1551  fResolutionHists2DPlus[part_type] = (TH2D*)fResolutionFile->Get(plus_name.c_str());
1552 
1553  std::string minus_name = res_name + "Minus";
1554  fResolutionHists2DMinus[part_type] = (TH2D*)fResolutionFile->Get(minus_name.c_str());
1555  */
1556 
1557  }
1558 }
1559 
1561  std::vector<std::string> particle_types = {
1562  "Muons", "Pions", "Protons", "Electrons", "Kaons"
1563  };
1564 
1565  for (size_t i = 0; i < particle_types.size(); ++i) {
1566  const std::string part_type = particle_types[i];
1567  if (part_type == "Muons") {
1568  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get("Pions");
1569  }
1570  else if (part_type == "Kaons") {
1571  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get("Protons");
1572  }
1573  else {
1574  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get(part_type.c_str());
1575  }
1576 
1577  //Also get the resolutions
1578  std::string res_name = "";
1579  if (part_type == "Muons") {
1580  res_name = "hPionsRes";
1581  }
1582  /*
1583  else if (part_type == "Kaons") {
1584  res_name = "hProtonsRes";
1585  }*/
1586  else {
1587  res_name = "h" + part_type + "Res";
1588  }
1589 
1590  //fResolutionHists[part_type] = (TH1D*)fResolutionFile->Get(res_name.c_str());
1591 
1592  res_name += "2D";
1593  fResolutionHists2D[part_type] = (TH2D*)fResolutionFile->Get(res_name.c_str());
1594 
1595  /*
1596  std::string plus_name = res_name + "Plus";
1597  fResolutionHists2DPlus[part_type] = (TH2D*)fResolutionFile->Get(plus_name.c_str());
1598 
1599  std::string minus_name = res_name + "Minus";
1600  fResolutionHists2DMinus[part_type] = (TH2D*)fResolutionFile->Get(minus_name.c_str());
1601  */
1602  }
1603 }
1604 
1606  std::vector<std::string> particle_types = {
1607  "Muons", "Pions", "Protons", "Electrons", "Kaons"
1608  };
1609 
1610  for (size_t i = 0; i < particle_types.size(); ++i) {
1611  const std::string part_type = particle_types[i];
1612  if (part_type == "Muons" || part_type == "Electrons") {
1613  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get("Pions");
1614  }
1615  else {
1616  fPDFs[part_type] = (THnSparseD*)fSamplingFile->Get(part_type.c_str());
1617  }
1618 
1619  //Also get the resolutions
1620  std::string res_name = "";
1621  if (part_type == "Muons") {
1622  res_name = "hPionsRes";
1623  }
1624  else {
1625  res_name = "h" + part_type + "Res";
1626  }
1627 
1628  //fResolutionHists[part_type] = (TH1D*)fResolutionFile->Get(res_name.c_str());
1629 
1630  res_name += "2D";
1631  fResolutionHists2D[part_type] = (TH2D*)fResolutionFile->Get(res_name.c_str());
1632 
1633  /*
1634  std::string plus_name = res_name + "Plus";
1635  fResolutionHists2DPlus[part_type] = (TH2D*)fResolutionFile->Get(plus_name.c_str());
1636 
1637  std::string minus_name = res_name + "Minus";
1638  fResolutionHists2DMinus[part_type] = (TH2D*)fResolutionFile->Get(minus_name.c_str());
1639  */
1640  }
1641 }
1642 
1644  beam::ProtoDUNEBeamEvent & beamEvent,
1645  double sampledHUp, double sampledVUp, double sampledHDown,
1646  double sampledVDown, double sampledMomentum) {
1647 
1648  beamEvent.SetTOFs(std::vector<double>{0.});
1649  beamEvent.SetTOFChans(std::vector<int>{0});
1650  beamEvent.SetUpstreamTriggers(std::vector<size_t>{0});
1651  beamEvent.SetDownstreamTriggers(std::vector<size_t>{0});
1652  beamEvent.SetCalibrations(0., 0., 0., 0.);
1653  beamEvent.DecodeTOF();
1654 
1655  beamEvent.SetMagnetCurrent(0.);
1656  beamEvent.SetTimingTrigger(12);
1657 
1658  beam::CKov dummy;
1659  dummy.trigger = 0;
1660  dummy.pressure = 0.;
1661  dummy.timeStamp = 0.;
1662  beamEvent.SetCKov0(dummy);
1663  beamEvent.SetCKov1(dummy);
1664 
1665  beamEvent.SetActiveTrigger(0);
1666  beamEvent.SetT0(std::make_pair(0.,0.));
1667 
1668  //Dummy positions for these
1669  beamEvent.SetFBMTrigger("XBPF022697", MakeFiberMonitor(.5));
1670  beamEvent.SetFBMTrigger("XBPF022698", MakeFiberMonitor(.5));
1671  beamEvent.SetFBMTrigger("XBPF022701", MakeFiberMonitor(.5));
1672  beamEvent.SetFBMTrigger("XBPF022702", MakeFiberMonitor(.5));
1673 
1674  const double upstream_x = sampledHUp;
1675  const double upstream_y = sampledVUp;
1676  const double downstream_x = sampledHDown;
1677  const double downstream_y = sampledVDown;
1678 
1679  beamEvent.SetFBMTrigger("XBPF022707", MakeFiberMonitor(96. - upstream_x));//X
1680  beamEvent.SetFBMTrigger("XBPF022708", MakeFiberMonitor(96. - upstream_y));//Y
1681 
1682  beamEvent.SetFBMTrigger("XBPF022716", MakeFiberMonitor(96. - downstream_x));//X
1683  beamEvent.SetFBMTrigger("XBPF022717", MakeFiberMonitor(96. - downstream_y));//Y
1684 
1685  MakeTracks(beamEvent);
1686 
1687  beamEvent.AddRecoBeamMomentum(sampledMomentum);
1688 }
1689 
1690 // Function written in similar way as "openDBs()" in CORSIKAGen_module.cc
1692 {
1693  // Setup ifdh object
1694  if (!fIFDH)
1695  {
1696  fIFDH = new ifdh_ns::ifdh;
1697  }
1698 
1699  const char* ifdh_debug_env = std::getenv("IFDH_DEBUG_LEVEL");
1700  if ( ifdh_debug_env )
1701  {
1702  mf::LogInfo("ProtoDUNETriggeredBeam") << "IFDH_DEBUG_LEVEL: " << ifdh_debug_env<<"\n";
1703  fIFDH->set_debug(ifdh_debug_env);
1704  }
1705 
1706  const std::string path(gSystem->DirName(filename.c_str()));
1707  const std::string pattern(gSystem->BaseName(filename.c_str()));
1708 
1709  auto const flist = fIFDH->findMatchingFiles(path,pattern);
1710  if (flist.empty())
1711  {
1712  struct stat buffer;
1713  if (stat(filename.c_str(), &buffer) != 0)
1714  {
1715  throw cet::exception("ProtoDUNETriggeredBeam") << "No files returned for path:pattern: "<<path<<":"<<pattern<<std::endl;
1716  }
1717  else
1718  {
1719  mf::LogInfo("ProtoDUNETriggeredBeam") << "For "<< filename <<"\n";
1720  }
1721  }
1722  else
1723  {
1724  std::pair<std::string, long> f = flist.front();
1725 
1726  mf::LogInfo("ProtoDUNETriggeredBeam") << "For "<< filename <<"\n";
1727 
1728  // Do the fetching, store local filepaths in locallist
1729 
1730  mf::LogInfo("ProtoDUNETriggeredBeam")
1731  << "Fetching: " << f.first << " " << f.second <<"\n";
1732  std::string fetchedfile(fIFDH->fetchInput(f.first));
1733  MF_LOG_DEBUG("ProtoDUNETriggeredBeam") << " Fetched; local path: " << fetchedfile;
1734 
1735  filename = fetchedfile;
1736  }
1737 }
1738 
1739 
1740 //----------------------------------------------------------------------------------
1741 
1743 
1744  // Convert to cm and shift to the detector coordinate frame
1745  x = (x/10.) + fBeamX;
1746  y = (y/10.) + fBeamY;
1747  z = fBeamZ; // Just use the z position
1748 }
1749 
1750 //--------------------------------------------------------------------------------
1751 
1753 
1754  // Convert to GeV
1755  px = px / 1000.;
1756  py = py / 1000.;
1757  pz = pz / 1000.;
1758 
1759  // If we want to rotate by changing theta and phi, do it here.
1760  TVector3 momVec(px,py,pz);
1761  momVec.SetTheta(momVec.Theta() + fBeamThetaShift);
1762  momVec.SetPhi(momVec.Phi() + fBeamPhiShift);
1763 
1764  px = momVec.X();
1765  py = momVec.Y();
1766  pz = momVec.Z();
1767 }
1768 
1769 //-----------------------------------------------------------------------------
1770 
1772 
1773  // The number of events to overlay is as follows:
1774  // N = Intensity * 2.0 * ReadoutWindow / BeamSpillLength
1775  fOverlays = fIntensity * (2.0 * fReadoutWindow / 1000.) / fBeamSpillLength;
1776  std::cout << "Number of overlays = " << fOverlays << std::endl;
1777 }
1778 
1779 //----------------------------------------------------------------------------------
1780 
1781 // We need to rotate the beam monitor coordinates into the detector frame (matching NP04front)
1782 // This means they can later be treated in the same way as the standard NP04front positions
1783 TLorentzVector evgen::ProtoDUNETriggeredBeam::ConvertBeamMonitorCoordinates(float x, float y, float z, float t, float zOffset){
1784 
1785  const float off = fNP04frontPos - zOffset;
1786 
1787 // TLorentzVector old(x,y,z,t);
1788 
1789  // Convert the coordinates using the rotated basis vectors
1790  float newX = x*fBMBasisX.X() + y*fBMBasisY.X() + (z-zOffset)*fBMBasisZ.X() + off*fabs(fBMBasisZ.X());
1791  float newY = x*fBMBasisX.Y() + y*fBMBasisY.Y() + (z-zOffset)*fBMBasisZ.Y() + off*fabs(fBMBasisZ.Y());
1792  float newZ = x*fBMBasisX.Z() + y*fBMBasisY.Z() + (z-zOffset) - off*fabs(fBMBasisZ.Z());
1793 
1794  // Account for the small differences between NP04front and the detector coordinates
1795  newX += fBeamX*10.;
1796  newY += fBeamY*10.;
1797  newZ += fBeamZ*10.;
1798 
1799  // Make our new beam monitor position in the detector coordinate system
1800  TLorentzVector result(newX,newY,newZ,t);
1801 
1802 // std::cout << "Coordinate transform..." << std::endl;
1803 // old.Print();
1804 // result.Print();
1805 
1806  return result;
1807 }
1808 
1809 //----------------------------------------------------------------------------------
1810 
1811 TVector3 evgen::ProtoDUNETriggeredBeam::ConvertProfCoordinates(double x, double y, double z, double zOffset){
1812  const double off = fNP04frontPos - zOffset;
1813 
1814 // TVector3 old(x,y,z);
1815 
1816  double newX = x*fBMBasisX.X() + y*fBMBasisY.X() + /*(z-zOffset)*fBMBasisZ.X()*/ + off*fabs(fBMBasisZ.X());
1817  double newY = x*fBMBasisX.Y() + y*fBMBasisY.Y() + /*(z-zOffset)*fBMBasisZ.Y()*/ + off*fabs(fBMBasisZ.Y());
1818  double newZ = x*fBMBasisX.Z() + y*fBMBasisY.Z() + /*(z-zOffset) */ - off*fabs(fBMBasisZ.Z());
1819 
1820  newX += fBeamX*10.;
1821  newY += fBeamY*10.;
1822  newZ += fBeamZ*10.;
1823 
1824  TVector3 result(newX/10., newY/10., newZ/10.);
1825  return result;
1826 }
1827 
1828 //----------------------------------------------------------------------------------
1829 
1831 
1832  TVector3 newMom(px,py,pz);
1833  RotateMonitorVector(newMom);
1834  return newMom;
1835 }
1836 
1837 //----------------------------------------------------------------------------------
1838 
1840 
1841  fBMBasisX = TVector3(1.,0.,0.);
1842  fBMBasisY = TVector3(0.,1.,0.);
1843  fBMBasisZ = TVector3(0.,0.,1.);
1847 
1848 }
1849 
1850 //----------------------------------------------------------------------------------
1851 
1853 
1854  // Note: reordering how these are done in order to keep the basis
1855  // vectors of the monitors parallel to the ground.
1856  vec.RotateX( fRotateMonitorYZ * TMath::Pi() / 180. );
1857  vec.RotateY( fRotateMonitorXZ * TMath::Pi() / 180. );
1858 
1859 }
1860 
1861 //----------------------------------------------------------------------------------
1862 
1864 
1865  const TVector3 pos(particle.fPosX,particle.fPosY,particle.fPosZ);
1866  const TVector3 dir = TVector3(particle.fMomX,particle.fMomY,particle.fMomZ).Unit();
1867 
1868  // Want to move the position upstream by a distance equal to fNP04frontPos - fBPROFEXTPos
1869  // This length is in the beam direction frame unless we account for it
1870  // Convert the instrument positions from mm to cm
1871  const float shiftLength = (fNP04frontPos - fBPROFEXTPos)/(10.0*fBMBasisZ.Z());
1872 
1873  const TVector3 shiftedPos = pos - shiftLength*dir;
1874 
1875  particle.fPosX = shiftedPos.X();
1876  particle.fPosY = shiftedPos.Y();
1877  particle.fPosZ = shiftedPos.Z();
1878 }
1879 
1880 //----------------------------------------------------------------------------------
1881 
1883 
1884  // Instrument names
1885  const std::string tof1Name = fTOF1TreeName.substr(fTOF1TreeName.find("/")+1);
1886  const std::string bprof1Name = fBPROF1TreeName.substr(fBPROF1TreeName.find("/")+1);
1887  const std::string bprof2Name = fBPROF2TreeName.substr(fBPROF2TreeName.find("/")+1);
1888  const std::string bprof3Name = fBPROF3TreeName.substr(fBPROF3TreeName.find("/")+1);
1889  const std::string trig1Name = fTRIG1TreeName.substr(fTRIG1TreeName.find("/")+1);
1890  const std::string bprofEXTName = fBPROFEXTTreeName.substr(fBPROFEXTTreeName.find("/")+1);
1891  const std::string bprof4Name = fBPROF4TreeName.substr(fBPROF4TreeName.find("/")+1);
1892  const std::string trig2Name = fTRIG2TreeName.substr(fTRIG2TreeName.find("/")+1);
1893 
1894  // TOF first
1895  const float trig2Time = triggerEvent.fTriggeredParticleInfo.at(trig2Name).fPosT;
1896  const float tof1Time = triggerEvent.fTriggeredParticleInfo.at(tof1Name).fPosT;
1897  beamevt.SetTOFs(std::vector<double>{trig2Time - tof1Time});
1898  beamevt.SetTOFChans( std::vector<int>{ 0 } );
1899  beamevt.SetUpstreamTriggers( std::vector<size_t>{0} );
1900  beamevt.SetDownstreamTriggers( std::vector<size_t>{0} );
1901  beamevt.SetCalibrations( 0., 0., 0., 0. );
1902  beamevt.DecodeTOF();
1903 
1904  // Fibre monitors
1905  const BeamParticle &bprof1Particle = triggerEvent.fTriggeredParticleInfo.at(bprof1Name);
1906  const BeamParticle &bprof2Particle = triggerEvent.fTriggeredParticleInfo.at(bprof2Name);
1907  const BeamParticle &bprof3Particle = triggerEvent.fTriggeredParticleInfo.at(bprof3Name);
1908  const BeamParticle &bprofExtParticle = triggerEvent.fTriggeredParticleInfo.at(bprofEXTName);
1909  const BeamParticle &bprof4Particle = triggerEvent.fTriggeredParticleInfo.at(bprof4Name);
1910  // (x,y) for BPROF1
1911  beamevt.SetFBMTrigger( "XBPF022697", MakeFiberMonitor( bprof1Particle.fPosX ) );
1912  beamevt.SetFBMTrigger( "XBPF022698", MakeFiberMonitor( bprof1Particle.fPosY ) );
1913  // Just x for BPROF2 and BPROF3
1914  beamevt.SetFBMTrigger( "XBPF022701", MakeFiberMonitor( bprof2Particle.fPosX ) );
1915  beamevt.SetFBMTrigger( "XBPF022702", MakeFiberMonitor( bprof3Particle.fPosX ) );
1916  // (x,y) for BPROFEXT
1917  beamevt.SetFBMTrigger( "XBPF022707", MakeFiberMonitor( bprofExtParticle.fPosX ) );
1918  beamevt.SetFBMTrigger( "XBPF022708", MakeFiberMonitor( bprofExtParticle.fPosY ) );
1919  // (x,y) for BPROF4
1920  beamevt.SetFBMTrigger( "XBPF022716", MakeFiberMonitor( bprof4Particle.fPosX ) );
1921  beamevt.SetFBMTrigger( "XBPF022717", MakeFiberMonitor( bprof4Particle.fPosY ) );
1922 
1923  // Cherenkovs aren't simulated, so set to dummy values
1924  beam::CKov dummy;
1925  dummy.trigger = 0;
1926  dummy.pressure = 0.;
1927  dummy.timeStamp = 0.;
1928  beamevt.SetCKov0( dummy );
1929  beamevt.SetCKov1( dummy );
1930 
1931  // Trigger information
1932  beamevt.SetMagnetCurrent( 0. );
1933  beamevt.SetTimingTrigger( 12 );
1934  beamevt.SetActiveTrigger(0);
1935  beamevt.SetT0( std::make_pair(0.,0.) );
1936 
1937  // Do the beamline instrumentation reconstruction
1938  MakeTracks( beamevt );
1939  MomentumSpectrometer( beamevt );
1940 
1941 /*
1942  //This will just use the class members
1943  beamevt.SetTOFs( std::vector<double>{ fGoodTRIG2_t - fGoodTOF1_t } );
1944  beamevt.SetTOFChans( std::vector<int>{ 0 } );
1945  beamevt.SetUpstreamTriggers( std::vector<size_t>{0} );
1946  beamevt.SetDownstreamTriggers( std::vector<size_t>{0} );
1947  beamevt.SetCalibrations( 0., 0., 0., 0. );
1948  beamevt.DecodeTOF();
1949 
1950  beamevt.SetMagnetCurrent( 0. );
1951  beamevt.SetTimingTrigger( 12 );
1952 
1953  beam::CKov dummy;
1954  dummy.trigger = 0;
1955  dummy.pressure = 0.;
1956  dummy.timeStamp = 0.;
1957  beamevt.SetCKov0( dummy );
1958  beamevt.SetCKov1( dummy );
1959 
1960  beamevt.SetActiveTrigger(0);
1961  beamevt.SetT0( std::make_pair(0.,0.) );
1962 
1963  beamevt.SetFBMTrigger( "XBPF022697", MakeFiberMonitor( fGoodBPROF1_x ) );
1964  beamevt.SetFBMTrigger( "XBPF022698", MakeFiberMonitor( fGoodBPROF1_y ) );
1965  beamevt.SetFBMTrigger( "XBPF022701", MakeFiberMonitor( fGoodBPROF2_x ) );
1966  beamevt.SetFBMTrigger( "XBPF022702", MakeFiberMonitor( fGoodBPROF3_x ) );
1967 
1968  beamevt.SetFBMTrigger( "XBPF022707", MakeFiberMonitor( fGoodBPROFEXT_x ) );
1969  beamevt.SetFBMTrigger( "XBPF022708", MakeFiberMonitor( fGoodBPROFEXT_y ) );
1970 
1971  beamevt.SetFBMTrigger( "XBPF022716", MakeFiberMonitor( fGoodBPROF4_x ) );
1972  beamevt.SetFBMTrigger( "XBPF022717", MakeFiberMonitor( fGoodBPROF4_y ) );
1973 
1974  MakeTracks( beamevt );
1975  MomentumSpectrometer( beamevt );
1976 
1977 
1978  if( fSaveOutputTree ){
1979  fReco_p = beamevt.GetRecoBeamMomentum(0);
1980  fReco_tof = beamevt.GetTOF();
1981  std::cout << "TOF: " << beamevt.GetTOFs()[0] << " " << beamevt.GetTOF() << std::endl;
1982  fNP04_PDG = fGoodNP04front_PDGid;
1983 
1984  fNP04front_p = sqrt( fGoodNP04front_Px * fGoodNP04front_Px
1985  + fGoodNP04front_Py * fGoodNP04front_Py
1986  + fGoodNP04front_Pz * fGoodNP04front_Pz );
1987 
1988  fXBPF697_p = sqrt( fGoodBPROF1_Px * fGoodBPROF1_Px
1989  + fGoodBPROF1_Py * fGoodBPROF1_Py
1990  + fGoodBPROF1_Pz * fGoodBPROF1_Pz );
1991 
1992  fXBPF701_p = sqrt( fGoodBPROF2_Px*fGoodBPROF2_Px
1993  + fGoodBPROF2_Py*fGoodBPROF2_Py
1994  + fGoodBPROF2_Pz*fGoodBPROF2_Pz );
1995 
1996  fXBPF702_p = sqrt( fGoodBPROF3_Px*fGoodBPROF3_Px
1997  + fGoodBPROF3_Py*fGoodBPROF3_Py
1998  + fGoodBPROF3_Pz*fGoodBPROF3_Pz );
1999  fXBPF697_x = fGoodBPROF1_x;
2000  fXBPF701_x = fGoodBPROF2_x;
2001  fXBPF702_x = fGoodBPROF3_x;
2002 
2003  fXBPF716_x = fGoodBPROF4_x;
2004  fXBPF717_y = fGoodBPROF4_y;
2005  fXBPF707_x = fGoodBPROFEXT_x;
2006  fXBPF708_y = fGoodBPROFEXT_y;
2007 
2008 
2009  fXBPF697_f = beamevt.GetFBM( "XBPF022697" ).active[0];
2010  fXBPF701_f = beamevt.GetFBM( "XBPF022701" ).active[0];
2011  fXBPF702_f = beamevt.GetFBM( "XBPF022702" ).active[0];
2012 
2013  fXBPF707_f = beamevt.GetFBM( "XBPF022707" ).active[0];
2014  fXBPF708_f = beamevt.GetFBM( "XBPF022708" ).active[0];
2015  fXBPF716_f = beamevt.GetFBM( "XBPF022716" ).active[0];
2016  fXBPF717_f = beamevt.GetFBM( "XBPF022717" ).active[0];
2017 
2018  fXBPF697_rx = GetPosition( fXBPF697_f );
2019  fXBPF701_rx = GetPosition( fXBPF701_f );
2020  fXBPF702_rx = GetPosition( fXBPF702_f );
2021 
2022  fXBPF716_rx = GetPosition( fXBPF716_f );
2023  fXBPF717_ry = GetPosition( fXBPF717_f );
2024  fXBPF707_rx = GetPosition( fXBPF707_f );
2025  fXBPF708_ry = GetPosition( fXBPF708_f );
2026 
2027  //fTrueFront_x = fGoodNP04front_x + fBeamX;
2028  //fTrueFront_y = fGoodNP04front_y + fBeamY;
2029  //fTrueFront_z = fGoodNP04front_z + fBeamZ;
2030 
2031  fRecoFront_x = beamevt.GetBeamTrack(0).End().X();
2032  fRecoFront_y = beamevt.GetBeamTrack(0).End().Y();
2033  fRecoFront_z = beamevt.GetBeamTrack(0).End().Z();
2034 
2035  fRecoTree->Fill();
2036  }
2037 */
2038 }
2039 
2040 //----------------------------------------------------------------------------------
2041 
2043  beam::FBM theFBM;
2044 
2045  //I should probably just make this into
2046  //a constructor for the FBM...
2047  theFBM.ID = -1;
2048  theFBM.glitch_mask = {};
2049  std::uninitialized_fill( std::begin(theFBM.fiberData), std::end(theFBM.fiberData), 0. );
2050  std::uninitialized_fill( std::begin(theFBM.timeData), std::end(theFBM.timeData), 0. );
2051  theFBM.timeStamp = 0.;
2052 
2053  const short f = 96 - short( floor(pos) ) - 1;
2054  theFBM.fibers[f] = 1;
2055  theFBM.active.push_back(f);
2056  theFBM.decoded = true;
2057 
2058  return theFBM;
2059 }
2060 
2061 //----------------------------------------------------------------------------------
2062 
2064  return ((96 - fiber) - .5);
2065 }
2066 
2067 //----------------------------------------------------------------------------------
2068 
2070 
2071  //We should only have one active fiber at a time
2072  //
2073  //Might need to ask Leigh, etc. if it's possible
2074  //to have multiple particles going through at the
2075  //same time. In which case -- try to implement it
2076 
2077  const short fx1 = beamEvent.GetFBM( "XBPF022707" ).active[0];
2078  const short fy1 = beamEvent.GetFBM( "XBPF022708" ).active[0];
2079 
2080  const double x1 = GetPosition( fx1 );
2081  const double y1 = GetPosition( fy1 );
2082 
2083  TVector3 pos1 = ConvertProfCoordinates( x1, y1, 0., fBPROFEXTPos );
2084 
2085  const short fx2 = beamEvent.GetFBM( "XBPF022716" ).active[0];
2086  const short fy2 = beamEvent.GetFBM( "XBPF022717" ).active[0];
2087 
2088  const double x2 = GetPosition( fx2 );
2089  const double y2 = GetPosition( fy2 );
2090 
2091  TVector3 pos2 = ConvertProfCoordinates( x2, y2, 0., fBPROF4Pos );
2092 
2093  std::vector< TVector3 > thePoints = { pos1, pos2, ProjectToTPC( pos1, pos2 ) };
2094  std::vector< TVector3 > theMomenta = {
2095  ( pos2 - pos1 ).Unit(),
2096  ( pos2 - pos1 ).Unit(),
2097  ( pos2 - pos1 ).Unit()
2098  };
2099 
2100  beamEvent.AddBeamTrack(
2101  recob::Track(
2104  recob::Track::Flags_t( thePoints.size() ),
2105  false ),
2107  )
2108  );
2109 
2110 }
2111 
2112 //----------------------------------------------------------------------------------
2113 
2114 TVector3 evgen::ProtoDUNETriggeredBeam::ProjectToTPC(TVector3 firstPoint, TVector3 secondPoint){
2115  const TVector3 dR = (secondPoint - firstPoint);
2116 
2117  const double deltaZ = -1.*secondPoint.Z();
2118  const double deltaX = deltaZ * (dR.X() / dR.Z());
2119  const double deltaY = deltaZ * (dR.Y() / dR.Z());
2120 
2121  TVector3 lastPoint = secondPoint + TVector3(deltaX, deltaY, deltaZ);
2122  return lastPoint;
2123 }
2124 
2125 //----------------------------------------------------------------------------------
2126 
2128 
2129  const short f1 = beamEvent.GetFBM( "XBPF022697" ).active[0];
2130  const short f2 = beamEvent.GetFBM( "XBPF022701" ).active[0];
2131  const short f3 = beamEvent.GetFBM( "XBPF022702" ).active[0];
2132 
2133  const double x1 = -1.e-3 * GetPosition( f1 );
2134  const double x2 = -1.e-3 * GetPosition( f2 );
2135  const double x3 = -1.e-3 * GetPosition( f3 );
2136 
2137  const double cos_theta = MomentumCosTheta( x1, x2, x3 );
2138  const double momentum = 299792458*fLB/(1.E9 * acos(cos_theta));
2139  beamEvent.AddRecoBeamMomentum( momentum );
2140 
2141 }
2142 
2143 //----------------------------------------------------------------------------------
2144 
2146  const double a = (x2*fL3 - x3*fL2)*cos(fBeamBend)/(fL3-fL2);
2147 
2148  const double numTerm = (a - x1)*( (fL3 - fL2)*tan(fBeamBend) + (x3 - x2)*cos(fBeamBend) ) + fL1*( fL3 - fL2 );
2149 
2150  const double denomTerm1 = sqrt( fL1*fL1 + (a - x1)*(a - x1) );
2151  const double denomTerm2 = sqrt( TMath::Power( ( (fL3 - fL2)*tan(fBeamBend) + (x3 - x2)*cos(fBeamBend) ),2)
2152  + TMath::Power( ( (fL3 - fL2) ),2) );
2153  const double denom = denomTerm1 * denomTerm2;
2154 
2155  const double cosTheta = numTerm/denom;
2156  return cosTheta;
2157 }
2158 
2159 
2161  mf::LogInfo("evgen::ProtoDUNETriggeredBeam::FindFile") << "Searching for " << filename;
2162  if (cet::file_exists(filename)) {
2163  mf::LogInfo("evgen::ProtoDUNETriggeredBeam::FindFile") << "File exists. Opening " << filename;
2164  /*theFile = new TFile(filename.c_str());
2165  if (!theFile ||theFile->IsZombie() || !theFile->IsOpen()) {
2166  delete theFile;
2167  theFile = 0x0;
2168  throw cet::exception("ProtoDUNECalibration.cxx") << "Could not open " << filename;
2169  }*/
2170  return filename;
2171  }
2172  else {
2173  mf::LogInfo("evgen::ProtoDUNETriggeredBeam::FindFile") << "File does not exist here. Searching FW_SEARCH_PATH";
2174  cet::search_path sp{"FW_SEARCH_PATH"};
2175  std::string found_filename;
2176  auto found = sp.find_file(filename, found_filename);
2177  if (!found) {
2178  throw cet::exception("ProtoDUNECalibration.cxx") << "Could not find " << filename;
2179  }
2180 
2181  mf::LogInfo("evgen::ProtoDUNETriggeredBeam::FindFile") << "Found file " << found_filename;
2182  /*
2183  theFile = new TFile(found_filename.c_str());
2184  if (!theFile ||theFile->IsZombie() || !theFile->IsOpen()) {
2185  delete theFile;
2186  theFile = 0x0;
2187  throw cet::exception("ProtoDUNECalibration.cxx") << "Could not open " << found_filename;
2188  }*/
2189  return found_filename;
2190  }
2191 }
2192 
2193 
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::map< std::string, BeamParticle > fTriggeredParticleInfo
intermediate_table::iterator iterator
base_engine_t & createEngine(seed_t seed)
std::string GetSecondaryProcess(const int &primary_pdg, const int &secondary_pdg)
const FBM & GetFBM(std::string) const
void AddDaughter(const int trackID)
Definition: MCParticle.h:268
int PdgCode() const
Definition: MCParticle.h:212
void MomentumSpectrometer(beam::ProtoDUNEBeamEvent &beamEvent)
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
Definition: MCParticle.h:257
static QCString result
double EndZ() const
Definition: MCParticle.h:228
std::map< std::string, THnSparseD * > fPDFs
void SetOrigin(simb::Origin_t origin)
Definition: MCTruth.h:82
void SetDataDrivenPosMom(TLorentzVector &position, TLorentzVector &momentum, double sampledHUp, double sampledVUp, double sampledHDown, double sampledVDown, double sampledMomentum, int beamPDG)
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
int Mother() const
Definition: MCParticle.h:213
void SetTimingTrigger(int theTrigger)
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
void ConvertSamplingPoint(double input_point[5], std::vector< double > minima, std::vector< double > maxima, double output_point[5])
double MomentumCosTheta(double, double, double)
static collection_type const & get() noexcept
TrackTrajectory::Flags_t Flags_t
Definition: Track.h:68
std::string FindFile(const std::string filename)
void SetDataDrivenBeamEvent(beam::ProtoDUNEBeamEvent &beamEvent, double sampledHUp, double sampledVUp, double sampledHDown, double sampledVDown, double sampledMomentum)
int NParticles() const
Definition: MCTruth.h:75
BeamParticle(int trackid, int pdg, int parentid, float posX, float posY, float posZ, float posT, float momX, float momY, float momZ)
string dir
simb::MCParticle BeamParticleToMCParticle(const BeamParticle &beamParticle, const int outputTrackID, const float triggerParticleTime, const int primaryStatus, const std::string process, const int motherID=-1)
ProtoDUNETriggeredBeam(fhicl::ParameterSet const &p)
Particle class.
double EndY() const
Definition: MCParticle.h:227
string filename
Definition: train.py:213
simb::MCParticle DataDrivenMCParticle(const BeamParticle &beamParticle, const int outputTrackID, const float triggerParticleTime, beam::ProtoDUNEBeamEvent &beamEvent, const int primaryStatus, const std::string process)
OverlaidTriggerEvent GenerateOverlaidEvent(const int &trigEventID)
std::vector< short > active
int NumberDaughters() const
Definition: MCParticle.h:217
TVector3 ConvertBeamMonitorMomentumVec(float px, float py, float pz)
art framework interface to geometry description
Definition: Run.h:17
int TrackId() const
Definition: MCParticle.h:210
int Daughter(const int i) const
Definition: MCParticle.cxx:112
void SetFBMTrigger(std::string, FBM)
void SetCKov0(CKov theCKov)
def process(f, kind)
Definition: search.py:254
T abs(T value)
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void SetMagnetCurrent(double theMagnetCurrent)
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
std::string getenv(std::string const &name)
Definition: getenv.cc:15
def move(depos, offset)
Definition: depos.py:107
ProtoDUNETriggeredBeam & operator=(ProtoDUNETriggeredBeam const &)=delete
TVector3 ProjectToTPC(TVector3 firstPoint, TVector3 secondPoint)
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
void FillInstrumentInformation(std::vector< int > &eventIDs, TTree *instrumentTree)
std::vector< Point_t > convertCollToPoint(std::vector< Point > const &coll)
Definition: TrackingTypes.h:55
void GenerateTrueEvent(simb::MCTruth &mcTruth, const OverlaidTriggerEvent &overlayEvent, beam::ProtoDUNEBeamEvent &beamEvent)
static QFile inputFile
std::string GetPrimaryEndProcess(const int &primary_pdg, const std::vector< int > &secondary_pdgs)
double UnsmearMomentum2D(double momentum, int pdg)
void AddBeamTrack(recob::Track theTrack)
std::map< std::string, TH2D * > fResolutionHists2D
void SetEndProcess(std::string s)
Definition: MCParticle.cxx:105
void AddRecoBeamMomentum(double theMomentum)
void SetBeamEvent(beam::ProtoDUNEBeamEvent &beamevt, const BeamEvent &triggerEvent)
std::array< short, 192 > fibers
void Add(simb::MCParticle const &part)
Definition: MCTruth.h:80
void MakeTracks(beam::ProtoDUNEBeamEvent &beamEvent)
std::vector< int > FindTriggeredEvents(TTree *trig1Tree, TTree *trig2Tree)
std::string pattern
Definition: regex_t.cc:35
void SetDownstreamTriggers(std::vector< size_t > theContent)
#define MF_LOG_DEBUG(id)
QTextStream & bin(QTextStream &s)
void SetUpstreamTriggers(std::vector< size_t > theContent)
void SetBackgroundPosition(BeamParticle &particle)
std::array< short, 192 > glitch_mask
cet::LibraryManager dummy("noplugin")
EventNumber_t event() const
Definition: EventID.h:116
list x
Definition: train.py:276
void SetT0(std::pair< double, double > theT0)
bool file_exists(std::string const &qualified_filename)
Definition: filesystem.cc:14
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.)
double EndX() const
Definition: MCParticle.h:226
TVector3 ConvertProfCoordinates(double x, double y, double z, double zOffset)
void ConvertCoordinates(float &x, float &y, float &z)
LArSoft geometry interface.
Definition: ChannelGeo.h:16
Event Generation using GENIE, cosmics or single particles.
void SetTOFs(std::vector< double > theContent)
void ConvertMomentum(float &px, float &py, float &pz)
double timeData[4]
EventID id() const
Definition: Event.cc:34
TLorentzVector ConvertBeamMonitorCoordinates(float x, float y, float z, float t, float offset)
void SetCalibrations(double TOFCalAA, double TOFCalBA, double TOFCalAB, double TOFCalBB)
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 SetTOFChans(std::vector< int > theContent)
std::vector< OverlaidTriggerEvent > fAllOverlaidTriggerEvents
QTextStream & endl(QTextStream &s)
Event finding and building.
void SetActiveTrigger(size_t theTrigger)