25 #include "CLHEP/Random/RandGauss.h" 33 std::vector<std::vector<float>>
36 if ((samples == 0) || inps.empty() || inps.front().empty() || inps.front().front().empty())
39 if ((samples == -1) || (samples > (
int)inps.size())) { samples = inps.
size(); }
41 std::vector<std::vector<float>> results;
42 for (
int i = 0; i < samples; ++i) {
43 results.push_back(
Run(inps[i]));
55 if (
stat(fileName, &buffer) == 0) { fname_out =
fileName; }
70 mf::LogInfo(
"KerasModelInterface") <<
"Keras model loaded.";
77 std::vector<std::vector<std::vector<float>>> inp3d;
78 inp3d.push_back(inp2d);
94 {
"cnn_output",
"_netout"});
97 mf::LogInfo(
"TfModelInterface") <<
"TF model loaded.";
101 std::vector<std::vector<float>>
104 if ((samples == 0) || inps.empty() || inps.front().empty() || inps.front().front().empty())
107 if ((samples == -1) || (samples > (
long long int)inps.size())) { samples = inps.
size(); }
109 long long int rows = inps.front().size(), cols = inps.front().front().size();
111 tensorflow::Tensor _x(tensorflow::DT_FLOAT, tensorflow::TensorShape({samples, rows, cols, 1}));
112 auto input_map = _x.tensor<
float, 4>();
113 for (
long long int s = 0;
s < samples; ++
s) {
114 const auto& sample = inps[
s];
115 for (
long long int r = 0;
r < rows; ++
r) {
116 const auto&
row = sample[
r];
117 for (
long long int c = 0;
c < cols; ++
c) {
118 input_map(
s,
r,
c, 0) =
row[
c];
130 long long int rows = inp2d.size(), cols = inp2d.front().size();
132 tensorflow::Tensor _x(tensorflow::DT_FLOAT, tensorflow::TensorShape({1, rows, cols, 1}));
133 auto input_map = _x.tensor<
float, 4>();
134 for (
long long int r = 0;
r < rows; ++
r) {
135 const auto&
row = inp2d[
r];
136 for (
long long int c = 0;
c < cols; ++
c) {
137 input_map(0,
r,
c, 0) =
row[
c];
141 auto out =
g->run(_x);
145 return std::vector<float>();
153 :
img::DataProviderAlg(config)
155 , fPatchSizeW(config.PatchSizeW())
156 , fPatchSizeD(config.PatchSizeD())
157 , fCurrentWireIdx(99999)
158 , fCurrentScaledDrift(99999)
174 mf::LogError(
"PointIdAlg") <<
"File name extension not supported.";
177 if (!
fNNet) {
throw cet::exception(
"nnet::PointIdAlg") <<
"Loading model from file failed."; }
204 mf::LogError(
"PointIdAlg") <<
"Patch buffering failed.";
210 if (!out.empty()) { result = out[outIdx]; }
212 mf::LogError(
"PointIdAlg") <<
"Problem with applying model to input.";
223 std::vector<float>
result;
226 mf::LogError(
"PointIdAlg") <<
"Patch buffering failed.";
232 if (result.empty()) {
mf::LogError(
"PointIdAlg") <<
"Problem with applying model to input."; }
239 std::vector<std::vector<float>>
242 if (points.empty() || !
fNNet) {
return std::vector<std::vector<float>>(); }
244 std::vector<std::vector<std::vector<float>>> inps(
246 for (
size_t i = 0; i < points.size(); ++i) {
247 unsigned int wire = points[i].first;
248 float drift = points[i].second;
267 if ((wire1 == wire2) && (sd1 == sd2))
return true;
270 if ((wire1 == wire2) && ((size_t)drift1 == (
size_t)drift2))
return true;
296 std::vector<float>
flat;
302 flat.resize(
patch.size() *
patch.front().size());
304 for (
size_t w = 0, i = 0;
w <
patch.size(); ++
w) {
305 auto const& wire =
patch[
w];
306 for (
size_t d = 0;
d < wire.size(); ++
d, ++i) {
322 if ((wire >= marginW) && (wire <
fAlgView.
fNWires - marginW) && (scaledDrift >= marginD) &&
337 , fWireProducerLabel(config.WireLabel())
338 , fHitProducerLabel(config.HitLabel())
339 , fTrackModuleLabel(config.TrackLabel())
340 , fSimulationProducerLabel(config.SimulationLabel())
341 , fSimChannelProducerLabel(config.SimChannelLabel())
342 , fSaveVtxFlags(config.SaveVtxFlags())
343 , fAdcDelay(config.AdcDelayTicks())
344 , fEventsPerBin(100, 0)
367 w.resize(view.fNCachedDrifts);
373 w.resize(view.fNCachedDrifts);
382 std::vector<int>
const&
pdgs,
385 if ((wireIdx >=
fWireDriftEdep.size()) || (edeps.size() != pdgs.size())) {
return false; }
396 size_t i0 = i * dstep;
397 size_t i1 = (i + 1) * dstep;
402 float max_edep = edeps[i0];
403 for (
size_t k = i0 + 1;
k < i1; ++
k) {
415 best_pdg |= type_flags;
427 const TLorentzVector& tvec,
428 unsigned int plane)
const 437 double vtx[3] = {tvec.X(), tvec.Y(), tvec.Z()};
440 unsigned int tpc = tpcid.
TPC, cryo = tpcid.
Cryostat;
445 if (driftDir == 1) { dx *= -1; }
446 else if (driftDir != -1) {
449 vtx[0] = tvec.X() + dx;
459 <<
"Vertex projection out of wire planes, just skipping this vertex.";
462 mf::LogWarning(
"TrainingDataAlg") <<
"Vertex projection out of wire planes, skip MC vertex.";
471 const std::unordered_map<int, const simb::MCParticle*>& particleMap)
const 473 const float minElectronLength2 = 2.5 * 2.5;
474 const float maxDeltaLength2 = 0.15 * 0.15;
477 if (pdg != 11)
return false;
480 for (
size_t d = 0;
d < nSec; ++
d) {
481 auto d_search = particleMap.find(particle.
Daughter(
d));
482 if (d_search != particleMap.end()) {
483 auto const& daughter = *((*d_search).second);
484 int d_pdg =
abs(daughter.PdgCode());
485 if (d_pdg != 22) {
return false; }
489 float trkLength2 = 0;
490 auto const*
p = &particle;
491 bool branching =
false;
494 auto m_search = particleMap.find(
p->Mother());
495 if (m_search != particleMap.end()) {
496 p = (*m_search).second;
497 int m_pdg =
abs(
p->PdgCode());
499 nSec =
p->NumberDaughters();
501 for (
size_t d = 0;
d < nSec; ++
d) {
502 auto d_search = particleMap.find(
p->Daughter(
d));
503 if (d_search != particleMap.end()) {
504 auto const& daughter = *((*d_search).second);
505 int d_pdg =
abs(daughter.PdgCode());
511 if (ne > 1) { branching =
true; }
520 return (trkLength2 > minElectronLength2);
526 const std::unordered_map<int, const simb::MCParticle*>& particleMap)
const 528 bool hasElectron =
false, hasNuMu =
false, hasNuE =
false;
532 if ((pdg == 13) && (particle.
EndProcess() ==
"FastScintillation" || particle.
EndProcess() ==
"Decay"))
535 for (
size_t d = 0;
d < nSec; ++
d) {
536 auto d_search = particleMap.find(particle.
Daughter(
d));
537 if (d_search != particleMap.end()) {
538 auto const& daughter = *((*d_search).second);
539 int d_pdg =
abs(daughter.PdgCode());
542 else if (d_pdg == 14)
544 else if (d_pdg == 12)
550 return (hasElectron && hasNuMu && hasNuE);
555 std::unordered_map<
size_t, std::unordered_map<int, int>>& wireToDriftToVtxFlags,
558 const std::unordered_map<int, const simb::MCParticle*>& particleMap,
559 unsigned int plane)
const 561 for (
auto const&
p : particleMap) {
562 auto const& particle = *
p.second;
564 double ekStart = 1000. * (particle.E() - particle.Mass());
565 double ekEnd = 1000. * (particle.EndE() - particle.Mass());
566 int pdg =
abs(particle.PdgCode());
572 if ((particle.EndProcess() ==
"conv") && (ekStart > 40.0))
593 if (ekStart > 50.0) {
594 if (particle.Mother() != 0) {
595 auto search = particleMap.find(particle.Mother());
596 if (
search != particleMap.end()) {
597 auto const& mother = *((*search).second);
598 int m_pdg =
abs(mother.PdgCode());
599 unsigned int nSec = mother.NumberDaughters();
600 unsigned int nVisible = 0;
602 for (
size_t d = 0;
d < nSec; ++
d) {
603 auto d_search = particleMap.find(mother.Daughter(
d));
604 if (d_search != particleMap.end()) {
605 auto const& daughter = *((*d_search).second);
606 int d_pdg =
abs(daughter.PdgCode());
607 if (((d_pdg == 2212) || (d_pdg == 211) || (d_pdg == 321)) &&
608 (1000. * (daughter.E() - daughter.Mass()) > 50.0)) {
617 if (((m_pdg != pdg) && (m_pdg != 2112)) || ((m_pdg != 2112) && (nVisible > 0)) ||
618 ((m_pdg == 2112) && (nVisible > 1))) {
624 if (particle.EndProcess() ==
"FastScintillation")
626 unsigned int nSec = particle.NumberDaughters();
627 for (
size_t d = 0;
d < nSec; ++
d) {
628 auto d_search = particleMap.find(particle.Daughter(
d));
629 if (d_search != particleMap.end()) {
630 auto const& daughter = *((*d_search).second);
631 int d_pdg =
abs(daughter.PdgCode());
632 if ((pdg == 321) && (d_pdg == 13)) {
636 if ((pdg == 211) && (d_pdg == 13)) {
644 if ((particle.EndProcess() ==
"Decay") && (ekEnd > 200.0))
646 unsigned int nSec = particle.NumberDaughters();
647 for (
size_t d = 0;
d < nSec; ++
d) {
648 auto d_search = particleMap.find(particle.Daughter(
d));
649 if (d_search != particleMap.end()) {
650 auto const& daughter = *((*d_search).second);
651 int d_pdg =
abs(daughter.PdgCode());
652 if ((pdg == 321) && (d_pdg == 13)) {
656 if ((pdg == 211) && (d_pdg == 13)) {
672 auto wd =
getProjection(clockData, detProp, particle.Position(), plane);
674 if ((wd.TPC ==
TPC()) && (wd.Cryo ==
Cryo())) {
675 wireToDriftToVtxFlags[wd.Wire][wd.Drift] |= flagsStart;
679 auto wd =
getProjection(clockData, detProp, particle.EndPosition(), plane);
680 if ((wd.TPC ==
TPC()) && (wd.Cryo ==
Cryo())) {
681 wireToDriftToVtxFlags[wd.Wire][wd.Drift] |= flagsEnd;
686 if (pdg == 321 || pdg == 211 || pdg == 2212) {
689 if (thisTrajectoryProcessMap1.size()) {
690 for (
auto const& couple1 : thisTrajectoryProcessMap1) {
691 if ((truetraj.
KeyToProcess(couple1.second)).find(
"Elastic") != std::string::npos) {
692 auto wd =
getProjection(clockData, detProp, truetraj.
at(couple1.first).first, plane);
693 if ((wd.TPC ==
TPC()) && (wd.Cryo ==
Cryo())) {
697 if ((truetraj.
KeyToProcess(couple1.second)).find(
"Inelastic") != std::string::npos) {
698 auto wd =
getProjection(clockData, detProp, truetraj.
at(couple1.first).first, plane);
699 if ((wd.TPC ==
TPC()) && (wd.Cryo ==
Cryo())) {
720 std::vector<art::Ptr<recob::Wire>> Wirelist;
725 mf::LogError(
"TrainingDataAlg") <<
"Wire data not set.";
731 std::vector<art::Ptr<recob::Hit>> Hitlist;
737 std::vector<art::Ptr<recob::Track>> Tracklist;
745 for (
size_t widx = 0; widx < 240; ++widx) {
751 for (
size_t subwidx = 0; subwidx < Wirelist.size(); ++subwidx) {
752 if (widx + 240 == Wirelist[subwidx]->Channel()) {
753 labels_deposit = Wirelist[subwidx]->Signal();
769 for (
size_t iHit = 0; iHit < Hitlist.size(); ++iHit) {
771 if (Hitlist[iHit]->Channel() != widx + 240) {
continue; }
772 if (Hitlist[iHit]->
View() != 1) {
continue; }
775 if (ass_trk_hits.at(iHit).size() == 0) {
continue; }
780 if (ass_trk_hits.at(iHit)[0]->Length() < 5) {
continue; }
786 for (
size_t jHit = 0; jHit < Hitlist.size(); ++jHit) {
787 if (jHit == iHit) {
continue; }
788 if (Hitlist[jHit]->
View() != 1) {
continue; }
790 if (ass_trk_hits.at(jHit).size() == 0) {
continue; }
791 if (ass_trk_hits.at(jHit)[0]->ID() != ass_trk_hits.at(iHit)[0]->ID()) {
continue; }
793 double dist = sqrt((Hitlist[iHit]->Channel() - Hitlist[jHit]->Channel()) *
794 (Hitlist[iHit]->Channel() - Hitlist[jHit]->Channel()) +
795 (Hitlist[iHit]->PeakTime() - Hitlist[jHit]->PeakTime()) *
796 (Hitlist[iHit]->PeakTime() - Hitlist[jHit]->PeakTime()));
798 if (far_dist < dist) {
808 for (
size_t jHit = 0; jHit < Hitlist.size(); ++jHit) {
809 if (jHit == iHit or
int(jHit) == far_index) {
continue; }
810 if (Hitlist[jHit]->
View() != 1) {
continue; }
812 if (ass_trk_hits.at(jHit).size() == 0) {
continue; }
813 if (ass_trk_hits.at(jHit)[0]->ID() != ass_trk_hits.at(iHit)[0]->ID()) {
continue; }
815 double dist = sqrt((Hitlist[far_index]->Channel() - Hitlist[jHit]->Channel()) *
816 (Hitlist[far_index]->Channel() - Hitlist[jHit]->Channel()) +
817 (Hitlist[far_index]->PeakTime() - Hitlist[jHit]->PeakTime()) *
818 (Hitlist[far_index]->PeakTime() - Hitlist[jHit]->PeakTime()));
820 if (other_dist < dist) {
827 double del_wire = double(Hitlist[other_end]->Channel() - Hitlist[far_index]->Channel());
828 double del_time = double(Hitlist[other_end]->PeakTime() - Hitlist[far_index]->PeakTime());
829 double hypo = sqrt(del_wire * del_wire + del_time * del_time);
831 if (hypo == 0) {
continue; }
833 double cosser = TMath::Abs(del_wire / hypo);
834 double norm_ang = TMath::ACos(cosser) * 2 / TMath::Pi();
848 labels_pdg[Hitlist[iHit]->PeakTime()] = 211;
870 mf::LogError(
"TrainingDataAlg") <<
"Wire data not set.";
875 mf::LogInfo(
"TrainingDataAlg") <<
"Skip MC simulation info.";
882 auto particleHandle =
885 auto simChannelHandle =
888 std::unordered_map<int, const simb::MCParticle*> particleMap;
889 for (
auto const& particle : *particleHandle) {
890 particleMap[particle.TrackId()] = &particle;
893 std::unordered_map<size_t, std::unordered_map<int, int>> wireToDriftToVtxFlags;
898 std::map<int, int> trackToPDG;
904 std::vector<int> labels_pdg(labels_deposit.size(), 0);
905 int labels_size = labels_deposit.size();
907 std::map<int, std::map<int, double>> timeToTrackToCharge;
908 for (
auto const&
channel : *simChannelHandle) {
909 if (
channel.Channel() != wireChannelNumber)
continue;
911 auto const& timeSlices =
channel.TDCIDEMap();
912 for (
auto const& timeSlice : timeSlices) {
913 int time = timeSlice.first;
915 auto const& energyDeposits = timeSlice.second;
916 for (
auto const& energyDeposit : energyDeposits) {
918 int tid = energyDeposit.trackID;
924 auto search = particleMap.find(tid);
925 if (
search == particleMap.end()) {
929 auto const& mother = *((*search).second);
930 int mPdg =
abs(mother.PdgCode());
931 if ((mPdg == 13) || (mPdg == 211) || (mPdg == 2212)) {
932 if (energyDeposit.numElectrons > 10)
937 auto search = particleMap.find(tid);
938 if (
search == particleMap.end()) {
942 auto const& particle = *((*search).second);
943 pdg =
abs(particle.PdgCode());
945 if (particle.Process() ==
"primary") {
949 else if (pdg == 13) {
968 if (particle.Process() ==
"Decay"){
971 else if (particle.Process() ==
"muIoni"){
977 trackToPDG[energyDeposit.trackID] =
pdg;
979 double energy = energyDeposit.numElectrons * electronsToGeV;
980 timeToTrackToCharge[time][energyDeposit.trackID] +=
energy;
988 for (
auto const& ttc : timeToTrackToCharge) {
989 float max_deposit = 0.0;
991 for (
auto const& tc : ttc.second) {
993 if (tc.second > max_deposit) {
994 max_deposit = tc.second;
995 max_pdg = trackToPDG[tc.first];
999 if (ttc.first < labels_size) {
1001 if (tick_idx < labels_size) {
1002 labels_deposit[tick_idx] = max_deposit;
1003 labels_pdg[tick_idx] = max_pdg & type_pdg_mask;
1008 for (
auto const& drift_flags : wireToDriftToVtxFlags[widx]) {
1009 int drift = drift_flags.first, flags = drift_flags.second;
1010 if ((drift >= 0) && (drift < labels_size)) { labels_pdg[drift] |= flags; }
1024 unsigned int& d1)
const 1028 float max_cut = 0.25 * max_e_cut;
1055 for (
size_t i = w0; i < w1; ++i)
1065 for (
size_t i = w0; i < w1; ++i)
1074 unsigned int margin = 20;
1075 if ((w1 - w0 > 8) && (d1 - d0 > 8)) {
bool isInsideFiducialRegion(unsigned int wire, float drift) const
void collectVtxFlags(std::unordered_map< size_t, std::unordered_map< int, int >> &wireToDriftToVtxFlags, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const std::unordered_map< int, const simb::MCParticle * > &particleMap, unsigned int plane) const
Store parameters for running LArG4.
geo::GeometryCore const * fGeometry
bool setWireEdepsAndLabels(std::vector< float > const &edeps, std::vector< int > const &pdgs, size_t wireIdx)
unsigned int fNCachedDrifts
bool isMuonDecaying(const simb::MCParticle &particle, const std::unordered_map< int, const simb::MCParticle * > &particleMap) const
static constexpr double g
std::vector< std::vector< float > > Run(std::vector< std::vector< std::vector< float >>> const &inps, int samples=-1) override
std::vector< std::vector< float > > fWireDriftPatch
bool setDataEventData(const art::Event &event, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, unsigned int plane, unsigned int tpc, unsigned int cryo)
AdcChannelData::View View
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
art::InputTag fTrackModuleLabel
virtual DataProviderAlgView resizeView(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, size_t wires, size_t drifts)
const value_type & at(const size_type i) const
bool setEventData(const art::Event &event, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, unsigned int plane, unsigned int tpc, unsigned int cryo)
bool bufferPatch(size_t wire, float drift, std::vector< std::vector< float >> &patch) const
bool isValid
Whether this ID points to a valid element.
std::string KeyToProcess(unsigned char const &key) const
virtual void set_data(std::vector< std::vector< std::vector< float > > > const &)
CryostatID_t Cryostat
Index of cryostat.
DataProviderAlg(const fhicl::ParameterSet &pset)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
WireDrift getProjection(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TLorentzVector &tvec, unsigned int plane) const
std::vector< float > compute_output(keras::DataChunk *dc)
std::vector< std::string > fNNetOutputs
bool isCurrentPatch(unsigned int wire, float drift) const
int NumberDaughters() const
int Daughter(const int i) const
art::InputTag fWireProducerLabel
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
bool isElectronEnd(const simb::MCParticle &particle, const std::unordered_map< int, const simb::MCParticle * > &particleMap) const
std::vector< float > predictIdVector(unsigned int wire, float drift) const
calculate multi-class probabilities for [wire, drift] point
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
std::string EndProcess() const
fhicl::Sequence< std::string > NNetOutputs
Collection of exceptions for Geometry system.
unsigned int fNScaledDrifts
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
std::vector< raw::ChannelID_t > fWireChannels
virtual std::vector< float > Run(std::vector< std::vector< float >> const &inp2d)=0
std::vector< size_t > fEventsPerBin
double ConvertXToTicks(double X, int p, int t, int c) const
KerasModelInterface(const char *modelFileName)
art::InputTag fSimChannelProducerLabel
bool findCrop(float max_e_cut, unsigned int &w0, unsigned int &w1, unsigned int &d0, unsigned int &d1) const
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
The data type to uniquely identify a TPC.
std::vector< float > Run(std::vector< std::vector< float >> const &inp2d) override
ProcessMap const & TrajectoryProcesses() const
DataProviderAlgView fAlgView
static std::unique_ptr< Graph > create(const char *graph_file_name, const std::vector< std::string > &outputs={}, int ninputs=1, int noutputs=1)
std::vector< std::vector< int > > fWireDriftPdg
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
bool setWireDriftData(const detinfo::DetectorClocksData &clock_data, const detinfo::DetectorPropertiesData &det_prop, const std::vector< recob::Wire > &wires, unsigned int plane, unsigned int tpc, unsigned int cryo)
fhicl::Atom< std::string > NNetModelFile
~TrainingDataAlg() override
TfModelInterface(const char *modelFileName)
std::vector< std::vector< float > > fWireDriftEdep
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
std::string findFile(const char *fileName) const
short int DetectDriftDirection() const
Returns the expected drift direction based on geometry.
unsigned int Cryo() const
Pool sum of pixels in a patch around the wire/drift pixel.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
static float particleRange2(const simb::MCParticle &particle)
img::DataProviderAlgView resizeView(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, size_t wires, size_t drifts) override
size_t fCurrentScaledDrift
std::string find_file(std::string const &filename) const
Interface for experiment-specific channel quality info provider.
nnet::ModelInterface * fNNet
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
Exception thrown on invalid wire number (e.g. NearestWireID())
art::InputTag fSimulationProducerLabel
std::string fNNetModelFilePath
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
TPCID_t TPC
Index of the TPC within its cryostat.
Interface for experiment-specific service for channel quality info.
bool isSamePatch(unsigned int wire1, float drift1, unsigned int wire2, float drift2) const
test if two wire/drift coordinates point to the same patch
Interface to algorithm class for a specific detector channel mapping.
std::vector< std::vector< float > > predictIdVectors(std::vector< std::pair< unsigned int, float >> points) const
art::InputTag fHitProducerLabel
double GeVToElectrons() const
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
Event finding and building.
TrainingDataAlg(const fhicl::ParameterSet &pset)
float predictIdValue(unsigned int wire, float drift, size_t outIdx=0) const
calculate single-value prediction (2-class probability) for [wire, drift] point
PointIdAlg(const fhicl::ParameterSet &pset)
static std::vector< float > flattenData2D(std::vector< std::vector< float >> const &patch)