41 #include "art_root_io/TFileService.h"
42 #include "art/Framework/Core/EDAnalyzer.h"
43 #include "art/Framework/Core/ModuleMacros.h"
44 #include "art/Framework/Principal/Event.h"
45 #include "art/Framework/Principal/Handle.h"
46 #include "art/Framework/Principal/Run.h"
47 #include "canvas/Persistency/Common/FindOneP.h"
48 #include "canvas/Persistency/Common/FindManyP.h"
49 #include "canvas/Persistency/Common/Assns.h"
50 #include "canvas/Persistency/Common/Ptr.h"
51 #include "canvas/Utilities/InputTag.h"
52 #include "fhiclcpp/types/TableAs.h"
53 #include "fhiclcpp/types/Sequence.h"
54 #include "fhiclcpp/types/Atom.h"
55 #include "fhiclcpp/types/OptionalAtom.h"
56 #include "messagefacility/MessageLogger/MessageLogger.h"
72 std::vector<geo::Point_t> extractTrajectory
75 std::vector<geo::Point_t> trackPath;
79 if (++index >= track.
NPoints())
break;
82 if (reverse) std::reverse(trackPath.begin(), trackPath.end());
90 namespace sbn {
class TimeTrackTreeStorage; }
181 fhicl::Atom<std::string>
Name {
183 Comment(
"name of the trigger (e.g. `\"M5O3\"`)")
187 Comment(
"tag of the input trigger info data product")
192 = fhicl::TableAs<TriggerInputSpec_t, TriggerSpecConfig>;
197 Comment(
"tag of the input particle flow objects to process")
203 Comment(
"tag of the input track time (t0) information [as PFPproducer]")
208 Name(
"T0selProducer"),
210 (
"tag of the selected tracks (as a collection of art::Ptr) [as PFPproducer]")
215 Name(
"TrackProducer"),
216 Comment(
"tag of the association of particles to tracks")
221 Name(
"TrackFitterProducer"),
222 Comment(
"tag of the association of the tracks with the hits")
227 Name(
"CaloProducer"),
228 Comment(
"tag of the association of the tracks with the calorimetry module")
234 Name(
"BeamGateProducer"),
235 Comment(
"tag of beam gate information")
240 Name(
"TriggerProducer"),
241 Comment(
"tag of hardware trigger information")
246 Name(
"FlashProducer"),
247 Comment(
"tag of flash information")
252 Name(
"EmulatedTriggers"),
253 Comment(
"the emulated triggers to include in the tree")
258 Comment(
"label for output messages of this module instance"),
259 "TimeTrackTreeStorage"
264 Comment(
"first recombination parameter for dE/dx calculations"),
270 Comment(
"second recombination parameter for dE/dx calculations"),
276 Comment(
"work function for recombination"),
282 Comment(
"Electric field in kV/cm"),
287 Name(
"ForceDowngoing"),
288 Comment(
"force all tracks to be downgoing, flipping them when necessary"),
311 void analyze(art::Event
const&
e)
override;
356 std::vector<std::pair<double, std::vector<raw::Channel_t>>>
fPMTwalls;
378 std::vector<std::pair<double, std::vector<raw::Channel_t>>>
403 , fPFPproducer {
p().PFPproducer() }
404 , fT0Producer {
p().T0Producer().value_or(fPFPproducer) }
405 , fT0selProducer {
p().T0selProducer().value_or(fPFPproducer) }
406 , fTrackProducer {
p().TrackProducer() }
407 , fTrackFitterProducer {
p().TrackFitterProducer() }
408 , fCaloProducer {
p().CaloProducer() }
409 , fBeamGateProducer {
p().BeamGateProducer() }
410 , fTriggerProducer {
p().TriggerProducer() }
411 , fFlashProducer {
p().FlashProducer() }
413 , fMODA {
p().MODA() }
414 , fMODB {
p().MODB() }
415 , fWion {
p().Wion() }
416 , fEfield {
p().Efield() }
417 , fForceDowngoing {
p().ForceDowngoing() }
419 , fPMTwalls { computePMTwalls() }
421 art::ServiceHandle<art::TFileService>()->make<TTree>
422 (
"TimedTrackStorage",
"Timed Track Tree")
433 consumes<std::vector<art::Ptr<recob::PFParticle>>>(fT0selProducer);
434 consumes<sbn::ExtraTriggerInfo>(fTriggerProducer);
435 consumes<std::vector<sim::BeamGateInfo>>(fBeamGateProducer);
436 consumes<art::Assns<recob::PFParticle, recob::Track>>(fTrackProducer);
437 consumes<art::Assns<recob::PFParticle, anab::T0>>(fT0Producer);
438 consumes<art::Assns<recob::Hit, recob::Track, recob::TrackHitMeta>>(fTrackProducer);
439 consumes<recob::OpFlash>(fFlashProducer);
444 fStoreTree->Branch(
"run", &fRun);
445 fStoreTree->Branch(
"subrun", &fSubRun);
446 fStoreTree->Branch(
"event", &fEvent);
447 fStoreTree->Branch(
"beamInfo", &fBeamInfo);
448 fStoreTree->Branch(
"triggerInfo", &fTriggerInfo);
449 fStoreTree->Branch(
"selTracks", &fTrackInfo);
450 fStoreTree->Branch(
"selFlashes", &fFlashStore);
451 fStoreTree->Branch(
"selHits", &fHitStore);
462 fSubRun = e.subRun();
466 std::vector<art::Ptr<recob::PFParticle>>
const& pfparticles = e.getProduct<std::vector<art::Ptr<recob::PFParticle>>> (fT0selProducer);
467 if(pfparticles.empty()) {
468 mf::LogDebug(
fLogCategory) <<
"No particles in '" << fT0selProducer.encode() <<
"'.";
472 std::vector<sim::BeamGateInfo>
const& beamgate = e.getProduct<std::vector<sim::BeamGateInfo>> (fBeamGateProducer);
474 mf::LogWarning(
fLogCategory) <<
"No Beam Gate Information!";
476 if(beamgate.size() > 1)
477 mf::LogWarning(
fLogCategory) <<
"Event has multiple beam gate info labels! (maybe this changes later to be standard)";
479 fBeamInfo.beamGateSimStart = bg.
Start();
480 fBeamInfo.beamGateDuration = bg.
Width();
481 fBeamInfo.beamGateType = bg.
BeamType();
488 fTriggerInfo.triggerID = triggerinfo.
triggerID;
489 fTriggerInfo.gateID = triggerinfo.
gateID;
492 art::FindOneP<recob::Track> particleTracks(pfparticles,e,fTrackProducer);
493 art::FindOneP<anab::T0> t0Tracks(pfparticles,e,fT0Producer);
494 std::vector<recob::OpFlash>
const &particleFlashes = e.getProduct<std::vector<recob::OpFlash>>(fFlashProducer);
497 art::ValidHandle<std::vector<recob::Track>> allTracks = e.getValidHandle<std::vector<recob::Track>>(fTrackProducer);
498 art::FindManyP<recob::Hit,recob::TrackHitMeta> trkht(allTracks,e,fTrackProducer);
499 art::FindManyP<anab::Calorimetry> calorim(allTracks, e, fCaloProducer);
503 = fTriggerResponses.extractorsFor(e);
504 unsigned int processed = 0;
505 for(
unsigned int iPart = 0; iPart < pfparticles.size(); ++iPart)
507 art::Ptr<recob::Track>
const& trackPtr = particleTracks.at(iPart);
508 if(trackPtr.isNull())
continue;
514 art::Ptr<anab::T0>
const& t0Ptr = t0Tracks.at(iPart);
515 float const track_t0 = t0Ptr->Time();
516 if(!particleFlashes.empty())
519 for(
unsigned int iFlash = 0; iFlash < particleFlashes.size(); ++iFlash)
523 float const flash_pe = flashPtr.
TotalPE();
524 float const flash_time = flashPtr.
Time();
525 float const flash_x = flashPtr.
XCenter();
526 float const flash_y = flashPtr.
YCenter();
527 float const flash_z = flashPtr.
ZCenter();
528 float flash_t0_diff = flash_time - track_t0/1e3;
531 fFlashInfo.flash_id = iFlash;
532 fFlashInfo.sum_pe = flash_pe;
533 fFlashInfo.flash_time = flash_time;
534 fFlashInfo.flash_x = flash_x;
535 fFlashInfo.flash_y = flash_y;
536 fFlashInfo.flash_z = flash_z;
537 fFlashInfo.diff_flash_t0 = flash_t0_diff;
539 fFlashStore.push_back(fFlashInfo);
544 trackInfo.
trackID = trackPtr->ID();
545 trackInfo.
t0 = track_t0/1e3;
552 bool const flipTrack = fForceDowngoing && (startDir.Y() > 0.0);
554 std::swap(startPoint, endPoint);
555 startDir = -trackPtr->EndDirection();
558 trackInfo.
start_x = startPoint.X();
559 trackInfo.
start_y = startPoint.Y();
560 trackInfo.
start_z = startPoint.Z();
561 trackInfo.
end_x = endPoint.X();
562 trackInfo.
end_y = endPoint.Y();
563 trackInfo.
end_z = endPoint.Z();
564 trackInfo.
dir_x = startDir.X();
565 trackInfo.
dir_y = startDir.Y();
566 trackInfo.
dir_z = startDir.Z();
567 trackInfo.
length = trackPtr->Length();
569 std::vector<geo::Point_t>
const trackPath
570 = extractTrajectory(*trackPtr, flipTrack);
573 trackInfo.
middle_x = middlePoint.X();
574 trackInfo.
middle_y = middlePoint.Y();
575 trackInfo.
middle_z = middlePoint.Z();
589 auto itBeforeCathode = trackPath.begin() + crossInfo.
indexBefore;
590 auto itAfterCathode = trackPath.begin() + crossInfo.
indexAfter;
598 if (
distance(middleAfterCathode, cathode) < 0.0) {
599 assert(
distance(middleBeforeCathode, cathode) >= 0.0);
601 std::swap(itBeforeCathode, itAfterCathode);
603 std::swap(middleBeforeCathode, middleAfterCathode);
626 unsigned int plane = 0;
628 std::vector<art::Ptr<recob::Hit>>
const& allHits = trkht.at(trackPtr.key());
629 std::vector<const recob::TrackHitMeta*>
const& trkmetas = trkht.data(trackPtr.key());
630 std::vector<art::Ptr<anab::Calorimetry>>
const& calorimetrycol = calorim.at(trackPtr.key());
631 std::vector<std::vector<unsigned int>> hits(plane);
635 for (
size_t ih = 0; ih < allHits.size(); ++ih)
638 sbn::selHitInfo hinfo = makeHit(*allHits[ih], allHits[ih].key(), *trackPtr, *trkmetas[ih], calorimetrycol, geom);
640 fHitStore.push_back(hinfo);
646 for (
size_t i = 0; i < fHitStore.size(); ++i)
648 if(fHitStore[i].
dEdx > -1)
650 float E_hit = fHitStore[i].dEdx*fHitStore[i].pitch;
654 if(fHitStore[i].dqdx > -1)
656 float q_hit = fHitStore[i].integral;
658 float q_hit_dqdx = fHitStore[i].dqdx*fHitStore[i].pitch;
659 totq_dqdx += q_hit_dqdx;
671 fTrackInfo = std::move(trackInfo);
683 triggerResponseExtractors.
fetch(iPart);
690 mf::LogInfo(
fLogCategory) <<
"Particles Processed: " << processed;
718 hinfo.
id = (int)hkey;
720 bool const badhit = (thm.
Index() == std::numeric_limits<unsigned int>::max()) ||
733 hinfo.
dirx = dir.X();
734 hinfo.
diry = dir.Y();
735 hinfo.
dirz = dir.Z();
738 for (
const art::Ptr<anab::Calorimetry> &c:
calo) {
739 if (c->PlaneID().Plane != hinfo.
plane)
continue;
742 for (
unsigned i_calo = 0; i_calo < c->dQdx().size(); i_calo++) {
744 if (c->TpIndices()[i_calo] != hkey)
continue;
747 hinfo.
pitch = c->TrkPitchVec()[i_calo];
748 hinfo.
dqdx = c->dQdx()[i_calo];
749 hinfo.
dEdx = dEdx_calc(hinfo.
dqdx, fMODA, fMODB, fWion, fEfield);
750 hinfo.
rr = c->ResidualRange()[i_calo];
768 float beta = B/(LAr_density_gmL*
E);
769 float dEdx = ((
std::exp(dQdx*Wion*beta) - alpha)/beta)*3.278;
779 mf::LogInfo(
fLogCategory) <<
"Processed " << fTotalProcessed <<
" tracks.";
785 std::vector<std::pair<double, std::vector<raw::Channel_t>>>
791 std::vector<std::pair<double, std::vector<geo::OpDetGeo const*>>> opDetWalls
796 std::map<geo::OpDetGeo const*, raw::Channel_t> opDetToChannel;
797 for (
auto const channel: util::counter<raw::Channel_t>(geom.MaxOpChannel()))
798 opDetToChannel[&geom.OpDetGeoFromOpChannel(channel)] = channel;
801 std::vector<std::pair<double, std::vector<raw::Channel_t>>> channelWalls;
802 for (
auto const& [
coord, PMTs ]: opDetWalls) {
803 std::vector<raw::Channel_t> channels;
804 channels.reserve(PMTs.size());
806 channels.push_back(opDetToChannel.at(
PMT));
808 channelWalls.emplace_back(
coord, std::move(channels));
sbn::selTriggerInfo fTriggerInfo
std::vector< sbn::selLightInfo > fFlashStore
std::vector< sbn::selHitInfo > fHitStore
sbn::selBeamInfo fBeamInfo
Information on a single trigger source for the tree.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
float middle_y
Half-way distance along the trajectory.
art::InputTag const fTriggerProducer
fhicl::Sequence< TriggerSpecConfigTable > EmulatedTriggers
fhicl::Atom< art::InputTag > TriggerTag
Utilities related to art service access.
art::InputTag const fBeamGateProducer
fhicl::Atom< art::InputTag > FlashProducer
fhicl::Atom< bool > ForceDowngoing
art::InputTag const fFlashProducer
float atcathode_z
Cathode crossing point of trajectory.
Manages extraction of trigger results and filling of their branches.
fhicl::Atom< art::InputTag > CaloProducer
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
geo::WireID WireID() const
void analyze(art::Event const &e) override
float RMS() const
RMS of the hit shape, in tick units.
geo::Point_t crossingPoint
Trajectory crossing point.
Declaration of signal hit object.
sbn::details::TriggerResponseManager fTriggerResponses
Manages filling of trigger result branches.
fhicl::Atom< float > MODA
Point_t const & LocationAtPoint(size_t i) const
bool HasValidPoint(size_t i) const
CathodeDesc_t findTPCcathode(geo::Point_t const &point, geo::GeometryCore const &geom)
Returns cathode information for cryostat at the specified point.
sbn::selLightInfo fFlashInfo
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
WireID_t Wire
Index of the wire within its plane.
double after
Length of the path "after" the cathode.
process_name use argoneut_mc_hitfinder track
fhicl::Atom< art::InputTag > TrackFitterProducer
float atcathode_x
Cathode crossing point of trajectory.
fhicl::Atom< art::InputTag > TriggerProducer
short int Multiplicity() const
How many hits could this one be shared with.
friend TriggerInputSpec_t convert(Config::TriggerSpecConfig const &config)
Algorithms dealing with a trajectory and the cathode.
float dEdx_calc(float dQdx, float A, float B, float Wion, float E)
process_name can override from command line with o or output calo
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Access the description of detector geometry.
art::InputTag const fCaloProducer
float beforecathode
Track path length before cathode (lower x).
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space. See recob::tracking::Coord_t for more details on the ...
Simple description for the cathode.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
fhicl::Atom< art::InputTag > PFPproducer
fhicl::TableAs< TriggerInputSpec_t, TriggerSpecConfig > TriggerSpecConfigTable
fhicl::OptionalAtom< art::InputTag > T0Producer
float midaftercathode_x
Midpoint of subpath after cathode.
float atcathode_y
Cathode crossing point of trajectory.
std::size_t indexBefore
Index of the point "before" cathode.
Helper managing the trigger response part of a TTree.
Algorihtm to group PMTs into piling towers.
BEGIN_PROLOG vertical distance to the surface Name
float middle_x
Half-way distance along the trajectory.
Test of util::counter and support utilities.
float midaftercathode_z
Midpoint of subpath after cathode.
PlaneID_t Plane
Index of the plane within its TPC.
std::string const fLogCategory
TimeTrackTreeStorage(Parameters const &p)
Description of geometry of one entire detector.
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
float midbeforecathode_x
Midpoint of subpath before cathode.
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
fhicl::Atom< float > Efield
Provides recob::Track data product.
fhicl::Atom< std::string > Name
std::vector< std::pair< double, std::vector< raw::Channel_t > > > computePMTwalls() const
Accesses detector geometry to return all PMT split by wall.
art::InputTag const fT0selProducer
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
unsigned int fTotalProcessed
size_t FirstValidPoint() const
Encapsulate the geometry of an optical detector.
std::vector< std::pair< double, std::vector< raw::Channel_t > > > fPMTwalls
PMT geometry objects, grouped by wall (drift) coordinate.
float midbeforecathode_y
Midpoint of subpath before cathode.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
float PeakTime() const
Time of the signal peak, in tick units.
float aftercathode
Track path length before cathode (higher x).
fhicl::Atom< float > Wion
CathodeCrossing_t detectCrossing(Iter begin, Iter end, CathodeDesc_t const &cathode)
Returns the crossing point of a trajectory on the cathode.
float midaftercathode_y
Midpoint of subpath after cathode.
size_t NextValidPoint(size_t index) const
double before
Length of the path "before" the cathode.
static constexpr size_t InvalidIndex
Value returned on failed index queries.
std::vector< std::pair< double, PMTlist_t > > PMTwalls(geo::CryostatGeo const &cryo) const
Groups optical detectors under the specified cryostat into walls.
Information about a single trigger logic (hardware or emulated).
fhicl::Atom< art::InputTag > TrackProducer
float middle_z
Half-way distance along the trajectory.
sbn::selHitInfo makeHit(const recob::Hit &hit, unsigned hkey, const recob::Track &trk, const recob::TrackHitMeta &thm, const std::vector< art::Ptr< anab::Calorimetry >> &calo, const geo::GeometryCore *geo)
fhicl::OptionalAtom< art::InputTag > T0selProducer
float SummedADC() const
The sum of calibrated ADC counts of the hit (0. by default)
sbn::selTrackInfo fTrackInfo
fhicl::Atom< float > MODB
Vector_t DirectionAtPoint(size_t i) const
float midbeforecathode_z
Midpoint of subpath before cathode.
auto pathMiddlePoint(FIter itFirst, LIter itLast, double relTarget=0.5)
Returns the geometric point in the middle of the specified path.
2D representation of charge deposited in the TDC/wire plane
art::EDAnalyzer::Table< Config > Parameters
art::InputTag const fPFPproducer
fhicl::Atom< art::InputTag > BeamGateProducer
Fills a ROOT tree with track-based triggering information.
art::InputTag const fTrackProducer
TPCID_t TPC
Index of the TPC within its cryostat.
double XCenter() const
Returns the estimated center on x direction (.
art::InputTag const fTrackFitterProducer
Algorithms dealing with a trajectory as a sequence of 3D points.
bool const fForceDowngoing
Whether to force all tracks to be downgoing.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space. See recob::tracking::Coord_t for more detai...
Information about the cathode crossing of a path.
BeamType_t BeamType() const
std::size_t indexAfter
Index of the point "after" cathode.
geo::Point_t middlePoint(BeginIter begin, EndIter end)
Returns the middle of the specified points.
fhicl::Atom< std::string > LogCategory
TimeTrackTreeStorage::TriggerInputSpec_t convert(TimeTrackTreeStorage::Config::TriggerSpecConfig const &config)
art framework interface to geometry description
art::InputTag const fT0Producer
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Algorithm clustering PMT according to their position.