18 #include "art/Framework/Core/EDProducer.h"
19 #include "art/Framework/Core/ModuleMacros.h"
20 #include "art/Framework/Principal/Event.h"
21 #include "art/Framework/Principal/Handle.h"
22 #include "art/Framework/Services/Registry/ServiceHandle.h"
23 #include "art_root_io/TFileService.h"
24 #include "canvas/Persistency/Common/FindManyP.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"
54 myfunction(CluLen c1, CluLen c2)
56 return (c1.length > c2.length);
61 operator()(art::Ptr<recob::Hit>
const& h1, art::Ptr<recob::Hit>
const& h2)
const
63 return h1->Channel() < h2->Channel();
91 fClusterModuleLabel = pset.get<std::string>(
"ClusterModuleLabel");
92 produces<std::vector<recob::Vertex>>();
93 produces<std::vector<recob::EndPoint2D>>();
94 produces<art::Assns<recob::EndPoint2D, recob::Hit>>();
95 produces<art::Assns<recob::Vertex, recob::Hit>>();
96 produces<art::Assns<recob::Vertex, recob::Shower>>();
97 produces<art::Assns<recob::Vertex, recob::Track>>();
105 art::ServiceHandle<art::TFileService const>
tfs;
106 dtIC = tfs->make<TH1D>(
"dtIC",
"It0-Ct0", 100, -5, 5);
114 art::ServiceHandle<geo::Geometry const> geom;
115 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
117 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
120 TString tpcName = geom->GetLArTPCVolumeName();
122 double YC = (geom->DetHalfHeight()) * 2.;
125 double Angle = geom->Plane(1).Wire(0).ThetaZ(
false) - TMath::Pi() / 2.;
132 double wire_pitch = geom->WirePitch();
133 double Efield_drift =
detProp.Efield();
134 double Temperature =
detProp.Temperature();
137 double driftvelocity =
detProp.DriftVelocity(Efield_drift, Temperature);
140 double timepitch = driftvelocity * timetick;
142 art::Handle<std::vector<recob::Cluster>> clusterListHandle;
145 art::PtrVector<recob::Cluster> clusters;
146 for (
unsigned int ii = 0; ii < clusterListHandle->size(); ++ii) {
147 art::Ptr<recob::Cluster> clusterHolder(clusterListHandle, ii);
148 clusters.push_back(clusterHolder);
154 std::unique_ptr<std::vector<recob::Vertex>> vcol(
new std::vector<recob::Vertex>);
155 std::unique_ptr<std::vector<recob::EndPoint2D>> epcol(
156 new std::vector<recob::EndPoint2D>);
157 std::unique_ptr<art::Assns<recob::EndPoint2D, recob::Hit>> assnep(
158 new art::Assns<recob::EndPoint2D, recob::Hit>);
159 std::unique_ptr<art::Assns<recob::Vertex, recob::Shower>> assnsh(
160 new art::Assns<recob::Vertex, recob::Shower>);
161 std::unique_ptr<art::Assns<recob::Vertex, recob::Track>> assntr(
162 new art::Assns<recob::Vertex, recob::Track>);
163 std::unique_ptr<art::Assns<recob::Vertex, recob::Hit>> assnh(
164 new art::Assns<recob::Vertex, recob::Hit>);
168 int nplanes = geom->Views().size();
170 std::vector<std::vector<int>> Cls(nplanes);
171 std::vector<std::vector<CluLen>> clulens(nplanes);
173 std::vector<double> dtdwstart;
176 for (
size_t iclu = 0; iclu < clusters.size(); ++iclu) {
178 float w0 = clusters[iclu]->StartWire();
179 float w1 = clusters[iclu]->EndWire();
180 float t0 = clusters[iclu]->StartTick();
181 float t1 = clusters[iclu]->EndTick();
185 clulen.length = std::hypot((w0 - w1) * wire_pitch,
186 detProp.ConvertTicksToX(t0, clusters[iclu]->View(), 0, 0) -
187 detProp.ConvertTicksToX(t1, clusters[iclu]->View(), 0, 0));
189 switch (clusters[iclu]->View()) {
191 case geo::kU: clulens[0].push_back(clulen);
break;
192 case geo::kV: clulens[1].push_back(clulen);
break;
193 case geo::kZ: clulens[2].push_back(clulen);
break;
197 std::vector<double> wires;
198 std::vector<double> times;
200 std::vector<art::Ptr<recob::Hit>>
hit = fmh.at(iclu);
201 std::sort(hit.begin(), hit.end(),
SortByWire());
203 for (
size_t i = 0; i < hit.size(); ++i) {
204 wires.push_back(hit[i]->
WireID().Wire);
205 times.push_back(hit[i]->PeakTime());
209 TGraph* the2Dtrack =
new TGraph(std::min(10, n), &wires[0], ×[0]);
211 the2Dtrack->Fit(
"pol1",
"Q");
212 TF1* pol1 = (TF1*)the2Dtrack->GetFunction(
"pol1");
214 pol1->GetParameters(par);
215 dtdwstart.push_back(par[1]);
218 mf::LogWarning(
"VertexFinder2D") <<
"Fitter failed";
220 dtdwstart.push_back(std::tan(clusters[iclu]->StartAngle()));
226 dtdwstart.push_back(std::tan(clusters[iclu]->StartAngle()));
230 for (
size_t i = 0; i < clulens.size(); ++i) {
231 std::sort(clulens[i].
begin(), clulens[i].
end(), myfunction);
232 for (
size_t j = 0; j < clulens[i].size(); ++j) {
233 Cls[i].push_back(clulens[i][j].index);
237 std::vector<std::vector<int>> cluvtx(nplanes);
238 std::vector<double> vtx_w;
239 std::vector<double> vtx_t;
241 for (
int i = 0; i < nplanes; ++i) {
242 if (Cls[i].
size() >= 1) {
258 for (
unsigned j = 0; j < Cls[i].size(); ++j) {
259 double lclu = std::sqrt(
260 pow((clusters[Cls[i][j]]->StartWire() - clusters[Cls[i][j]]->EndWire()) * 13.5, 2) +
261 pow(clusters[Cls[i][j]]->
StartTick() - clusters[Cls[i][j]]->EndTick(), 2));
263 bool deltaraylike =
false;
264 bool enoughhits =
false;
266 double wb = clusters[Cls[i][j]]->StartWire();
267 double we = clusters[Cls[i][j]]->EndWire();
268 double tt = clusters[Cls[i][j]]->StartTick();
269 double dtdw = dtdwstart[Cls[i][j]];
270 int nhits = fmh.at(Cls[i][j]).size();
271 ww0 = (tt - tt1 + dtdw1 * wb1 - dtdw * wb) / (dtdw1 - dtdw);
273 if ((!rev && ww0 > wb1 + 15) || (rev && ww0 < we1 - 15)) deltaraylike =
true;
274 if (((!rev && ww0 > wb1 + 10) || (rev && ww0 < we1 - 10)) && nhits < 5)
276 if (wb > wb1 + 20 && nhits < 20) deltaraylike =
true;
277 if (wb > wb1 + 50 && nhits < 20) deltaraylike =
true;
278 if (wb > wb1 + 8 && TMath::Abs(dtdw1 - dtdw) < 0.15) deltaraylike =
true;
279 if (
std::abs(wb - wb1) > 30 &&
std::abs(we - we1) > 30) deltaraylike =
true;
284 double alpha = std::atan(dtdw);
285 if (nhits >=
int(2 + 3 * (1 -
std::abs(std::cos(alpha))))) enoughhits =
true;
286 if (nhits < 5 && (ww0 < wb1 - 20 || ww0 > we1 + 20)) enoughhits =
false;
290 if (c1 != -1 && c2 != -1) {
291 double wb = clusters[Cls[i][j]]->StartWire();
292 double we = clusters[Cls[i][j]]->EndWire();
293 ww0 = (tt2 - tt1 + dtdw1 * wb1 - dtdw2 * wb2) / (dtdw1 - dtdw2);
300 if (c1 != -1 && !deltaraylike && enoughhits) {
310 wb1 = clusters[Cls[i][j]]->StartWire();
311 we1 = clusters[Cls[i][j]]->EndWire();
312 tt1 = clusters[Cls[i][j]]->StartTick();
314 wb1 = clusters[Cls[i][j]]->EndWire();
315 we1 = clusters[Cls[i][j]]->StartWire();
316 tt1 = clusters[Cls[i][j]]->EndTick();
318 dtdw1 = dtdwstart[Cls[i][j]];
320 else if (lclu2 < lclu) {
321 if (!deltaraylike && enoughhits && replace) {
324 wb2 = clusters[Cls[i][j]]->StartWire();
325 we2 = clusters[Cls[i][j]]->EndWire();
326 tt2 = clusters[Cls[i][j]]->StartTick();
327 dtdw2 = dtdwstart[Cls[i][j]];
331 if (c1 != -1 && c2 != -1) {
332 cluvtx[i].push_back(c1);
333 cluvtx[i].push_back(c2);
335 double w1 = clusters[c1]->StartWire();
336 double t1 = clusters[c1]->StartTick();
337 if (clusters[c1]->StartWire() > clusters[c1]->EndWire()) {
338 w1 = clusters[c1]->EndWire();
339 t1 = clusters[c1]->EndTick();
341 double k1 = dtdwstart[c1];
342 double w2 = clusters[c2]->StartWire();
343 double t2 = clusters[c2]->StartTick();
344 if (clusters[c2]->StartWire() > clusters[c2]->EndWire()) {
345 w1 = clusters[c2]->EndWire();
346 t1 = clusters[c2]->EndTick();
348 double k2 = dtdwstart[c2];
355 double t0 = (k1 * k2 * (w1 - w2) + k1 * t2 - k2 * t1) / (k1 - k2);
356 double w0 = (t2 - t1 + k1 * w1 - k2 * w2) / (k1 - k2);
361 else if (Cls[i].
size() >= 1) {
363 cluvtx[i].push_back(c1);
364 vtx_w.push_back(wb1);
365 vtx_t.push_back(tt1);
368 cluvtx[i].push_back(Cls[i][0]);
369 vtx_w.push_back(clusters[Cls[i][0]]->StartWire());
370 vtx_t.push_back(clusters[Cls[i][0]]->
StartTick());
377 std::vector<art::Ptr<recob::Hit>> hits = fmh.at(Cls[i][0]);
379 for (
size_t h = 0;
h < hits.size(); ++
h)
380 totalQ += hits[
h]->Integral();
385 (
unsigned int)vtx_w.back());
391 clusters[Cls[i][0]]->View(),
405 Double_t vtxcoord[3];
406 if (Cls[0].
size() > 0 && Cls[1].
size() > 0) {
407 double Iw0 = (vtx_w[0] + 3.95) * wire_pitch;
408 double Cw0 = (vtx_w[1] + 1.84) * wire_pitch;
410 double It0 = vtx_t[0] - presamplings;
412 double Ct0 = vtx_t[1] - presamplings;
414 vtxcoord[0] =
detProp.ConvertTicksToX(vtx_t[1], 1, 0, 0);
415 vtxcoord[1] = (Cw0 - Iw0) / (2. * std::sin(Angle));
416 vtxcoord[2] = (Cw0 + Iw0) / (2. * std::cos(Angle)) - YC / 2. * std::tan(Angle);
419 if (vtx_w[0] >= 0 && vtx_w[0] <= 239 && vtx_w[1] >= 0 && vtx_w[1] <= 239) {
420 if (geom->ChannelsIntersect(geom->PlaneWireToChannel(0, (
int)((Iw0 / wire_pitch) - 3.95)),
421 geom->PlaneWireToChannel(1, (
int)((Cw0 / wire_pitch) - 1.84)),
430 vtxcoord[0] = -99999;
431 vtxcoord[1] = -99999;
432 vtxcoord[2] = -99999;
435 dtIC->Fill(It0 - Ct0);
438 vtxcoord[0] = -99999;
439 vtxcoord[1] = -99999;
440 vtxcoord[2] = -99999;
445 art::PtrVector<recob::Track> vTracks_vec;
446 art::PtrVector<recob::Shower> vShowers_vec;
449 vcol->push_back(the3Dvertex);
451 if (vShowers_vec.size() > 0) {
util::CreateAssn(evt, *vcol, vShowers_vec, *assnsh); }
453 if (vTracks_vec.size() > 0) {
util::CreateAssn(evt, *vcol, vTracks_vec, *assntr); }
455 MF_LOG_VERBATIM(
"Summary") << std::setfill(
'-') << std::setw(175) <<
"-" << std::setfill(
' ');
456 MF_LOG_VERBATIM(
"Summary") <<
"VertexFinder2D Summary:";
457 for (
size_t i = 0; i < epcol->size(); ++i)
458 MF_LOG_VERBATIM(
"Summary") << epcol->at(i);
459 for (
size_t i = 0; i < vcol->size(); ++i)
460 MF_LOG_VERBATIM(
"Summary") << vcol->at(i);
462 evt.put(std::move(epcol));
463 evt.put(std::move(vcol));
464 evt.put(std::move(assnep));
465 evt.put(std::move(assntr));
466 evt.put(std::move(assnsh));
467 evt.put(std::move(assnh));
476 DEFINE_ART_MODULE(VertexFinder2D)
std::string fClusterModuleLabel
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
VertexFinder2D(fhicl::ParameterSet const &pset)
Declaration of signal hit object.
std::size_t size(FixedBins< T, C > const &) noexcept
Planes which measure Z direction.
Definition of vertex object for LArSoft.
bool SortByWire(art::Ptr< recob::Hit > const &h1, art::Ptr< recob::Hit > const &h2)
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
auto end(FixedBins< T, C > const &) noexcept
void produce(art::Event &evt) override
Declaration of cluster object.
Provides recob::Track data product.
Encapsulate the geometry of a wire.
auto begin(FixedBins< T, C > const &) noexcept
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.
int trigger_offset(DetectorClocksData const &data)
art::ServiceHandle< art::TFileService > tfs
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
art framework interface to geometry description