11 #include "art/Framework/Core/EDProducer.h"
21 #include "art/Framework/Core/ModuleMacros.h"
22 #include "art/Framework/Principal/Event.h"
23 #include "art/Framework/Principal/Handle.h"
24 #include "art/Framework/Services/Registry/ServiceHandle.h"
25 #include "canvas/Persistency/Common/Ptr.h"
26 #include "canvas/Persistency/Common/PtrVector.h"
27 #include "fhiclcpp/ParameterSet.h"
28 #include "messagefacility/MessageLogger/MessageLogger.h"
31 #include "canvas/Persistency/Common/FindManyP.h"
53 explicit Track3Dreco(fhicl::ParameterSet
const& pset);
70 fClusterModuleLabel = pset.get<std::string>(
"ClusterModuleLabel");
71 ftmatch = pset.get<
int>(
"TMatch");
72 fchi2dof = pset.get<
double>(
"Chi2DOFmax");
74 produces<std::vector<recob::Track>>();
75 produces<std::vector<recob::SpacePoint>>();
76 produces<art::Assns<recob::Track, recob::Cluster>>();
77 produces<art::Assns<recob::Track, recob::SpacePoint>>();
78 produces<art::Assns<recob::SpacePoint, recob::Hit>>();
79 produces<art::Assns<recob::Track, recob::Hit>>();
86 art::ServiceHandle<geo::Geometry const> geom;
88 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt);
90 auto tcol = std::make_unique<std::vector<recob::Track>>();
91 auto spacepoints = std::make_unique<std::vector<recob::SpacePoint>>();
92 auto cassn = std::make_unique<art::Assns<recob::Track, recob::Cluster>>();
93 auto sassn = std::make_unique<art::Assns<recob::Track, recob::SpacePoint>>();
94 auto shassn = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
95 auto hassn = std::make_unique<art::Assns<recob::Track, recob::Hit>>();
98 TString tpcName = geom->GetLArTPCVolumeName();
100 double YC = (geom->DetHalfHeight()) * 2.;
101 double Angle = geom->Plane(1).Wire(0).ThetaZ(
false) -
104 double timetick = 0.198;
105 double presamplings = 60.;
106 const double wireShift =
108 double plane_pitch = geom->PlanePitch(0, 1);
109 double wire_pitch = geom->WirePitch();
110 double Efield_drift = 0.5;
111 double Efield_SI = 0.7;
112 double Efield_IC = 0.9;
113 double Temperature = 87.6;
115 double driftvelocity =
116 detProp.DriftVelocity(Efield_drift, Temperature);
118 double driftvelocity_SI =
119 detProp.DriftVelocity(Efield_SI, Temperature);
121 double driftvelocity_IC =
122 detProp.DriftVelocity(Efield_IC, Temperature);
124 double timepitch = driftvelocity * timetick;
125 double tSI = plane_pitch / driftvelocity_SI / timetick;
127 double tIC = plane_pitch / driftvelocity_IC / timetick;
131 art::Handle<std::vector<recob::Cluster>> clusterListHandle;
136 std::vector<double> Iwirefirsts;
137 std::vector<double> Iwirelasts;
138 std::vector<double> Itimefirsts;
139 std::vector<double> Itimelasts;
140 std::vector<double> Itimefirsts_line;
141 std::vector<double> Itimelasts_line;
142 std::vector<std::vector<art::Ptr<recob::Hit>>> IclusHitlists;
143 std::vector<unsigned int> Icluster_count;
146 std::vector<double> Cwirefirsts;
147 std::vector<double> Cwirelasts;
148 std::vector<double> Ctimefirsts;
149 std::vector<double> Ctimelasts;
150 std::vector<double> Ctimefirsts_line;
151 std::vector<double> Ctimelasts_line;
152 std::vector<std::vector<art::Ptr<recob::Hit>>> CclusHitlists;
153 std::vector<unsigned int> Ccluster_count;
157 unsigned int wire = 0;
158 unsigned int plane = 0;
160 size_t startSPIndex =
167 for (
size_t ii = 0; ii < clusterListHandle->size(); ++ii) {
168 art::Ptr<recob::Cluster> cl(clusterListHandle, ii);
177 if (cl->View() ==
geo::kZ)
continue;
180 std::vector<art::Ptr<recob::Hit>> hitlist(fmh.at(ii));
182 if (hitlist.size() == 1)
187 std::sort(hitlist.begin(), hitlist.end());
189 TGraph* the2Dtrack =
new TGraph(hitlist.size());
191 std::vector<double> wires;
192 std::vector<double> times;
196 for (art::PtrVector<recob::Hit>::const_iterator theHit = hitlist.begin();
197 theHit != hitlist.end();
200 time = (*theHit)->PeakTime();
202 time -= presamplings;
204 plane = (*theHit)->WireID().Plane;
205 wire = (*theHit)->WireID().Wire;
208 if (plane == 1) time -= tIC;
213 wire_cm = (double)((wire + 3.95) * wire_pitch);
215 wire_cm = (double)((wire + 1.84) * wire_pitch);
219 time_cm = (double)((time - tSI) * timepitch + tSI * driftvelocity_SI * timetick);
221 time_cm = time * driftvelocity_SI * timetick;
223 wires.push_back(wire_cm);
224 times.push_back(time_cm);
226 the2Dtrack->SetPoint(np, wire_cm, time_cm);
232 the2Dtrack->Fit(
"pol1",
"Q");
235 mf::LogWarning(
"Track3Dreco") <<
"The 2D track fit failed";
239 TF1* pol1 = (TF1*)the2Dtrack->GetFunction(
"pol1");
241 pol1->GetParameters(par);
242 double intercept = par[0];
243 double slope = par[1];
245 double w0 = wires.front();
246 double w1 = wires.back();
247 double t0 = times.front();
248 double t1 = times.back();
249 double t0_line = intercept + (w0)*slope;
250 double t1_line = intercept + (w1)*slope;
255 Iwirefirsts.push_back(w0);
256 Iwirelasts.push_back(w1);
257 Itimefirsts.push_back(t0);
258 Itimelasts.push_back(t1);
259 Itimefirsts_line.push_back(t0_line);
260 Itimelasts_line.push_back(t1_line);
261 IclusHitlists.push_back(hitlist);
262 Icluster_count.push_back(ii);
265 Cwirefirsts.push_back(w0);
266 Cwirelasts.push_back(w1);
267 Ctimefirsts.push_back(t0);
268 Ctimelasts.push_back(t1);
269 Ctimefirsts_line.push_back(t0_line);
270 Ctimelasts_line.push_back(t1_line);
271 CclusHitlists.push_back(hitlist);
272 Ccluster_count.push_back(ii);
283 for (
size_t collectionIter = 0; collectionIter < CclusHitlists.size(); ++collectionIter) {
285 double Cw0 = Cwirefirsts[collectionIter];
286 double Cw1 = Cwirelasts[collectionIter];
289 double Ct0_line = Ctimefirsts_line[collectionIter];
290 double Ct1_line = Ctimelasts_line[collectionIter];
291 std::vector<art::Ptr<recob::Hit>> hitsCtrk = CclusHitlists[collectionIter];
293 double collLength = std::hypot(Ct1_line - Ct0_line, Cw1 - Cw0);
296 for (
size_t inductionIter = 0; inductionIter < IclusHitlists.size(); ++inductionIter) {
298 double Iw0 = Iwirefirsts[inductionIter];
299 double Iw1 = Iwirelasts[inductionIter];
300 double It0_line = Itimefirsts_line[inductionIter];
301 double It1_line = Itimelasts_line[inductionIter];
302 std::vector<art::Ptr<recob::Hit>> hitsItrk = IclusHitlists[inductionIter];
304 double indLength = std::hypot(It1_line - It0_line, Iw1 - Iw0);
306 bool forward_match = ((
std::abs(Ct0_line - It0_line) <
ftmatch * timepitch) &&
308 bool backward_match = ((
std::abs(Ct0_line - It1_line) <
ftmatch * timepitch) &&
312 if (forward_match || backward_match) {
317 XYZ0.SetXYZ(Ct0_line,
318 (Cw0 - Iw0) / (2. * std::sin(Angle)),
319 (Cw0 + Iw0) / (2. * std::cos(Angle)) - YC / 2. * std::tan(Angle));
320 XYZ1.SetXYZ(Ct1_line,
321 (Cw1 - Iw1) / (2. * std::sin(Angle)),
322 (Cw1 + Iw1) / (2. * std::cos(Angle)) - YC / 2. * std::tan(Angle));
325 XYZ0.SetXYZ(Ct0_line,
326 (Cw0 - Iw1) / (2. * std::sin(Angle)),
327 (Cw0 + Iw1) / (2. * std::cos(Angle)) - YC / 2. * std::tan(Angle));
328 XYZ1.SetXYZ(Ct1_line,
329 (Cw1 - Iw0) / (2. * std::sin(Angle)),
330 (Cw1 + Iw0) / (2. * std::cos(Angle)) - YC / 2. * std::tan(Angle));
336 TVector3 startpointVec, endpointVec;
337 TVector2 collVtx, indVtx;
338 if (XYZ0.Z() <= XYZ1.Z()) {
339 startpointVec.SetXYZ(XYZ0.X(), XYZ0.Y(), XYZ0.Z());
340 endpointVec.SetXYZ(XYZ1.X(), XYZ1.Y(), XYZ1.Z());
342 collVtx.Set(Ct0_line, Cw0);
343 indVtx.Set(It0_line, Iw0);
346 collVtx.Set(Ct0_line, Cw0);
347 indVtx.Set(It1_line, Iw1);
351 startpointVec.SetXYZ(XYZ1.X(), XYZ1.Y(), XYZ1.Z());
352 endpointVec.SetXYZ(XYZ0.X(), XYZ0.Y(), XYZ0.Z());
354 collVtx.Set(Ct1_line, Cw1);
355 indVtx.Set(It1_line, Iw1);
358 collVtx.Set(Ct1_line, Cw1);
359 indVtx.Set(It0_line, Iw0);
364 TVector3 DirCos = endpointVec - startpointVec;
371 mf::LogWarning(
"Track3Dreco") <<
"The Spacepoint is infinitely small";
375 art::Ptr<recob::Cluster> cl1(clusterListHandle, Icluster_count[inductionIter]);
376 art::Ptr<recob::Cluster> cl2(clusterListHandle, Ccluster_count[collectionIter]);
377 art::PtrVector<recob::Cluster> clustersPerTrack;
378 clustersPerTrack.push_back(cl1);
379 clustersPerTrack.push_back(cl2);
385 std::vector<art::Ptr<recob::Hit>> minhits =
386 hitsCtrk.size() <= hitsItrk.size() ? hitsCtrk : hitsItrk;
387 std::vector<art::Ptr<recob::Hit>> maxhits =
388 hitsItrk.size() <= hitsCtrk.size() ? hitsCtrk : hitsItrk;
390 std::vector<bool> maxhitsMatch(maxhits.size());
391 for (
size_t it = 0; it < maxhits.size(); ++it)
392 maxhitsMatch[it] =
false;
394 std::vector<recob::Hit*> hits3Dmatched;
396 unsigned int imaximum = 0;
399 startSPIndex = spacepoints->size();
401 for (
size_t imin = 0; imin < minhits.size(); ++imin) {
403 unsigned int wire, plane1, plane2;
404 wire = minhits[imin]->WireID().Wire;
405 plane1 = minhits[imin]->WireID().Plane;
410 w1 = (double)((wire + 3.95) * wire_pitch);
412 w1 = (double)((wire + 1.84) * wire_pitch);
413 double temptime1 = minhits[imin]->PeakTime() - presamplings;
414 if (plane1 == 1) temptime1 -= tIC;
417 t1 = (double)((temptime1 - tSI) * timepitch + tSI * driftvelocity_SI * timetick);
419 t1 = temptime1 * driftvelocity_SI * timetick;
423 plane1 == 1 ? minVtx2D.Set(collVtx.X(), collVtx.Y()) :
424 minVtx2D.Set(indVtx.X(), indVtx.Y());
426 plane1 == 1 ? maxVtx2D.Set(indVtx.X(), indVtx.Y()) :
427 maxVtx2D.Set(collVtx.X(), collVtx.Y());
430 (collLength > indLength) ? collLength / indLength : indLength / collLength;
433 double minDistance = ratio *
TMath::Sqrt(TMath::Power(t1 - minVtx2D.X(), 2) +
434 TMath::Power(w1 - minVtx2D.Y(), 2));
437 double difference = 9999999.;
440 for (
size_t imax = 0; imax < maxhits.size(); ++imax) {
441 if (!maxhitsMatch[imax]) {
443 wire = maxhits[imax]->WireID().Wire;
444 plane2 = maxhits[imax]->WireID().Plane;
448 w2 = (double)((wire + 3.95) * wire_pitch);
450 w2 = (double)((wire + 1.84) * wire_pitch);
451 double temptime2 = maxhits[imax]->PeakTime() - presamplings;
452 if (plane2 == 1) temptime2 -= tIC;
455 t2 = (double)((temptime2 - tSI) * timepitch + tSI * driftvelocity_SI * timetick);
457 t2 = temptime2 * driftvelocity_SI * timetick;
460 bool wirematch = (
std::abs(w1 - w2) < wireShift * wire_pitch);
462 double maxDistance =
TMath::Sqrt(TMath::Power(t2 - maxVtx2D.X(), 2) +
463 TMath::Power(w2 - maxVtx2D.Y(), 2));
464 if (wirematch && timematch &&
std::abs(maxDistance - minDistance) < difference) {
465 difference =
std::abs(maxDistance - minDistance);
470 maxhitsMatch[imaximum] =
true;
472 art::PtrVector<recob::Hit> sp_hits;
473 if (difference != 9999999.) {
474 sp_hits.push_back(minhits[imin]);
475 sp_hits.push_back(maxhits[imaximum]);
479 wire = maxhits[imaximum]->WireID().Wire;
480 plane2 = maxhits[imaximum]->WireID().Plane;
484 w1_match = (double)((wire + 3.95) * wire_pitch);
486 w1_match = (double)((wire + 1.84) * wire_pitch);
487 double temptime3 = maxhits[imaximum]->PeakTime() - presamplings;
488 if (plane2 == 1) temptime3 -= tIC;
492 (double)((temptime3 - tSI) * timepitch + tSI * driftvelocity_SI * timetick);
494 t1_match = temptime3 * driftvelocity_SI * timetick;
497 double Ct = plane1 == 1 ? t1 : t1_match;
498 double Cw = plane1 == 1 ? w1 : w1_match;
499 double Iw = plane1 == 1 ? w1_match : w1;
501 const TVector3 hit3d(Ct,
502 (Cw - Iw) / (2. * std::sin(Angle)),
503 (Cw + Iw) / (2. * std::cos(Angle)) - YC / 2. * std::tan(Angle));
504 Double_t hitcoord[3];
505 hitcoord[0] = hit3d.X();
506 hitcoord[1] = hit3d.Y();
507 hitcoord[2] = hit3d.Z();
509 Double_t hitcoord_errs[3];
510 for (
int i = 0; i < 3; i++)
511 hitcoord_errs[i] = -1.000;
516 spacepoints->push_back(mysp);
523 endSPIndex = spacepoints->size();
526 if (spacepoints->size() > startSPIndex || clustersPerTrack.size() > 0) {
528 std::vector<TVector3> xyz;
529 xyz.push_back(startpointVec);
530 xyz.push_back(endpointVec);
531 std::vector<TVector3> dir_xyz;
532 dir_xyz.push_back(DirCos);
533 dir_xyz.push_back(DirCos);
546 tcol->push_back(the3DTrack);
549 util::CreateAssn(evt, *tcol, *spacepoints, *sassn, startSPIndex, endSPIndex);
557 for (
size_t p = 0;
p < clustersPerTrack.size(); ++
p) {
558 const std::vector<art::Ptr<recob::Hit>>& hits = fmhc.at(
p);
569 mf::LogVerbatim(
"Summary") << std::setfill(
'-') << std::setw(175) <<
"-" << std::setfill(
' ');
570 mf::LogVerbatim(
"Summary") <<
"Track3Dreco Summary:";
571 for (
unsigned int i = 0; i < tcol->size(); ++i) {
572 mf::LogVerbatim(
"Summary") << tcol->at(i);
575 evt.put(std::move(tcol));
576 evt.put(std::move(spacepoints));
577 evt.put(std::move(cassn));
578 evt.put(std::move(sassn));
579 evt.put(std::move(hassn));
580 evt.put(std::move(shassn));
void produce(art::Event &evt) override
ROOT::Math::SMatrix< Double32_t, 5, 5, ROOT::Math::MatRepSym< Double32_t, 5 > > SMatrixSym55
std::vector< Vector_t > convertCollToVector(std::vector< Vector > const &coll)
Declaration of signal hit object.
std::string fClusterModuleLabel
label for input cluster collection
TrackTrajectory::Flags_t Flags_t
Planes which measure Z direction.
double fchi2dof
tolerance for chi2/dof of cluster fit to function
A trajectory in space reconstructed from hits.
std::vector< Point_t > convertCollToPoint(std::vector< Point > const &coll)
Declaration of cluster object.
Provides recob::Track data product.
int ftmatch
tolerance for time matching (in time samples)
Encapsulate the geometry of a wire.
bool CreateAssn(art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t index=UINT_MAX)
Creates a single one-to-one association.
Encapsulate the construction of a single detector plane.
Var Sqrt(const Var &v)
Use to take sqrt of a var.
Track3Dreco(fhicl::ParameterSet const &pset)
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: