25 #include "delaunator.hpp" 26 #include <torch/script.h> 43 template <
typename T,
typename A>
44 int arg_max(std::vector<T, A>
const& vec)
46 return static_cast<int>(std::distance(vec.begin(), max_element(vec.begin(), vec.end())));
49 template <
typename T,
size_t N>
50 void softmax(std::array<T, N>& arr)
52 T m = -std::numeric_limits<T>::max();
53 for (
size_t i = 0; i < arr.size(); i++) {
54 if (arr[i] > m) { m = arr[i]; }
57 for (
size_t i = 0; i < arr.size(); i++) {
58 sum += expf(arr[i] - m);
60 T offset = m + logf(sum);
61 for (
size_t i = 0; i < arr.size(); i++) {
62 arr[i] = expf(arr[i] - offset);
87 vector<vector<float>>
avgs;
88 vector<vector<float>>
devs;
92 torch::jit::script::Module
model;
97 ,
planes(p.get<vector<std::string>>(
"planes"))
100 ,
minHits(p.get<
size_t>(
"minHits"))
101 ,
debug(p.get<
bool>(
"debug"))
107 for (
size_t ip = 0; ip <
planes.size(); ++ip) {
108 avgs.push_back(p.get<vector<float>>(
"avgs_" +
planes[ip]));
109 devs.push_back(p.get<vector<float>>(
"devs_" +
planes[ip]));
112 if (
filterDecoder) { produces<vector<FeatureVector<1>>>(
"filter"); }
115 produces<vector<FeatureVector<5>>>(
"semantic");
116 produces<MVADescription<5>>(
"semantic");
119 if (
vertexDecoder) { produces<vector<recob::Vertex>>(
"vertex"); }
121 cet::search_path sp(
"FW_SEARCH_PATH");
122 model = torch::jit::load(sp.find_file(p.get<std::string>(
"modelFileName")));
129 vector<art::Ptr<Hit>> hitlist;
132 std::unique_ptr<vector<FeatureVector<1>>> filtcol(
136 hitlist.size(),
FeatureVector<5>(std::array<float, 5>({-1., -1., -1., -1., -1.}))));
137 std::unique_ptr<MVADescription<5>> semtdes(
140 {
"MIP",
"HIP",
"shower",
"michel",
"diffuse"}));
142 std::unique_ptr<vector<recob::Vertex>> vertcol(
new vector<recob::Vertex>());
144 if (
debug) std::cout <<
"Hits size=" << hitlist.size() << std::endl;
145 if (hitlist.size() <
minHits) {
148 e.
put(std::move(semtcol),
"semantic");
149 e.
put(std::move(semtdes),
"semantic");
155 vector<vector<float>> nodeft_bare(
planes.size(), vector<float>());
156 vector<vector<float>> nodeft(
planes.size(), vector<float>());
157 vector<vector<double>> coords(
planes.size(), vector<double>());
158 vector<vector<size_t>> idsmap(
planes.size(), vector<size_t>());
159 vector<size_t> idsmapRev(hitlist.size(), hitlist.size());
160 for (
auto h : hitlist) {
161 idsmap[h->View()].push_back(h.key());
162 idsmapRev[h.key()] = idsmap[h->View()].size() - 1;
163 coords[h->View()].push_back(h->PeakTime() * 0.055);
164 coords[h->View()].push_back(h->WireID().Wire * 0.3);
165 nodeft[h->View()].push_back((h->WireID().Wire * 0.3 -
avgs[h->View()][0]) /
devs[h->View()][0]);
166 nodeft[h->View()].push_back((h->PeakTime() * 0.055 -
avgs[h->View()][1]) /
devs[h->View()][1]);
167 nodeft[h->View()].push_back((h->Integral() -
avgs[h->View()][2]) /
devs[h->View()][2]);
168 nodeft[h->View()].push_back((h->RMS() -
avgs[h->View()][3]) /
devs[h->View()][3]);
169 nodeft_bare[h->View()].push_back(h->WireID().Wire * 0.3);
170 nodeft_bare[h->View()].push_back(h->PeakTime() * 0.055);
171 nodeft_bare[h->View()].push_back(h->Integral());
172 nodeft_bare[h->View()].push_back(h->RMS());
180 if (this->n1 == other.n1 && this->n2 == other.n2)
186 vector<vector<Edge>> edge2d(
planes.size(), vector<Edge>());
187 for (
size_t p = 0; p <
planes.size(); p++) {
188 if (
debug) std::cout <<
"Plane " << p <<
" has N hits=" << coords[p].size() / 2 << std::endl;
189 if (coords[p].
size() / 2 < 3)
continue;
190 delaunator::Delaunator
d(coords[p]);
191 if (
debug) std::cout <<
"Found N triangles=" << d.triangles.size() / 3 << std::endl;
192 for (std::size_t i = 0; i < d.triangles.size(); i += 3) {
195 e.n1 = d.triangles[i];
196 e.n2 = d.triangles[i + 1];
197 edge2d[p].push_back(e);
198 e.n1 = d.triangles[i + 1];
199 e.n2 = d.triangles[i];
200 edge2d[p].push_back(e);
202 e.n1 = d.triangles[i];
203 e.n2 = d.triangles[i + 2];
204 edge2d[p].push_back(e);
205 e.n1 = d.triangles[i + 2];
206 e.n2 = d.triangles[i];
207 edge2d[p].push_back(e);
209 e.n1 = d.triangles[i + 1];
210 e.n2 = d.triangles[i + 2];
211 edge2d[p].push_back(e);
212 e.n1 = d.triangles[i + 2];
213 e.n2 = d.triangles[i + 1];
214 edge2d[p].push_back(e);
218 std::sort(edge2d[p].
begin(), edge2d[p].
end(), [](
const auto& i,
const auto& j) {
219 return (i.n1 != j.n1 ? i.n1 < j.n1 : i.n2 < j.n2);
222 for (
auto& e : edge2d[p]) {
223 std::cout <<
"sorted plane=" << p <<
" e1=" << e.n1 <<
" e2=" << e.n2 << std::endl;
226 edge2d[p].erase(std::unique(edge2d[p].
begin(), edge2d[p].
end()), edge2d[p].
end());
230 for (
size_t p = 0; p <
planes.size(); p++) {
231 for (
auto& e : edge2d[p]) {
232 std::cout <<
" plane=" << p <<
" e1=" << e.n1 <<
" e2=" << e.n2 << std::endl;
239 vector<art::Ptr<SpacePoint>> splist;
242 vector<vector<art::Ptr<Hit>>> sp2Hit(splist.size());
243 if (splist.size() > 0) {
245 for (
size_t spIdx = 0; spIdx < sp2Hit.size(); ++spIdx) {
246 sp2Hit[spIdx] = fmp.at(spIdx);
252 vector<vector<Edge>> edge3d(
planes.size(), vector<Edge>());
253 for (
size_t i = 0; i < splist.size(); ++i) {
254 for (
size_t j = 0; j < sp2Hit[i].size(); ++j) {
256 e.n1 = idsmapRev[sp2Hit[i][j].key()];
258 edge3d[sp2Hit[i][j]->View()].push_back(e);
262 auto x = torch::Dict<std::string, torch::Tensor>();
263 auto batch = torch::Dict<std::string, torch::Tensor>();
264 for (
size_t p = 0; p <
planes.size(); p++) {
265 long int dim = nodeft[p].size() / 4;
266 torch::Tensor ix = torch::zeros({dim, 4}, torch::dtype(torch::kFloat32));
268 std::cout <<
"plane=" << p << std::endl;
269 std::cout << std::fixed;
270 std::cout << std::setprecision(4);
271 std::cout <<
"before, plane=" <<
planes[p] << std::endl;
272 for (
size_t n = 0;
n < nodeft_bare[p].size();
n =
n + 4) {
273 std::cout << nodeft_bare[p][
n] <<
" " << nodeft_bare[p][
n + 1] <<
" " 274 << nodeft_bare[p][
n + 2] <<
" " << nodeft_bare[p][
n + 3] <<
" " << std::endl;
276 std::cout << std::scientific;
277 std::cout <<
"after, plane=" <<
planes[p] << std::endl;
278 for (
size_t n = 0;
n < nodeft[p].size();
n =
n + 4) {
279 std::cout << nodeft[p][
n] <<
" " << nodeft[p][
n + 1] <<
" " << nodeft[p][
n + 2] <<
" " 280 << nodeft[p][
n + 3] <<
" " << std::endl;
283 for (
size_t n = 0;
n < nodeft[p].size();
n =
n + 4) {
284 ix[
n / 4][0] = nodeft[p][
n];
285 ix[
n / 4][1] = nodeft[p][
n + 1];
286 ix[
n / 4][2] = nodeft[p][
n + 2];
287 ix[
n / 4][3] = nodeft[p][
n + 3];
290 torch::Tensor ib = torch::zeros({dim}, torch::dtype(torch::kInt64));
291 batch.insert(
planes[p], ib);
294 auto edge_index_plane = torch::Dict<std::string, torch::Tensor>();
295 for (
size_t p = 0; p <
planes.size(); p++) {
296 long int dim = edge2d[p].size();
297 torch::Tensor ix = torch::zeros({2, dim}, torch::dtype(torch::kInt64));
298 for (
size_t n = 0;
n < edge2d[p].size();
n++) {
299 ix[0][
n] = int(edge2d[p][
n].n1);
300 ix[1][
n] = int(edge2d[p][
n].n2);
302 edge_index_plane.insert(
planes[p], ix);
304 std::cout <<
"plane=" << p << std::endl;
305 std::cout <<
"2d edge size=" << edge2d[p].size() << std::endl;
306 for (
size_t n = 0;
n < edge2d[p].size();
n++) {
307 std::cout << edge2d[p][
n].n1 <<
" ";
309 std::cout << std::endl;
310 for (
size_t n = 0;
n < edge2d[p].size();
n++) {
311 std::cout << edge2d[p][
n].n2 <<
" ";
313 std::cout << std::endl;
317 auto edge_index_nexus = torch::Dict<std::string, torch::Tensor>();
318 for (
size_t p = 0; p <
planes.size(); p++) {
319 long int dim = edge3d[p].size();
320 torch::Tensor ix = torch::zeros({2, dim}, torch::dtype(torch::kInt64));
321 for (
size_t n = 0;
n < edge3d[p].size();
n++) {
322 ix[0][
n] = int(edge3d[p][
n].n1);
323 ix[1][
n] = int(edge3d[p][
n].n2);
325 edge_index_nexus.insert(
planes[p], ix);
327 std::cout <<
"plane=" << p << std::endl;
328 std::cout <<
"3d edge size=" << edge3d[p].size() << std::endl;
329 for (
size_t n = 0;
n < edge3d[p].size();
n++) {
330 std::cout << edge3d[p][
n].n1 <<
" ";
332 std::cout << std::endl;
333 for (
size_t n = 0;
n < edge3d[p].size();
n++) {
334 std::cout << edge3d[p][
n].n2 <<
" ";
336 std::cout << std::endl;
340 long int spdim = splist.size();
341 auto nexus =
torch::empty({spdim, 0}, torch::dtype(torch::kFloat32));
343 std::vector<torch::jit::IValue> inputs;
345 inputs.push_back(edge_index_plane);
346 inputs.push_back(edge_index_nexus);
347 inputs.push_back(nexus);
348 inputs.push_back(batch);
349 if (
debug) std::cout <<
"FORWARD!" << std::endl;
350 auto outputs =
model.forward(inputs).toGenericDict();
351 if (
debug) std::cout <<
"output =" << outputs << std::endl;
353 for (
size_t p = 0; p <
planes.size(); p++) {
354 torch::Tensor s = outputs.at(
"x_semantic").toGenericDict().at(
planes[p]).toTensor();
355 for (
int i = 0; i < s.sizes()[0]; ++i) {
356 size_t idx = idsmap[p][i];
357 std::array<float, 5> input({s[i][0].item<
float>(),
358 s[i][1].item<float>(),
359 s[i][2].item<
float>(),
360 s[i][3].item<float>(),
361 s[i][4].item<
float>()});
364 (*semtcol)[idx] = semt;
367 for (
int j = 0; j < 5; j++) {
368 std::cout <<
"x_semantic category=" << j <<
" : ";
369 for (
size_t p = 0; p <
planes.size(); p++) {
370 torch::Tensor s = outputs.
at(
"x_semantic").toGenericDict().at(
planes[p]).toTensor();
371 for (
int i = 0; i < s.sizes()[0]; ++i)
372 std::cout << s[i][j].item<float>() <<
", ";
374 std::cout << std::endl;
380 for (
size_t p = 0; p <
planes.size(); p++) {
381 torch::Tensor
f = outputs.at(
"x_filter").toGenericDict().at(
planes[p]).toTensor();
382 for (
int i = 0; i < f.numel(); ++i) {
383 size_t idx = idsmap[p][i];
384 std::array<float, 1> input({f[i].item<
float>()});
389 std::cout <<
"x_filter : ";
390 for (
size_t p = 0; p <
planes.size(); p++) {
391 torch::Tensor
f = outputs.at(
"x_filter").toGenericDict().at(
planes[p]).toTensor();
392 for (
int i = 0; i < f.numel(); ++i)
393 std::cout << f[i].item<float>() <<
", ";
395 std::cout << std::endl;
399 torch::Tensor v = outputs.at(
"x_vtx").toGenericDict().at(
"evt").toTensor()[0];
401 vpos[0] = v[0].item<
float>();
402 vpos[1] = v[1].item<
float>();
403 vpos[2] = v[2].item<
float>();
409 e.
put(std::move(semtcol),
"semantic");
410 e.
put(std::move(semtdes),
"semantic");
NuGraphInference & operator=(NuGraphInference const &)=delete
torch::jit::script::Module model
Declaration of signal hit object.
EDProducer(fhicl::ParameterSet const &pset)
vector< std::string > planes
boost::graph_traits< ModuleGraph >::edge_descriptor Edge
void produce(art::Event &e) override
Definition of vertex object for LArSoft.
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
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.
auto array(Array const &a)
Returns a manipulator which will print the specified array.
#define DEFINE_ART_MODULE(klass)
Provenance const * provenance() const
vector< vector< float > > devs
vector< vector< float > > avgs
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
float at(size_t index) const
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
NuGraphInference(fhicl::ParameterSet const &p)
2D representation of charge deposited in the TDC/wire plane
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.