31 #include "canvas/Persistency/Common/FindManyP.h" 54 #include "Geant4/G4ThreeVector.hh" 108 fCTCut =
p.get<
float>(
"CTCut",0.99);
109 fMaxDX =
p.get<
float>(
"MaxDX",50.0);
110 fMinDX =
p.get<
float>(
"MinDX",-50.0);
113 consumes< std::vector<rec::Track> >(inputTrackTag);
114 consumes< art::Assns<rec::TPCCluster, rec::Track> >(inputTrackTag);
116 consumes< art::Assns<rec::Vertex, rec::Track> >(inputVertexTag);
117 consumes<std::vector<rec::TrackIoniz>>(inputTrackTag);
118 consumes<art::Assns<rec::TrackIoniz, rec::Track>>(inputTrackTag);
120 consumes<art::Assns<rec::Hit, rec::TPCCluster>>(inputHitTag);
122 consumes< std::vector<rec::TPCCluster>>(inputTPCClusterTag);
128 produces< std::vector<rec::Track> >();
129 produces< art::Assns<rec::TPCCluster, rec::Track> >();
130 produces<std::vector<rec::TrackIoniz>>();
131 produces<art::Assns<rec::TrackIoniz, rec::Track>>();
132 produces< std::vector<rec::Vertex> >();
133 produces< art::Assns<rec::Track, rec::Vertex, rec::TrackEnd> >();
134 produces< std::vector<gar::rec::TPCCluster> >();
135 produces< art::Assns<gar::rec::Hit, gar::rec::TPCCluster> >();
145 typedef struct locVtx
155 typedef struct trkiend
163 float xtpccent = geo->TPCXCent();
167 auto detProp = gar::providerFrom<detinfo::DetectorPropertiesService>();
168 double DriftVelocity = detProp->DriftVelocity(detProp->Efield(),detProp->Temperature());
174 std::unique_ptr< std::vector<rec::Track> > trkCol(
new std::vector<rec::Track>);
175 std::unique_ptr<std::vector<gar::rec::TPCCluster> > TPCClusterCol (
new std::vector<gar::rec::TPCCluster> );
177 std::unique_ptr< std::vector<rec::TrackIoniz> > ionCol(
new std::vector<rec::TrackIoniz>);
179 std::unique_ptr< std::vector<rec::Vertex> > vtxCol(
new std::vector<rec::Vertex>);
186 auto const& inputTracks = *inputTrackHandle;
188 auto const& inputTPCClusters = *inputTPCClusterHandle;
190 const art::FindManyP<rec::TPCCluster> TPCClustersFromInputTracks(inputTrackHandle,e,
fInputTrackLabel);
191 const art::FindManyP<rec::TrackIoniz> TrackIonizFromInputTracks(inputTrackHandle,e,
fInputTrackLabel);
192 const art::FindManyP<rec::Vertex, rec::TrackEnd> VerticesFromInputTracks(inputTrackHandle,e,
fInputVertexLabel);
193 const art::FindManyP<rec::Hit> HitsFromInputTPCClusters(inputTPCClusterHandle,e,
fInputTPCClusterLabel);
209 std::map<rec::IDNumber,size_t> hcim;
210 for (
size_t iclus = 0; iclus<inputTPCClusters.size(); ++iclus)
212 rec::IDNumber clusid = inputTPCClusters.at(iclus).getIDNumber();
213 hcim[clusid] = iclus;
219 std::vector<int> trackside;
220 float chanpos[3] = {0,0,0};
221 for (
size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
225 for (
size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(itrack).size(); ++iTPCCluster)
227 size_t icindex = hcim[TPCClustersFromInputTracks.at(itrack).at(iTPCCluster)->getIDNumber()];
228 for (
size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
230 auto hitchan = HitsFromInputTPCClusters.at(icindex).at(ihit)->Channel();
231 geo->ChannelToPosition(hitchan, chanpos);
232 if (chanpos[0] > xtpccent)
244 trackside.push_back(1);
248 trackside.push_back(-1);
256 size_t nti = inputTracks.size();
257 std::vector<int> mergedflag(nti,-1);
258 std::vector<int> fwdflag(nti,0);
259 std::vector<float> dx(nti,0);
261 for (
size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
263 if (mergedflag.at(itrack) >= 0)
continue;
264 for (
size_t jtrack = itrack+1; jtrack < inputTracks.size(); ++jtrack)
266 if (mergedflag.at(jtrack)>=0)
continue;
267 if (trackside.at(itrack) == trackside.at(jtrack))
continue;
268 if (
cathodematch(inputTracks.at(itrack),inputTracks.at(jtrack),fwdflag.at(itrack),fwdflag.at(jtrack),dx.at(itrack)))
272 std::cout <<
"found a merge. dx= " <<
274 " flip flags: " << fwdflag.at(itrack) <<
" " << fwdflag.at(jtrack) <<
std::endl;
276 mergedflag.at(itrack) = jtrack;
277 mergedflag.at(jtrack) = itrack;
278 dx.at(jtrack) = -dx.at(itrack);
289 std::map<rec::IDNumber,locVtx_t> vtxmap;
292 std::map<rec::IDNumber,std::vector<trkiend_t>> vttrackmap;
295 std::map<rec::IDNumber,bool> vtxshifted;
300 for (
size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
303 tmpti.trkindex = itrack;
304 tmpti.dx = dx.at(itrack);
306 for (
size_t ivtx = 0; ivtx < VerticesFromInputTracks.at(itrack).size(); ++ivtx)
308 auto vtxp = VerticesFromInputTracks.at(itrack).at(ivtx);
310 auto vtxiter = vtxmap.find(vtxid);
311 if (vtxiter == vtxmap.end())
314 tmpvtxdat.fTime = vtxp->Time();
315 for (
int i=0; i<3; ++i)
317 tmpvtxdat.fPosition[i] = vtxp->Position()[i];
319 for (
int i=0; i<9; ++i)
321 tmpvtxdat.fCovMat[i] = vtxp->CovMat()[i];
323 vtxmap[vtxid] = tmpvtxdat;
324 vtxshifted[vtxid] =
false;
326 std::vector<trkiend_t> trkindexvector;
327 tmpti.trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
328 trkindexvector.push_back(tmpti);
329 vttrackmap[vtxid] = trkindexvector;
333 tmpti.trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
334 vttrackmap[vtxid].push_back(tmpti);
343 bool moretodo =
true;
347 for (
const auto &vtxi : vttrackmap)
349 if (vtxshifted[vtxi.first])
continue;
353 for (
size_t i=0; i< vtxi.second.size(); ++i)
355 size_t itrack = vtxi.second.at(i).trkindex;
356 if (mergedflag.at(itrack) >= 0 || dx.at(itrack) != 0)
358 avgdx += dx.at(itrack);
364 avgdx /= (
float) numdx;
365 vtxshifted[vtxi.first] =
true;
368 vtxmap[vtxi.first].fPosition[0] += avgdx;
370 double ts = vtxmap[vtxi.first].fTime;
371 double deltat = avgdx/DriftVelocity;
373 vtxmap[vtxi.first].fTime = ts;
376 for (
size_t i=0; i< vtxi.second.size(); ++i)
378 size_t itrack = vtxi.second.at(i).trkindex;
379 if (mergedflag.at(itrack) < 0 && dx.at(itrack) == 0)
381 dx.at(itrack) = avgdx;
390 std::map<rec::IDNumber,size_t> vtxoutmap;
391 for (
const auto &vtxr : vtxmap)
393 vtxCol->emplace_back(vtxr.second.fPosition,vtxr.second.fCovMat,vtxr.second.fTime);
394 vtxoutmap[vtxr.first] = vtxCol->size() - 1;
402 for (
size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
404 if (mergedflag.at(itrack) < 0)
406 TrackPar tpi(inputTracks.at(itrack));
408 double deltat = dx.at(itrack)/DriftVelocity;
410 TrackPar tpm(tpi.getLengthForwards(),
411 tpi.getLengthBackwards(),
412 tpi.getNTPCClusters(),
413 tpi.getXBeg() + dx.at(itrack),
414 tpi.getTrackParametersBegin(),
416 tpi.getChisqForwards(),
417 tpi.getXEnd() + dx.at(itrack),
418 tpi.getTrackParametersEnd(),
420 tpi.getChisqBackwards(),
422 trkCol->push_back(tpm.CreateTrack());
426 auto const trackpointer = trackPtrMaker(trkCol->size()-1);
427 float cpos[3] = {0,0,0};
428 for (
size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(itrack).size(); ++iTPCCluster)
430 auto const &tc = TPCClustersFromInputTracks.at(itrack).at(iTPCCluster);
431 for (
size_t i=0; i<3; ++i)
433 cpos[i] = tc->Position()[i];
435 cpos[0] += dx.at(itrack);
436 TPCClusterCol->emplace_back(tc->Signal(),
443 auto const TPCClusterPointer = TPCClusterPtrMaker(TPCClusterCol->size()-1);
444 TPCClusterTrkAssns->addSingle(TPCClusterPointer,trackpointer);
446 size_t icindex = hcim[oldclusid];
447 for (
size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
449 HitTPCClusterAssns->addSingle(HitsFromInputTPCClusters.at(icindex).at(ihit),TPCClusterPointer);
456 for (
size_t iTrkIoniz=0; iTrkIoniz<TrackIonizFromInputTracks.at(itrack).size(); ++iTrkIoniz)
458 ionCol->push_back(*TrackIonizFromInputTracks.at(itrack).at(iTrkIoniz));
459 auto const ionizpointer = ionizPtrMaker(ionCol->size()-1);
460 ionTrkAssns->addSingle(ionizpointer, trackpointer);
466 for (
size_t ivtx = 0; ivtx < VerticesFromInputTracks.at(itrack).size(); ++ivtx)
468 auto vtxp = VerticesFromInputTracks.at(itrack).at(ivtx);
469 auto trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
471 size_t ivout = vtxoutmap[vtxid];
472 auto const vtxptr = vtxPtrMaker(ivout);
473 trkVtxAssns->addSingle(trackpointer,vtxptr,trkend);
479 if (mergedflag.at(itrack) < 0)
481 MF_LOG_WARNING(
"tpccathodestitch: inconsistent merge flags ") << itrack <<
" " << mergedflag.at(itrack);
484 size_t jtrack = mergedflag.at(itrack);
485 if (jtrack < itrack)
continue;
490 TrackPar tpi(inputTracks.at(itrack), fwdflag.at(itrack) != 1);
491 TrackPar tpj(inputTracks.at(jtrack), fwdflag.at(jtrack) != 1);
493 tpi.
setXBeg( tpi.getXBeg() + dx.at(itrack) );
494 tpi.setXEnd( tpi.getXEnd() + dx.at(itrack) );
495 tpj.setXBeg( tpj.getXBeg() + dx.at(jtrack) );
496 tpj.setXEnd( tpj.getXEnd() + dx.at(jtrack) );
499 double ts = tpi.getTime();
500 int deltat = dx.at(itrack)/DriftVelocity;
501 if ( (
int) ts + deltat >= 0)
506 TrackPar tpm(tpi.getLengthForwards() + tpj.getLengthForwards(),
507 tpi.getLengthBackwards() + tpj.getLengthBackwards(),
508 tpi.getNTPCClusters() + tpj.getNTPCClusters(),
510 tpi.getTrackParametersBegin(),
512 tpi.getChisqForwards() + tpj.getChisqForwards(),
514 tpj.getTrackParametersEnd(),
516 tpi.getChisqBackwards() + tpj.getChisqBackwards(),
518 trkCol->push_back(tpm.CreateTrack());
519 auto const trackpointer = trackPtrMaker(trkCol->size()-1);
523 float cpos[3] = {0,0,0};
524 for (
size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(itrack).size(); ++iTPCCluster)
526 auto const &tc = TPCClustersFromInputTracks.at(itrack).at(iTPCCluster);
527 for (
size_t i=0; i<3; ++i)
529 cpos[i] = tc->Position()[i];
531 cpos[0] += dx.at(itrack);
532 TPCClusterCol->emplace_back(tc->Signal(),
539 auto const TPCClusterPointer = TPCClusterPtrMaker(TPCClusterCol->size()-1);
540 TPCClusterTrkAssns->addSingle(TPCClusterPointer,trackpointer);
542 size_t icindex = hcim[oldclusid];
543 for (
size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
545 HitTPCClusterAssns->addSingle(HitsFromInputTPCClusters.at(icindex).at(ihit),TPCClusterPointer);
548 for (
size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(jtrack).size(); ++iTPCCluster)
550 auto const &tc = TPCClustersFromInputTracks.at(jtrack).at(iTPCCluster);
551 for (
size_t i=0; i<3; ++i)
553 cpos[i] = tc->Position()[i];
555 cpos[0] += dx.at(jtrack);
556 TPCClusterCol->emplace_back(tc->Signal(),
563 auto const TPCClusterPointer = TPCClusterPtrMaker(TPCClusterCol->size()-1);
564 TPCClusterTrkAssns->addSingle(TPCClusterPointer,trackpointer);
566 size_t icindex = hcim[oldclusid];
567 for (
size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
569 HitTPCClusterAssns->addSingle(HitsFromInputTPCClusters.at(icindex).at(ihit),TPCClusterPointer);
576 const auto itif = TrackIonizFromInputTracks.at(itrack).at(0)->getFWD_dSigdXs();
577 const auto itib = TrackIonizFromInputTracks.at(itrack).at(0)->getBAK_dSigdXs();
578 const auto jtif = TrackIonizFromInputTracks.at(jtrack).at(0)->getFWD_dSigdXs();
579 const auto jtib = TrackIonizFromInputTracks.at(jtrack).at(0)->getBAK_dSigdXs();
583 if (fwdflag.at(itrack) != 1)
590 if (fwdflag.at(jtrack) != 1)
596 for (
size_t i=0; i<jmtif.size(); ++i)
598 mtif.push_back(jmtif.at(i));
600 for (
size_t i=0; i<jmtib.size(); ++i)
602 mtib.push_back(jmtib.at(i));
606 ionCol->push_back(tim);
607 auto const ionizpointer = ionizPtrMaker(ionCol->size()-1);
608 ionTrkAssns->addSingle(ionizpointer, trackpointer);
610 for (
size_t ivtx = 0; ivtx < VerticesFromInputTracks.at(itrack).size(); ++ivtx)
612 auto vtxp = VerticesFromInputTracks.at(itrack).at(ivtx);
613 auto trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
614 if (fwdflag.at(itrack) != 1)
619 size_t ivout = vtxoutmap[vtxid];
620 auto const vtxptr = vtxPtrMaker(ivout);
621 trkVtxAssns->addSingle(trackpointer,vtxptr,trkend);
646 bool matchable =
false;
654 double xtpccent = geo->TPCXCent();
655 TVector3 xhat(1,0,0);
656 TVector3 xcentv = xhat*xtpccent;
658 std::vector<TVector3> apt;
659 std::vector<TVector3> bpt;
660 std::vector<TVector3> adir;
661 std::vector<TVector3> bdir;
663 apt.emplace_back(atrack.
Vertex());
664 apt.emplace_back(atrack.
End());
665 adir.emplace_back(atrack.
VtxDir());
666 adir.emplace_back(atrack.
EndDir());
667 bpt.emplace_back(btrack.
Vertex());
668 bpt.emplace_back(btrack.
End());
669 bdir.emplace_back(btrack.
VtxDir());
670 bdir.emplace_back(btrack.
EndDir());
674 for (
size_t i=0; i<apt.size(); ++i) apt.at(i) -= xcentv;
675 for (
size_t i=0; i<bpt.size(); ++i) bpt.at(i) -= xcentv;
677 std::vector<int> fwflag = {2, 1};
679 for (
size_t ia=0; ia<apt.size(); ++ia)
681 for (
size_t ib=0; ib<bpt.size(); ++ib)
684 TVector3 v=adir.at(ia);
685 TVector3 u=bdir.at(ib);
687 if (v.Dot(u) > -
fCTCut)
continue;
696 float tdenom = 1.0 - TMath::Sq(xhat.Dot(v));
697 if (tdenom == 0)
continue;
698 TVector3
d = apt.at(ia) - bpt.at(ib);
699 float tau = (0.5/tdenom) * d.Dot( (v.Dot(xhat))*v - xhat );
701 if (tau >
fMaxDX)
continue;
702 if (tau <
fMinDX)
continue;
706 float gamma = -v.Dot(2*tau*xhat + d);
707 TVector3 chivec = d + gamma*v + 2.0*tau*xhat;
708 if (chivec.Mag() >
fDistCut)
continue;
712 bfw = fwflag.at(1-ib);
718 if (matchable)
break;
std::string fInputTrackLabel
input tracks and associations with TPCClusters. Get vertices associated with these tracks from the as...
tpccathodestitch(fhicl::ParameterSet const &p)
EDProducer(fhicl::ParameterSet const &pset)
const float * VtxDir() const
int fPrintLevel
debug printout: 0: none, 1: just track parameters and residuals, 2: all
const float * Vertex() const
#define DEFINE_ART_MODULE(klass)
void produce(art::Event &e) override
std::string fInputTPCClusterLabel
input TPC Clusters
float fMinDX
cut on minimum translation of dX on one side.
std::string fInputVertexLabel
input vertices and associations with tracks
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
float fDistCut
cut in distance between best-matching points
double gamma(double KE, const simb::MCParticle *part)
const float * End() const
float fMaxDX
cut on maximum translation of dX on one side.
tpccathodestitch & operator=(tpccathodestitch const &)=delete
General GArSoft Utilities.
void setXBeg(const float xbeg)
void setData(std::vector< std::pair< float, float >> dSigdX_FWD, std::vector< std::pair< float, float >> dSigdX_BAK)
std::string fInputHitLabel
needed to make TPCCluster - hit associations
float fCTCut
cut on cosine of angle matching
#define MF_LOG_WARNING(category)
bool cathodematch(const gar::rec::Track &trackA, const gar::rec::Track &trackB, int &fwdflagA, int &fwdflagB, float &deltaX)
LArSoft geometry interface.
art framework interface to geometry description
QTextStream & endl(QTextStream &s)
const float * EndDir() const