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