90 for (
auto const&
t : trk_input.
tracks()) {
94 if ((
t.Track()->GetT0() != 0) ||
103 double l =
t.Track()->Length();
126 std::vector<pma::VtxCandidate>
129 std::vector<pma::VtxCandidate> candidates;
139 candidates.push_back(candidate);
146 std::vector<pma::VtxCandidate>
149 std::vector<pma::VtxCandidate> candidates;
159 candidates.push_back(candidate);
168 std::vector<pma::VtxCandidate>& candidates)
171 while (merged && (candidates.size() > 1)) {
172 size_t k_best, l_best,
k = 0;
173 while (k < candidates.size() - 1) {
175 while (l < candidates.size()) {
176 if (candidates[l].Has(candidates[k])) {
177 candidates[
k] = candidates[
l];
178 candidates.erase(candidates.begin() +
l);
180 else if (candidates[k].Has(candidates[l])) {
181 candidates.erase(candidates.begin() +
l);
191 double d, dmin = d_thr;
194 while (k < candidates.size() - 1) {
196 while (l < candidates.size()) {
197 d = candidates[
k].Test(candidates[l]);
207 if ((dmin < d_thr) && candidates[k_best].MergeWith(candidates[l_best])) {
208 candidates.erase(candidates.begin() + l_best);
213 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
"*** Vtx candidates: " << candidates.size();
214 std::vector<pma::VtxCandidate> toJoin;
217 int s, nmax = 0, c_best = -1;
218 double a, amax = 0.0;
220 for (
size_t v = 0; v < candidates.size(); v++) {
221 if (candidates[v].HasLoops())
continue;
223 bool maybeCorrelated =
false;
224 for (
size_t u = 0; u < toJoin.size(); u++)
225 if (toJoin[u].IsAttached(candidates[v]) ||
226 (
pma::Dist2(toJoin[u].Center(), candidates[v].Center()) < 15.0 * 15.0)) {
227 maybeCorrelated =
true;
230 if (maybeCorrelated)
continue;
233 a = candidates[v].MaxAngle(1.0);
235 if ((s > nmax) || ((s == nmax) && (a > amax))) {
258 toJoin.push_back(candidates[c_best]);
259 candidates.erase(candidates.begin() + c_best);
264 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
"*** Vtx selected to join: " << toJoin.size();
267 for (
auto&
c : toJoin) {
281 if (trk_input.
size() < 2) {
282 mf::LogWarning(
"pma::PMAlgVertexing") <<
"need min two source tracks!";
295 if (candidates.size()) {
301 }
while (nfound > 0);
314 if (candidates.size()) {
348 std::vector<std::pair<double, double>>
351 std::vector<std::pair<double, double>>
result;
354 unsigned int nhits = trk.
NHits(view);
355 unsigned int max = nhits;
370 std::map<size_t, std::vector<double>> dqdx;
373 for (
size_t i = 0; i < trk.
size(); i++) {
374 auto it = dqdx.find(i);
375 if (it != dqdx.end()) {
376 if (it->second[6] > 0.0)
378 double dvalue = it->second[5] / it->second[6];
379 result.emplace_back(std::pair<double, double>(dvalue, it->second[7]));
392 size_t half = len >> 1;
394 for (
size_t i = 0; i < len; i++) {
395 v = adc[idx - half + i];
404 for (
size_t i = 0; i < len; i++)
405 sum += (adc[idx - half + i] - mean) * shape[i];
407 return sum / sqrt(
stdev);
413 const double minCos = 0.996194698;
415 trk1->
Segments().back()->GetDirection3D().Dot(trk2->
Segments().front()->GetDirection3D());
416 if (segCos < minCos) {
417 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
" has large angle, cos: " << segCos;
421 const size_t stepShapeLen = 16;
422 const size_t stepShapeHalf = stepShapeLen >> 1;
423 const double stepShape[stepShapeLen] = {
424 -1., -1., -1., -1., -1., -1., -1., -1., 1., 1., 1., 1., 1., 1., 1., 1.};
427 if (dqdx1.size() < stepShapeHalf)
return false;
429 if (dqdx2.size() < stepShapeHalf)
return false;
431 const size_t adcLen =
433 const size_t adcHalf = adcLen >> 1;
436 for (
size_t i = 0; i < adcLen; i++)
440 for (
int i = adcHalf - 1, j = dqdx1.size() - 1; i >= 0; i--, j--) {
442 dqdx[i] = dqdx1[j].first;
444 dqdx[i] = dqdx[i + 1];
449 for (
size_t i = adcHalf, j = 0; i < adcLen; i++, j++) {
450 if (j < dqdx2.size())
451 dqdx[i] = dqdx2[j].first;
453 dqdx[i] = dqdx[i - 1];
459 if (has_m) sum_m =
convolute(adcHalf - 1, stepShapeLen, dqdx, stepShape);
460 double sum_0 =
convolute(adcHalf, stepShapeLen, dqdx, stepShape);
462 if (has_p) sum_p =
convolute(adcHalf + 1, stepShapeLen, dqdx, stepShape);
464 const double convMin = 0.8;
465 if ((fabs(sum_m) >= convMin) || (fabs(sum_0) >= convMin) || (fabs(sum_p) >= convMin)) {
467 <<
" has step in conv.values: " << sum_m <<
", " << sum_0 <<
", " << sum_p;
472 <<
" single particle, conv.values: " << sum_m <<
", " << sum_0 <<
", " << sum_p;
480 if (trk_input.
size() < 2)
return;
482 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
"Find and merge tracks broken by vertices.";
486 for (
size_t t = 0;
t < trk_input.
size();
t++) {
502 double c, maxc = 0.0;
504 node = trk1->
Nodes().back();
510 c = dir1.Dot(tst->
Segments().front()->GetDirection3D());
530 if (trk_input.
size() < 1)
return;
532 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
"Find missed vtx by dQ/dx steps along merged tracks.";
534 while (t < trk_input.
size()) {
545 if (trk_input.
size() < 1)
return;
548 <<
"Find kinks on tracks, reopt with no penalty on angle where kinks.";
549 for (
size_t t = 0;
t < trk_input.
size(); ++
t) {
551 if (trk->
Nodes().size() < 5)
continue;
553 trk->
Optimize(detProp, 0, 1.0
e-5,
false);
555 std::vector<size_t> tested_nodes;
556 bool kinkFound =
true;
558 int kinkIdx = -1, nnodes = 0;
560 for (
size_t n = 1;
n < trk->
Nodes().size() - 1; ++
n) {
561 auto const& node = *(trk->
Nodes()[
n]);
563 if (node.IsVertex() || node.IsTPCEdge())
continue;
566 double c = -node.SegmentCosTransverse();
567 double a = 180.0 * (1 - std::acos(node.SegmentCosTransverse()) / TMath::Pi());
570 if ((c <
min) && !
has(tested_nodes,
n)) {
571 if ((
n > 1) && (
n < trk->
Nodes().size() - 2)) kinkIdx =
n;
578 if ((nnodes > 2) && (kinkIdx > 0) && (max_a >
fKinkMinDeg)) {
585 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
" kink a: " << max_a <<
"deg";
586 trk->
Nodes()[kinkIdx]->SetVertex(
true);
587 tested_nodes.push_back(kinkIdx);
590 trk->
Optimize(detProp, 0, 1.0
e-5,
false,
false);
591 double c = -trk->
Nodes()[kinkIdx]->SegmentCosTransverse();
593 180.0 * (1 - std::acos(trk->
Nodes()[kinkIdx]->SegmentCosTransverse()) / TMath::Pi());
597 mf::LogVerbatim(
"pma::PMAlgVertexing") <<
" -> tag removed after reopt";
598 trk->
Nodes()[kinkIdx]->SetVertex(
610 std::vector<std::pair<TVector3, std::vector<std::pair<size_t, bool>>>>
613 std::vector<std::pair<TVector3, std::vector<std::pair<size_t, bool>>>> vsel;
614 std::vector<pma::Node3D const*> bnodes;
616 for (
size_t t = 0;
t < tracks.
size(); ++
t) {
619 if (!(onlyBranching || firstNode->
IsBranching())) {
620 std::vector<std::pair<size_t, bool>> tidx;
621 tidx.emplace_back(std::pair<size_t, bool>(
t,
true));
627 for (
auto node : trk->
Nodes())
628 if (node->IsBranching()) {
630 for (
size_t n = 0;
n < bnodes.size();
n++)
631 if (node == bnodes[
n]) {
632 vsel[
n].second.emplace_back(std::pair<size_t, bool>(
t, pri));
637 std::vector<std::pair<size_t, bool>> tidx;
638 tidx.emplace_back(std::pair<size_t, bool>(
t, pri));
640 std::pair<TVector3,
std::vector<std::pair<size_t, bool>>>(node->Point3D(), tidx));
641 bnodes.push_back(node);
651 std::vector<std::pair<TVector3, size_t>>
654 std::vector<std::pair<TVector3, size_t>> ksel;
655 for (
size_t t = 0;
t < tracks.
size(); ++
t) {
657 for (
size_t n = 1;
n < trk->
Nodes().size() - 1; ++
n) {
660 ksel.emplace_back(std::pair<TVector3, size_t>(node->
Point3D(),
t));
pma::TrkCandidateColl fEmTracks
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TVector3 const & Point3D() const
pma::TrkCandidateColl fShortTracks
size_t run(const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &trk_input)
double Dist2(const TVector2 &v1, const TVector2 &v2)
std::vector< pma::VtxCandidate > firstPassCandidates() const
std::vector< std::pair< TVector3, size_t > > getKinks(const pma::TrkCandidateColl &tracks) const
std::vector< pma::VtxCandidate > secondPassCandidates() const
pma::Hit3D const * front() const
Implementation of the Projection Matching Algorithm.
void collectTracks(pma::TrkCandidateColl &result)
virtual unsigned int NextCount(void) const
TVector3 const & Point3D() const
Planes which measure Z direction.
fhicl::Atom< double > MinTrackLength
std::vector< std::pair< TVector3, std::vector< std::pair< size_t, bool > > > > getVertices(const pma::TrkCandidateColl &tracks, bool onlyBranching=false) const
recob::tracking::Vector_t Vector3D
PMAlgVertexing(const Config &config)
double Optimize(const detinfo::DetectorPropertiesData &detProp, int nNodes=-1, double eps=0.01, bool selAllHits=true, bool setAllNodes=true, size_t selSegHits=0, size_t selVtxHits=0)
Main optimization method.
unsigned int NHits(unsigned int view) const
fhicl::Atom< bool > FindKinks
std::vector< pma::Segment3D * > const & Segments() const noexcept
std::vector< std::pair< double, double > > getdQdx(const pma::Track3D &trk) const
Get dQ/dx sequence to detect various features.
pma::TrkCandidateColl fOutTracks
fhicl::Atom< double > KinkMinStd
bool IsVertex() const
Check fIsVertex flag.
pma::TrkCandidateColl fExcludedTracks
static int max(int a, int b)
auto select(T const &...t)
size_t makeVertices(detinfo::DetectorPropertiesData const &detProp, std::vector< pma::VtxCandidate > &candidates)
Implementation of the Projection Matching Algorithm.
double convolute(size_t idx, size_t len, double *adc, double const *shape) const
Get convolution value.
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
double GetRawdEdxSequence(std::map< size_t, std::vector< double >> &dedx, unsigned int view=geo::kZ, unsigned int skip=0, bool inclDisabled=false) const
bool Add(const pma::TrkCandidate &trk)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
bool IsBranching() const
Belongs to more than one track?
void sortTracks(const pma::TrkCandidateColl &trk_input)
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
bool isSingleParticle(pma::Track3D *trk1, pma::Track3D *trk2) const
Check if colinear in 3D and dQ/dx with no significant step.
std::vector< pma::Node3D * > const & Nodes() const noexcept
void splitMergedTracks(pma::TrkCandidateColl &trk_input) const
Split track and add vertex and reoptimize when dQ/dx step detected.
virtual pma::SortedObjectBase * Prev(void) const
fhicl::Atom< double > KinkMinDeg
void findKinksOnTracks(const detinfo::DetectorPropertiesData &detProp, pma::TrkCandidateColl &trk_input) const
Remove penalty on the angle if kink detected and reopt track.
pma::Track3D * Parent(void) const
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
void push_back(const TrkCandidate &trk)
bool has(const std::vector< size_t > &v, size_t idx) const
std::vector< TrkCandidate > const & tracks() const
QTextStream & endl(QTextStream &s)
void mergeBrokenTracks(pma::TrkCandidateColl &trk_input) const