21 #include "art/Framework/Services/Registry/ServiceHandle.h"
22 #include "messagefacility/MessageLogger/MessageLogger.h"
30 if (trk == t.first.Track())
return true;
38 if (!Has(t.first.Track()))
return false;
46 if (!rootTrk)
throw cet::exception(
"pma::VtxCandidate") <<
"Broken track.";
48 for (
const auto& t : fAssigned) {
50 if (!rootAssn)
throw cet::exception(
"pma::VtxCandidate") <<
"Broken track.";
61 if (IsAttached(t.first.Track()))
return true;
68 for (
size_t t = 0; t < fAssigned.size(); t++) {
70 if (!trk_t)
throw cet::exception(
"pma::VtxCandidate") <<
"Broken track.";
72 for (
size_t u = 0; u < fAssigned.size(); u++)
75 if (!trk_u)
throw cet::exception(
"pma::VtxCandidate") <<
"Broken track.";
87 for (
auto const& c : fAssigned)
88 if (c.first.Track()->Length() > minLength) n++;
95 if (IsAttached(trk.
Track()))
return false;
97 fAssigned.emplace_back(trk, 0);
100 double mse, min_mse = kMaxDistToTrack * kMaxDistToTrack;
101 if (fAssigned.size() > 2) {
103 d_best = kMaxDistToTrack;
104 for (
size_t n = 0;
n < trk.
Track()->
Nodes().size() - 1;
n++) {
106 if (seg->
Length() < fSegMinLength)
continue;
108 fAssigned.back().second =
n;
121 if (d_best < kMaxDistToTrack) {
122 fAssigned.back().second = n_best;
124 fMse2D = ComputeMse2D();
128 fAssigned.pop_back();
130 fMse2D = ComputeMse2D();
134 else if (fAssigned.size() == 2) {
137 size_t n_best = 0, m_best = 0;
138 d_best = kMaxDistToTrack;
140 double lm, ln, l_best = 0;
141 for (
size_t m = 0;
m < p0->
Nodes().size() - 1;
m++) {
144 if (lm < fSegMinLength)
continue;
146 fAssigned.front().second =
m;
148 for (
size_t n = 0;
n < trk.
Track()->
Nodes().size() - 1;
n++) {
151 if (ln < fSegMinLength)
continue;
153 fAssigned.back().second =
n;
157 d = sqrt(ComputeMse2D());
160 double d_dist = (d_best - d) / d_best;
161 if (lm + ln > 0.8 * d_dist * l_best)
173 if (d_best < kMaxDistToTrack) {
174 fAssigned.front().second = m_best;
175 fAssigned.back().second = n_best;
178 fMse2D = ComputeMse2D();
183 fAssigned.pop_back();
184 fCenter.SetXYZ(0., 0., 0.);
191 for (
size_t n = 0;
n < trk.
Track()->
Nodes().size() - 1;
n++) {
193 if (seg->
Length() >= fSegMinLength) {
return true; }
195 fAssigned.pop_back();
196 fCenter.SetXYZ(0., 0., 0.);
206 art::ServiceHandle<geo::Geometry const> geom;
210 for (
const auto& t : fAssigned) {
214 int tpc = trk->
Nodes()[t.second]->TPC();
215 int cryo = trk->
Nodes()[t.second]->Cryo();
219 if (geom->TPC(tpc, cryo).HasPlane(
geo::kU)) {
224 if (geom->TPC(tpc, cryo).HasPlane(
geo::kV)) {
229 if (geom->TPC(tpc, cryo).HasPlane(
geo::kZ)) {
234 mse += m / (double)k;
237 return mse / fAssigned.size();
243 double dx = fCenter[0] - other.
fCenter[0];
244 double dy = fCenter[1] - other.
fCenter[1];
245 double dz = fCenter[2] - other.
fCenter[2];
246 double dw = fErr[0] * other.
fErr[0] * dx * dx + fErr[1] * other.
fErr[1] * dy * dy +
247 fErr[2] * other.
fErr[2] * dz * dz;
255 size_t max_l_idx = 0;
256 double l, max_l = 0.0;
257 for (
size_t i = 0; i < fAssigned.size() - 1; i++) {
258 l = fAssigned[i].first.Track()->Length();
266 dir_i *= 1.0 / dir_i.Mag();
271 for (
size_t j = 0; j < fAssigned.size(); j++)
272 if ((j != max_l_idx) && (fAssigned[j].first.Track()->Length() > minLength)) {
277 dir_j *= 1.0 / dir_j.Mag();
278 a = fabs(dir_i * dir_j);
279 if (a < min) min =
a;
282 return 180.0 * acos(min) / TMath::Pi();
290 mf::LogVerbatim(
"pma::VtxCandidate") <<
"too far..";
294 double dw =
Test(other);
298 if (IsAttached(t.first.Track())) {
299 mf::LogVerbatim(
"pma::VtxCandidate") <<
"already attached..";
302 if (!Has(t.first.Track())) {
303 fAssigned.push_back(t);
308 double mse0 = fMse, mse1 = other.
fMse;
309 mf::LogVerbatim(
"pma::VtxCandidate")
310 <<
"try: " << d <<
" mse0:" << sqrt(mse0) <<
" mse1:" << sqrt(mse1);
313 double mse = Compute();
314 mf::LogVerbatim(
"pma::VtxCandidate")
315 <<
"out: " << Size() <<
" mse:" << sqrt(mse) <<
" dw:" << dw;
321 fMse2D = ComputeMse2D();
325 mf::LogVerbatim(
"pma::VtxCandidate") <<
"high mse..";
327 fAssigned.pop_back();
330 fMse2D = ComputeMse2D();
335 mf::LogVerbatim(
"pma::VtxCandidate") <<
"no tracks..";
343 std::vector<pma::Segment3D*> segments;
344 std::vector<std::pair<TVector3, TVector3>> lines;
345 std::vector<double> weights;
346 for (
const auto& v : fAssigned) {
352 double segLength = seg->
Length();
353 if (segLength >= fSegMinLength) {
356 std::pair<TVector3, TVector3> endpoints(vtx1->
Point3D(), vtx2->
Point3D());
357 double dy = endpoints.first.Y() - endpoints.second.Y();
358 double fy_norm = asin(fabs(dy) / segLength) / (0.5 * TMath::Pi());
359 double w = 1.0 - pow(fy_norm - 1.0, 12);
360 if (w < 0.3) w = 0.3;
362 lines.push_back(endpoints);
363 segments.push_back(seg);
364 weights.push_back(w);
368 fCenter.SetXYZ(0., 0., 0.);
369 fErr.SetXYZ(0., 0., 0.);
373 if (resultMse < 0.0) {
374 mf::LogWarning(
"pma::VtxCandidate") <<
"Cannot compute crossing point.";
381 for (
size_t s = 0;
s < segments.size();
s++) {
391 fErr[0] += weights[
s] * weights[
s];
395 fCenter[0] += weights[
s] * pproj.X();
396 fCenter[1] += pproj.Y();
397 fCenter[2] += pproj.Z();
401 fCenter[1] /= segments.size();
402 fCenter[2] /= segments.size();
404 fErr *= 1.0 / segments.size();
405 fErr[0] = sqrt(fErr[0]);
406 fErr[1] = sqrt(fErr[1]);
407 fErr[2] = sqrt(fErr[2]);
418 mf::LogError(
"pma::VtxCandidate") <<
"Tracks already attached to the vertex.";
423 mf::LogVerbatim(
"pma::VtxCandidate")
424 <<
"JoinTracks (" << fAssigned.size() <<
") at:"
425 <<
" vx:" << fCenter.X() <<
" vy:" << fCenter.Y() <<
" vz:" << fCenter.Z();
427 for (
auto const& c : fAssigned) {
429 while (t < src.
size()) {
430 if (c.first.Track() == src[t].Track()) {
441 for (
auto& c : fAssigned)
442 for (
auto const& t : tracks.
tracks())
443 if (c.first.Track() == t.Track()) {
444 c.first.SetTreeId(t.TreeId());
449 std::vector<int> treeIds;
453 bool hasInnerCenter =
false;
455 for (
size_t i = 0; i < fAssigned.size(); i++) {
456 mf::LogVerbatim(
"pma::VtxCandidate") <<
"----------> track #" << i;
459 int key = fAssigned[i].first.Key();
460 int tid = fAssigned[i].first.TreeId();
461 size_t idx = fAssigned[i].second;
463 mf::LogVerbatim(
"pma::VtxCandidate") <<
" track tid:" << tid <<
", size:" << trk->
size()
464 <<
" (nodes:" << trk->
Nodes().size() <<
")";
466 if (!has(treeIds, tid))
468 treeIds.push_back(tid);
473 mf::LogError(
"pma::VtxCandidate") <<
"Root of the tree not found in tracks collection.";
476 TVector3 p0(trk->
Nodes()[idx]->Point3D());
477 TVector3
p1(trk->
Nodes()[idx + 1]->Point3D());
479 int tpc0 = trk->
Nodes()[idx]->TPC();
480 int tpc1 = trk->
Nodes()[idx + 1]->TPC();
482 int cryo0 = trk->
Nodes()[idx]->Cryo();
483 int cryo1 = trk->
Nodes()[idx + 1]->Cryo();
491 if ((idx == 0) && (f * ds <= kMinDistToNode)) {
493 mf::LogVerbatim(
"pma::VtxCandidate") <<
" new at front";
494 vtxCenter = trk->
Nodes().front();
499 mf::LogVerbatim(
"pma::VtxCandidate") <<
" front to center";
500 if (trk->
AttachTo(vtxCenter)) nOK++;
503 else if ((idx + 2 == trk->
Nodes().size()) && ((1.0 - f) * ds <= kMinDistToNode)) {
506 mf::LogVerbatim(
"pma::VtxCandidate") <<
" flip trk to make new center";
508 vtxCenter = trk->
Nodes().front();
511 mf::LogVerbatim(
"pma::VtxCandidate") <<
" new center at the endpoint";
512 vtxCenter = trk->
Nodes().back();
519 mf::LogVerbatim(
"pma::VtxCandidate") <<
" flip trk to attach to inner";
521 if (trk->
AttachTo(vtxCenter)) nOK++;
524 mf::LogVerbatim(
"pma::VtxCandidate") <<
" endpoint to center";
530 bool canFlipPrev =
true;
531 if (vtxCenter && vtxCenter->
Prev()) {
539 if (hasInnerCenter || !canFlipPrev) {
540 mf::LogVerbatim(
"pma::VtxCandidate") <<
" split track";
542 if ((f >= 0.0
F) && (f <= 1.0) && (f * ds > kMinDistToNode) &&
543 ((1.0 - f) * ds > kMinDistToNode)) {
544 mf::LogVerbatim(
"pma::VtxCandidate") <<
" add center inside segment";
556 trk->
InsertNode(detProp, fCenter, ++idx, tpc, cryo);
560 mf::LogVerbatim(
"pma::VtxCandidate") <<
" add center at end of segment";
564 mf::LogVerbatim(
"pma::VtxCandidate") <<
" center at start of segment - no action";
571 mf::LogVerbatim(
"pma::VtxCandidate")
572 <<
" trk size:" << trk->
size() <<
" (nodes:" << trk->
Nodes().size() <<
")";
576 mf::LogVerbatim(
"pma::VtxCandidate")
577 <<
" t0 size:" << t0->
size() <<
" (nodes:" << t0->
Nodes().size() <<
")";
581 tracks.
tracks().emplace_back(t0, key, tid);
583 mf::LogVerbatim(
"pma::VtxCandidate") <<
" center at trk0 back";
584 vtxCenter = trk->
Nodes().front();
588 mf::LogVerbatim(
"pma::VtxCandidate") <<
" attach trk to trk0";
589 if (trk->
AttachTo(vtxCenter)) nOK += 2;
592 mf::LogVerbatim(
"pma::VtxCandidate") <<
" done";
595 mf::LogVerbatim(
"pma::VtxCandidate") <<
" inner center";
596 hasInnerCenter =
true;
598 if ((f >= 0.0
F) && (f <= 1.0) && (f * ds > kMinDistToNode) &&
599 ((1.0 - f) * ds > kMinDistToNode)) {
600 mf::LogVerbatim(
"pma::VtxCandidate") <<
" add center inside segment";
612 trk->
InsertNode(detProp, fCenter, ++idx, tpc, cryo);
616 mf::LogVerbatim(
"pma::VtxCandidate") <<
" add center at end of segment";
620 mf::LogVerbatim(
"pma::VtxCandidate") <<
" center at start of segment - no action";
631 rootBranch = seg->
Parent();
638 for (
size_t j = 0; j < branches.size(); ++j) {
639 if (branches[j]->AttachTo(innerCenter,
true)) {}
641 vtxCenter = innerCenter;
644 vtxCenter = innerCenter;
649 mf::LogVerbatim(
"pma::VtxCandidate") <<
" done";
658 rootSeg = static_cast<pma::Segment3D*>(vtxCenter->
Next(0));
659 else if (vtxCenter->
Prev())
660 rootSeg = static_cast<pma::Segment3D*>(vtxCenter->
Prev());
662 throw cet::exception(
"pma::VtxCandidate") <<
"Vertex with no segments attached.";
665 if (!rootTrk) rootTrk = rootSeg->
Parent();
667 std::vector<pma::Track3D const*> branchesToRemove;
668 bool noLoops = rootTrk->
GetBranches(branchesToRemove);
671 if (noLoops && (nOK > 1)) {
673 fCenter = vtxCenter->
Point3D();
688 if (noLoops && tuneOK) {
689 mf::LogVerbatim(
"pma::VtxCandidate") <<
"remove backup tracks";
690 for (
auto& c : backupTracks.
tracks())
694 mf::LogVerbatim(
"pma::VtxCandidate") <<
"restore tracks from backup....";
695 for (
int tid : treeIds) {
697 while (t < tracks.
size()) {
698 if (tracks[t].TreeId() == tid) {
699 tracks[t].DeleteTrack();
706 for (
const auto& c : backupTracks.
tracks())
708 mf::LogVerbatim(
"pma::VtxCandidate") <<
" done";
712 mf::LogError(
"pma::VtxCandidate") <<
"Cannot create common vertex";
Vertex finding helper for the Projection Matching Algorithm.
TVector3 const & Point3D() const
bool Has(pma::Track3D *trk) const
double SolveLeastSquares3D(const std::vector< std::pair< TVector3, TVector3 >> &lines, TVector3 &result)
pma::Track3D * getTreeCopy(pma::TrkCandidateColl &dst, size_t trkIdx, bool isRoot=true)
bool AttachTo(pma::Node3D *vStart, bool noFlip=false)
ClusterModuleLabel join with tracks
Implementation of the Projection Matching Algorithm.
bool IsAttachedTo(pma::Track3D const *trk) const
double Dist2(const TVector2 &v1, const TVector2 &v2)
double GetDistance2To(const TVector3 &p3d) const override
Distance [cm] from the 3D segment to the point 3D.
double Test(const VtxCandidate &other) const
bool JoinTracks(detinfo::DetectorPropertiesData const &detProp, pma::TrkCandidateColl &tracks, pma::TrkCandidateColl &src)
pma::Hit3D const * front() const
void erase_at(size_t pos)
Implementation of the Projection Matching Algorithm.
bool GetBranches(std::vector< pma::Track3D const * > &branches, bool skipFirst=false) const
std::vector< std::pair< pma::TrkCandidate, size_t > > fAssigned
virtual unsigned int NextCount(void) const
std::vector< pma::Track3D * > GetBranches() const
std::vector< pma::Node3D * > const & Nodes() const noexcept
Planes which measure Z direction.
Implementation of the Projection Matching Algorithm.
void Test(TFile *pFile=nullptr, bool statChecks=true)
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
double TuneFullTree(double eps=0.001, double gmax=50.0)
pma::Track3D * Split(detinfo::DetectorPropertiesData const &detProp, size_t idx, bool try_start_at_idx=true)
bool CanFlip() const
Check if the track can be flipped without breaking any other track.
TVector2 GetProjectionToSegment(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
int getCandidateIndex(pma::Track3D const *candidate) const
bool SetPoint3D(const TVector3 &p3d)
Definition of data types for geometry description.
double MaxAngle(double minLength=0.0) const
void InsertNode(detinfo::DetectorPropertiesData const &detProp, TVector3 const &p3d, size_t at_idx, unsigned int tpc, unsigned int cryo)
bool MergeWith(const VtxCandidate &other)
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
bool Add(const pma::TrkCandidate &trk)
double GetSegmentProjVector(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
then echo File list $list not found else cat $list while read file do echo $file sed s
TVector2 GetProjectionToPlane(const TVector3 &p, unsigned int plane, unsigned int tpc, unsigned int cryo)
bool IsAttached(pma::Track3D *trk) const
virtual pma::SortedObjectBase * Prev(void) const
bool Flip(const detinfo::DetectorPropertiesData &detProp, std::vector< pma::Track3D * > &allTracks)
pma::Track3D * Track() const
pma::Track3D * Parent(void) const
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
bool AttachBackTo(pma::Node3D *vStart)
pma::Segment3D * NextSegment(pma::Node3D *vtx) const
double Length(void) const
physics associatedGroupsWithLeft p1
void push_back(const TrkCandidate &trk)
art framework interface to geometry description
std::vector< TrkCandidate > const & tracks() const