All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MuonTrackProducer_module.cc
Go to the documentation of this file.
1 // Framework includes
2 #include "art/Framework/Core/EDProducer.h"
3 #include "art/Framework/Core/ModuleMacros.h"
4 #include "art/Framework/Principal/Event.h"
5 #include "fhiclcpp/ParameterSet.h"
6 #include "art/Framework/Principal/Handle.h"
7 #include "canvas/Persistency/Common/Ptr.h"
8 #include "canvas/Persistency/Common/PtrVector.h"
9 #include "art/Framework/Services/Registry/ServiceHandle.h"
10 #include "art_root_io/TFileService.h"
11 #include "messagefacility/MessageLogger/MessageLogger.h"
12 
13 // LArSoft includes
15 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
24 #include "lardataobj/RawData/raw.h"
26 
27 
28 // SBN/SBND includes
30 
31 // ROOT includes
32 #include "TRandom3.h"
33 
34 // C++ includes
35 #include <vector>
36 #include <algorithm>
37 #include <stdlib.h>
38 #include <math.h>
39 #include <vector>
40 #include <iostream>
41 #include <cmath>
42 #include <bitset>
43 #include <memory>
44 
45 using std::vector;
46 
47 class MuonTrackProducer: public art::EDProducer {
48 public:
49  // The destructor generated by the compiler is fine for classes
50  // without bare pointers or other resource use.
51 
52  // Plugins should not be copied or assigned.
53  explicit MuonTrackProducer(fhicl::ParameterSet const & p);
54  MuonTrackProducer(MuonTrackProducer const &) = delete;
58 
59  // Required functions.
60  void produce(art::Event & evt) override;
61  void reconfigure(fhicl::ParameterSet const & p);
62 
63 private:
64  // Define functions
65  // Resets hit information for collection plane
66  void ResetCollectionHitVectors(int n);
67  // Resets hit information for induction planes
68  void ResetInductionHitVectors(int n);
69  // Resets variables for AC Crossing muons
70  void ResetMuonVariables(int n);
71  // Finds distance between two points
72  float Distance(int x1, int y1, int x2, int y2);
73  // Performs Hough Transform for collection planes
74  void Hough(vector<vector<int>> coords, vector<int> param, bool save_hits, int nentry,
75  vector<vector<int>>& lines, vector<vector<int>>& hit_idx);
76  // Finds t0, stores them in a vector<vector<double>>
77  void FindEndpoints(vector<vector<int>>& lines_col, vector<vector<int>>& lines_ind, vector<vector<int>>& hit_idx,
78  int range, vector<art::Ptr<recob::Hit>> hitlist,
79  vector<vector<geo::Point_t>>& muon_endpoints, vector<vector<int>>& muon_hitpeakT, vector<vector<int>>& muon_hit_idx);
80  // Fixes endpoints, returns true if conditions are fulfilled
81  bool FixEndpoints(geo::WireID wire_col, geo::WireID wire_ind, geo::Point_t& point);
82  // Sorts endpoints into categories
83  void SortEndpoints(vector<vector<geo::Point_t>>& muon_endpoints, vector<vector<int>> muon_hitpeakT, vector<int>& muon_type);
84  // Finds trajectories, stores them in a vector<vector<double>>
85  void Findt0(vector<vector<int>> muon_hitpeakT, vector<int> muon_type, vector<double>& muon_t0);
86  // Finds endpoints, stores them in a vector<vector<geo::Point_t>>
87  void FindTrajectories(vector<vector<geo::Point_t>> muon_endpoints, vector<vector<int>> muon_hitpeakT,
88  vector<vector<double>>& muon_trajectories);
89 
90  void PrintHoughLines(vector<vector<int>>& lines, int plane);
91 
92  // Define variables
93  int nhits;
94 
95  vector<vector<int>> hit_02, hit_12;
96  vector<vector<int>> lines_02, lines_12;
97  vector<vector<int>> hit_idx_02, hit_idx_12;
98 
99  vector<vector<int>> hit_00, hit_01, hit_10, hit_11;
100  vector<vector<int>> lines_00, lines_01, lines_10, lines_11;
101 
102  vector<int> muon_tpc, muon_type;
103  vector<double> muon_t0;
104  vector<vector<geo::Point_t>> muon_endpoints;
105  vector<vector<int>> muon_hitpeakT, muon_hit_idx;
106  vector<vector<double>> muon_trajectories;
107 
108  // parameters from the fcl file
109  std::string fHitsModuleLabel;
110  int fHoughThreshold; // threshold to pass in Hough accumulator
111  int fHoughMaxGap; // maximum gap between last identified point on line and data point (flexibility in end point search)
112  int fHoughRange; // range between expected value for point on line and actual (flexibility in line point identification)
113  int fHoughMinLength; // minimum length of track (distance between endpoints), will only be used if fHoughMuonLength == 0
114  int fHoughMuonLength; // minimum change in hit_peakT (x pos); useful to do quick cut for AC-crossing muons, set to 0 otherwise
115  int fEndpointRange; // range between expected value and given value for hit_peakT matching in 3D endpoint function
116  std::vector<int> fKeepMuonTypes = {0, 1, 2, 3, 4, 5};
117  // [ac crossing, anode, cathode, top-bottom, up-downstream, other], define in fcl
118 
119  int fLineCount; // number of estimated hit lines/muon tracks
120 
121  // services
122  art::ServiceHandle<art::TFileService> tfs;
124 
125 }; // class MuonTrackProducer
126 
127 MuonTrackProducer::MuonTrackProducer(fhicl::ParameterSet const & p)
128  : EDProducer(p)
129 {
130  produces< std::vector<sbnd::comm::MuonTrack> >();
131  produces< art::Assns<recob::Hit, sbnd::comm::MuonTrack> >();
132 
133  fGeometryService = lar::providerFrom<geo::Geometry>();
134  this->reconfigure(p);
135 }
136 
137 // Constructor
138 void MuonTrackProducer::reconfigure(fhicl::ParameterSet const & p)
139 {
140  // Initialize member data here.
141  fHitsModuleLabel = p.get<std::string>("HitsModuleLabel");
142 
143  // Hough parameters
144  fHoughThreshold = p.get<int>("HoughThreshold",10);
145  fHoughMaxGap = p.get<int>("HoughMaxGap",30);
146  fHoughRange = p.get<int>("HoughRange",100);
147  fHoughMinLength = p.get<int>("HoughMinLength",500);
148  fHoughMuonLength = p.get<int>("HoughMuonLength",2500);
149 
150  // Muon function parameters
151  fEndpointRange = p.get<int>("EndpointRange",30);
152  fKeepMuonTypes = p.get<std::vector<int>>("KeepMuonTypes");
153 
154  // Reset function parameters
155  fLineCount = p.get<int>("LineCount",20);
156 
157 } // MuonTrackProducer()
158 
159 void MuonTrackProducer::produce(art::Event & evt)
160 {
161  std::unique_ptr<vector<sbnd::comm::MuonTrack>> muon_tracks(new vector<sbnd::comm::MuonTrack>);
162  std::unique_ptr<art::Assns<recob::Hit, sbnd::comm::MuonTrack>> muon_tracks_assn(new art::Assns<recob::Hit, sbnd::comm::MuonTrack>);
163 
164  int event = evt.id().event();
165  std::cout << "Processing event " << event << std::endl;
166  // get nhits
167  art::Handle<vector<recob::Hit>> hitListHandle;
168  vector<art::Ptr<recob::Hit>> hitlist;
169  if (evt.getByLabel(fHitsModuleLabel,hitListHandle)) {
170  art::fill_ptr_vector(hitlist, hitListHandle);
171  nhits = hitlist.size();
172  }
173  else {
174  std::cout << "Failed to get recob::Hit data product." << std::endl;
175  nhits = 0;
176  }
177 
178  // obtain collection hits, perform hough transform, obtain tracks, and save col track info
180 
181  for (int i = 0; i < nhits; ++i) {
182  geo::WireID wireid = hitlist[i]->WireID();
183  int hit_wire = int(wireid.Wire), hit_peakT = int(hitlist[i]->PeakTime()), hit_plane = wireid.Plane, hit_tpc = wireid.TPC;
184  if (hit_plane==2 && hit_peakT>0){ // if collection plane and only positive peakT
185  vector<int> v{hit_wire,hit_peakT,i};
186  if (hit_tpc==0)
187  hit_02.push_back(v);
188  else
189  hit_12.push_back(v);
190  }
191  } // end of nhit loop
192  hit_02.shrink_to_fit(); hit_12.shrink_to_fit();
193 
194  // perform hough transform
195  bool save_col_hits = true;
197  Hough(hit_02, HoughParam, save_col_hits, event, lines_02, hit_idx_02);
198  Hough(hit_12, HoughParam, save_col_hits, event, lines_12, hit_idx_12);
199 
200  bool muon_in_tpc0 = !(lines_02.empty()); // will be true if a muon was detected in tpc0
201  bool muon_in_tpc1 = !(lines_12.empty()); // will be true if a muon was detected in tpc1
202 
203  //find induction plane hits, tracks, and fill muon variables
206 
207  if (muon_in_tpc0 == true || muon_in_tpc1 == true){
208  for (int i = 0; i < nhits; ++i) {
209  geo::WireID wireid = hitlist[i]->WireID();
210  int hit_wire = int(wireid.Wire), hit_peakT = int(hitlist[i]->PeakTime()), hit_tpc = wireid.TPC, hit_plane = wireid.Plane;
211  vector<int> v{hit_wire,hit_peakT,i};
212  if (muon_in_tpc0 == true){ //if ac muon was found in tpc0
213  if (hit_plane==0 && hit_tpc==0 && hit_peakT>0)
214  hit_00.push_back(v);
215  else if (hit_plane==1 && hit_tpc==0 && hit_peakT>0)
216  hit_01.push_back(v);
217  }
218  if (muon_in_tpc1 == true){ // if ac muon was found in tpc 1
219  if (hit_plane==0 && hit_tpc==1 && hit_peakT>0)
220  hit_10.push_back(v);
221  else if (hit_plane==1 && hit_tpc==1 && hit_peakT>0)
222  hit_11.push_back(v);
223  }
224  }
225  bool save_ind_hits = false;
226  vector<vector<int>> ind_empty; // placeholder empty vector
227  if (muon_in_tpc0){
228  Hough(hit_00, HoughParam, save_ind_hits, event, lines_00, ind_empty);
229  Hough(hit_01, HoughParam, save_ind_hits, event, lines_01, ind_empty);
230 
233  }
234  if (muon_in_tpc1){
235  Hough(hit_10, HoughParam, save_ind_hits, event, lines_10, ind_empty);
236  Hough(hit_11, HoughParam, save_ind_hits, event, lines_11, ind_empty);
237 
240  }
241  if (muon_endpoints.empty() == false){
245 
246  for (size_t i=0; i<muon_endpoints.size(); i++){
247  int track_type = muon_type.at(i);
248  vector<int> track_hit_idx = muon_hit_idx.at(i);
249  bool keep_track = false;
250 
251  for (auto t : fKeepMuonTypes){
252  if (track_type == t)
253  keep_track = true;
254  }
255  if (keep_track){
256  geo::Point_t endpoint1 = (muon_endpoints.at(i)).at(0), endpoint2 = (muon_endpoints.at(i)).at(1);
257 
258  sbnd::comm::MuonTrack mytrack;
259  mytrack.t0_us = muon_t0.at(i);
260  mytrack.x1_pos = float(endpoint1.X());
261  mytrack.y1_pos = float(endpoint1.Y());
262  mytrack.z1_pos = float(endpoint1.Z());
263  mytrack.x2_pos = float(endpoint2.X());
264  mytrack.y2_pos = float(endpoint2.Y());
265  mytrack.z2_pos = float(endpoint2.Z());
266 
267  mytrack.theta_xz = (muon_trajectories.at(i)).at(0);
268  mytrack.theta_yz = (muon_trajectories.at(i)).at(1);
269 
270  mytrack.tpc = (endpoint1.X() < 0)? 0:1;
271  mytrack.type = muon_type.at(i);
272 
273  muon_tracks->push_back(mytrack);
274  for (size_t hit_i=0; hit_i<track_hit_idx.size(); hit_i++){
275  int idx = track_hit_idx[hit_i];
276  util::CreateAssn(*this, evt, *muon_tracks, hitlist[idx], *muon_tracks_assn);
277  }
278  }
279  }
280  }
281  } // end of finding ind hits
282  evt.put(std::move(muon_tracks));
283  evt.put(std::move(muon_tracks_assn));
284 } // MuonTrackProducer::produce()
285 
286 float MuonTrackProducer::Distance(int x1, int y1, int x2, int y2){
287  return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2) * 1.0);
288 }
289 
290 void MuonTrackProducer::Hough(vector<vector<int>> coords, vector<int> param, bool save_hits, int nentry,
291  vector<vector<int>>& lines, vector<vector<int>>& hit_idx){
292  // set parameters
293  int threshold = param.at(0);
294  int max_gap = param.at(1);
295  int range = param.at(2);
296  int min_length = param.at(3);
297  int muon_length = param.at(4);
298 
299  // set global variables
300  TRandom3 rndgen;
301  const int h = 3500; const int w = 2000; //range of hit_wire
302  constexpr int accu_h = h + w + 1 ; const int accu_w = 180;
303  const int x_c = (w/2); const int y_c = (h/2);
304 
305  // create accumulator/pointer to accumulator
306  int accu[accu_h][accu_w] = {{0}};
307  int (*adata)[accu_w];
308  adata = &accu[(accu_h-1)/2]; // have pointer point to the middle of the accumulator array (then we can use negative indices)
309 
310  // declare necessary vectors
311  vector<vector<int>> data = coords; // points will not be removed
312  vector<vector<int>> deaccu; // deaccumulator
313  vector<vector<int>> outlines;
314  vector<vector<int>> outhit_idx;
315 
316  // loop over points and perform transform
317  int count = coords.size();
318  for ( ; count>0; count--){
319  int idx = rndgen.Uniform(count);
320  int max_val = threshold-1;
321  if ((coords.at(idx)).empty())
322  continue;
323  int x = coords[idx][0], y = coords[idx][1], rho = 0, theta = 0;
324  vector<int> v{x,y};
325  deaccu.push_back(v);
326  //loop over all angles and fill the accumulator
327  for (int j=0; j<accu_w; j++){
328  int r = int(round((x-x_c)*cos(j*M_PI/accu_w) + (y-y_c)*sin(j*M_PI/accu_w)));
329  int val = ++(adata[r][j]);
330  if (max_val < val){
331  max_val = val;
332  rho = r;
333  theta = j*180/accu_w;
334  }
335  }
336  if (max_val < threshold){
337  (coords.at(idx)).clear();
338  continue;
339  }
340  //start at point and walk the corridor on both sides
341  vector<vector<int>> endpoint(2, vector<int>(4));
342  vector<int> lines_idx;
343  lines_idx.clear();
344  for (int k=0; k<2;k++){
345  int i=0, gap=0;
346  while (gap < max_gap){
347  (k==0)? i++ : i--;
348  if ( (idx+i) == int(data.size()) || (idx+i) <0) // if we reach the edges of the data set
349  break;
350  if ((data.at(idx+i)).empty()) // if the point has already been removed
351  continue;
352  int x1 = data[idx+i][0], y1 = int(data[idx+i][1]), wire_idx = data[idx+i][2];
353  int last_x, diffx;
354  if (endpoint[k][0]!= 0){ // ensure we don't jump large x-values
355  last_x = endpoint[k][0];
356  diffx = abs(last_x - x1);
357  if (diffx > 30){
358  break;
359  }
360  }
361  int y_val = int(round((rho - (x1 - x_c)*cos(theta*M_PI/180.0))/sin(theta*M_PI/180.0) + y_c));
362  if (abs(y_val-y1) <= range){
363  gap = 0;
364  endpoint[k] = {x1, y1, wire_idx, idx+i};
365  (coords.at(idx+i)).clear();
366  (data.at(idx+i)).clear();
367  if (save_hits){
368  lines_idx.push_back(wire_idx);
369  }
370  }
371  else
372  gap++;
373  } // end of while loop
374  } // end of k loop
375 
376  // unvote from the accumulator
377  for (int n = (deaccu.size()-1); n>=0; n--){
378  int x1 = deaccu[n][0], y1 = int(deaccu[n][1]);
379  int y_val = int(round((rho - (x1 - x_c)*cos(theta*M_PI/180.0))/sin(theta*M_PI/180.0) + y_c));
380  if (y1 >= (y_val-range) && y1 <= (y_val+range)){
381  for (int m=0; m<accu_w; m++){
382  int r = int(round((x1-x_c)*cos(m*M_PI/accu_w) + (y1-y_c)*sin(m*M_PI/accu_w)));
383  (adata[r][m])--;
384  }
385  deaccu.erase(deaccu.begin() + n);
386  }
387  } // end of deaccumulator loop
388 
389  int x0_end = endpoint[0][0], y0_end = endpoint[0][1], x1_end = endpoint[1][0], y1_end = endpoint[1][1];
390  int wire0_end = endpoint[0][2], wire1_end = endpoint[1][2];
391  int idx0_end = endpoint[0][3], idx1_end = endpoint[1][3];
392  if ((x0_end==0 && y0_end==0) || (x1_end==0 && y1_end==0)) // don't add the (0,0) points
393  continue;
394  vector<int> outline = {x0_end, y0_end, x1_end, y1_end, wire0_end, wire1_end, idx0_end, idx1_end, rho, theta};
395 
396  outlines.push_back(outline);
397  if (save_hits){
398  outhit_idx.push_back(lines_idx);
399  }
400 
401  } // end of point loop
402  // combine lines that are split
403  for (size_t i=0; i<outlines.size(); i++){
404  bool same = false;
405  for (size_t j=i+1; j<outlines.size() && same == false; j++){
406  int xi_coords[2] = {outlines[i][0], outlines[i][2]}; int xj_coords[2] = {outlines[j][0], outlines[j][2]};
407  int yi_coords[2] = {outlines[i][1], outlines[i][3]}; int yj_coords[2] = {outlines[j][1], outlines[j][3]};
408  int rhoi = outlines[i][8], rhoj = outlines[j][8];
409  int thetai = outlines[i][9], thetaj = outlines[j][9];
410 
411  int var = 100;
412  int rho_var = 30;
413  int theta_var = 20;
414  for (int k=0; k<2 && same == false; k++){
415  for (int l=0; l<2 && same == false; l++){
416  int counter = 0;
417  if ((xi_coords[k] < (xj_coords[l] + var)) && (xi_coords[k] > (xj_coords[l] - var)))
418  counter++;
419  if ((yi_coords[k] < (yj_coords[l] + var)) && (yi_coords[k] > (yj_coords[l] - var)))
420  counter++ ;
421  if ((rhoi < (rhoj + rho_var)) && (rhoi > (rhoj - rho_var)))
422  counter++;
423  if ((thetai < (thetaj + theta_var)) && (thetai > (thetaj - theta_var)))
424  counter++;
425  if (counter >= 3){ // if at least three of the conditions are fulfilled
426  if(k==0){
427  if(l==0){
428  outlines[j][2] = outlines[i][0];
429  outlines[j][3] = outlines[i][1];
430  }
431  else{
432  outlines[j][0] = outlines[i][0];
433  outlines[j][1] = outlines[i][1];
434  }
435  }
436  else{
437  if(l==0){
438  outlines[j][2] = outlines[i][2];
439  outlines[j][3] = outlines[i][3];
440  }
441  else{
442  outlines[j][0] = outlines[i][2];
443  outlines[j][1] = outlines[i][3];
444  }
445  }
446  same = true;
447  // remove the extra segment
448  (outlines.at(i)).clear();
449  if (save_hits){
450  (outhit_idx.at(j)).insert( (outhit_idx.at(j)).end(), (outhit_idx.at(i)).begin(), (outhit_idx.at(i)).end());
451  (outhit_idx.at(i)).clear();
452  }
453  }
454  }
455  }
456  } // end of j loop
457  } // end of i loop
458 
459  for (size_t i=0; i < outlines.size(); i++){
460  if ((outlines.at(i)).empty())
461  continue;
462  int x0_end = outlines[i][0], y0_end = outlines[i][1], x1_end = outlines[i][2], y1_end = outlines[i][3];
463  if (muon_length!=0){
464  int y_diff = abs(y0_end-y1_end);
465  if (y_diff > muon_length){
466  lines.push_back(outlines.at(i));
467  if (save_hits)
468  hit_idx.push_back(outhit_idx.at(i));
469  }
470  }
471  else{
472  float length = Distance(x0_end,y0_end,x1_end,y1_end);
473  if (length > min_length){
474  lines.push_back(outlines.at(i));
475  if (save_hits)
476  hit_idx.push_back(outhit_idx.at(i));
477  }
478  }
479  }
480  //free memory
481  data.clear(); deaccu.clear(); outlines.clear(); outhit_idx.clear();
482 } // end of hough
483 
485  hit_02.clear();
486  hit_12.clear();
487  lines_02.clear();
488  lines_12.clear();
489  hit_idx_02.clear();
490  hit_idx_12.clear();
491 
492  hit_02.reserve(3000);
493  hit_12.reserve(3000);
494  lines_02.reserve(n);
495  lines_12.reserve(n);
496  hit_idx_02.reserve(3000);
497  hit_idx_12.reserve(3000);
498 }
499 
501  hit_00.clear();
502  hit_01.clear();
503  hit_10.clear();
504  hit_11.clear();
505 
506  lines_00.clear();
507  lines_01.clear();
508  lines_10.clear();
509  lines_11.clear();
510  hit_00.reserve(5000);
511  hit_01.reserve(5000);
512  hit_10.reserve(5000);
513  hit_11.reserve(5000);
514 
515  lines_00.reserve(n);
516  lines_01.reserve(n);
517  lines_10.reserve(n);
518  lines_11.reserve(n);
519 }
520 
522  muon_tpc.clear();
523  muon_endpoints.clear();
524  muon_hitpeakT.clear();
525  muon_hit_idx.clear();
526  muon_type.clear();
527  muon_trajectories.clear();
528  muon_t0.clear();
529 
530  muon_tpc.reserve(n);
531  muon_endpoints.reserve(n);
532  muon_hitpeakT.reserve(n);
533  muon_hit_idx.reserve(n);
534  muon_type.reserve(n);
535  muon_trajectories.reserve(n);
536  muon_t0.reserve(n);
537 
538 }
539 
540 void MuonTrackProducer::FindEndpoints(vector<vector<int>>& lines_col, vector<vector<int>>& lines_ind, vector<vector<int>>& hit_idx,
541  int range, vector<art::Ptr<recob::Hit>> hitlist,
542  vector<vector<geo::Point_t>>& muon_endpoints, vector<vector<int>>& muon_hitpeakT, vector<vector<int>>& muon_hit_idx){
543  if (lines_ind.empty() == false){
544  for (size_t i=0; i<lines_col.size(); i++){
545  bool match = false;
546  if ((lines_col.at(i)).empty() == true)
547  continue;
548  for (size_t j=0; j < lines_ind.size() && match == false; j++){
549  int peakT0_col, peakT1_col, peakT0_ind, peakT1_ind;
550  int wire0_col, wire1_col, wire0_ind, wire1_ind;
551 
552  bool order_col = (lines_col.at(i)).at(1) < (lines_col.at(i)).at(3);
553  peakT0_col = order_col? (lines_col.at(i)).at(1) : (lines_col.at(i)).at(3);
554  peakT1_col = order_col? (lines_col.at(i)).at(3) : (lines_col.at(i)).at(1);
555  wire0_col = order_col? (lines_col.at(i)).at(4) : (lines_col.at(i)).at(5);
556  wire1_col = order_col? (lines_col.at(i)).at(5) : (lines_col.at(i)).at(4);
557 
558  bool order_ind = (lines_ind.at(j)).at(1) < (lines_ind.at(j)).at(3);
559  peakT0_ind = order_ind? (lines_ind.at(j)).at(1) : (lines_ind.at(j)).at(3);
560  peakT1_ind = order_ind? (lines_ind.at(j)).at(3) : (lines_ind.at(j)).at(1);
561  wire0_ind = order_ind? (lines_ind.at(j)).at(4) : (lines_ind.at(j)).at(5);
562  wire1_ind = order_ind? (lines_ind.at(j)).at(5) : (lines_ind.at(j)).at(4);
563 
564  int peakT_range = range;
565  if ( (abs(peakT0_col - peakT0_ind) < peakT_range) && (abs(peakT1_col - peakT1_ind) < peakT_range)){
566  geo::WireID awire_col = hitlist[wire0_col]->WireID();
567  geo::WireID awire_ind = hitlist[wire0_ind]->WireID();
568  geo::WireID cwire_col = hitlist[wire1_col]->WireID();
569  geo::WireID cwire_ind = hitlist[wire1_ind]->WireID();
570  geo::Point_t apoint, cpoint, endpoint1, endpoint2;
571 
572  bool aintersect = fGeometryService->WireIDsIntersect(awire_col, awire_ind, apoint);
573  bool cintersect = fGeometryService->WireIDsIntersect(cwire_col, cwire_ind, cpoint);
574 
575  if (aintersect)
576  endpoint1 = apoint;
577  else{ // NOTE: hardcoded fix
578  bool afix = FixEndpoints(awire_col, awire_ind, apoint);
579  if (afix == true)
580  endpoint1 = apoint;
581  }
582  if (cintersect)
583  endpoint2 = cpoint;
584  else{ // NOTE:: hardcoded fix
585  bool cfix = FixEndpoints(cwire_col, cwire_ind, cpoint);
586  if ( cfix == true)
587  endpoint2 = cpoint;
588  }
589  if (endpoint1.Mag2() != 0 && endpoint2.Mag2() != 0 ){
590  vector<geo::Point_t> pair{endpoint1,endpoint2};
591  muon_endpoints.push_back(pair);
592 
593  vector<int> v{peakT0_col, peakT1_col};
594  vector<int> indices = hit_idx.at(i);
595 
596  muon_hitpeakT.push_back(v);
597  muon_hit_idx.push_back(indices);
598  match = true;
599  lines_col.at(i).clear();
600  }
601  }
602  } // end of j loop
603  } // end of i loop
604  }
605 }
606 
608  bool pass = false;
609  double col_end1[3], col_end2[3], ind_end1[3], ind_end2[3];
610  fGeometryService->WireEndPoints(wire_col, col_end1, col_end2);
611  fGeometryService->WireEndPoints(wire_ind, ind_end1, ind_end2);
612  if (abs(ind_end1[1]) > 198 || abs(ind_end2[1]) > 198){ // if it's located on the top or bottom
613  double ind_y = (abs(ind_end1[1]) == 199.792) ? ind_end1[1] : ind_end2[1];
614  double ind_z = (abs(ind_end1[1]) == 199.792) ? ind_end1[2] : ind_end2[2];
615  if (abs(col_end1[2] - ind_z) < 8){
616  point.SetX(col_end1[0]);
617  point.SetY(ind_y);
618  point.SetZ(ind_z);
619  pass = true;
620  }
621  }
622  return pass;
623 }
624 
625 void MuonTrackProducer::SortEndpoints(vector<vector<geo::Point_t>>& muon_endpoints, vector<vector<int>> muon_hitpeakT, vector<int>& muon_type){
626  for (size_t i=0; i< muon_endpoints.size(); i++){
627  geo::Point_t &endpoint1 = (muon_endpoints.at(i)).at(0), &endpoint2 = (muon_endpoints.at(i)).at(1);
628  int dt = (muon_hitpeakT.at(i)).at(1) - (muon_hitpeakT.at(i)).at(0);
629 
630  if (dt > 2400){
631  muon_type.push_back(0); // anode-cathode crosser
632  endpoint2.SetX(0);
633  continue;
634  }
635 
636  bool end1_edge = (endpoint1.Y() > 198 || endpoint1.Y() < -198 || endpoint1.Z() > 503 || endpoint1.Z() < 6);
637  bool end2_edge = (endpoint2.Y() > 198 || endpoint2.Y() < -198 || endpoint2.Z() > 503 || endpoint2.Z() < 6);
638 
639  if (end1_edge == false && end2_edge == true ){ // if the later one was on an edge, the earlier one must be on anode
640  muon_type.push_back(1); // anode crosser
641  double dx = dt*0.5*0.16; // conversion to distance (cm)
642  double true_x = (endpoint2.X() > 0)? (202.05-dx):(-202.05+dx);
643  endpoint2.SetX(true_x);
644  }
645  else if (end1_edge == true && end2_edge == false){ // if the earlier one was on an edge, the later one must be on cathode
646  muon_type.push_back(2); // cathode crosser
647  double dx = dt*0.5*0.16; // conversion to distance (cm)
648  double true_x = (endpoint1.X() > 0)? (202.05-dx):(-202.05+dx);
649  endpoint1.SetX(true_x);
650  endpoint2.SetX(0.0); // change to location of cathode
651  }
652  else if ( (endpoint1.Y() > 198 && endpoint2.Y() < -198) || (endpoint1.Y() < -198 && endpoint2.Y() > 198) ){
653  muon_type.push_back(3); // top-bottom crosser
654  }
655  else if ( (endpoint1.Z() > 503 && endpoint2.Z() < 6) || (endpoint1.Z() < 6 && endpoint2.Z() > 503)){
656  muon_type.push_back(4); // upstream/downstream crosser
657  }
658  else{
659  muon_type.push_back(5); // uncategorized
660  }
661  }
662 }
663 
664 void MuonTrackProducer::FindTrajectories(vector<vector<geo::Point_t>> muon_endpoints, vector<vector<int>> muon_hitpeakT,
665  vector<vector<double>>& muon_trajectories){
666  for (size_t i=0; i< muon_endpoints.size(); i++){
667  vector<geo::Point_t> pair = muon_endpoints[i];
668 
669  int dt = (muon_hitpeakT.at(i)).at(1) - (muon_hitpeakT.at(i)).at(0);
670 
671  double dx = dt*0.5*0.16;
672  double dy = float(pair[1].Y())-float(pair[0].Y());
673  double dz = float(pair[1].Z())-float(pair[0].Z());
674 
675  double theta_xz = atan2(dx,dz) * 180/M_PI;
676  double theta_yz = atan2(dy,dz) * 180/M_PI;
677 
678  // std::cout << "theta_xz: " << theta_xz << std::endl;
679  // std::cout << "theta_yz: " << theta_yz << std::endl;
680  vector<double> trajectories{theta_xz, theta_yz};
681  muon_trajectories.push_back(trajectories);
682  }
683 }
684 
685 void MuonTrackProducer::Findt0(vector<vector<int>> muon_hitpeakT, vector<int> muon_type,
686  vector<double>& muon_t0){
687  for (size_t i=0; i< muon_hitpeakT.size(); i++){
688  double t0;
689  if (muon_type.at(i) == 0 || muon_type.at(i) == 1) // anode-cathode crosser or anode crosser
690  t0 = ((muon_hitpeakT.at(i)).at(0) - 500)*0.5;
691  else if (muon_type.at(i) == 2) // cathode crosser
692  t0 = ((muon_hitpeakT.at(i)).at(1) - 3000)*0.5;
693  else
694  t0 = -999;
695  muon_t0.push_back(t0);
696  }
697 }
698 
699 void MuonTrackProducer::PrintHoughLines(vector<vector<int>>& lines, int plane){
700  if (lines.empty()==false){
701  std::cout << "plane = " << plane << std::endl;
702  for (size_t i=0; i< lines.size(); i++){
703  vector<int> line = lines.at(i);
704  int wire0 = line.at(0), wire1 = line.at(2);
705  int peakT0 = line.at(1), peakT1 = line.at(3);
706  std::cout << "wire0, peakT0: (" << wire0 << ", " << peakT0 << ")" << std::endl;
707  std::cout << "wire1, peakT1: (" << wire1 << ", " << peakT1 << ")" << std::endl;
708  }
709  }
710  else
711  std::cout << "no lines found for this plane" << std::endl;
712 }
713 
714 // A macro required for a JobControl module.
715 DEFINE_ART_MODULE(MuonTrackProducer)
vector< vector< int > > hit_11
vector< vector< int > > hit_12
vector< vector< int > > lines_12
void SortEndpoints(vector< vector< geo::Point_t >> &muon_endpoints, vector< vector< int >> muon_hitpeakT, vector< int > &muon_type)
Utilities related to art service access.
vector< vector< int > > hit_01
process_name opflash particleana ie x
art::ServiceHandle< art::TFileService > tfs
bool FixEndpoints(geo::WireID wire_col, geo::WireID wire_ind, geo::Point_t &point)
vector< vector< int > > lines_01
Declaration of signal hit object.
pdgs p
Definition: selectors.fcl:22
void PrintHoughLines(vector< vector< int >> &lines, int plane)
vector< vector< int > > lines_02
vector< vector< int > > hit_idx_12
Definition of basic raw digits.
void FindTrajectories(vector< vector< geo::Point_t >> muon_endpoints, vector< vector< int >> muon_hitpeakT, vector< vector< double >> &muon_trajectories)
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
vector< vector< int > > muon_hitpeakT
vector< vector< geo::Point_t > > muon_endpoints
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
std::vector< int > fKeepMuonTypes
vector< vector< int > > muon_hit_idx
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
MuonTrackProducer(fhicl::ParameterSet const &p)
Access the description of detector geometry.
T abs(T value)
object containing MC truth information necessary for making RawDigits and doing back tracking ...
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
void FindEndpoints(vector< vector< int >> &lines_col, vector< vector< int >> &lines_ind, vector< vector< int >> &hit_idx, int range, vector< art::Ptr< recob::Hit >> hitlist, vector< vector< geo::Point_t >> &muon_endpoints, vector< vector< int >> &muon_hitpeakT, vector< vector< int >> &muon_hit_idx)
process_name opflash particleana ie ie y
float Distance(int x1, int y1, int x2, int y2)
Collect all the RawData header files together.
art framework interface to geometry description for auxiliary detectors
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
vector< vector< int > > lines_11
geo::GeometryCore const * fGeometryService
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Description of geometry of one entire detector.
Definition of data types for geometry description.
Encapsulate the geometry of a wire.
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
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.
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
vector< vector< int > > hit_00
void produce(art::Event &evt) override
Encapsulate the construction of a single detector plane.
vector< vector< int > > lines_00
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
constexpr WireID()=default
Default constructor: an invalid TPC ID.
vector< vector< int > > hit_idx_02
void Hough(vector< vector< int >> coords, vector< int > param, bool save_hits, int nentry, vector< vector< int >> &lines, vector< vector< int >> &hit_idx)
TCEvent evt
Definition: DataStructs.cxx:8
pdgs k
Definition: selectors.fcl:22
std::size_t count(Cont const &cont)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
vector< vector< int > > lines_10
vector< vector< int > > hit_02
vector< vector< int > > hit_10
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
esac echo uname r
void reconfigure(fhicl::ParameterSet const &p)
MuonTrackProducer & operator=(MuonTrackProducer const &)=delete
vector< vector< double > > muon_trajectories
art framework interface to geometry description
BEGIN_PROLOG could also be cout
void Findt0(vector< vector< int >> muon_hitpeakT, vector< int > muon_type, vector< double > &muon_t0)