LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
lar::example::AnalysisExample Class Reference

Example analyzer module. More...

Inheritance diagram for lar::example::AnalysisExample:
art::EDAnalyzer art::EventObserverBase art::Consumer art::EngineCreator

Classes

struct  Config
 

Public Types

using Parameters = art::EDAnalyzer::Table< Config >
 
using WorkerType = WorkerT< EDAnalyzer >
 
using ModuleType = EDAnalyzer
 

Public Member Functions

 AnalysisExample (Parameters const &config)
 Constructor: configures the module (see the Config structure above) More...
 
virtual void beginJob () override
 
virtual void beginRun (const art::Run &run) override
 
virtual void analyze (const art::Event &event) override
 
std::string workerType () const
 
bool modifiesEvent () const
 
void registerProducts (MasterProductRegistry &, ProductDescriptions &, ModuleDescription const &)
 
std::string const & processName () const
 
bool wantAllEvents () const
 
bool wantEvent (Event const &e)
 
fhicl::ParameterSetID selectorConfig () const
 
art::Handle< art::TriggerResultsgetTriggerResults (Event const &e) const
 
template<typename T , BranchType = InEvent>
ProductToken< T > consumes (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ProductToken< T > consumes (InputTag const &it)
 
template<typename T , BranchType = InEvent>
void consumesMany ()
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > consumesView (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ViewToken< T > consumesView (InputTag const &it)
 
template<typename T , BranchType = InEvent>
ProductToken< T > mayConsume (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ProductToken< T > mayConsume (InputTag const &it)
 
template<typename T , BranchType = InEvent>
void mayConsumeMany ()
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > mayConsumeView (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ViewToken< T > mayConsumeView (InputTag const &it)
 
base_engine_tcreateEngine (seed_t seed)
 
base_engine_tcreateEngine (seed_t seed, std::string const &kind_of_engine_to_make)
 
base_engine_tcreateEngine (seed_t seed, std::string const &kind_of_engine_to_make, label_t const &engine_label)
 
seed_t get_seed_value (fhicl::ParameterSet const &pset, char const key[]="seed", seed_t const implicit_seed=-1)
 

Static Public Member Functions

static cet::exempt_ptr< Consumernon_module_context ()
 

Protected Member Functions

CurrentProcessingContext const * currentContext () const
 
detail::CachedProducts & cachedProducts ()
 
void validateConsumedProduct (BranchType const bt, ProductInfo const &pi)
 
void prepareForJob (fhicl::ParameterSet const &pset)
 
void showMissingConsumes () const
 

Private Attributes

art::InputTag fSimulationProducerLabel
 The name of the producer that tracked simulated particles through the detector. More...
 
art::InputTag fHitProducerLabel
 The name of the producer that created hits. More...
 
art::InputTag fClusterProducerLabel
 The name of the producer that created clusters. More...
 
int fSelectedPDG
 PDG code of particle we'll focus on. More...
 
double fBinSize
 For dE/dx work: the value of dx. More...
 
TH1D * fPDGCodeHist
 PDG code of all particles. More...
 
TH1D * fMomentumHist
 momentum [GeV] of all selected particles More...
 
TH1D * fTrackLengthHist
 true length [cm] of all selected particles More...
 
TTree * fSimulationNtuple
 tuple with simulated data More...
 
TTree * fReconstructionNtuple
 tuple with reconstructed data More...
 
geo::GeometryCore const * fGeometryService
 pointer to Geometry provider More...
 
detinfo::DetectorClocks const * fTimeService
 pointer to detector clock time service provider More...
 
double fElectronsToGeV
 conversion factor More...
 
int fTriggerOffset
 (units of ticks) time of expected neutrino event More...
 
The variables that will go into both n-tuples.
int fEvent
 number of the event being processed More...
 
int fRun
 number of the run being processed More...
 
int fSubRun
 
The variables that will go into the simulation n-tuple.
int fSimPDG
 PDG ID of the particle being processed. More...
 
int fSimTrackID
 GEANT ID of the particle being processed. More...
 
double fStartXYZT [4]
 (x,y,z,t) of the true start of the particle More...
 
double fEndXYZT [4]
 (x,y,z,t) of the true end of the particle More...
 
double fStartPE [4]
 (Px,Py,Pz,E) at the true start of the particle More...
 
double fEndPE [4]
 (Px,Py,Pz,E) at the true end of the particle More...
 
int fSimNdEdxBins
 Number of dE/dx bins in a given track. More...
 
std::vector< double > fSimdEdxBins
 The vector that will be used to accumulate dE/dx values as a function of range. More...
 
Variables used in the reconstruction n-tuple
int fRecoPDG
 PDG ID of the particle being processed. More...
 
int fRecoTrackID
 GEANT ID of the particle being processed. More...
 
int fRecoNdEdxBins
 Number of dE/dx bins in a given track. More...
 
std::vector< double > fRecodEdxBins
 The vector that will be used to accumulate dE/dx values as a function of range. More...
 

Detailed Description

Example analyzer module.

See also
analysis module example overview

This class extracts information from the generated and reconstructed particles.

It produces histograms for the simulated particles in the input file:

  • PDG ID (flavor) of all particles
  • momentum of the primary particles selected to have a specific PDG ID
  • length of the selected particle trajectory

It also produces two ROOT trees.

The first ROOT tree contains information on the simulated particles, including "dEdx", a binned histogram of collected charge as function of track range.

The second ROOT tree contains information on the reconstructed hits.

Configuration parameters

  • SimulationLabel (string, default: "largeant"): tag of the input data product with the detector simulation information (typically an instance of the LArG4 module)
  • HitLabel (string, mandatory): tag of the input data product with reconstructed hits
  • ClusterLabel (string, mandatory): tag of the input data product with reconstructed clusters
  • PDGcode (integer, mandatory): particle type (PDG ID) to be selected; only primary particles of this type will be considered
  • BinSize (real, mandatory): $ dx $ [cm] used for the $ dE/dx $ calculation

Definition at line 182 of file AnalysisExample_module.cc.

Member Typedef Documentation

Definition at line 39 of file EDAnalyzer.h.

Definition at line 38 of file EDAnalyzer.h.

Constructor & Destructor Documentation

lar::example::AnalysisExample::AnalysisExample ( Parameters const &  config)
explicit

Constructor: configures the module (see the Config structure above)

Definition at line 383 of file AnalysisExample_module.cc.

References fClusterProducerLabel, fGeometryService, fHitProducerLabel, fSimulationProducerLabel, fTimeService, and fTriggerOffset.

384  : EDAnalyzer(config)
385  , fSimulationProducerLabel(config().SimulationLabel())
386  , fHitProducerLabel (config().HitLabel())
387  , fClusterProducerLabel (config().ClusterLabel())
388  , fSelectedPDG (config().PDGcode())
389  , fBinSize (config().BinSize())
390  {
391  // Get a pointer to the geometry service provider.
392  fGeometryService = lar::providerFrom<geo::Geometry>();
393  // The same for detector TDC clock services.
394  fTimeService = lar::providerFrom<detinfo::DetectorClocksService>();
395  // Access to detector properties.
396  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
397  fTriggerOffset = detprop->TriggerOffset();
398 
399  // Since art 2.8, you can and should tell beforehand, here in the constructor,
400  // all the data the module is going to read ("consumes") or might read
401  // ("may_consume"). Diligence here will in the future help the framework
402  // execute modules in parallel, making sure the order is correct.
403  consumes<std::vector<simb::MCParticle>>(fSimulationProducerLabel);
404  consumes<std::vector<sim::SimChannel>>(fSimulationProducerLabel);
405  consumes<art::Assns<simb::MCTruth, simb::MCParticle>>(fSimulationProducerLabel);
406  consumes<std::vector<recob::Hit>>(fHitProducerLabel);
407  consumes<std::vector<recob::Cluster>>(fClusterProducerLabel);
408  consumes<art::Assns<recob::Cluster, recob::Hit>>(fHitProducerLabel);
409 
410  }
art::InputTag fHitProducerLabel
The name of the producer that created hits.
geo::GeometryCore const * fGeometryService
pointer to Geometry provider
art::InputTag fSimulationProducerLabel
The name of the producer that tracked simulated particles through the detector.
detinfo::DetectorClocks const * fTimeService
pointer to detector clock time service provider
art::InputTag fClusterProducerLabel
The name of the producer that created clusters.
EDAnalyzer(Table< Config > const &config)
Definition: EDAnalyzer.h:100
int fTriggerOffset
(units of ticks) time of expected neutrino event
double fBinSize
For dE/dx work: the value of dx.
int fSelectedPDG
PDG code of particle we&#39;ll focus on.

Member Function Documentation

void lar::example::AnalysisExample::analyze ( const art::Event event)
overridevirtual

Definition at line 489 of file AnalysisExample_module.cc.

References bin, DEFINE_ART_MODULE, geo::GeometryCore::DetHalfHeight(), geo::GeometryCore::DetHalfWidth(), geo::GeometryCore::DetLength(), energy, fBinSize, fClusterProducerLabel, fElectronsToGeV, fEndPE, fEndXYZT, fEvent, fGeometryService, fHitProducerLabel, fMomentumHist, fPDGCodeHist, fRecodEdxBins, fRecoNdEdxBins, fReconstructionNtuple, fRecoPDG, fRecoTrackID, fRun, fSelectedPDG, fSimdEdxBins, fSimNdEdxBins, fSimPDG, fSimTrackID, fSimulationNtuple, fSimulationProducerLabel, fStartPE, fStartXYZT, fSubRun, fTimeService, fTrackLengthHist, art::DataViewImpl::getByLabel(), hits(), geo::kCollection, LOG_DEBUG, max, min, simb::MCParticle::PdgCode(), simb::MCParticle::Position(), simb::MCParticle::Process(), geo::GeometryCore::SignalType(), and detinfo::DetectorClocks::TPCTick2TDC().

490  {
491  // Start by fetching some basic event information for our n-tuple.
492  fEvent = event.id().event();
493  fRun = event.run();
494  fSubRun = event.subRun();
495 
496  // This is the standard method of reading multiple objects
497  // associated with the same event; see
498  // <https://cdcvs.fnal.gov/redmine/projects/larsoft/wiki/Using_art_in_LArSoft>
499  // for more information.
500  //
501  // Define a "handle" to point to a vector of the objects.
503 
504  // Then tell the event to fill the vector with all the objects of
505  // that type produced by a particular producer.
506  //
507  // Note that if I don't test whether this is successful, and there
508  // aren't any simb::MCParticle objects, then the first time we
509  // access particleHandle, art will display a "ProductNotFound"
510  // exception message and, depending on art settings, it may skip
511  // all processing for the rest of this event (including any
512  // subsequent analysis steps) or stop the execution.
513  if (!event.getByLabel(fSimulationProducerLabel, particleHandle))
514  {
515  // If we have no MCParticles at all in an event, then we're in
516  // big trouble. Throw an exception to force this module to
517  // stop. Try to include enough information for the user to
518  // figure out what's going on. Note that when we throw a
519  // cet::exception, the run and event number will automatically
520  // be displayed.
521  //
522  // __LINE__ and __FILE__ are values computed by the compiler.
523 
524  throw cet::exception("AnalysisExample")
525  << " No simb::MCParticle objects in this event - "
526  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
527  }
528 
529  // Get all the simulated channels for the event. These channels
530  // include the energy deposited for each simulated track.
531  //
532  // Here we use a different method to access objects:
533  // art::ValidHandle. Using this method, if there aren't any
534  // objects of the given type (sim::SimChannel in this case) in the
535  // input file for this art::Event, art will throw a
536  // ProductNotFound exception.
537  //
538  // The "auto" type means that the C++ compiler will determine the
539  // appropriate type for us, based on the return type of
540  // art::Event::getValidHandle<T>(). The "auto" keyword is a great
541  // timesaver, especially with frameworks like LArSoft which often
542  // have complicated data product structures.
543 
544  auto simChannelHandle =
545  event.getValidHandle<std::vector<sim::SimChannel>>(fSimulationProducerLabel);
546 
547  //
548  // Let's compute the variables for the simulation n-tuple first.
549  //
550 
551  // The MCParticle objects are not necessarily in any particular
552  // order. Since we may have to search the list of particles, let's
553  // put them into a map, a sorted container that will make
554  // searching fast and easy. To save both space and time, the map
555  // will not contain a copy of the MCParticle, but a pointer to it.
556  std::map< int, const simb::MCParticle* > particleMap;
557 
558  // This is a "range-based for loop" in the 2011 version of C++; do
559  // a web search on "c++ range based for loop" for more
560  // information. Here's how it breaks down:
561 
562  // - A range-based for loop operates on a container.
563  // "particleHandle" is not a container; it's a pointer to a
564  // container. If we want C++ to "see" a container, we have to
565  // dereference the pointer, like this: *particleHandle.
566 
567  // - The loop variable that is set to each object in the container
568  // is named "particle". As for the loop variable's type:
569 
570  // - To save a little bit of typing, and to make the code easier
571  // to maintain, we're going to let the C++ compiler deduce the
572  // type of what's in the container (simb::MCParticle objects
573  // in this case), so we use "auto".
574 
575  // - We do _not_ want to change the contents of the container,
576  // so we use the "const" keyword to make sure.
577 
578  // - We don't need to copy each object from the container into
579  // the variable "particle". It's sufficient to refer to the
580  // object by its address. So we use the reference operator "&"
581  // to tell the compiler to just copy the address, not the
582  // entire object.
583 
584  // It sounds complicated, but the end result is that we loop over
585  // the list of particles in the art::Event in the most efficient
586  // way possible.
587 
588  for ( auto const& particle : (*particleHandle) )
589  {
590  // For the methods you can call to get particle information,
591  // see ${NUSIMDATA_INC}/nusimdata/SimulationBase/MCParticle.h.
592  fSimTrackID = particle.TrackId();
593 
594  // Add the address of the MCParticle to the map, with the
595  // track ID as the key.
596  particleMap[fSimTrackID] = &particle;
597 
598  // Histogram the PDG code of every particle in the event.
599  fSimPDG = particle.PdgCode();
600  fPDGCodeHist->Fill( fSimPDG );
601 
602  // For this example, we want to fill the n-tuples and histograms
603  // only with information from the primary particles in the
604  // event, whose PDG codes match a value supplied in the .fcl file.
605  if ( particle.Process() != "primary" || fSimPDG != fSelectedPDG )
606  continue;
607 
608  // A particle has a trajectory, consisting of a set of
609  // 4-positions and 4-mommenta.
610  const size_t numberTrajectoryPoints = particle.NumberTrajectoryPoints();
611 
612  // For trajectories, as for vectors and arrays, the first
613  // point is #0, not #1.
614  const int last = numberTrajectoryPoints - 1;
615  const TLorentzVector& positionStart = particle.Position(0);
616  const TLorentzVector& positionEnd = particle.Position(last);
617  const TLorentzVector& momentumStart = particle.Momentum(0);
618  const TLorentzVector& momentumEnd = particle.Momentum(last);
619 
620  // Make a histogram of the starting momentum.
621  fMomentumHist->Fill( momentumStart.P() );
622 
623  // Fill arrays with the 4-values. (Don't be fooled by
624  // the name of the method; it just puts the numbers from
625  // the 4-vector into the array.)
626  positionStart.GetXYZT( fStartXYZT );
627  positionEnd.GetXYZT( fEndXYZT );
628  momentumStart.GetXYZT( fStartPE );
629  momentumEnd.GetXYZT( fEndPE );
630 
631  // Use a polar-coordinate view of the 4-vectors to
632  // get the track length.
633  const double trackLength = ( positionEnd - positionStart ).Rho();
634 
635  // Let's print some debug information in the job output to see
636  // that everything is fine. LOG_DEBUG() is a messagefacility
637  // macro that prints stuff when the message level is set to
638  // standard_debug in the .fcl file.
639  LOG_DEBUG("AnalysisExample")
640  << "Track length: " << trackLength << " cm";
641 
642  // Fill a histogram of the track length.
643  fTrackLengthHist->Fill( trackLength );
644 
645  LOG_DEBUG("AnalysisExample")
646  << "track ID=" << fSimTrackID
647  << " (PDG ID: " << fSimPDG << ") "
648  << trackLength << " cm long, momentum "
649  << momentumStart.P() << " GeV/c, has "
650  << numberTrajectoryPoints << " trajectory points";
651 
652  // Determine the number of dE/dx bins for the n-tuple.
653  fSimNdEdxBins = int( trackLength / fBinSize ) + 1;
654  // Initialize the vector of dE/dx bins to be empty.
655  fSimdEdxBins.clear();
656 
657  // To look at the energy deposited by this particle's track,
658  // we loop over the SimChannel objects in the event.
659  for ( auto const& channel : (*simChannelHandle) )
660  {
661  // Get the numeric ID associated with this channel. (The
662  // channel number is a 32-bit unsigned int, which normally
663  // requires a special data type. Let's use "auto" so we
664  // don't have to remember "raw::ChannelID_t".
665  auto const channelNumber = channel.Channel();
666 
667  // A little care: There is more than one plane that reacts
668  // to charge in the TPC. We only want to include the
669  // energy from the collection plane. Note:
670  // geo::kCollection is defined in
671  // ${LARCOREOBJ_INC}/larcoreobj/SimpleTypesAndConstants/geo_types.h
672  if ( fGeometryService->SignalType( channelNumber ) != geo::kCollection )
673  continue;
674 
675  // Each channel has a map inside it that connects a time
676  // slice to energy deposits in the detector. We'll use
677  // "auto", but it's worth noting that the full type of
678  // this map is
679  // std::map<unsigned short, std::vector<sim::IDE>>
680  auto const& timeSlices = channel.TDCIDEMap();
681 
682  // For every time slice in this channel:
683  for ( auto const& timeSlice : timeSlices )
684  {
685  // Each entry in a map is a pair<first,second>. For
686  // the timeSlices map, the 'first' is a time slice
687  // number. The 'second' is a vector of IDE objects.
688  auto const& energyDeposits = timeSlice.second;
689 
690  // Loop over the energy deposits. An "energy deposit"
691  // object is something that knows how much
692  // charge/energy was deposited in a small volume, by
693  // which particle, and where. The type of
694  // 'energyDeposit' will be sim::IDE, which is defined
695  // in
696  // ${LARDATAOBJ_INC}/lardataobj/Simulation/SimChannel.h.
697  for ( auto const& energyDeposit : energyDeposits )
698  {
699  // Check if the track that deposited the
700  // energy matches the track of the particle.
701  if ( energyDeposit.trackID != fSimTrackID ) continue;
702  // Get the (x,y,z) of the energy deposit.
703  TVector3 location( energyDeposit.x,
704  energyDeposit.y,
705  energyDeposit.z );
706 
707  // Distance from the start of the track.
708  const double distance = ( location - positionStart.Vect() ).Mag();
709 
710  // Into which bin of the dE/dx array do we add the energy?
711  const unsigned int bin = (unsigned int)( distance / fBinSize );
712 
713  // Is the dE/dx array big enough to include this bin?
714  if ( fSimdEdxBins.size() < bin+1 )
715  {
716  // Increase the array size to accomodate
717  // the new bin, padding it with zeros.
718  fSimdEdxBins.resize( bin+1 , 0. );
719  }
720 
721  // Add the energy deposit to that bin. (If you look at the
722  // definition of sim::IDE, you'll see that there's another
723  // way to get the energy. Are the two methods equivalent?
724  // Compare the results and see!)
725  fSimdEdxBins[bin] += energyDeposit.numElectrons * fElectronsToGeV;
726 
727  } // For each energy deposit
728  } // For each time slice
729  } // For each SimChannel
730 
731  // At this point we've filled in the values of all the
732  // variables and arrays we want to write to the n-tuple
733  // for this particle. The following command actually
734  // writes those values.
735  fSimulationNtuple->Fill();
736 
737  } // loop over all particles in the event.
738 
739  //
740  // Reconstruction n-tuple
741  //
742 
743  // All of the above is based on objects entirely produced by the
744  // simulation. Let's try to do something based on reconstructed
745  // objects. A Hit (see ${LARDATAOBJ_INC}/lardataobj/RecoBase/Hit.h)
746  // is a 2D object in a plane.
747 
748  // This code duplicates much of the code in the previous big
749  // simulation loop, and will produce the similar results. (It
750  // won't be identical, because of shaping and other factors; not
751  // every bit of charge in a channel ends up contributing to a
752  // hit.) The point is to show different methods of accessing
753  // information, not to produce profound physics results -- that
754  // part is up to you!
755 
756  // For the rest of this method, I'm going to assume you've read
757  // the comments in previous section; I won't repeat all the C++
758  // coding tricks and whatnot.
759 
760  // Start by reading the Hits. We don't use art::ValidHandle here
761  // because there might be no hits in the input; e.g., we ran the
762  // simulation but did not run the reconstruction steps yet. If
763  // there are no hits we may as well skip the rest of this module.
764 
766  if (!event.getByLabel(fHitProducerLabel, hitHandle)) return;
767 
768  // Our goal is to accumulate the dE/dx of any particles associated
769  // with the hits that match our criteria: primary particles with
770  // the PDG code from the .fcl file. I don't know how many such
771  // particles there will be in a given event. We'll use a map, with
772  // track ID as the key, to hold the vectors of dE/dx information.
773  std::map< int, std::vector<double> > dEdxMap;
774 
775  // For every Hit:
776  for ( auto const& hit : (*hitHandle) )
777  {
778  // The channel associated with this hit.
779  auto hitChannelNumber = hit.Channel();
780 
781  // We have a hit. For this example let's just focus on the
782  // hits in the collection plane.
783  if ( fGeometryService->SignalType( hitChannelNumber ) != geo::kCollection )
784  continue;
785 
786  LOG_DEBUG("AnalysisExample")
787  << "Hit in collection plane"
788  << std::endl;
789 
790  // In a few lines we're going to look for possible energy
791  // deposits that correspond to that hit. Determine a
792  // reasonable range of times that might correspond to those
793  // energy deposits.
794 
795  // In reconstruction, the channel waveforms are truncated. So
796  // we have to adjust the Hit TDC ticks to match those of the
797  // SimChannels, which were created during simulation.
798 
799  // Save a bit of typing, while still allowing for potential
800  // changes in the definitions of types in
801  // $LARDATAOBJ_DIR/source/lardataobj/Simulation/SimChannel.h
802 
803  typedef sim::SimChannel::StoredTDC_t TDC_t;
804  TDC_t start_tdc = fTimeService->TPCTick2TDC( hit.StartTick() );
805  TDC_t end_tdc = fTimeService->TPCTick2TDC( hit.EndTick() );
806  TDC_t hitStart_tdc = fTimeService->TPCTick2TDC( hit.PeakTime() - 3.*hit.SigmaPeakTime() );
807  TDC_t hitEnd_tdc = fTimeService->TPCTick2TDC( hit.PeakTime() + 3.*hit.SigmaPeakTime() );
808 
809  start_tdc = std::max(start_tdc, hitStart_tdc);
810  end_tdc = std::min(end_tdc, hitEnd_tdc );
811 
812  // In the simulation section, we started with particles to find
813  // channels with a matching track ID. Now we search in reverse:
814  // search the SimChannels for matching channel number, then look
815  // at the tracks inside the channel.
816 
817  for ( auto const& channel : (*simChannelHandle) )
818  {
819  auto simChannelNumber = channel.Channel();
820  if ( simChannelNumber != hitChannelNumber ) continue;
821 
822  LOG_DEBUG("AnalysisExample")
823  << "SimChannel number = " << simChannelNumber
824  << std::endl;
825 
826  // The time slices in this channel.
827  auto const& timeSlices = channel.TDCIDEMap();
828 
829  // We want to look over the range of time slices in this
830  // channel that correspond to the range of hit times.
831 
832  // To do this, we're going to use some fast STL search
833  // methods; STL algorithms are usually faster than the
834  // ones you might write yourself. The price for this speed
835  // is a bit of code complexity: in particular, we need to
836  // a custom comparison function, TDCIDETimeCompare, to
837  // define a "less-than" function for the searches.
838 
839  // For an introduction to STL algorithms, see
840  // <http://www.learncpp.com/cpp-tutorial/16-4-stl-algorithms-overview/>.
841  // For a list of available STL algorithms, see
842  // <http://en.cppreference.com/w/cpp/algorithm>
843 
844  // We have to create "dummy" time slices for the search.
845  sim::TDCIDE startTime;
846  sim::TDCIDE endTime;
847  startTime.first = start_tdc;
848  endTime.first = end_tdc;
849 
850  // Here are the fast searches:
851 
852  // Find a pointer to the first channel with time >= start_tdc.
853  auto const startPointer
854  = std::lower_bound( timeSlices.begin(), timeSlices.end(), startTime, TDCIDETimeCompare);
855 
856  // From that time slice, find the last channel with time < end_tdc.
857  auto const endPointer
858  = std::upper_bound( startPointer, timeSlices.end(), endTime, TDCIDETimeCompare);
859 
860  // Did we find anything? If not, skip.
861  if ( startPointer == timeSlices.end() || startPointer == endPointer ) continue;
862  LOG_DEBUG("AnalysisExample")
863  << "Time slice start = " << (*startPointer).first
864  << std::endl;
865 
866  // Loop over the channel times we found that match the hit
867  // times.
868  for ( auto slicePointer = startPointer; slicePointer != endPointer; slicePointer++)
869  {
870  auto const timeSlice = *slicePointer;
871  auto time = timeSlice.first;
872 
873  // How to debug a problem: Lots of print statements. There are
874  // debuggers such as gdb, but they can be tricky to use with
875  // shared libraries and don't work if you're using software
876  // that was compiled somewhere else (e.g., you're accessing
877  // LArSoft libraries via CVMFS).
878 
879  // The LOG_DEBUG statements below are left over from when I
880  // was trying to solve a problem about hit timing. I could
881  // have deleted them, but decided to leave them to demonsrate
882  // what a typical debugging process looks like.
883 
884  LOG_DEBUG("AnalysisExample")
885  << "Hit index = " << hit.LocalIndex()
886  << " channel number = " << hitChannelNumber
887  << " start TDC tick = " << hit.StartTick()
888  << " end TDC tick = " << hit.EndTick()
889  << " peak TDC tick = " << hit.PeakTime()
890  << " sigma peak time = " << hit.SigmaPeakTime()
891  << " adjusted start TDC tick = " << fTimeService->TPCTick2TDC(hit.StartTick())
892  << " adjusted end TDC tick = " << fTimeService->TPCTick2TDC(hit.EndTick())
893  << " adjusted peak TDC tick = " << fTimeService->TPCTick2TDC(hit.PeakTime())
894  << " adjusted start_tdc = " << start_tdc
895  << " adjusted end_tdc = " << end_tdc
896  << " time = " << time
897  << std::endl;
898 
899  // Loop over the energy deposits.
900  auto const& energyDeposits = timeSlice.second;
901  for ( auto const& energyDeposit : energyDeposits )
902  {
903  // Remember that map of MCParticles we created
904  // near the top of this method? Now we can use
905  // it. Search the map for the track ID associated
906  // with this energy deposit. Since a map is
907  // automatically sorted, we can use a fast binary
908  // search method, 'find()'.
909 
910  // By the way, the type of "search" is an iterator
911  // (to be specific, it's an
912  // std::map<int,simb::MCParticle*>::const_iterator,
913  // which makes you thankful for the "auto"
914  // keyword). If you're going to work with C++
915  // containers, you'll have to learn about
916  // iterators eventually; do a web search on "STL
917  // iterator" to get started.
918  auto search = particleMap.find( energyDeposit.trackID );
919 
920  // Did we find this track ID in the particle map?
921  // It's possible for the answer to be "no"; some
922  // particles are too low in kinetic energy to be
923  // written by the simulation (see
924  // ${LARSIM_DIR}/job/simulationservices.fcl,
925  // parameter ParticleKineticEnergyCut).
926  if ( search == particleMap.end() ) continue;
927 
928  // "search" points to a pair in the map: <track ID, MCParticle*>
929  int trackID = (*search).first;
930  const simb::MCParticle& particle = *((*search).second);
931 
932  // Is this a primary particle, with a PDG code that
933  // matches the user input?
934  if ( particle.Process() != "primary"
935  || particle.PdgCode() != fSelectedPDG )
936  continue;
937 
938  // Determine the dE/dx of this particle.
939  const TLorentzVector& positionStart = particle.Position(0);
940  TVector3 location( energyDeposit.x,
941  energyDeposit.y,
942  energyDeposit.z );
943  double distance = ( location - positionStart.Vect() ).Mag();
944  unsigned int bin = int( distance / fBinSize );
945  double energy = energyDeposit.numElectrons * fElectronsToGeV;
946 
947  // A feature of maps: if we refer to
948  // dEdxMap[trackID], and there's no such entry in
949  // the map yet, it will be automatically created
950  // with a zero-size vector. Test to see if the
951  // vector for this track ID is big enough.
952  //
953  // dEdxMap is a map, which is a slow container
954  // compared to a vector. If we are going to access
955  // the same element over and over, it is a good
956  // idea to find that element once, and then refer
957  // to that item directly. Since we don't care
958  // about the specific type of dEdxMap[trackID] (a
959  // vector, by the way), we can use "auto" to save
960  // some time. This must be a reference, since we
961  // want to change the original value in the map,
962  // and can't be constant.
963  auto& track_dEdX = dEdxMap[trackID];
964  if ( track_dEdX.size() < bin+1 )
965  {
966  // Increase the vector size, padding it with
967  // zeroes.
968  track_dEdX.resize( bin+1, 0 );
969  }
970 
971  // Add the energy to the dE/dx bins for this track.
972  track_dEdX[bin] += energy;
973 
974  } // loop over energy deposits
975  } // loop over time slices
976  } // for each SimChannel
977  } // for each Hit
978 
979  // We have a map of dE/dx vectors. Write each one of them to the
980  // reconstruction n-tuple.
981  for ( const auto& dEdxEntry : dEdxMap )
982  {
983  // Here, the map entries are <first,second>=<track ID, dE/dx vector>
984  fRecoTrackID = dEdxEntry.first;
985 
986  // This is an example of how we'd pick out the PDG code if
987  // there are multiple particle types or tracks in a single
988  // event allowed in the n-tuple.
989  fRecoPDG = particleMap[fRecoTrackID]->PdgCode();
990 
991  // Get the number of bins for this track.
992  const std::vector<double>& dEdx = dEdxEntry.second;
993  fRecoNdEdxBins = dEdx.size();
994 
995  // Copy this track's dE/dx information.
996  fRecodEdxBins = dEdx;
997 
998  // At this point, we've filled in all the reconstruction
999  // n-tuple's variables. Write it.
1000  fReconstructionNtuple->Fill();
1001  }
1002 
1003  // Think about the two big loops above, One starts from the
1004  // particles then looks at the channels; the other starts with the
1005  // hits and backtracks to the particles. What links the
1006  // information in simb::MCParticle and sim::SimChannel is the
1007  // track ID number assigned by the LArG4 simulation; what links
1008  // sim::SimChannel and recob::Hit is the channel ID.
1009 
1010  // In general, that is not how objects in the LArSoft
1011  // reconstruction chain are linked together. Most of them are
1012  // linked using associations and the art::Assns class:
1013  // <https://cdcvs.fnal.gov/redmine/projects/larsoft/wiki/Using_art_in_LArSoft#artAssns>
1014 
1015  // The web page may a bit difficult to understand (at least, it is
1016  // for me), so let's try to simplify things:
1017 
1018  // - If you're doing an analysis task, you don't have to worry
1019  // about creating art::Assns objects.
1020 
1021  // - You don't have to read the art:Assns objects on your
1022  // own. There are helper classes (FindXXX) which will do that for
1023  // you.
1024 
1025  // - There's only one helper you need: art::FindManyP. It will do
1026  // what you want with a minimum of fuss.
1027 
1028  // - Associations are symmetric. If you see an
1029  // art::Assns<ClassA,ClassB>, the helper classes will find all of
1030  // ClassA associated with ClassB or all of ClassB associated with
1031  // ClassA.
1032 
1033  // - To know what associations exist, you have to be a 'code
1034  // detective'. The important clue is to look for a 'produces' line
1035  // in the code that writes objects to an art::Event. For example,
1036  // in ${LARSIM_DIR}/source/larsim/LArG4/LArG4_module.cc, you'll see this
1037  // line:
1038 
1039  // produces< art::Assns<simb::MCTruth, simb::MCParticle> >();
1040 
1041  // That means a simulated event will have an association between
1042  // simb::MCTruth (the primary particle produced by the event
1043  // generator) and the simb::MCParticle objects (the secondary
1044  // particles produced in the detector simulation).
1045 
1046  // Let's try it. The following statement will find the
1047  // simb::MCTruth objects associated with the simb::MCParticle
1048  // objects in the event (referenced by particleHandle):
1049 
1050  const art::FindManyP<simb::MCTruth> findManyTruth(particleHandle, event, fSimulationProducerLabel);
1051 
1052  // Note that we still have to supply the module label of the step
1053  // that created the association. Also note that we did not have to
1054  // explicitly read in the simb::MCTruth objects from the
1055  // art::Event object 'event'; FindManyP did that for us.
1056 
1057  // Also note that at this point art::FindManyP has already found
1058  // all the simb::MCTruth associated with each of the particles in
1059  // particleHandle. This is a slow process, so in general you want
1060  // to do it only once. If we had a loop over the particles, we
1061  // would still do this outside that loop.
1062 
1063  // Now we can query the 'findManyTruth' object to access the
1064  // information. First, check that there wasn't some kind of error:
1065 
1066  if ( ! findManyTruth.isValid() )
1067  {
1068  mf::LogError("AnalysisExample")
1069  << "findManyTruth simb::MCTruth for simb::MCParticle failed!";
1070  }
1071 
1072  // I'm going to be lazy, and just look at the simb::MCTruth object
1073  // associated with the first simb::MCParticle we read in. (The
1074  // main reason I'm being lazy is that if I used the
1075  // single-particle generator in prodsingle.fcl, every particle in
1076  // the event is going to be associated with just the one primary
1077  // particle from the event generator.)
1078 
1079  size_t particle_index = 0; // look at first particle in
1080  // particleHandle's vector.
1081 
1082  // I'm using "auto" to save on typing. The result of
1083  // FindManyP::at() is a vector of pointers, in this case
1084  // simb::MCTruth*. In this case it will be a vector with just one
1085  // entry; I could have used art::FindOneP instead. (This will be a
1086  // vector of art::Ptr, which is a type of smart pointer; see
1087  // <https://cdcvs.fnal.gov/redmine/projects/larsoft/wiki/Using_art_in_LArSoft#artPtrltTgt-and-artPtrVectorltTgt>
1088  // To avoid unnecessary copying, and since art::FindManyP returns
1089  // a constant reference, use "auto const&".
1090 
1091  auto const& truth = findManyTruth.at( particle_index );
1092 
1093  // Make sure there's no problem.
1094  if ( truth.empty() )
1095  {
1096  mf::LogError("AnalysisExample")
1097  << "Particle ID=" << particleHandle->at( particle_index ).TrackId()
1098  << " has no primary!";
1099  }
1100 
1101  // Use the message facility to write output. I don't have to write
1102  // the event, run, or subrun numbers; the message facility takes
1103  // care of that automatically. I'm "going at warp speed" with the
1104  // vectors, pointers, and methods; see
1105  // ${NUSIMDATA_INC}/nusimdata/SimulationBase/MCTruth.h and
1106  // ${NUSIMDATA_INC}/nusimdata/SimulationBase/MCParticle.h for the
1107  // nested calls I'm using.
1108  mf::LogInfo("AnalysisExample")
1109  << "Particle ID=" << particleHandle->at( particle_index ).TrackId()
1110  << " primary PDG code=" << truth[0]->GetParticle(0).PdgCode();
1111 
1112  // Let's try a slightly more realistic example. Suppose I want to
1113  // read in the clusters, and learn what hits are associated with
1114  // them. Then I could backtrack from those hits to determine the
1115  // dE/dx of the particles in the clusters. (Don't worry; I won't
1116  // put you through the n-tuple creation procedure for a third
1117  // time.)
1118 
1119  // First, read in the clusters (if there are any).
1121  if (!event.getByLabel(fClusterProducerLabel, clusterHandle)) return;
1122 
1123  // Now use the associations to find which hits are associated with
1124  // which clusters. Note that this is not as trivial a query as the
1125  // one with MCTruth, since it's possible for a hit to be assigned
1126  // to more than one cluster.
1127 
1128  // We have to include fClusterProducerLabel, since that's the step
1129  // that created the art::Assns<recob::Hit,recob::Cluster> object;
1130  // look at the modules in ${LARRECO_DIR}/source/larreco/ClusterFinder/
1131  // and search for the 'produces' lines. (I did not know this before I
1132  // wrote these comments. I had to be a code detective and use UNIX
1133  // tools like 'grep' and 'find' to locate those routines.)
1134  const art::FindManyP<recob::Hit> findManyHits(clusterHandle, event, fClusterProducerLabel);
1135 
1136  if ( ! findManyHits.isValid() )
1137  {
1138  mf::LogError("AnalysisExample")
1139  << "findManyHits recob::Hit for recob::Cluster failed;"
1140  << " cluster label='" << fClusterProducerLabel << "'";
1141  }
1142 
1143  // Now we'll loop over the clusters to see the hits associated
1144  // with each one. Note that we're not using a range-based for
1145  // loop. That's because FindManyP::at() expects a number as an
1146  // argument, so we might as well go through the cluster objects
1147  // via numerical index instead.
1148  for ( size_t cluster_index = 0; cluster_index != clusterHandle->size(); cluster_index++ )
1149  {
1150  // In this case, FindManyP::at() will return a vector of
1151  // pointers to recob::Hit that corresponds to the
1152  // "cluster_index"-th cluster.
1153  auto const& hits = findManyHits.at( cluster_index );
1154 
1155  // We have a vector of pointers to the hits associated
1156  // with the cluster, but for this example I'm not going to
1157  // do anything fancy with them. I'll just print out how
1158  // many there are.
1159  mf::LogInfo("AnalysisExample")
1160  << "Cluster ID=" << clusterHandle->at( cluster_index ).ID()
1161  << " has " << hits.size() << " hits";
1162  }
1163 
1164  } // AnalysisExample::analyze()
int fSimNdEdxBins
Number of dE/dx bins in a given track.
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:223
int PdgCode() const
Definition: MCParticle.h:216
TH1D * fPDGCodeHist
PDG code of all particles.
int fRecoTrackID
GEANT ID of the particle being processed.
std::pair< unsigned short, std::vector< sim::IDE > > TDCIDE
List of energy deposits at the same time (on this channel)
Definition: SimChannel.h:125
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
art::InputTag fHitProducerLabel
The name of the producer that created hits.
double fEndXYZT[4]
(x,y,z,t) of the true end of the particle
geo::GeometryCore const * fGeometryService
pointer to Geometry provider
std::vector< double > fSimdEdxBins
The vector that will be used to accumulate dE/dx values as a function of range.
double fStartPE[4]
(Px,Py,Pz,E) at the true start of the particle
int fSimTrackID
GEANT ID of the particle being processed.
TTree * fReconstructionNtuple
tuple with reconstructed data
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::string Process() const
Definition: MCParticle.h:219
art::InputTag fSimulationProducerLabel
The name of the producer that tracked simulated particles through the detector.
int fRecoNdEdxBins
Number of dE/dx bins in a given track.
Int_t max
Definition: plot.C:27
void hits()
Definition: readHits.C:15
double fStartXYZT[4]
(x,y,z,t) of the true start of the particle
double energy
Definition: plottest35.C:25
std::vector< double > fRecodEdxBins
The vector that will be used to accumulate dE/dx values as a function of range.
detinfo::DetectorClocks const * fTimeService
pointer to detector clock time service provider
art::InputTag fClusterProducerLabel
The name of the producer that created clusters.
float bin[41]
Definition: plottest35.C:14
int fRecoPDG
PDG ID of the particle being processed.
Detector simulation of raw signals on wires.
int fSimPDG
PDG ID of the particle being processed.
int fRun
number of the run being processed
virtual double TPCTick2TDC(double tick) const =0
Converts a TPC time tick into a electronics time tick.
TH1D * fMomentumHist
momentum [GeV] of all selected particles
int fEvent
number of the event being processed
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
Int_t min
Definition: plot.C:26
#define LOG_DEBUG(id)
double fEndPE[4]
(Px,Py,Pz,E) at the true end of the particle
TTree * fSimulationNtuple
tuple with simulated data
double fElectronsToGeV
conversion factor
double fBinSize
For dE/dx work: the value of dx.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
TH1D * fTrackLengthHist
true length [cm] of all selected particles
int fSelectedPDG
PDG code of particle we&#39;ll focus on.
TDCIDE::first_type StoredTDC_t
Type for TDC tick used in the internal representation.
Definition: SimChannel.h:147
Signal from collection planes.
Definition: geo_types.h:93
void lar::example::AnalysisExample::beginJob ( )
overridevirtual

Reimplemented from art::EDAnalyzer.

Definition at line 414 of file AnalysisExample_module.cc.

References fEndPE, fEndXYZT, fEvent, fGeometryService, fMomentumHist, fPDGCodeHist, fRecodEdxBins, fRecoNdEdxBins, fReconstructionNtuple, fRecoPDG, fRecoTrackID, fRun, fSimdEdxBins, fSimNdEdxBins, fSimPDG, fSimTrackID, fSimulationNtuple, fStartPE, fStartXYZT, fSubRun, fTrackLengthHist, and art::TFileDirectory::make().

415  {
416  // Get the detector length, to determine the maximum bin edge of one
417  // of the histograms.
418  const double detectorLength = DetectorDiagonal(*fGeometryService);
419 
420  // Access ART's TFileService, which will handle creating and writing
421  // histograms and n-tuples for us.
423 
424  // For TFileService, the arguments to 'make<whatever>' are the
425  // same as those passed to the 'whatever' constructor, provided
426  // 'whatever' is a ROOT class that TFileService recognizes.
427 
428  // Define the histograms. Putting semi-colons around the title
429  // causes it to be displayed as the x-axis label if the histogram
430  // is drawn (the format is "title;label on abscissae;label on ordinates").
431  fPDGCodeHist = tfs->make<TH1D>("pdgcodes",";PDG Code;", 5000, -2500, 2500);
432  fMomentumHist = tfs->make<TH1D>("mom", ";particle Momentum (GeV);", 100, 0., 10.);
433  fTrackLengthHist = tfs->make<TH1D>("length", ";particle track length (cm);", 200, 0, detectorLength);
434 
435  // Define our n-tuples, which are limited forms of ROOT
436  // TTrees. Start with the TTree itself.
437  fSimulationNtuple = tfs->make<TTree>("AnalysisExampleSimulation", "AnalysisExampleSimulation");
438  fReconstructionNtuple = tfs->make<TTree>("AnalysisExampleReconstruction","AnalysisExampleReconstruction");
439 
440  // Define the branches (columns) of our simulation n-tuple. To
441  // write a variable, we give the address of the variable to
442  // TTree::Branch.
443  fSimulationNtuple->Branch("Event", &fEvent, "Event/I");
444  fSimulationNtuple->Branch("SubRun", &fSubRun, "SubRun/I");
445  fSimulationNtuple->Branch("Run", &fRun, "Run/I");
446  fSimulationNtuple->Branch("TrackID", &fSimTrackID, "TrackID/I");
447  fSimulationNtuple->Branch("PDG", &fSimPDG, "PDG/I");
448  // When we write arrays, we give the address of the array to
449  // TTree::Branch; in C++ this is simply the array name.
450  fSimulationNtuple->Branch("StartXYZT", fStartXYZT, "StartXYZT[4]/D");
451  fSimulationNtuple->Branch("EndXYZT", fEndXYZT, "EndXYZT[4]/D");
452  fSimulationNtuple->Branch("StartPE", fStartPE, "StartPE[4]/D");
453  fSimulationNtuple->Branch("EndPE", fEndPE, "EndPE[4]/D");
454  // For a variable-length array: include the number of bins.
455  fSimulationNtuple->Branch("NdEdx", &fSimNdEdxBins, "NdEdx/I");
456  // ROOT branches can contain std::vector objects.
457  fSimulationNtuple->Branch("dEdx", &fSimdEdxBins);
458 
459  // A similar definition for the reconstruction n-tuple. Note that we
460  // use some of the same variables in both n-tuples.
461  fReconstructionNtuple->Branch("Event", &fEvent, "Event/I");
462  fReconstructionNtuple->Branch("SubRun", &fSubRun, "SubRun/I");
463  fReconstructionNtuple->Branch("Run", &fRun, "Run/I");
464  fReconstructionNtuple->Branch("TrackID", &fRecoTrackID, "TrackID/I");
465  fReconstructionNtuple->Branch("PDG", &fRecoPDG, "PDG/I");
466  fReconstructionNtuple->Branch("NdEdx", &fRecoNdEdxBins, "NdEdx/I");
467  fReconstructionNtuple->Branch("dEdx", &fRecodEdxBins);
468  }
int fSimNdEdxBins
Number of dE/dx bins in a given track.
TH1D * fPDGCodeHist
PDG code of all particles.
int fRecoTrackID
GEANT ID of the particle being processed.
double fEndXYZT[4]
(x,y,z,t) of the true end of the particle
geo::GeometryCore const * fGeometryService
pointer to Geometry provider
std::vector< double > fSimdEdxBins
The vector that will be used to accumulate dE/dx values as a function of range.
double fStartPE[4]
(Px,Py,Pz,E) at the true start of the particle
int fSimTrackID
GEANT ID of the particle being processed.
TTree * fReconstructionNtuple
tuple with reconstructed data
int fRecoNdEdxBins
Number of dE/dx bins in a given track.
double fStartXYZT[4]
(x,y,z,t) of the true start of the particle
std::vector< double > fRecodEdxBins
The vector that will be used to accumulate dE/dx values as a function of range.
int fRecoPDG
PDG ID of the particle being processed.
int fSimPDG
PDG ID of the particle being processed.
int fRun
number of the run being processed
T * make(ARGS...args) const
TH1D * fMomentumHist
momentum [GeV] of all selected particles
int fEvent
number of the event being processed
double fEndPE[4]
(Px,Py,Pz,E) at the true end of the particle
TTree * fSimulationNtuple
tuple with simulated data
TH1D * fTrackLengthHist
true length [cm] of all selected particles
void lar::example::AnalysisExample::beginRun ( const art::Run run)
overridevirtual

Definition at line 478 of file AnalysisExample_module.cc.

References fElectronsToGeV, and sim::LArG4Parameters::GeVToElectrons().

479  {
480  // How to convert from number of electrons to GeV. The ultimate
481  // source of this conversion factor is
482  // ${LARCOREOBJ_INC}/larcoreobj/SimpleTypesAndConstants/PhysicalConstants.h.
483  // But sim::LArG4Parameters might in principle ask a database for it.
485  fElectronsToGeV = 1./larParameters->GeVToElectrons();
486  }
double fElectronsToGeV
conversion factor
double GeVToElectrons() const
detail::CachedProducts& art::EventObserverBase::cachedProducts ( )
inlineprotectedinherited

Definition at line 79 of file EventObserverBase.h.

References art::EventObserverBase::selectors_.

Referenced by art::EDAnalyzer::doEvent(), and art::OutputModule::doWriteEvent().

80  {
81  return selectors_;
82  }
detail::CachedProducts selectors_
template<typename T , BranchType = InEvent>
ProductToken<T> art::Consumer::consumes ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ProductToken<T> art::Consumer::consumes ( InputTag const &  it)
inherited

Definition at line 147 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

148 {
149  if (!moduleContext_)
150  return ProductToken<T>::invalid();
151 
152  consumables_[BT].emplace_back(ConsumableType::Product,
153  TypeID{typeid(T)},
154  it.label(),
155  it.instance(),
156  it.process());
157  return ProductToken<T>{it};
158 }
static ProductToken< T > invalid()
Definition: ProductToken.h:47
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename T , art::BranchType BT>
void art::Consumer::consumesMany ( )
inherited

Definition at line 162 of file Consumer.h.

163 {
164  if (!moduleContext_)
165  return;
166 
167  consumables_[BT].emplace_back(ConsumableType::Many, TypeID{typeid(T)});
168 }
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::Consumer::consumesView ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ViewToken<T> art::Consumer::consumesView ( InputTag const &  it)
inherited

Definition at line 172 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

173 {
174  if (!moduleContext_)
175  return ViewToken<T>::invalid();
176 
177  consumables_[BT].emplace_back(ConsumableType::ViewElement,
178  TypeID{typeid(T)},
179  it.label(),
180  it.instance(),
181  it.process());
182  return ViewToken<T>{it};
183 }
static ViewToken< Element > invalid()
Definition: ProductToken.h:75
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
EngineCreator::base_engine_t & EngineCreator::createEngine ( seed_t  seed,
std::string const &  kind_of_engine_to_make 
)
inherited

Definition at line 32 of file EngineCreator.cc.

References art::EngineCreator::rng().

34 {
35  return rng()->createEngine(
36  placeholder_schedule_id(), seed, kind_of_engine_to_make);
37 }
long seed
Definition: chem4.cc:68
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
EngineCreator::base_engine_t & EngineCreator::createEngine ( seed_t  seed,
std::string const &  kind_of_engine_to_make,
label_t const &  engine_label 
)
inherited

Definition at line 40 of file EngineCreator.cc.

References art::EngineCreator::rng().

43 {
44  return rng()->createEngine(
45  placeholder_schedule_id(), seed, kind_of_engine_to_make, engine_label);
46 }
long seed
Definition: chem4.cc:68
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
CurrentProcessingContext const * art::EDAnalyzer::currentContext ( ) const
protectedinherited

Definition at line 114 of file EDAnalyzer.cc.

References art::EDAnalyzer::current_context_.

Referenced by art::EDAnalyzer::workerType().

115  {
116  return current_context_.get();
117  }
CPC_exempt_ptr current_context_
Definition: EDAnalyzer.h:179
EngineCreator::seed_t EngineCreator::get_seed_value ( fhicl::ParameterSet const &  pset,
char const  key[] = "seed",
seed_t const  implicit_seed = -1 
)
inherited

Definition at line 49 of file EngineCreator.cc.

References fhicl::ParameterSet::get().

Referenced by art::MixFilter< T >::initEngine_().

52 {
53  auto const& explicit_seeds = pset.get<std::vector<int>>(key, {});
54  return explicit_seeds.empty() ? implicit_seed : explicit_seeds.front();
55 }
art::Handle<art::TriggerResults> art::EventObserverBase::getTriggerResults ( Event const &  e) const
inlineinherited

Definition at line 61 of file EventObserverBase.h.

References art::detail::CachedProducts::getOneTriggerResults(), and art::EventObserverBase::selectors_.

Referenced by art::OutputModule::doWriteEvent().

62  {
64  }
detail::CachedProducts selectors_
art::Handle< art::TriggerResults > getOneTriggerResults(Event const &) const
Float_t e
Definition: plot.C:34
template<typename T , BranchType = InEvent>
ProductToken<T> art::Consumer::mayConsume ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ProductToken<T> art::Consumer::mayConsume ( InputTag const &  it)
inherited

Definition at line 190 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

191 {
192  if (!moduleContext_)
193  return ProductToken<T>::invalid();
194 
195  consumables_[BT].emplace_back(ConsumableType::Product,
196  TypeID{typeid(T)},
197  it.label(),
198  it.instance(),
199  it.process());
200  return ProductToken<T>{it};
201 }
static ProductToken< T > invalid()
Definition: ProductToken.h:47
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename T , art::BranchType BT>
void art::Consumer::mayConsumeMany ( )
inherited

Definition at line 205 of file Consumer.h.

206 {
207  if (!moduleContext_)
208  return;
209 
210  consumables_[BT].emplace_back(ConsumableType::Many, TypeID{typeid(T)});
211 }
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::Consumer::mayConsumeView ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ViewToken<T> art::Consumer::mayConsumeView ( InputTag const &  it)
inherited

Definition at line 215 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

216 {
217  if (!moduleContext_)
218  return ViewToken<T>::invalid();
219 
220  consumables_[BT].emplace_back(ConsumableType::ViewElement,
221  TypeID{typeid(T)},
222  it.label(),
223  it.instance(),
224  it.process());
225  return ViewToken<T>{it};
226 }
static ViewToken< Element > invalid()
Definition: ProductToken.h:75
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
bool art::EventObserverBase::modifiesEvent ( ) const
inlineinherited

Definition at line 25 of file EventObserverBase.h.

26  {
27  return false;
28  }
void art::Consumer::prepareForJob ( fhicl::ParameterSet const &  pset)
protectedinherited

Definition at line 89 of file Consumer.cc.

References fhicl::ParameterSet::get_if_present().

Referenced by art::EDProducer::doBeginJob(), art::EDFilter::doBeginJob(), and art::EDAnalyzer::doBeginJob().

90 {
91  if (!moduleContext_)
92  return;
93 
94  pset.get_if_present("errorOnMissingConsumes", requireConsumes_);
95  for (auto& consumablesPerBranch : consumables_) {
96  cet::sort_all(consumablesPerBranch);
97  }
98 }
bool requireConsumes_
Definition: Consumer.h:137
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
std::string const& art::EventObserverBase::processName ( ) const
inlineinherited
void art::EventObserverBase::registerProducts ( MasterProductRegistry ,
ProductDescriptions ,
ModuleDescription const &   
)
inlineinherited

Definition at line 33 of file EventObserverBase.h.

36  {}
fhicl::ParameterSetID art::EventObserverBase::selectorConfig ( ) const
inlineinherited

Definition at line 56 of file EventObserverBase.h.

References art::EventObserverBase::selector_config_id_.

Referenced by art::RootOutputFile::writeOne().

57  {
58  return selector_config_id_;
59  }
fhicl::ParameterSetID selector_config_id_
void art::Consumer::showMissingConsumes ( ) const
protectedinherited

Definition at line 125 of file Consumer.cc.

Referenced by art::EDProducer::doEndJob(), art::EDFilter::doEndJob(), art::EDAnalyzer::doEndJob(), and art::RootOutput::endJob().

126 {
127  if (!moduleContext_)
128  return;
129 
130  // If none of the branches have missing consumes statements, exit early.
131  if (std::all_of(cbegin(missingConsumes_),
132  cend(missingConsumes_),
133  [](auto const& perBranch) { return perBranch.empty(); }))
134  return;
135 
136  constexpr cet::HorizontalRule rule{60};
137  mf::LogPrint log{"MTdiagnostics"};
138  log << '\n'
139  << rule('=') << '\n'
140  << "The following consumes (or mayConsume) statements are missing from\n"
141  << module_context(moduleDescription_) << '\n'
142  << rule('-') << '\n';
143 
144  cet::for_all_with_index(
145  missingConsumes_, [&log](std::size_t const i, auto const& perBranch) {
146  for (auto const& pi : perBranch) {
147  log << " "
148  << assemble_consumes_statement(static_cast<BranchType>(i), pi)
149  << '\n';
150  }
151  });
152  log << rule('=');
153 }
cet::exempt_ptr< ModuleDescription const > moduleDescription_
Definition: Consumer.h:140
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
bool moduleContext_
Definition: Consumer.h:136
ConsumableProductSets missingConsumes_
Definition: Consumer.h:139
void art::Consumer::validateConsumedProduct ( BranchType const  bt,
ProductInfo const &  pi 
)
protectedinherited

Definition at line 101 of file Consumer.cc.

References art::errors::ProductRegistrationFailure.

103 {
104  // Early exits if consumes tracking has been disabled or if the
105  // consumed product is an allowed consumable.
106  if (!moduleContext_)
107  return;
108 
109  if (cet::binary_search_all(consumables_[bt], pi))
110  return;
111 
112  if (requireConsumes_) {
114  "Consumer: an error occurred during validation of a "
115  "retrieved product\n\n")
116  << "The following consumes (or mayConsume) statement is missing from\n"
117  << module_context(moduleDescription_) << ":\n\n"
118  << " " << assemble_consumes_statement(bt, pi) << "\n\n";
119  }
120 
121  missingConsumes_[bt].insert(pi);
122 }
cet::exempt_ptr< ModuleDescription const > moduleDescription_
Definition: Consumer.h:140
bool requireConsumes_
Definition: Consumer.h:137
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
ConsumableProductSets missingConsumes_
Definition: Consumer.h:139
bool art::EventObserverBase::wantAllEvents ( ) const
inlineinherited
bool art::EventObserverBase::wantEvent ( Event const &  e)
inlineinherited
std::string art::EDAnalyzer::workerType ( ) const
inlineinherited

Definition at line 109 of file EDAnalyzer.h.

References art::EDAnalyzer::currentContext().

110  {
111  return "WorkerT<EDAnalyzer>";
112  }

Member Data Documentation

double lar::example::AnalysisExample::fBinSize
private

For dE/dx work: the value of dx.

Definition at line 307 of file AnalysisExample_module.cc.

Referenced by analyze().

art::InputTag lar::example::AnalysisExample::fClusterProducerLabel
private

The name of the producer that created clusters.

Definition at line 305 of file AnalysisExample_module.cc.

Referenced by AnalysisExample(), and analyze().

double lar::example::AnalysisExample::fElectronsToGeV
private

conversion factor

Definition at line 362 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginRun().

double lar::example::AnalysisExample::fEndPE[4]
private

(Px,Py,Pz,E) at the true end of the particle

Definition at line 337 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

double lar::example::AnalysisExample::fEndXYZT[4]
private

(x,y,z,t) of the true end of the particle

Definition at line 335 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fEvent
private

number of the event being processed

Definition at line 321 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

geo::GeometryCore const* lar::example::AnalysisExample::fGeometryService
private

pointer to Geometry provider

Definition at line 360 of file AnalysisExample_module.cc.

Referenced by AnalysisExample(), analyze(), and beginJob().

art::InputTag lar::example::AnalysisExample::fHitProducerLabel
private

The name of the producer that created hits.

Definition at line 304 of file AnalysisExample_module.cc.

Referenced by AnalysisExample(), and analyze().

TH1D* lar::example::AnalysisExample::fMomentumHist
private

momentum [GeV] of all selected particles

Definition at line 311 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

TH1D* lar::example::AnalysisExample::fPDGCodeHist
private

PDG code of all particles.

Definition at line 310 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

std::vector<double> lar::example::AnalysisExample::fRecodEdxBins
private

The vector that will be used to accumulate dE/dx values as a function of range.

Definition at line 355 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fRecoNdEdxBins
private

Number of dE/dx bins in a given track.

Definition at line 352 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

TTree* lar::example::AnalysisExample::fReconstructionNtuple
private

tuple with reconstructed data

Definition at line 316 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fRecoPDG
private

PDG ID of the particle being processed.

Definition at line 348 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fRecoTrackID
private

GEANT ID of the particle being processed.

Definition at line 349 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fRun
private

number of the run being processed

Definition at line 322 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fSelectedPDG
private

PDG code of particle we'll focus on.

Definition at line 306 of file AnalysisExample_module.cc.

Referenced by analyze().

std::vector<double> lar::example::AnalysisExample::fSimdEdxBins
private

The vector that will be used to accumulate dE/dx values as a function of range.

Definition at line 343 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fSimNdEdxBins
private

Number of dE/dx bins in a given track.

Definition at line 340 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fSimPDG
private

PDG ID of the particle being processed.

Definition at line 328 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fSimTrackID
private

GEANT ID of the particle being processed.

Definition at line 329 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

TTree* lar::example::AnalysisExample::fSimulationNtuple
private

tuple with simulated data

Definition at line 315 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

art::InputTag lar::example::AnalysisExample::fSimulationProducerLabel
private

The name of the producer that tracked simulated particles through the detector.

Definition at line 303 of file AnalysisExample_module.cc.

Referenced by AnalysisExample(), and analyze().

double lar::example::AnalysisExample::fStartPE[4]
private

(Px,Py,Pz,E) at the true start of the particle

Definition at line 336 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

double lar::example::AnalysisExample::fStartXYZT[4]
private

(x,y,z,t) of the true start of the particle

Definition at line 334 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fSubRun
private

number of the sub-run being processed

Definition at line 323 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

detinfo::DetectorClocks const* lar::example::AnalysisExample::fTimeService
private

pointer to detector clock time service provider

Definition at line 361 of file AnalysisExample_module.cc.

Referenced by AnalysisExample(), and analyze().

TH1D* lar::example::AnalysisExample::fTrackLengthHist
private

true length [cm] of all selected particles

Definition at line 312 of file AnalysisExample_module.cc.

Referenced by analyze(), and beginJob().

int lar::example::AnalysisExample::fTriggerOffset
private

(units of ticks) time of expected neutrino event

Definition at line 363 of file AnalysisExample_module.cc.

Referenced by AnalysisExample().


The documentation for this class was generated from the following file: