33 bool greaterThan1(PlnLen p1, PlnLen p2)
35 return p1.length > p2.length;
43 fSPTAlg = pset.
get<
int>(
"SPTAlg", 0);
44 fTrajOnly = pset.
get<
bool>(
"TrajOnly",
false);
45 ftmatch = pset.
get<
double>(
"TMatch");
46 fsmatch = pset.
get<
double>(
"SMatch");
61 if (fSPTAlg == 0) { TrackTrajectory(detProp, fHits); }
62 else if (fSPTAlg == 1) {
63 Track3D(clockData, detProp, fHits);
67 <<
"Unknown SPTAlg " << fSPTAlg <<
", needs to be 0 or 1";
70 if (!fTrajOnly && trajPos.size())
71 MakeSPT(clockData, detProp, fHits);
83 std::array<std::vector<geo::WireID>, 3> trkWID;
84 std::array<std::vector<double>, 3> trkX;
85 std::array<std::vector<double>, 3> trkXErr;
87 std::array<std::vector<art::Ptr<recob::Hit>>, 3> trajHits;
89 for (
size_t i = 0; i < fHits.size(); ++i) {
90 trajHits[fHits[i]->WireID().Plane].push_back(fHits[i]);
93 std::vector<PlnLen> spl;
95 for (
unsigned int ipl = 0; ipl < 3; ++ipl) {
97 plnlen.length = trajHits[ipl].size();
98 spl.push_back(plnlen);
100 std::sort(spl.begin(), spl.end(), greaterThan1);
103 for (
size_t ipl = 0; ipl < 3; ++ipl) {
104 if (!trajHits[ipl].
size())
continue;
105 double xbeg0 = detProp.
ConvertTicksToX(trajHits[spl[0].index][0]->PeakTime(),
107 trajHits[spl[0].index][0]->
WireID().TPC,
108 trajHits[spl[0].index][0]->
WireID().Cryostat);
109 double xend0 = detProp.
ConvertTicksToX(trajHits[spl[0].index].back()->PeakTime(),
111 trajHits[spl[0].index].back()->
WireID().TPC,
112 trajHits[spl[0].index].back()->
WireID().Cryostat);
115 trajHits[ipl][0]->
WireID().TPC,
116 trajHits[ipl][0]->
WireID().Cryostat);
117 double xend1 = detProp.
ConvertTicksToX(trajHits[ipl].back()->PeakTime(),
119 trajHits[ipl].back()->
WireID().TPC,
120 trajHits[ipl].back()->
WireID().Cryostat);
127 std::reverse(trajHits[ipl].
begin(), trajHits[ipl].
end());
131 for (
size_t ipl = 0; ipl < 3; ++ipl) {
133 trkWID[ipl].resize(trajHits[ipl].
size());
134 trkX[ipl].resize(trajHits[ipl].
size());
135 trkXErr[ipl].resize(trajHits[ipl].
size());
136 for (
size_t iht = 0; iht < trajHits[ipl].size(); ++iht) {
137 trkWID[ipl][iht] = trajHits[ipl][iht]->WireID();
138 trkX[ipl][iht] = detProp.
ConvertTicksToX(trajHits[ipl][iht]->PeakTime(),
140 trajHits[ipl][iht]->
WireID().TPC,
141 trajHits[ipl][iht]->
WireID().Cryostat);
142 trkXErr[ipl][iht] = 0.2 * trajHits[ipl][iht]->RMS() * trajHits[ipl][iht]->Multiplicity();
145 fTrackTrajectoryAlg.TrackTrajectory(trkWID, trkX, trkXErr, trajPos, trajDir);
146 if (!trajPos.size() || !trajDir.size()) {
147 mf::LogWarning(
"CosmicTrackerAlg") <<
"Failed to reconstruct trajectory points.";
151 for (
auto ipos = trajPos.begin(), idir = trajDir.begin(); ipos != trajPos.end() - 1;) {
152 auto ipos1 = ipos + 1;
153 if (*ipos1 == *ipos) {
154 ipos = trajPos.erase(ipos);
155 idir = trajDir.erase(idir);
165 vw.resize(geom->Ncryostats());
166 vt.resize(geom->Ncryostats());
167 vtraj.resize(geom->Ncryostats());
169 auto const cstat = cryostat.ID().Cryostat;
170 vw[cstat].resize(cryostat.NTPC());
171 vt[cstat].resize(cryostat.NTPC());
172 vtraj[cstat].resize(cryostat.NTPC());
173 for (
size_t tpc = 0; tpc < cryostat.NTPC(); ++tpc) {
175 unsigned int nplanes = wireReadoutGeom->Nplanes(tpcgeom.
ID());
176 vw[cstat][tpc].resize(nplanes);
177 vt[cstat][tpc].resize(nplanes);
178 vtraj[cstat][tpc].resize(nplanes);
179 for (
unsigned int plane = 0; plane < nplanes; ++plane) {
180 for (
size_t i = 0; i < trajPos.size(); ++i) {
181 double wirecord = wireReadoutGeom->Plane({tpcgeom.
ID(), plane})
182 .WireCoordinate(
geo::Point_t{0, trajPos[i].Y(), trajPos[i].Z()});
184 vw[cstat][tpc][plane].push_back(wirecord);
185 vt[cstat][tpc][plane].push_back(tick);
186 vtraj[cstat][tpc][plane].push_back(i);
198 larprop = lar::providerFrom<detinfo::LArPropertiesService>();
201 std::vector<std::map<int, double>> vtimemap(3);
202 std::vector<std::map<int, art::Ptr<recob::Hit>>> vhitmap(3);
205 for (
size_t ihit = 0; ihit < fHits.size(); ++ihit) {
207 unsigned int w = hitWireID.
Wire;
208 unsigned int pl = hitWireID.
Plane;
209 double time = fHits[ihit]->PeakTime();
212 vtimemap[pl][
w] = time;
213 vhitmap[pl][
w] = fHits[ihit];
220 unsigned maxnumhits0 = 0;
221 unsigned maxnumhits1 = 0;
223 std::vector<double> tmin(vtimemap.size());
224 std::vector<double> tmax(vtimemap.size());
225 for (
size_t iclu = 0; iclu < vtimemap.size(); ++iclu) {
230 for (
size_t iclu = 0; iclu < vtimemap.size(); ++iclu) {
231 for (
auto itime = vtimemap[iclu].
begin(); itime != vtimemap[iclu].end(); ++itime) {
232 if (itime->second > tmax[iclu]) { tmax[iclu] = itime->second; }
233 if (itime->second < tmin[iclu]) { tmin[iclu] = itime->second; }
235 if (vtimemap[iclu].
size() > maxnumhits0) {
238 maxnumhits1 = maxnumhits0;
241 maxnumhits0 = vtimemap[iclu].size();
243 else if (vtimemap[iclu].
size() > maxnumhits1) {
245 maxnumhits1 = vtimemap[iclu].size();
249 std::swap(iclu1, iclu2);
252 for (
int iclu = 0; iclu < (int)vtimemap.size(); ++iclu) {
253 if (iclu != iclu1 && iclu != iclu2) iclu3 = iclu;
256 if (iclu1 != -1 && iclu2 != -1) {
258 auto ihit = vhitmap[iclu1].begin();
259 auto itime = vtimemap[iclu1].begin();
260 while (itime != vtimemap[iclu1].
end()) {
261 if (itime->second < std::max(tmin[iclu1], tmin[iclu2]) - ftmatch ||
262 itime->second > std::min(tmax[iclu1], tmax[iclu2]) + ftmatch) {
263 vtimemap[iclu1].erase(itime++);
264 vhitmap[iclu1].erase(ihit++);
272 ihit = vhitmap[iclu2].begin();
273 itime = vtimemap[iclu2].begin();
274 while (itime != vtimemap[iclu2].
end()) {
275 if (itime->second < std::max(tmin[iclu1], tmin[iclu2]) - ftmatch ||
276 itime->second > std::min(tmax[iclu1], tmax[iclu2]) + ftmatch) {
277 vtimemap[iclu2].erase(itime++);
278 vhitmap[iclu2].erase(ihit++);
287 if (!vtimemap[iclu1].
size()) {
288 if (iclu3 != -1) { std::swap(iclu3, iclu1); }
290 if (!vtimemap[iclu2].
size()) {
292 std::swap(iclu3, iclu2);
293 std::swap(iclu1, iclu2);
296 if ((!vtimemap[iclu1].
size()) || (!vtimemap[iclu2].
size()))
return;
299 auto times1 = vtimemap[iclu1].begin();
300 auto timee1 = vtimemap[iclu1].end();
302 auto times2 = vtimemap[iclu2].begin();
303 auto timee2 = vtimemap[iclu2].end();
306 double ts1 = times1->second;
307 double te1 = timee1->second;
308 double ts2 = times2->second;
309 double te2 = timee2->second;
317 double Efield_drift = detProp.
Efield(0);
321 Efield_drift, Temperature);
322 double timepitch = driftvelocity * timetick;
324 double wire_pitch = wireReadoutGeom->Plane(vhitmap[0].
begin()->
second->WireID().asPlaneID())
328 std::vector<double> vtracklength;
329 for (
size_t iclu = 0; iclu < vtimemap.size(); ++iclu) {
331 double tracklength = 0;
332 if (vtimemap[iclu].
size() == 1) { tracklength = wire_pitch; }
333 else if (!vtimemap[iclu].
empty()) {
335 wend = vtimemap[iclu].cend();
336 double t0 = iw->first, w0 = iw->second;
337 while (++iw != wend) {
338 tracklength += std::hypot((iw->first - w0) * wire_pitch, (iw->second - t0) * timepitch);
343 vtracklength.push_back(tracklength);
346 std::map<int, int> maxhitsMatch;
348 auto ihit1 = vhitmap[iclu1].begin();
349 for (
auto itime1 = vtimemap[iclu1].
begin(); itime1 != vtimemap[iclu1].end();
351 std::vector<art::Ptr<recob::Hit>> sp_hits;
352 sp_hits.push_back(ihit1->second);
353 double hitcoord[3] = {0., 0., 0.};
355 if (vtimemap[iclu1].
size() == 1) { length1 = wire_pitch; }
357 for (
auto iw1 = vtimemap[iclu1].
begin(); iw1 != itime1; ++iw1) {
360 length1 += std::hypot((iw1->first - iw2->first) * wire_pitch,
361 (iw1->second - iw2->second) * timepitch);
364 double difference = 1e10;
365 auto matchedtime = vtimemap[iclu2].end();
366 auto matchedhit = vhitmap[iclu2].end();
368 auto ihit2 = vhitmap[iclu2].begin();
369 for (
auto itime2 = vtimemap[iclu2].
begin(); itime2 != vtimemap[iclu2].end();
371 if (maxhitsMatch[itime2->first])
continue;
373 if (vtimemap[iclu2].
size() == 1) { length2 = wire_pitch; }
375 for (
auto iw1 = vtimemap[iclu2].
begin(); iw1 != itime2; ++iw1) {
378 length2 += std::hypot((iw1->first - iw2->first) * wire_pitch,
379 (iw1->second - iw2->second) * timepitch);
382 if (rev) length2 = vtracklength[iclu2] - length2;
383 length2 = vtracklength[iclu1] / vtracklength[iclu2] * length2;
384 bool timematch =
std::abs(itime1->second - itime2->second) < ftmatch;
385 if (timematch &&
std::abs(length2 - length1) < difference) {
386 difference =
std::abs(length2 - length1);
387 matchedtime = itime2;
391 if (difference < fsmatch) {
393 matchedtime->second + detProp.
GetXTicksOffset((matchedhit->second)->WireID().Plane,
394 (matchedhit->second)->
WireID().TPC,
395 (matchedhit->second)->
WireID().Cryostat),
396 (matchedhit->second)->WireID().Plane,
397 (matchedhit->second)->
WireID().TPC,
398 (matchedhit->second)->
WireID().Cryostat);
408 if (
auto intersection = wireReadoutGeom->WireIDsIntersect(c1, c2)) {
409 hitcoord[1] = intersection->y;
410 hitcoord[2] = intersection->z;
413 if (hitcoord[1] > -1e9 && hitcoord[2] > -1e9) {
414 maxhitsMatch[matchedtime->first] = 1;
415 sp_hits.push_back(matchedhit->second);
418 if (sp_hits.size() > 1) {
419 trajPos.push_back(TVector3(hitcoord));
420 trajHit.push_back(sp_hits);
431 larprop = lar::providerFrom<detinfo::LArPropertiesService>();
434 double Efield_drift = detProp.
Efield(0);
436 double driftvelocity =
438 double time_pitch = driftvelocity * timetick;
440 for (
size_t i = 0; i < fHits.size(); ++i) {
447 double mindis1 = 1e9;
448 double mindis2 = 1e9;
449 double mindis2p = 1e9;
451 unsigned int wire = wireid.
Wire;
452 unsigned int plane = wireid.
Plane;
453 unsigned int tpc = wireid.
TPC;
454 unsigned int cstat = wireid.
Cryostat;
455 double wire_pitch = wireReadoutGeom->Plane(wireid).WirePitch();
458 for (
size_t j = 0; j < vw[cstat][tpc][plane].size(); ++j) {
459 double dis = std::hypot(wire_pitch * (wire - vw[cstat][tpc][plane][j]),
460 time_pitch * (fHits[i]->PeakTime() - vt[cstat][tpc][plane][j]));
463 ip1 = vtraj[cstat][tpc][plane][j];
468 for (
size_t j = 0; j < vw[cstat][tpc][plane].size(); ++j) {
469 if (
int(j) == ih1)
continue;
470 double dis = std::hypot(wire_pitch * (wire - vw[cstat][tpc][plane][j]),
471 time_pitch * (fHits[i]->PeakTime() - vt[cstat][tpc][plane][j]));
474 ip2 = vtraj[cstat][tpc][plane][j];
477 TVector3 v1(wire_pitch * (wire - vw[cstat][tpc][plane][ih1]),
478 time_pitch * (fHits[i]->PeakTime() - vt[cstat][tpc][plane][j]),
480 TVector3 v2(wire_pitch * (wire - vw[cstat][tpc][plane][j]),
481 time_pitch * (fHits[i]->PeakTime() - vt[cstat][tpc][plane][j]),
483 if (v1.Dot(v2) < 0) {
484 if (dis < mindis2p) {
486 ip2p = vtraj[cstat][tpc][plane][j];
495 if (ip1 == -1 || ip2 == -1) {
497 throw cet::exception(
"CosmicTrackerAlg") <<
"Cannot find two nearest trajectory points.";
499 TVector3 v1(wire_pitch * (wire - vw[cstat][tpc][plane][ih1]),
500 time_pitch * (fHits[i]->PeakTime() - vt[cstat][tpc][plane][ih1]),
502 TVector3 v2(wire_pitch * (vw[cstat][tpc][plane][ih2] - vw[cstat][tpc][plane][ih1]),
503 time_pitch * (vt[cstat][tpc][plane][ih2] - vt[cstat][tpc][plane][ih1]),
506 throw cet::exception(
"CosmicTrackerAlg") <<
"Two identical trajectory points.";
508 double ratio = v1.Dot(v2) / v2.Mag2();
509 TVector3 pos = trajPos[ip1] + ratio * (trajPos[ip2] - trajPos[ip1]);
510 trkPos.push_back(pos);
511 if (trajDir[ip1].Mag()) { trkDir.push_back(trajDir[ip1]); }
512 else if (trajDir[ip2].Mag()) {
513 trkDir.push_back(trajDir[ip2]);
516 trkDir.push_back((trajPos[ip2] - trajPos[ip1]).Unit());
code to link reconstructed objects back to the MC truth information
Utilities related to art service access.
Encapsulate the construction of a single cyostat .
double GetXTicksOffset(int p, int t, int c) const
Declaration of signal hit object.
Geometry information for a single TPC.
double Temperature() const
In kelvin.
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
WireID_t Wire
Index of the wire within its plane.
Geometry information for a single cryostat.
double Efield(unsigned int planegap=0) const
kV/cm
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
T get(std::string const &key) const
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
double ConvertXToTicks(double X, int p, int t, int c) const
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
PlaneID_t Plane
Index of the plane within its TPC.
Definition of data types for geometry description.
Class defining a plane for tracking. It provides various functionalities to convert track parameters ...
double ConvertTicksToX(double ticks, int p, int t, int c) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Contains all timing reference information for the detector.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
constexpr WireID()=default
Default constructor: an invalid TPC ID.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
TPCID_t TPC
Index of the TPC within its cryostat.
second_as<> second
Type of time stored in seconds, in double precision.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
TPCID const & ID() const
Returns the identifier of this TPC.
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Encapsulate the construction of a single detector plane .