12 #include "art/Framework/Core/EDProducer.h"
13 #include "art/Framework/Core/ModuleMacros.h"
14 #include "art/Framework/Principal/Event.h"
15 #include "art/Framework/Principal/Handle.h"
16 #include "art/Framework/Principal/Run.h"
17 #include "art/Framework/Principal/SubRun.h"
18 #include "canvas/Utilities/InputTag.h"
19 #include "fhiclcpp/ParameterSet.h"
20 #include "messagefacility/MessageLogger/MessageLogger.h"
44 #include "art/Utilities/make_tool.h"
50 class VertexChargeVacuum;
67 void produce(art::Event&
e)
override;
80 std::vector<std::unique_ptr<INormalizeCharge>>
fNormTools;
94 fPFParticleLabel(
p.get<std::string>(
"PFParticleLabel",
"pandora")),
95 fTrackLabel(
p.get<std::string>(
"TrackLabel",
"pandoraTrack")),
96 fHitVacuumRadius(
p.get<
float>(
"HitVacuumRadius")),
97 fUseTrackSPRecovery(
p.get<
bool>(
"UseTrackSPRecovery")),
98 fCorrectSCE(
p.get<
bool>(
"CorrectSCE")),
99 fPositionsAreSCECorrected(
p.get<
bool>(
"PositionsAreSCECorrected")),
100 fSelectNeutrino(
p.get<
bool>(
"SelectNeutrino")),
101 fNormToolConfig(
p.get<std::vector<fhicl::ParameterSet>>(
"NormTools", {})),
102 fCaloAlg(
p.get<fhicl::ParameterSet >(
"CaloAlg"))
105 for (
const fhicl::ParameterSet &
p: fNormToolConfig) {
106 fNormTools.push_back(art::make_tool<INormalizeCharge>(
p));
109 produces<std::vector<sbn::VertexHit>>();
110 produces<art::Assns<recob::Slice, sbn::VertexHit>>();
111 produces<art::Assns<recob::Hit, sbn::VertexHit>>();
112 produces<art::Assns<recob::Vertex, sbn::VertexHit>>();
118 float wire_distance_cm = wire_distance * geo->
WirePitch();
120 float time_distance = hit.
PeakTime();
124 return {wire_distance_cm, time_distance_cm};
133 std::array<float, 2> hit_v =
HitVector(hit, geo, dprop);
135 return sqrt((vert_v[0] - hit_v[0]) * (vert_v[0] - hit_v[0]) + (vert_v[1] - hit_v[1]) * (vert_v[1] - hit_v[1]));
141 if (!hits.size())
return {0., 0.};
148 for (
const art::Ptr<recob::Hit> &
h: hits) {
149 std::array<float, 2> hit_v =
HitVector(*
h, geo, dprop);
151 avg += (hit_p - vert_p).Unit();
156 return {(float)avg.X(), (float)avg.Y()};
176 std::array<float, 2> h_plane =
HitVector(hit, geo, dprop);
184 float plane_dist = (h_plane[0] - v_plane[0]) + (h_plane[1] - v_plane[1]);
187 float dist_3d = plane_dist / t_dir_parallel_plane;
202 return vert.
position() + trk_dir * dist_3d;
215 if (tpc && !fPositionsAreSCECorrected)
return sbn::GetLocation(sce, p, tpc);
224 if (fNormTools.size()) {
225 for (
auto const &nt: fNormTools) {
226 ret = nt->Normalize(ret, e, h, location, direction, t0);
231 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
233 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e, clock_data);
235 ret = ret * fCaloAlg.LifetimeCorrection(clock_data, dprop, h.
PeakTime(), 0.);
244 std::unique_ptr<std::vector<sbn::VertexHit>> outVHit(
new std::vector<sbn::VertexHit>);
245 std::unique_ptr<art::Assns<recob::Slice, sbn::VertexHit>> assn(
new art::Assns<recob::Slice, sbn::VertexHit>);
246 std::unique_ptr<art::Assns<recob::Vertex, sbn::VertexHit>> vtxAssn(
new art::Assns<recob::Vertex, sbn::VertexHit>);
247 std::unique_ptr<art::Assns<recob::Hit, sbn::VertexHit>> hitAssn(
new art::Assns<recob::Hit, sbn::VertexHit>);
249 art::PtrMaker<sbn::VertexHit> vhitPtrMaker {evt};
253 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
255 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clock_data);
256 auto const* sce = lar::providerFrom<spacecharge::SpaceChargeService>();
258 if (!fCorrectSCE) sce =
nullptr;
261 art::Handle<std::vector<recob::PFParticle>> pfparticle_handle;
262 evt.getByLabel(fPFParticleLabel, pfparticle_handle);
264 std::vector<art::Ptr<recob::PFParticle>> pfparticles;
265 art::fill_ptr_vector(pfparticles, pfparticle_handle);
267 art::FindManyP<recob::Vertex> pfparticleVertices(pfparticles, evt, fPFParticleLabel);
268 art::FindManyP<recob::Cluster> pfparticleClusters(pfparticles, evt, fPFParticleLabel);
269 art::FindManyP<recob::Slice> pfparticleSlices(pfparticles, evt, fPFParticleLabel);
270 art::FindManyP<recob::Track> pfparticleTracks(pfparticles, evt, fTrackLabel);
273 std::map<unsigned, art::Ptr<recob::PFParticle>> id_to_pfp;
274 for (
unsigned i = 0; i < pfparticles.size(); i++) {
275 id_to_pfp[pfparticles[i]->Self()] = pfparticles[i];
289 for (
unsigned i_pfp = 0; i_pfp < pfparticles.size(); i_pfp++) {
293 if (!pfparticleVertices.at(i_pfp).size())
continue;
297 if(fSelectNeutrino &&
298 (pfpPDGC != 12) && (pfpPDGC != 14) && (pfpPDGC != 16) )
continue;
301 const art::Ptr<recob::Vertex> &vtx_ptr = pfparticleVertices.at(i_pfp).at(0);
322 const std::vector<size_t> &daughters = pfp.
Daughters();
323 std::vector<art::Ptr<recob::PFParticle>> daughterPFPs;
324 for (
size_t d: daughters) {
325 daughterPFPs.push_back(id_to_pfp.at(d));
329 std::array<std::vector<std::vector<art::Ptr<recob::Hit>>>, 3> daughterPlaneHits;
330 for (
const art::Ptr<recob::PFParticle> &d: daughterPFPs) {
331 for (
unsigned i_plane = 0; i_plane < 3; i_plane++) {
332 daughterPlaneHits[i_plane].emplace_back();
334 const std::vector<art::Ptr<recob::Cluster>> &d_clusters = pfparticleClusters.at(d.key());
335 art::FindManyP<recob::Hit> d_cluster_hits(d_clusters, evt, fPFParticleLabel);
336 for (
unsigned i = 0; i < d_clusters.size(); i++) {
337 const std::vector<art::Ptr<recob::Hit>> &this_cluster_hits = d_cluster_hits.at(i);
338 daughterPlaneHits[d_clusters[i]->Plane().Plane].back().insert(
339 daughterPlaneHits[d_clusters[i]->
Plane().
Plane].back().
end(),
340 this_cluster_hits.begin(), this_cluster_hits.end());
345 art::Ptr<recob::Slice> thisSlc = pfparticleSlices.at(i_pfp).at(0);
347 art::FindManyP<recob::Hit> thisSlcHits({thisSlc},
evt, fPFParticleLabel);
348 const std::vector<art::Ptr<recob::Hit>> &hits = thisSlcHits.at(0);
351 for (
unsigned i_plane = 0; i_plane < 3; i_plane++) {
353 std::vector<art::Ptr<recob::Hit>> nearbyHits;
354 for (
unsigned i_hit = 0; i_hit < hits.size(); i_hit++) {
358 nearbyHits.push_back(hits[i_hit]);
364 art::FindManyP<recob::SpacePoint> hitSPs(nearbyHits, evt, fPFParticleLabel);
367 for (
unsigned i_hit = 0; i_hit < nearbyHits.size(); i_hit++) {
374 vhit.
vtxx = vert_atwires.position().x();
375 vhit.
vtxXYZ = vert_absolute.position();
379 vert_absolute.position() ,
386 const std::vector<art::Ptr<recob::SpacePoint>> &hit_sp = hitSPs.at(i_hit);
388 bool has_xyz =
false;
395 spXYZ = PositionAbsolute(sp.
position(), geo, sce);
399 else if (fUseTrackSPRecovery) {
400 unsigned plane = hit.WireID().Plane;
401 art::Ptr<recob::PFParticle> matchingPFP;
402 for (
unsigned i_pfp_chk = 0; i_pfp_chk < daughterPlaneHits[plane].size(); i_pfp_chk++) {
403 for (
unsigned i_hit_chk = 0; i_hit_chk < daughterPlaneHits[plane][i_pfp_chk].size(); i_hit_chk++) {
404 if (daughterPlaneHits[plane][i_pfp_chk][i_hit_chk] == nearbyHits[i_hit]) {
405 matchingPFP = daughterPFPs[i_pfp_chk];
411 const std::vector<art::Ptr<recob::Track>> &pfptrack = pfparticleTracks.at(matchingPFP.key());
412 if (pfptrack.size()) {
414 spXYZ = PositionAbsolute(
PlaceHitAlongTrack(thisTrack, vert_atwires, hit, geo, dprop), geo, sce);
433 float EField =
sbn::GetEfield(dprop, sce, spXYZ, hit.WireID(),
false);
435 vhit.
dedx = fCaloAlg.dEdx_AREA(clock_data, dprop, vhit.
dqdx, hit.PeakTime(), hit.WireID().Plane, 0., EField);
445 outVHit->push_back(vhit);
446 art::Ptr<sbn::VertexHit> thisVHitPtr = vhitPtrMaker(outVHit->size()-1);
447 assn->addSingle(thisSlc, thisVHitPtr);
448 vtxAssn->addSingle(vtx_ptr, thisVHitPtr);
449 hitAssn->addSingle(nearbyHits[i_hit], thisVHitPtr);
455 evt.put(std::move(outVHit));
456 evt.put(std::move(vtxAssn));
457 evt.put(std::move(assn));
458 evt.put(std::move(hitAssn));
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
art::InputTag fTrackLabel
const std::vector< size_t > & Daughters() const
Returns the collection of daughter particles.
float dqdx
charge/pitch [#elec/cm]
Utilities related to art service access.
void produce(art::Event &e) override
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
geo::Point_t spXYZ
3D location of the SpacePoint associated with this hit. Space charge corrected. [cm] ...
VertexChargeVacuum(fhicl::ParameterSet const &p)
float dedx
Recombination corrected dQ/dx [MeV/cm].
geo::WireID WireID() const
geo::WireID wire
Wire that the hit is on.
Declaration of signal hit object.
geo::Point_t PositionAbsolute(const geo::Point_t &p, const geo::GeometryCore *geo, const spacecharge::SpaceCharge *sce)
The data type to uniquely identify a Plane.
geo::Point_t position() const
Returns the position of the point in world coordinates [cm].
geo::Point_t GetLocation(const spacecharge::SpaceCharge *sce, geo::Point_t loc_w, geo::TPCID TPC, float xsign=1.)
Get the location in the presence of space charge.
int PdgCode() const
Return the type of particle as a PDG ID.
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.
Definition of vertex object for LArSoft.
float charge
Calibrated and lifetime-corrected charge on the hit [#elec].
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
std::array< float, 2 > HitVector(const recob::Hit &hit, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
bool fPositionsAreSCECorrected
geo::Point_t GetLocationAtWires(const spacecharge::SpaceCharge *sce, const geo::GeometryCore *geo, geo::Point_t loc, geo::TPCID TPC, float xsign=1.)
Get the SCE-distorted location (i.e. the location "seen" by the wireplanes)
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Access the description of detector geometry.
Vector_t StartDirection() const
Access to track direction at different points.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::array< float, 2 > HitDirection(const std::vector< art::Ptr< recob::Hit >> &hits, const recob::Vertex &vert, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
double Normalize(double dQdx, const art::Event &e, const recob::Hit &h, const geo::Point_t &location, const geo::Vector_t &direction, double t0)
std::vector< fhicl::ParameterSet > fNormToolConfig
auto end(FixedBins< T, C > const &) noexcept
float proj_dist_to_vertex
Distnace from the hit to the vertex on the wireplane.
float TrackDirectionParallel(const recob::Track &trk, const geo::PlaneID &plane, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
bool IsPrimary() const
Returns whether the particle is the root of the flow.
double GetPitch(const geo::GeometryCore *geo, const spacecharge::SpaceCharge *sce, geo::Point_t loc, geo::Vector_t dir, geo::View_t view, geo::TPCID tpc, bool correct_sce, bool track_is_sce_corrected, float xsign=1.)
Computes the track-pitch on a plane given an input direction and location.
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
Description of geometry of one entire detector.
Declaration of cluster object.
float vtxx
X-Position of the vertex associated with this hit as seen by wire-planes. Not space charge corrected...
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
float Vert2HitDistance(const recob::Hit &hit, const recob::Vertex &vert, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
Provides recob::Track data product.
geo::Point_t PlaceHitAlongTrack(const recob::Track &trk, const recob::Vertex &vert, const recob::Hit &hit, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
const SMatrixSym33 & covariance() const
Return vertex 3D covariance (be careful, the matrix may have rank=2).
double ConvertTicksToX(double ticks, int p, int t, int c) const
float pitch
Computed pitch of a track traversing from the vertex to this hit. Space charge corrected. [cm].
float PeakTime() const
Time of the signal peak, in tick units.
Hierarchical representation of particle flow.
calo::CalorimetryAlg fCaloAlg
int ID() const
Return vertex id.
geo::Point_t PositionAtWires(const geo::Point_t &p, const geo::GeometryCore *geo, const spacecharge::SpaceCharge *sce)
std::vector< std::unique_ptr< INormalizeCharge > > fNormTools
double GetEfield(const detinfo::DetectorPropertiesData &dprop, const spacecharge::SpaceCharge *sce, geo::Point_t loc, geo::TPCID TPC, bool correct_loc_sce, float xsign=1.)
Get the E-Field in the presence of space charge.
Declaration of basic channel signal object.
VertexChargeVacuum & operator=(VertexChargeVacuum const &)=delete
int spID
ID of the SpacePoint associated with this hit.
2D representation of charge deposited in the TDC/wire plane
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
std::array< float, 2 > VertexVector(const recob::Vertex &vert, const geo::PlaneID &plane, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
const Point_t & position() const
Return vertex 3D position.
art framework interface to geometry description
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
art::InputTag fPFParticleLabel
geo::Point_t vtxXYZ
3D location of the Vertex associated with this hit. Space charge corrected. [cm]
float vtxw
Wire of the vertex associated with this hit. Not space charge corrected. [cm].
This is an interface for an art Tool which scales charge by some factor given information about its a...