10 #include "art/Framework/Core/EDProducer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "canvas/Utilities/InputTag.h"
17 #include "fhiclcpp/ParameterSet.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
35 #include "sbnobj/Common/Reco/PCAnglePlane.h"
39 class PCAnglePlaneMaker;
64 void produce(art::Event&
e)
override;
78 void SaveHits(std::map<
unsigned,
std::array<std::vector<unsigned>, 3>> &pfpToHits,
const std::vector<art::Ptr<recob::Hit>> &hits,
unsigned plane,
const art::Ptr<recob::PFParticle> &pfp) {
79 for (
const art::Ptr<recob::Hit> &
h: hits) {
80 pfpToHits[pfp.key()][plane].push_back(
h.key());
89 std::array<std::list<art::Ptr<recob::Hit>>, 3> planar {};
90 for (
unsigned i_plane = 0; i_plane < 3; i_plane++) {
91 planar[i_plane].insert(planar[i_plane].
begin(), hits[i_plane].
begin(), hits[i_plane].
end());
95 std::array<std::vector<art::Ptr<recob::Hit>>, 3> ret {};
96 for (
unsigned i = 0; i < 3; i++) {
97 if (planar[i].
size()) {
100 std::list<art::Ptr<recob::Hit>>::iterator firstHit = std::min_element(planar[i].
begin(), planar[i].
end(),
101 [start, geo, dprop](
auto const &lhs,
auto const &rhs) {
104 ret[i].push_back(*firstHit);
105 planar[i].erase(firstHit);
107 while (planar[i].
size()) {
109 std::list<art::Ptr<recob::Hit>>::iterator closest = std::min_element(planar[i].
begin(), planar[i].
end(),
110 [lastHit, geo, dprop](
auto const &lhs,
auto const &rhs) {
114 ret[i].push_back(*closest);
115 planar[i].erase(closest);
127 bool DoBranch(art::Ptr<recob::PFParticle> particle,
const std::map<
unsigned, art::Ptr<recob::PFParticle>> &pfpMap) {
135 std::map<unsigned, std::vector<sbn::PCAngleInfo>>
RemoveDupes(std::vector<sbn::PCAngleInfo> &angles) {
139 struct angle_compare {
154 std::sort(angles.begin(), angles.end(),
155 [](
auto const &lhs,
auto const &rhs) {
return lhs.generation < rhs.generation;});
158 std::set<sbn::PCAngleInfo, angle_compare> unique(angles.begin(), angles.end());
161 std::map<unsigned, std::vector<sbn::PCAngleInfo>> ret;
167 for (
auto &pair: ret) {
168 std::sort(pair.second.begin(), pair.second.end(),
169 [](
auto const &lhs,
auto const &rhs) {
170 return lhs.hit_ind < rhs.hit_ind;
179 fPFParticleLabel(
p.get<std::string>(
"PFParticleLabel",
"pandora")),
180 fFollowDaughters(
p.get<
bool>(
"FollowDaughters",
true)),
181 fHitGroupDistance(
p.get<
float>(
"HitGroupDistance")),
182 fOnlyPrimary(
p.get<
bool>(
"OnlyPrimary",
true))
184 produces<std::vector<sbn::PCAnglePlane>>();
185 produces<art::Assns<recob::PFParticle, sbn::PCAnglePlane>>();
191 std::unique_ptr<std::vector<sbn::PCAnglePlane>> outAngles(
new std::vector<sbn::PCAnglePlane>);
192 std::unique_ptr<art::Assns<recob::PFParticle, sbn::PCAnglePlane>> assn(
new art::Assns<recob::PFParticle, sbn::PCAnglePlane>);
194 art::PtrMaker<sbn::PCAnglePlane> anglePtrMaker {evt};
198 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
200 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clock_data);
204 art::Handle<std::vector<recob::PFParticle>> pfparticle_handle;
205 evt.getByLabel(fPFParticleLabel, pfparticle_handle);
207 std::vector<art::Ptr<recob::PFParticle>> pfparticles;
208 art::fill_ptr_vector(pfparticles, pfparticle_handle);
211 std::map<unsigned, art::Ptr<recob::PFParticle>> id_to_pfp;
212 for (
unsigned i = 0; i < pfparticles.size(); i++) {
213 id_to_pfp[pfparticles[i]->Self()] = pfparticles[i];
216 art::FindManyP<recob::Cluster> pfparticleClusters(pfparticles, evt, fPFParticleLabel);
217 art::FindManyP<recob::Vertex> pfparticleVertices(pfparticles, evt, fPFParticleLabel);
220 for (
unsigned i_part = 0; i_part < pfparticles.size(); i_part++) {
221 std::cout <<
"New particle! " << i_part << std::endl;
222 art::Ptr<recob::PFParticle> thisPFP = pfparticles[i_part];
224 std::cout <<
"Child of: " << thisPFP->Parent() << std::endl;
234 std::map<unsigned, std::array<std::vector<unsigned>, 3>> pfpToHits;
235 std::map<unsigned, std::array<std::vector<art::Ptr<recob::Hit>>,3>> allHits;
237 const std::vector<art::Ptr<recob::Cluster>> &thisCluster = pfparticleClusters.at(i_part);
238 art::FindManyP<recob::Hit> clusterHits(thisCluster, evt, fPFParticleLabel);
241 if (!thisCluster.size()) {
246 const std::vector<art::Ptr<recob::Vertex>> &pfpVerts = pfparticleVertices.at(i_part);
249 if (!pfpVerts.size()) {
259 for (
unsigned i_clus = 0; i_clus < thisCluster.size(); i_clus++) {
260 allHits[thisPFP->Self()][thisCluster[i_clus]->Plane().Plane].insert(allHits[thisPFP->Self()][thisCluster[i_clus]->Plane().Plane].begin(),
261 clusterHits.at(i_clus).begin(), clusterHits.at(i_clus).end());
262 SaveHits(pfpToHits, clusterHits.at(i_clus), thisCluster[i_clus]->Plane().Plane, thisPFP);
266 if (fFollowDaughters) {
268 struct daughter_stack_info {
269 unsigned daughter_id;
270 long unsigned hit_key;
273 std::stack<daughter_stack_info> d_pfps;
274 for (
unsigned d: thisPFP->Daughters()) {
275 daughter_stack_info dsi {d, thisPFP->Self()};
280 while (!d_pfps.empty()) {
281 daughter_stack_info daughter_info = d_pfps.top();
282 unsigned daughter = daughter_info.daughter_id;
283 unsigned hit_key = daughter_info.hit_key;
287 const art::Ptr<recob::PFParticle> &d_pfp = id_to_pfp.at(daughter);
294 allHits[d_pfp->Self()][0] = allHits[hit_key][0];
295 allHits[d_pfp->Self()][1] = allHits[hit_key][1];
296 allHits[d_pfp->Self()][2] = allHits[hit_key][2];
299 hit_key = d_pfp->Self();
303 for (
unsigned d: d_pfp->Daughters()) {
304 daughter_stack_info dsi {d, hit_key};
309 const std::vector<art::Ptr<recob::Cluster>> &d_cluster = pfparticleClusters.at(d_pfp.key());
312 if (!d_cluster.size())
continue;
314 art::FindManyP<recob::Hit> d_cluster_hits(d_cluster, evt, fPFParticleLabel);
315 for (
unsigned i_clus = 0; i_clus < d_cluster.size(); i_clus++) {
316 allHits[hit_key][d_cluster[i_clus]->Plane().Plane].insert(allHits[hit_key][d_cluster[i_clus]->
Plane().
Plane].
begin(),
317 d_cluster_hits.at(i_clus).begin(), d_cluster_hits.at(i_clus).end());
318 SaveHits(pfpToHits, d_cluster_hits.at(i_clus), d_cluster[i_clus]->Plane().Plane, d_pfp);
324 std::array<std::vector<sbn::PCAngleInfo>, 3> planeAngles;
328 for (
auto const &pair: allHits) {
329 unsigned branch_id = pair.first;
330 const std::array<std::vector<art::Ptr<recob::Hit>>, 3> &branchHits = pair.second;
335 std::array<std::vector<art::Ptr<recob::Hit>>, 3> sortedHits =
SortHits(branchHits, pfpVert, geo, dprop);
338 for (
unsigned i_plane = 0; i_plane < 3; i_plane++) {
339 for (
unsigned i_hit = 0; i_hit < sortedHits[i_plane].size(); i_hit++) {
341 auto [hitslo, hitshi, complete] =
sbnpca::GetNearestHits(sortedHits[i_plane], i_hit, fHitGroupDistance, geo, dprop);
354 std::array<float, 2> pca_vec_lo =
sbnpca::HitPCAVec(hitslo, *sortedHits[i_plane][i_hit], geo, dprop);
355 std::array<float, 2> pca_vec_hi =
sbnpca::HitPCAVec(hitshi, *sortedHits[i_plane][i_hit], geo, dprop);
358 if (pca_vec_lo[0] > -99. && pca_vec_lo[1] > -99. && pca_vec_hi[0] > -99. && pca_vec_hi[1] > -99.) {
363 std::array<float, 2> hv =
sbnpca::HitVector(*sortedHits[i_plane][i_hit], geo, dprop);
367 thisAngle.
angle.wire = sortedHits[i_plane][i_hit]->WireID();
369 thisAngle.
angle.lo_vector = pca_vec_lo;
370 thisAngle.
angle.hi_vector = pca_vec_hi;
371 thisAngle.
angle.hit_wire_cm = hv[0];
372 thisAngle.
angle.hit_time_cm = hv[1];
373 thisAngle.
angle.complete = complete;
374 thisAngle.
angle.hitID = sortedHits[i_plane][i_hit].key();
376 if (hitshi.size()) thisAngle.
angle.dist_to_hi =
sbnpca::HitDistance(*hitshi.back(), *sortedHits[i_plane][i_hit], geo, dprop);
377 else thisAngle.
angle.dist_to_hi = -100.;
378 if (hitslo.size()) thisAngle.
angle.dist_to_lo =
sbnpca::HitDistance(*hitslo.back(), *sortedHits[i_plane][i_hit], geo, dprop);
379 else thisAngle.
angle.dist_to_lo = -100.;
381 if (hitshi.size()) thisAngle.
angle.hitIDHi = hitshi.back().key();
382 else thisAngle.
angle.hitIDHi = -1;
383 if (hitslo.size()) thisAngle.
angle.hitIDLo = hitslo.back().key();
384 else thisAngle.
angle.hitIDLo = -1;
386 thisAngle.
branch = branch_id;
391 art::Ptr<recob::PFParticle>
check = id_to_pfp.at(branch_id);
392 while (check->Self() != thisPFP->Self()) {
394 check = id_to_pfp.at(check->Parent());
397 planeAngles[i_plane].push_back(thisAngle);
403 for (
unsigned i_plane = 0; i_plane < 3; i_plane++) {
404 std::map<unsigned, std::vector<sbn::PCAngleInfo>> selected =
RemoveDupes(planeAngles[i_plane]);
406 sbn::PCAnglePlane thisPlane;
408 thisPlane.plane = planeID;
409 for (
auto const &pair: selected) {
410 thisPlane.branchIDs.push_back(pair.first);
413 thisPlane.branchHierarchy.emplace_back();
414 art::Ptr<recob::PFParticle>
check = id_to_pfp.at(pair.first);
415 thisPlane.branchHierarchy.back().push_back(check->Self());
416 while (check->Self() != thisPFP->Self()) {
417 check = id_to_pfp.at(check->Parent());
418 thisPlane.branchHierarchy.back().push_back(check->Self());
421 if (pair.second.size()) thisPlane.generations.push_back(pair.second.front().generation);
422 else thisPlane.generations.push_back(-1);
424 if (pair.second.size()) thisPlane.plane = pair.second.front().angle.wire;
426 thisPlane.angles.emplace_back();
429 thisPlane.nBranches = thisPlane.angles.size();
430 outAngles->push_back(thisPlane);
431 art::Ptr<sbn::PCAnglePlane> thisAnglePtr = anglePtrMaker(outAngles->size()-1);
432 assn->addSingle(thisPFP, thisAnglePtr);
437 evt.put(std::move(outAngles));
438 evt.put(std::move(assn));
void produce(art::Event &e) override
void SaveHits(std::map< unsigned, std::array< std::vector< unsigned >, 3 >> &pfpToHits, const std::vector< art::Ptr< recob::Hit >> &hits, unsigned plane, const art::Ptr< recob::PFParticle > &pfp)
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
float Vert2HitDistance(const recob::Hit &hit, const recob::Vertex &vert, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
std::array< float, 2 > HitPCAVec(const std::vector< art::Ptr< recob::Hit >> &hits, const recob::Hit ¢er, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
PCAnglePlaneMaker & operator=(PCAnglePlaneMaker const &)=delete
static constexpr size_t kPFParticlePrimary
Define index to signify primary particle.
PCAnglePlaneMaker(fhicl::ParameterSet const &p)
std::map< unsigned, std::vector< sbn::PCAngleInfo > > RemoveDupes(std::vector< sbn::PCAngleInfo > &angles)
Declaration of signal hit object.
The data type to uniquely identify a Plane.
std::size_t size(FixedBins< T, C > const &) noexcept
Definition of vertex object for LArSoft.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Access the description of detector geometry.
then echo ***************************************echo array
std::tuple< std::vector< art::Ptr< recob::Hit > >, std::vector< art::Ptr< recob::Hit > >, bool > GetNearestHits(const std::vector< art::Ptr< recob::Hit >> &hits, int ihit, float distance, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
auto end(FixedBins< T, C > const &) noexcept
process_name tightIsolTest check
std::array< std::vector< art::Ptr< recob::Hit > >, 3 > SortHits(const std::array< std::vector< art::Ptr< recob::Hit >>, 3 > &hits, const recob::Vertex &start, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
float VecAngle(std::array< float, 2 > A, std::array< float, 2 > B)
float HitDistance(const recob::Hit &A, const recob::Hit &B, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
Description of geometry of one entire detector.
Declaration of cluster object.
auto begin(FixedBins< T, C > const &) noexcept
Declaration of basic channel signal object.
finds tracks best matching by angle
2D representation of charge deposited in the TDC/wire plane
bool DoBranch(art::Ptr< recob::PFParticle > particle, const std::map< unsigned, art::Ptr< recob::PFParticle >> &pfpMap)
art::InputTag fPFParticleLabel
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::array< float, 2 > HitVector(const recob::Hit &A, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)