63 #include "nusimdata/SimulationBase/MCParticle.h"
64 #include "nusimdata/SimulationBase/MCTruth.h"
67 #include "art/Framework/Core/EDAnalyzer.h"
68 #include "art/Framework/Core/ModuleMacros.h"
69 #include "art/Framework/Principal/Event.h"
70 #include "art/Framework/Principal/Handle.h"
71 #include "art/Framework/Services/Registry/ServiceHandle.h"
72 #include "art_root_io/TFileService.h"
73 #include "canvas/Persistency/Common/FindManyP.h"
74 #include "canvas/Utilities/Exception.h"
77 #include "cetlib/pow.h"
78 #include "fhiclcpp/types/Atom.h"
79 #include "fhiclcpp/types/Table.h"
80 #include "messagefacility/MessageLogger/MessageLogger.h"
86 #include "TLorentzVector.h"
205 Name(
"SimulationLabel"),
206 Comment(
"tag of the input data product with the detector simulation "
211 Comment(
"tag of the input data product with reconstructed hits")};
214 Name(
"ClusterLabel"),
215 Comment(
"tag of the input data product with reconstructed clusters")};
219 Comment(
"particle type (PDG ID) of the primary particle to be selected")};
222 Comment(
"dx [cm] used for the dE/dx calculation")};
281 virtual void beginRun(
const art::Run& run)
override;
284 virtual void analyze(
const art::Event& event)
override;
376 , fSimulationProducerLabel(config().SimulationLabel())
377 , fHitProducerLabel(config().HitLabel())
378 , fClusterProducerLabel(config().ClusterLabel())
379 , fSelectedPDG(config().PDGcode())
380 , fBinSize(config().BinSize())
385 auto const clock_data =
386 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
412 art::ServiceHandle<art::TFileService const>
tfs;
421 fPDGCodeHist = tfs->make<TH1D>(
"pdgcodes",
";PDG Code;", 5000, -2500, 2500);
422 fMomentumHist = tfs->make<TH1D>(
"mom",
";particle Momentum (GeV);", 100, 0., 10.);
424 tfs->make<TH1D>(
"length",
";particle track length (cm);", 200, 0, detectorLength);
429 tfs->make<TTree>(
"AnalysisExampleSimulation",
"AnalysisExampleSimulation");
431 tfs->make<TTree>(
"AnalysisExampleReconstruction",
"AnalysisExampleReconstruction");
436 fSimulationNtuple->Branch(
"Event", &
fEvent,
"Event/I");
437 fSimulationNtuple->Branch(
"SubRun", &
fSubRun,
"SubRun/I");
438 fSimulationNtuple->Branch(
"Run", &
fRun,
"Run/I");
439 fSimulationNtuple->Branch(
"TrackID", &
fSimTrackID,
"TrackID/I");
440 fSimulationNtuple->Branch(
"PDG", &
fSimPDG,
"PDG/I");
443 fSimulationNtuple->Branch(
"StartXYZT",
fStartXYZT,
"StartXYZT[4]/D");
444 fSimulationNtuple->Branch(
"EndXYZT",
fEndXYZT,
"EndXYZT[4]/D");
445 fSimulationNtuple->Branch(
"StartPE",
fStartPE,
"StartPE[4]/D");
446 fSimulationNtuple->Branch(
"EndPE",
fEndPE,
"EndPE[4]/D");
448 fSimulationNtuple->Branch(
"NdEdx", &
fSimNdEdxBins,
"NdEdx/I");
454 fReconstructionNtuple->Branch(
"Event", &
fEvent,
"Event/I");
455 fReconstructionNtuple->Branch(
"SubRun", &
fSubRun,
"SubRun/I");
456 fReconstructionNtuple->Branch(
"Run", &
fRun,
"Run/I");
457 fReconstructionNtuple->Branch(
"TrackID", &
fRecoTrackID,
"TrackID/I");
458 fReconstructionNtuple->Branch(
"PDG", &
fRecoPDG,
"PDG/I");
459 fReconstructionNtuple->Branch(
"NdEdx", &
fRecoNdEdxBins,
"NdEdx/I");
478 art::ServiceHandle<sim::LArG4Parameters const> larParameters;
487 fEvent =
event.id().event();
497 art::Handle<std::vector<simb::MCParticle>> particleHandle;
518 throw cet::exception(
"AnalysisExample")
519 <<
" No simb::MCParticle objects in this event - "
520 <<
" Line " << __LINE__ <<
" in file " << __FILE__ << std::endl;
538 auto simChannelHandle =
550 std::map<int, const simb::MCParticle*> particleMap;
582 for (
auto const& particle : (*particleHandle)) {
602 const size_t numberTrajectoryPoints = particle.NumberTrajectoryPoints();
606 const int last = numberTrajectoryPoints - 1;
607 const TLorentzVector& positionStart = particle.Position(0);
608 const TLorentzVector& positionEnd = particle.Position(last);
609 const TLorentzVector& momentumStart = particle.Momentum(0);
610 const TLorentzVector& momentumEnd = particle.Momentum(last);
621 momentumEnd.GetXYZT(
fEndPE);
625 const double trackLength = (positionEnd - positionStart).Rho();
631 MF_LOG_DEBUG(
"AnalysisExample") <<
"Track length: " << trackLength <<
" cm";
636 MF_LOG_DEBUG(
"AnalysisExample")
638 <<
" cm long, momentum " << momentumStart.P() <<
" GeV/c, has " << numberTrajectoryPoints
639 <<
" trajectory points";
648 for (
auto const& channel : (*simChannelHandle)) {
653 auto const channelNumber = channel.Channel();
667 auto const& timeSlices = channel.TDCIDEMap();
670 for (
auto const& timeSlice : timeSlices) {
674 auto const& energyDeposits = timeSlice.second;
683 for (
auto const& energyDeposit : energyDeposits) {
686 if (energyDeposit.trackID !=
fSimTrackID)
continue;
688 TVector3 location(energyDeposit.x, energyDeposit.y, energyDeposit.z);
691 const double distance = (location - positionStart.Vect()).Mag();
694 const unsigned int bin = (
unsigned int)(distance /
fBinSize);
747 art::Handle<std::vector<recob::Hit>> hitHandle;
755 std::map<int, std::vector<double>> dEdxMap;
757 auto const clock_data =
758 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
761 for (
auto const&
hit : (*hitHandle)) {
763 auto hitChannelNumber =
hit.Channel();
769 MF_LOG_DEBUG(
"AnalysisExample") <<
"Hit in collection plane" << std::endl;
785 TDC_t start_tdc = clock_data.TPCTick2TDC(
hit.StartTick());
786 TDC_t end_tdc = clock_data.TPCTick2TDC(
hit.EndTick());
787 TDC_t hitStart_tdc = clock_data.TPCTick2TDC(
hit.PeakTime() - 3. *
hit.SigmaPeakTime());
788 TDC_t hitEnd_tdc = clock_data.TPCTick2TDC(
hit.PeakTime() + 3. *
hit.SigmaPeakTime());
790 start_tdc = std::max(start_tdc, hitStart_tdc);
791 end_tdc = std::min(end_tdc, hitEnd_tdc);
798 for (
auto const& channel : (*simChannelHandle)) {
799 auto simChannelNumber = channel.Channel();
800 if (simChannelNumber != hitChannelNumber)
continue;
802 MF_LOG_DEBUG(
"AnalysisExample")
803 <<
"SimChannel number = " << simChannelNumber << std::endl;
806 auto const& timeSlices = channel.TDCIDEMap();
826 startTime.first = start_tdc;
827 endTime.first = end_tdc;
832 auto const startPointer =
833 std::lower_bound(timeSlices.begin(), timeSlices.end(), startTime, TDCIDETimeCompare);
836 auto const endPointer =
837 std::upper_bound(startPointer, timeSlices.end(), endTime, TDCIDETimeCompare);
840 if (startPointer == timeSlices.end() || startPointer == endPointer)
continue;
841 MF_LOG_DEBUG(
"AnalysisExample")
842 <<
"Time slice start = " << (*startPointer).first << std::endl;
846 for (
auto slicePointer = startPointer; slicePointer != endPointer; slicePointer++) {
847 auto const timeSlice = *slicePointer;
848 auto time = timeSlice.first;
861 MF_LOG_DEBUG(
"AnalysisExample")
862 <<
"Hit index = " <<
hit.LocalIndex() <<
" channel number = " << hitChannelNumber
863 <<
" start TDC tick = " <<
hit.StartTick() <<
" end TDC tick = " <<
hit.EndTick()
864 <<
" peak TDC tick = " <<
hit.PeakTime()
865 <<
" sigma peak time = " <<
hit.SigmaPeakTime()
866 <<
" adjusted start TDC tick = " << clock_data.TPCTick2TDC(
hit.StartTick())
867 <<
" adjusted end TDC tick = " << clock_data.TPCTick2TDC(
hit.EndTick())
868 <<
" adjusted peak TDC tick = " << clock_data.TPCTick2TDC(
hit.PeakTime())
869 <<
" adjusted start_tdc = " << start_tdc <<
" adjusted end_tdc = " << end_tdc
870 <<
" time = " << time << std::endl;
873 auto const& energyDeposits = timeSlice.second;
874 for (
auto const& energyDeposit : energyDeposits) {
890 auto search = particleMap.find(energyDeposit.trackID);
898 if (search == particleMap.end())
continue;
901 int trackID = (*search).first;
902 const simb::MCParticle& particle = *((*search).second);
906 if (particle.Process() !=
"primary" || particle.PdgCode() !=
fSelectedPDG)
continue;
909 const TLorentzVector& positionStart = particle.Position(0);
910 TVector3 location(energyDeposit.x, energyDeposit.y, energyDeposit.z);
911 double distance = (location - positionStart.Vect()).Mag();
931 auto& track_dEdX = dEdxMap[trackID];
932 if (track_dEdX.size() < bin + 1) {
935 track_dEdX.resize(bin + 1, 0);
939 track_dEdX[
bin] += energy;
948 for (
const auto& dEdxEntry : dEdxMap) {
958 const std::vector<double>&
dEdx = dEdxEntry.second;
1016 const art::FindManyP<simb::MCTruth> findManyTruth(
1033 if (!findManyTruth.isValid()) {
1034 mf::LogError(
"AnalysisExample")
1035 <<
"findManyTruth simb::MCTruth for simb::MCParticle failed!";
1045 size_t particle_index = 0;
1057 auto const& truth = findManyTruth.at(particle_index);
1060 if (truth.empty()) {
1061 mf::LogError(
"AnalysisExample")
1062 <<
"Particle ID=" << particleHandle->at(particle_index).TrackId() <<
" has no primary!";
1072 mf::LogInfo(
"AnalysisExample")
1073 <<
"Particle ID=" << particleHandle->at(particle_index).TrackId()
1074 <<
" primary PDG code=" << truth[0]->GetParticle(0).PdgCode();
1084 art::Handle<std::vector<recob::Cluster>> clusterHandle;
1100 if (!findManyHits.isValid()) {
1101 mf::LogError(
"AnalysisExample") <<
"findManyHits recob::Hit for recob::Cluster failed;"
1110 for (
size_t cluster_index = 0; cluster_index != clusterHandle->size(); cluster_index++) {
1114 auto const& hits = findManyHits.at(cluster_index);
1120 mf::LogInfo(
"AnalysisExample") <<
"Cluster ID=" << clusterHandle->at(cluster_index).ID()
1121 <<
" has " << hits.size() <<
" hits";
1144 return std::sqrt(cet::sum_of_squares(length, width, height));
1152 return lhs.first < rhs.first;
Store parameters for running LArG4.
int fSimNdEdxBins
Number of dE/dx bins in a given track.
TH1D * fPDGCodeHist
PDG code of all particles.
Utilities related to art service access.
fhicl::Atom< art::InputTag > HitLabel
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
fhicl::Atom< double > BinSize
fhicl::Atom< art::InputTag > SimulationLabel
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)
Declaration of signal hit object.
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
double fStartPE[4]
(Px,Py,Pz,E) at the true start of the particle
AnalysisExample(Parameters const &config)
Constructor: configures the module (see the Config structure above)
int fSimTrackID
GEANT ID of the particle being processed.
TTree * fReconstructionNtuple
tuple with reconstructed data
virtual void analyze(const art::Event &event) override
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
art::InputTag fSimulationProducerLabel
int fRecoNdEdxBins
Number of dE/dx bins in a given track.
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
Access the description of detector geometry.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
fhicl::Atom< art::InputTag > ClusterLabel
virtual void beginRun(const art::Run &run) override
art::EDAnalyzer::Table< Config > Parameters
double fStartXYZT[4]
(x,y,z,t) of the true start of the particle
std::vector< double > fRecodEdxBins
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
BEGIN_PROLOG vertical distance to the surface Name
art::InputTag fClusterProducerLabel
Description of geometry of one entire detector.
Declaration of cluster object.
int fRecoPDG
PDG ID of the particle being processed.
Definition of data types for geometry description.
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
fhicl::Atom< int > PDGcode
int fSimPDG
PDG ID of the particle being processed.
int fRun
number of the run being processed
TH1D * fMomentumHist
momentum [GeV] of all selected particles
int fEvent
number of the event being processed
object containing MC truth information necessary for making RawDigits and doing back tracking ...
int trigger_offset(DetectorClocksData const &data)
double fEndPE[4]
(Px,Py,Pz,E) at the true end of the particle
virtual void beginJob() override
TTree * fSimulationNtuple
tuple with simulated data
art::ServiceHandle< art::TFileService > tfs
double fElectronsToGeV
conversion factor
int fTriggerOffset
(units of ticks) time of expected neutrino event
double fBinSize
For dE/dx work: the value of dx.
art framework interface to geometry description
TH1D * fTrackLengthHist
true length [cm] of all selected particles
int fSelectedPDG
PDG code of particle we'll focus on.
TDCIDE::first_type StoredTDC_t
Type for TDC tick used in the internal representation.
Signal from collection planes.