All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SEAviewer.cxx
Go to the documentation of this file.
2 #include <algorithm>
3 #include <cmath>
4 
5 namespace seaview{
6 
7  int cluster::InNuSlice(const std::map<int, std::vector<art::Ptr<recob::Hit>> >& sliceIDToHitsMap, int nuSliceID){
8 
9  const std::vector<art::Ptr<recob::Hit>>& slice_hits = sliceIDToHitsMap.at(nuSliceID);
10  bool found_hit_in_slice = false, found_hit_not_in_slice = false;
11  for(auto hit : f_hits){
12  auto iter = std::find(slice_hits.begin(), slice_hits.end(), hit);
13  if( iter == slice_hits.end())
14  found_hit_not_in_slice = true;
15  else{
16  found_hit_in_slice = true;
17  }
18 
19  if(found_hit_in_slice && found_hit_not_in_slice) return 0;
20  }
21 
22  return found_hit_in_slice ? 1 : -1;
23  }
24 
25 
26  void SEAviewer::TrackLikeClusterAnalyzer(cluster &cl, const std::vector<double> &shower_start_pt_2D, const std::vector<double> &shower_other_pt_2D){
27 
28  //first round, grab min ioc, impact, conversion distance, and ADC_histogram, and indx of the hits with min/max IOC
29  double max_ioc_to_shower_start = DBL_MIN;
30  size_t num_hits = cl.f_hits.size();
31 
32 
33  for(size_t i = 0; i!= num_hits; ++i){
34  auto &h = cl.f_hits[i]; //type of h: art_ptr<recob::Hit>
35  double h_tick = (double)h->PeakTime();
36  double h_wire = (double)h->WireID().Wire;
37 
38  //geometric properties
39  double impact_parameter_to_shower = dist_line_point(shower_start_pt_2D, shower_other_pt_2D, {h_wire, h_tick});
40  double conversion_dist_to_shower_start = dist_point_point(h_wire, h_tick, shower_start_pt_2D[0], shower_start_pt_2D[1]);
41  double ioc_to_shower_start = impact_parameter_to_shower/conversion_dist_to_shower_start;
42  cl.f_min_impact_parameter_to_shower = std::min(cl.f_min_impact_parameter_to_shower, impact_parameter_to_shower);
43  cl.f_min_conversion_dist_to_shower_start = std::min(cl.f_min_conversion_dist_to_shower_start, conversion_dist_to_shower_start);
44 
45  //remember two hits with min/max IOC
46  if( ioc_to_shower_start < cl.f_min_ioc_to_shower_start){
47  cl.f_min_ioc_to_shower_start = ioc_to_shower_start;
48  cl.start_hit_idx = i;
49  }
50  if( ioc_to_shower_start > max_ioc_to_shower_start){ //be careful, should not be "else if" here.
51  max_ioc_to_shower_start = ioc_to_shower_start;
52  cl.end_hit_idx = i;
53  }
54 
55 
56  } //end of hit loop
57 
58 
59  // second round: group hits in two categories, first half and second half
60  // get the direction of the cluster
61  auto start_hit_ptr = cl.f_hits.at(cl.start_hit_idx), end_hit_ptr = cl.f_hits.at(cl.end_hit_idx);
62  std::vector<double> start_hit_point = { (double)start_hit_ptr->WireID().Wire, (double)start_hit_ptr->PeakTime()};
63  std::vector<double> end_hit_point= { (double)end_hit_ptr->WireID().Wire, (double)end_hit_ptr->PeakTime()};
64  std::vector<double> mid_point = { (start_hit_point[0] + end_hit_point[0])/2, (start_hit_point[1] + end_hit_point[1])/2};
65  std::vector<double> start_to_mid_vec = { (- start_hit_point[0] + end_hit_point[0])/2, ( - start_hit_point[1] + end_hit_point[1])/2};
66  cl.f_ioc_based_length = sqrt(pow((start_hit_point[0]-end_hit_point[0])*wire_con, 2.0) + pow((start_hit_point[1]-end_hit_point[1])*tick_con, 2.0));
67 
68  cl.f_hit_group.resize(num_hits);
69  for(size_t i = 0; i!=num_hits; ++i){
70  auto h = cl.f_hits[i]; //type of h: art_ptr<recob::Hit>
71  double h_tick = (double)h->PeakTime();
72  double h_wire = (double)h->WireID().Wire;
73 
74  std::vector<double> mid_to_h_vec = { h_wire - mid_point[0], h_tick - mid_point[1]};
75 
76  if( start_to_mid_vec[0]*mid_to_h_vec[0]*pow(wire_con, 2.0) + start_to_mid_vec[1] * mid_to_h_vec[1] *pow(tick_con, 2.0)<= 0 ){
77  cl.f_hit_group[i] = 1;
78  cl.f_mean_ADC_first_half += h->SummedADC();
79  }
80  else{
81  cl.f_hit_group[i] = 2;
82  cl.f_mean_ADC_second_half += h->SummedADC();
83  }
84  }
85  cl.f_track_treated = true;
86 
87  size_t nhits_first_half = std::count(cl.f_hit_group.begin(), cl.f_hit_group.end(), 1);
88  size_t nhits_second_half = std::count(cl.f_hit_group.begin(), cl.f_hit_group.end(), 2);
89  if(nhits_first_half) cl.f_mean_ADC_first_half /= nhits_first_half;
90  if(nhits_second_half) cl.f_mean_ADC_second_half /= nhits_second_half;
92 
93  if( num_hits < 2){
94  std::cerr << "SEAviewer::TrackLikeClusterAnalyzer\t|| this cluster only has " << num_hits << " hits, can't calculate direction, skipping it... " << std::endl;
95  return;
96  }
97 
98  //angle between the track cluster and the shower direction
99  //cluster direction unit vector
100  double start_to_mid_length = sqrt( pow(start_to_mid_vec[0]*wire_con, 2.0) + pow(start_to_mid_vec[1]*tick_con, 2.0));
101  std::vector<double> cluster_dir = {start_to_mid_vec[0]*wire_con/start_to_mid_length, start_to_mid_vec[1]*tick_con/start_to_mid_length};
102  //shower direction unit vector
103  double shower_direction_length = sqrt(pow((shower_start_pt_2D[0] - shower_other_pt_2D[0])*wire_con, 2.0) + pow((shower_start_pt_2D[1] - shower_other_pt_2D[1])*tick_con, 2.0));
104  std::vector<double> shower_dir = { (shower_other_pt_2D[0] - shower_start_pt_2D[0])*wire_con/shower_direction_length, (shower_other_pt_2D[1] - shower_start_pt_2D[1])*tick_con/shower_direction_length};
105  //angle between two unit vector, in radian
106  cl.f_angle_wrt_shower_direction = acos( cluster_dir[0]*shower_dir[0] + cluster_dir[1]*shower_dir[1]);
107 
108 
109  if(cl.f_score.min_wire == cl.f_score.max_wire){
110  std::cout << "SEAviewer::TrackLikeClusterAnalyzer\t|| this cluster spans only on 1 wire: " << cl.f_score.min_wire << ", setting its straight-line fit chi2 to 0.." << std::endl;
111  return;
112  }
113  //fit to wire-tick plot of the cluster, see how straight cluster is
114  TF1 *f1 = new TF1("f1", "1 ++ x", cl.f_score.min_wire, cl.f_score.max_wire);
115  //TGraph* graph_copy = (TGraph*)cl.f_graph.Clone("temp");
116  //int fit_status = graph_copy->Fit(f1, "RQ0"); //if fit status is 0, the fit is ok.
117  int fit_status = cl.f_graph.Fit(f1, "RQ0"); //if fit status is 0, the fit is ok.
118  if(fit_status == 0){
119  //f1 = graph_copy->GetFunction("f1");
120  f1 = cl.f_graph.GetFunction("f1");
121  cl.f_fit_chi2 = f1->GetChisquare();
122  }
123  //std::cout << "SEAviewer::TrackLikeClusterAnalyzer\t|| End" << std::endl;
124  }
125 
126 
127  // constructor
128  // CHECK, this constructor is not found;
129  SEAviewer::SEAviewer(std::string intag,
130  geo::GeometryCore const * ingeom,
131  detinfo::DetectorPropertiesData const & intheDetector )
132  : tag(intag), geom(ingeom), theDetector(intheDetector){
133  chan_max = {-9999,-9999,-9999};
134  chan_min = {9999,9999,9999};
135  tick_max = -99999;
136  tick_min = 99999;
137 
138  plot_true_vertex = false;
139  vertex_tick.resize(3);
140  vertex_chan.resize(3);
141  vertex_graph.resize(3);
142 
143  true_vertex_tick.resize(3);
144  true_vertex_chan.resize(3);
145  true_vertex_graph.resize(3);
146 
147  tick_shift = 350;
148  chan_shift = 100;
149 
150  n_showers=0;
151  n_pfps = 0;
152  has_been_clustered = false;
153  hit_threshold = -10;
154 
155  rangen = new TRandom3(0); //same seed everytime
156  }
157 
158 
159  int SEAviewer::setBadChannelList(std::vector<std::pair<int,int>> &in){
161  return 0;
162  }
163 
164  int SEAviewer::addHitsToConsider(std::vector<art::Ptr<recob::Hit>>& hits){
165  for(auto &h: hits){
166  map_unassociated_hits[h] = true;
167  map_considered_hits[h] = true;
168  }
169  return 0;
170  }
171 
172  int SEAviewer::filterConsideredHits(double dist_to_vertex){
173 
174  //collect all hits that are under consideration for clustering
175  std::vector<art::Ptr<recob::Hit>> current_hits;
176  for(auto map_iter = map_considered_hits.begin(); map_iter != map_considered_hits.end(); ++map_iter){
177  current_hits.push_back(map_iter->first);
178  }
179 
180  //remove hits that are too far from vertex
181  for(auto &h: current_hits){
182  int p = h->View();
183  double wire = (double)h->WireID().Wire;
184  double tick = (double)h->PeakTime();
185  double dist = dist_point_point(wire, tick, vertex_chan[p], vertex_tick[p]);
186 
187  if(dist > dist_to_vertex){
188  map_unassociated_hits.erase(h);
189  map_considered_hits.erase(h);
190  }
191  }
192  return 0;
193  }
194 
196  hit_threshold = h;
197  return 0;
198  }
199 
200  int SEAviewer::addAllHits(std::vector<art::Ptr<recob::Hit>>& hits){
201 
202  std::vector<std::vector<double>> vec_tick(3);
203  std::vector<std::vector<double>> vec_chan(3);
204 
205  for(auto&h: hits){
206  if(map_considered_hits.count(h)==0){ // if h is not in the map, push its plane ID, wire ID, and time tick to the vectors
207  double wire = (double)h->WireID().Wire;
208  vec_chan[(int)h->View()].push_back(wire);
209  vec_tick[(int)h->View()].push_back((double)h->PeakTime());
210  //tick_max = std::max(tick_max, (double)h->PeakTime());
211  //tick_min = std::min(tick_min, (double)h->PeakTime());
212  //chan_max[(int)h->View()] = std::max( chan_max[(int)h->View()],wire);
213  //chan_min[(int)h->View()] = std::min( chan_min[(int)h->View()],wire);
214  }
215  }
216 
217  for(int i=0; i<3; i++){
218  vec_all_graphs.emplace_back(vec_tick[i].size(),&vec_chan[i][0],&vec_tick[i][0]); //implicitly converted to TGraph
219  }
220 
221  vec_all_ticks = vec_tick;
222  vec_all_chans = vec_chan;
223 
224  return 0;
225  }
226 
228  int n_unassoc=0;
229  int n_below_thresh = 0;
230  std::vector<std::vector<double>> vec_tick(3);
231  std::vector<std::vector<double>> vec_chan(3);
232  std::vector<std::vector<std::vector<double>>> vec_pts(3);
233  std::vector<std::vector<art::Ptr<recob::Hit>>> vec_hits(3);
234 
235 
236  int n_all =map_considered_hits.size();
237 
238  for(const auto &pair: map_considered_hits ){
239  auto& h = pair.first; //type of h: recob::Hit
240  if(map_unassociated_hits.count(h) !=0 && map_unassociated_hits[h]){
241 
242  if(h->SummedADC() < hit_threshold){
243  n_below_thresh++;
244  continue;
245  }
246 
247  // if summed ADC of the hit passes threshold
248  n_unassoc++;
249  double wire = (double)h->WireID().Wire;
250  double tick = (double)h->PeakTime();
251  vec_chan[(int)h->View()].push_back(wire);
252  vec_tick[(int)h->View()].push_back(tick);
253 
254  vec_pts[(int)h->View()].push_back({wire,tick});
255  vec_hits[(int)h->View()].push_back(h);
256  tick_max = std::max(tick_max, tick);
257  tick_min = std::min(tick_min, tick);
258  //chan_max, chan_min stores: max, min unassociated channel for each plane
259  chan_max[(int)h->View()] = std::max( chan_max[(int)h->View()],wire);
260  chan_min[(int)h->View()] = std::min( chan_min[(int)h->View()],wire);
261 
262  }
263 
264  }
265 
266  for(int i=0; i<3; i++){
267  vec_unass_graphs.emplace_back(vec_tick[i].size(),&vec_chan[i][0],&vec_tick[i][0]);
268  }
269 
270  vec_unass_ticks = vec_tick;
271  vec_unass_chans = vec_chan;
272  vec_unass_pts = vec_pts;
273  vec_unass_hits = vec_hits;
274 
275  return {n_all,n_unassoc,n_below_thresh};
276  }
277 
278 
279  int SEAviewer::addPFParticleHits(std::vector<art::Ptr<recob::Hit>>& hits, std::string legend, double arg1, double arg2, double arg3){
280  n_pfps++;
281 
282  format_legend(legend, arg1, arg2, arg3);
283 
284  vec_pfp_legend.push_back(legend);
285 
286  std::vector<std::vector<double>> vec_tick(3);
287  std::vector<std::vector<double>> vec_chan(3);
288 
289  for(auto &h: hits){
290  double wire = (double)h->WireID().Wire;
291  vec_chan[(int)h->View()].push_back(wire);
292  vec_tick[(int)h->View()].push_back((double)h->PeakTime());
293  tick_max = std::max(tick_max, (double)h->PeakTime());
294  tick_min = std::min(tick_min, (double)h->PeakTime());
295  chan_max[(int)h->View()] = std::max( chan_max[(int)h->View()],wire);
296  chan_min[(int)h->View()] = std::min( chan_min[(int)h->View()],wire);
297 
298  //remove from unassociated hits
299  map_unassociated_hits[h] = false;
300  }
301 
302  std::vector<TGraph> t_graphs;
303  for(int i=0; i<3; i++){
304  t_graphs.emplace_back(vec_tick[i].size(),&vec_chan[i][0],&vec_tick[i][0]);
305  }
306  vec_graphs.push_back(t_graphs);
307  vec_ticks.push_back(vec_tick);
308  vec_chans.push_back(vec_chan);
309  return 0;
310  }
311 
312  int SEAviewer::addShower(art::Ptr<recob::Shower>&shr){
313  n_showers++;
314 
315  vec_showers.push_back(shr);
316 
317  return 0;
318  }
319 
320  int SEAviewer::addTrack(art::Ptr<recob::Track>&trk){
321  n_tracks++;
322 
323  vec_tracks.push_back(trk);
324 
325  return 0;
326  }
327 
328 
329  std::vector<std::vector<double>> SEAviewer::to2D(std::vector<double> & threeD){
330 
331  auto const TPC = (*geom).begin_TPC(); //returns iterator pointing to the first TPC of detector
332  auto ID = TPC.ID();
333  int fCryostat = ID.Cryostat;
334  int fTPC = ID.TPC;
335 
336  std::vector<std::vector<double>> ans(3);
337 
338  for(int i=0; i<3; i++){
339  double wire = (double)calcWire(threeD[1], threeD[2], i, fTPC, fCryostat, *geom);
340  double time = calcTime(threeD[0], i, fTPC,fCryostat, theDetector);
341 
342  ans[i] = {wire,time};
343  }
344 
345  return ans;
346  }
347 
348 
349 
350  int SEAviewer::loadVertex(double m_vertex_pos_x, double m_vertex_pos_y, double m_vertex_pos_z){
351 
352  auto const TPC = (*geom).begin_TPC();
353  auto ID = TPC.ID();
354  int fCryostat = ID.Cryostat;
355  int fTPC = ID.TPC;
356 
357  for(int i=0; i<3; i++){
358 
359  // use vector here, so that to plot the single point using TGraph
360  std::vector<double> wire = {(double)calcWire(m_vertex_pos_y, m_vertex_pos_z, i, fTPC, fCryostat, *geom)};
361  std::vector<double> time = {calcTime(m_vertex_pos_x, i, fTPC,fCryostat, theDetector)};
362 
363  vertex_tick[i] = time[0];
364  vertex_chan[i] = wire[0];
365 
366  chan_max[i] = std::max( chan_max[i],wire[0]);
367  chan_min[i] = std::min( chan_min[i],wire[0]);
368 
369  TGraph gtmp(1, &wire[0], &time[0]);
370  vertex_graph[i] = gtmp;
371  }
372 
373  return 0;
374  }
375 
376 
377  int SEAviewer::addTrueVertex(double m_vertex_pos_x, double m_vertex_pos_y, double m_vertex_pos_z){
378 
379  plot_true_vertex = true;
380 
381  auto const TPC = (*geom).begin_TPC();
382  auto ID = TPC.ID();
383  int fCryostat = ID.Cryostat;
384  int fTPC = ID.TPC;
385 
386  for(int i=0; i<3; i++){
387 
388  std::vector<double> wire = {(double)calcWire(m_vertex_pos_y, m_vertex_pos_z, i, fTPC, fCryostat, *geom)};
389  std::vector<double> time = {calcTime(m_vertex_pos_x, i, fTPC,fCryostat, theDetector)};
390 
391  true_vertex_tick[i] = time[0];
392  true_vertex_chan[i] = wire[0];
393 
394  chan_max[i] = std::max( chan_max[i],wire[0]);
395  chan_min[i] = std::min( chan_min[i],wire[0]);
396 
397  TGraph gtmp(1, &wire[0], &time[0]);
398  true_vertex_graph[i] = gtmp;
399  }
400 
401  return 0;
402  }
403 
404 
405  int SEAviewer::Print(double plot_distance){
406 
407 
408  std::string print_name = "SEAview_"+tag;
409  TCanvas *can=new TCanvas(print_name.c_str(),print_name.c_str(),3000,800);
410  can->Divide(4,1,0,0.1);
411 
412  double plot_point_size=0.4;
413 
414  //******************************* First plot "Vertex" ***************************************
415 
416  //Calculate some things
417  //Guanqun: what does tick_min - tick_shift actually mean?
418  double real_tick_min = (fabs(vertex_tick[0] - (tick_min-tick_shift))*tick_con > plot_distance) ? vertex_tick[0]-plot_distance/tick_con : tick_min-tick_shift ;
419  double real_tick_max = (fabs(vertex_tick[0] - (tick_max+tick_shift))*tick_con > plot_distance) ? vertex_tick[0]+plot_distance/tick_con : tick_max+tick_shift ;
420  //double real_tick_min = tick_min-tick_shift ;
421  //double real_tick_max = tick_max+tick_shift ;
422 
423 
424  std::vector<double> real_wire_min(3); //real x axis edges for 3 planes
425  std::vector<double> real_wire_max(3);
426 
427  for(int i=0; i<3; i++){
428  TPad * pader = (TPad*)can->cd(i+1);
429 
430  if(i==0 || i ==4 || i == 8) pader->SetLeftMargin(0.1);
431 
432  //only show area surrounding the vertex up to std::min(plot_distance, distance_bw_vertex_channel_min/max)
433  real_wire_min[i] = (fabs(vertex_chan[i] - (chan_min[i]-chan_shift))*wire_con > plot_distance ) ? vertex_chan[i]-plot_distance/wire_con : chan_min[i]-chan_shift ;
434  real_wire_max[i] = (fabs(vertex_chan[i] - (chan_max[i]+chan_shift))*wire_con > plot_distance ) ? vertex_chan[i]+plot_distance/wire_con : chan_max[i]+chan_shift ;
435 
436  //fix the area to show, always show area large enough to hold all track/showers
437  //real_wire_min[i] = chan_min[i]-chan_shift ;
438  //real_wire_max[i] = chan_max[i]+chan_shift ;
439 
440  vertex_graph[i].SetMarkerStyle(29);
441  vertex_graph[i].SetMarkerSize(2);
442  vertex_graph[i].SetMarkerColor(kMagenta-3);
443  vertex_graph[i].GetYaxis()->SetRangeUser(real_tick_min,real_tick_max);
444  vertex_graph[i].GetXaxis()->SetLimits(real_wire_min[i], real_wire_max[i]);
445  vertex_graph[i].SetTitle(("Plane " +std::to_string(i)).c_str());
446  vertex_graph[i].GetYaxis()->SetTitle("Peak Hit Time Tick");
447  vertex_graph[i].GetXaxis()->SetTitle( ("Wire Number Plane " +std::to_string(i)).c_str());
448  vertex_graph[i].Draw("ap");
449 
450  if(i>0){
451  vertex_graph[i].GetYaxis()->SetLabelOffset(999);
452  vertex_graph[i].GetYaxis()->SetLabelSize(0);
453  }
454  }
455 
456  /********************************* Non Slice Hits ****************************/
457 
458 
459  for(int i=0; i<3; i++){
460  can->cd(i+1);
461  if(vec_all_graphs[i].GetN()>0){//need a check in case this track has no hits on this plane.
462  vec_all_graphs[i].Draw("p same");
463  vec_all_graphs[i].SetMarkerColor(kGray);
464  vec_all_graphs[i].SetFillColor(kWhite);
465  vec_all_graphs[i].SetMarkerStyle(20);
466  vec_all_graphs[i].SetMarkerSize(plot_point_size*0.75);
467  }
468  }
469 
470  //******************************** DeadWireRegions********************************************
471  for(size_t i=0; i< m_bad_channel_list.size(); i++){
472  int badchan = m_bad_channel_list[i].first;
473  int ok = m_bad_channel_list[i].second;
474 
475  if(ok>1)continue;
476  auto hs = geom->ChannelToWire(badchan); //type of hs: vector containing the ID of all the connected wires
477 
478  int thisp = (int)hs[0].Plane;
479  double bc = hs[0].Wire;
480 
481  if(real_wire_min[thisp] < bc && bc < real_wire_max[thisp] ){
482  //if(chan_min[thisp]-chan_shift < bc && bc < chan_max[thisp]+chan_shift ){}
483  can->cd(thisp+1);
484  TLine *l = new TLine(bc, real_tick_min, bc, real_tick_max);
485  //TLine *l = new TLine(bc,tick_min-tick_shift,bc,tick_max+tick_shift);
486  l->SetLineColor(kGray+1);
487  l->Draw("same");
488  //can->cd(thisp+5);// Guanqun: how many values can plane ID take?
489  //l->Draw("same");
490  //can->cd(thisp+9);
491  //l->Draw("same");
492  }
493  }
494 
495 
496  ///******************************** Plotting all PFP's *********************************8
497 
498  std::vector<int> tcols = {kRed-7, kBlue-7, kGreen-3, kOrange-3, kCyan-3, kMagenta-3, kGreen+1 , kRed+1};
499  int used_col=0;
500 
501  if(n_pfps > (int)tcols.size()){
502  for(int i =0; i< (int)(n_pfps +2); i++){
503  //tcols.push_back(tcols[(int)rangen->Uniform(0,7)]+(int)rangen->Uniform(-5,5));
504  tcols.push_back(kRed);
505  }
506  }
507 
508 
509  for(int p=0; p<n_pfps; p++){
510 
511  int tcol = tcols[used_col];
512  used_col++;
513 
514  for(int i=0; i<3; i++){
515  can->cd(i+1);
516  if(vec_graphs[p][i].GetN()>0){//need a check in case this track has no hits on this plane.
517 
518  vec_graphs[p][i].Draw("p same");
519  vec_graphs[p][i].SetMarkerColor(tcol);
520  vec_graphs[p][i].SetFillColor(tcol);
521  vec_graphs[p][i].SetMarkerStyle(20);
522  vec_graphs[p][i].SetMarkerSize(plot_point_size);
523  }
524  }
525  }
526 
527 
528  //Plot all Shower lines. Might need a bit of work here..
529  std::vector<TLine*> lines;
530 
531  for(size_t s=0; s<vec_showers.size(); ++s){
532  std::vector<double> shr_start_3D= {vec_showers[s]->ShowerStart().X(), vec_showers[s]->ShowerStart().Y(),vec_showers[s]->ShowerStart().Z()};
533  std::vector<double> shr_other_3D= {vec_showers[s]->ShowerStart().X()+vec_showers[s]->Direction().X(),vec_showers[s]->ShowerStart().Y()+vec_showers[s]->Direction().Y(), vec_showers[s]->ShowerStart().Z()+vec_showers[s]->Direction().Z()};
534 
535  //std::cout<<" "<<shr_start_3D[0]<<" "<<shr_start_3D[1]<<" "<<shr_start_3D[2]<<std::endl;
536  //std::cout<<" "<<shr_other_3D[0]<<" "<<shr_other_3D[1]<<" "<<shr_other_3D[2]<<std::endl;
537 
538  std::vector<std::vector<double>> start_pt = this->to2D(shr_start_3D);
539  std::vector<std::vector<double>> other_pt = this->to2D(shr_other_3D);
540 
541  for(int i=0; i<3; i++){
542  //std::cout<<start_pt[i][0]<<" "<<start_pt[i][1]<<" "<<other_pt[i][0]<<" "<<other_pt[i][1]<<std::endl;
543  can->cd(i+1);
544  double slope = (start_pt[i][1]-other_pt[i][1])/(start_pt[i][0]-other_pt[i][0]);
545  double inter = start_pt[i][1]-slope*start_pt[i][0];
546 
547  double x1_plot = other_pt[i][0];//chan_min[i]-chan_shift;
548  double y1_plot = slope*x1_plot+inter;
549 
550  double x2_plot;
551  if(other_pt[i][0]<start_pt[i][0]){
552  //x2_plot = chan_max[i]+chan_shift; //guanqun: my guess is this needs to be updated as well to use real_wire_max/min
553  x2_plot = real_wire_max[i];
554  }else{
555  //x2_plot = chan_min[i]-chan_shift;
556  x2_plot = real_wire_min[i];
557  }
558  double y2_plot = slope*x2_plot+inter;
559 
560  can->cd(i+1);
561  TLine *l = new TLine(x1_plot, y1_plot, x2_plot, y2_plot);
562  lines.push_back(l);
563  l->SetLineColorAlpha(tcols[s],0.5);
564  l->SetLineWidth(1);
565  l->SetLineStyle(2);
566  l->Draw();
567 
568  }
569 
570  }
571 
572  /********************************* Unassociated Hits ****************************/
573  for(int i=0; i<3; i++){
574  can->cd(i+1);
575  if(vec_unass_graphs[i].GetN()>0){//need a check in case this track has no hits on this plane.
576 
577  vec_unass_graphs[i].Draw("p same");
578  vec_unass_graphs[i].SetMarkerColor(kBlack);
579  vec_unass_graphs[i].SetFillColor(kBlack);
580  vec_unass_graphs[i].SetMarkerStyle(20);
581  vec_unass_graphs[i].SetMarkerSize(plot_point_size);
582  }
583  }
584 
585  /******************************* Clustered Hits ***********************************/
586  // draw cluster hits after drawing all unassociated hits such that clustered hits would be colored while un-clustered ones will be black.
587  if(has_been_clustered){
588 
589  std::vector<int> cluster_colors(vec_clusters.size()+1,0);
590  std::vector<int> base_col = {632,416, 600, 400, 616, 432, 800, 820, 840, 860, 880, 900};
591 
592  for(size_t j=0; j< vec_clusters.size()+1; j++){
593  int b = (int)rangen->Uniform(0,11);
594  int mod = (int)rangen->Uniform(-10,+3);
595 
596  cluster_colors[j] = base_col[b]+mod;
597  }
598  int c_offset = 0;
599 
600  for(auto &c: vec_clusters){
601  int pl = c.getPlane();
602  can->cd(pl+1);
603  if (c.getGraph()->GetN()>0){
604  c.getGraph()->Draw("p same");
605  c.getGraph()->SetMarkerColor(cluster_colors[c_offset]);
606  c.getGraph()->SetFillColor(cluster_colors[c_offset]);
607  c.getGraph()->SetMarkerStyle(20);
608  //c.getGraph()->SetMarkerSize(plot_point_size);
609  c.getGraph()->SetMarkerSize(plot_point_size*1.5);
610  //std::cout<<"Printing cluster "<<c.getID()<<" on plane "<<pl<<" col "<<cluster_colors[c_offset]<<std::endl;
611  //auto ll = c.getPTS();
612  //for(auto &p :ll){
613  // std::cout<<p[0]<<" "<<p[1]<<std::endl;
614  //}
615  }
616  c_offset++;
617  }
618  }//end clusters
619 
620 
621 
622  //****** just plto vertex again with elipse;
623  for(int i=0; i<3; i++){
624  can->cd(i+1);
625  vertex_graph[i].Draw("p same");
626 
627  double rad_cm = 12.0;
628  TEllipse ell_p(vertex_chan[i],vertex_tick[i],rad_cm/wire_con,rad_cm/tick_con);
629  ell_p.SetLineColor(kRed);
630  ell_p.SetFillStyle(0);
631  ell_p.Draw("same");
632  }
633 
634  //**************************** INFO ***************************/
635  TPad *p_top_info = (TPad*)can->cd(4);
636  p_top_info->cd();
637 
638  /*TLatex pottex;
639  pottex.SetTextSize(0.045);
640  pottex.SetTextAlign(13); //align at top
641  pottex.SetNDC();
642  std::string pot_draw = "Run: "+std::to_string(m_run_number)+" SubRun: "+std::to_string(m_subrun_number)+" Event: "+std::to_string(m_event_number);
643  pottex.DrawLatex(.1,.94, pot_draw.c_str());
644  */
645  TLegend l_top(0.1,0.0,0.9,1.0);
646  l_top.SetTextSize(0.05);
647 
648  for(int p=0; p<n_pfps; p++){
649 
650 
651  if(vec_graphs[p][0].GetN()>0){
652  l_top.AddEntry(&vec_graphs[p][0],vec_pfp_legend[p].c_str(),"f");
653  }else if(vec_graphs[p][1].GetN()>0){
654  l_top.AddEntry(&vec_graphs[p][1],vec_pfp_legend[p].c_str(),"f");
655  }else if(vec_graphs[p][2].GetN()>0){
656  l_top.AddEntry(&vec_graphs[p][2],vec_pfp_legend[p].c_str(),"f");
657  }
658 
659  }
660 
661  // draw legend for clustered hits if there is any
662  for(const auto &cluster : vec_clusters){
663 
664  // only consider clusters that are second shower candidates
665  if(cluster.getLegend().empty()) continue;
666 
667  // if the cluster is out of the plotting range, do not include it in the legend
668  if(cluster.InRange(real_tick_max, real_tick_min, real_wire_max[cluster.getPlane()], real_wire_min[cluster.getPlane()])){
669  l_top.AddEntry(cluster.getGraph(), cluster.getLegend().c_str(), "f");
670  }
671  }
672 
673  l_top.SetHeader(print_name.c_str(),"C");
674  l_top.SetLineWidth(0);
675  l_top.SetLineColor(kWhite);
676  l_top.Draw("same");
677 
678 
679 
680  can->Update();
681  can->SaveAs((print_name+".pdf").c_str(),"pdf");
682 
683 
684  return 0;
685  }
686 
687  int SEAviewer::runseaDBSCAN(double min_pts, double eps){
688 
689  has_been_clustered = true;
690  num_clusters = {0,0,0};
691  cluster_labels.resize(3);
692 
693  for(int i=0; i<3; i++){
694 
695  std::cout<<"SinglePhoton::seaDBSCAN\t||\tStarting to run seaDBSCAN for plane: "<<i<<" has "<<vec_unass_pts[i].size()<<" pts to do using eps: "<<eps<<" and min_pts: "<<min_pts<<std::endl;
696  seaDBSCAN ReCluster(eps,min_pts);
697  cluster_labels[i] = ReCluster.Scan2D(vec_unass_pts[i]);
698 
699  for(auto &c: cluster_labels[i]){
700  num_clusters[i] = std::max(c,num_clusters[i]);
701 
702  }
703 
704  std::cout << "SinglePhoton::seaDBSCAN\t||\tOn this plane "<<i<<" seaDBSCAN found: "<<num_clusters[i]<<" clusters"<<std::endl;
705  }
706 
707  //Now fill the clusters
708 
709  for(int i=0; i<3; i++){
710 
711  for(int c=0; c<num_clusters[i]+1; c++){
712 
713  std::vector<std::vector<double>> t_pts;
714  std::vector<art::Ptr<recob::Hit>> hitz;
715 
716 
717  for(size_t p=0; p< vec_unass_pts[i].size(); p++){
718  if(cluster_labels[i][p] == 0) continue;//noise
719  if(cluster_labels[i][p] == c){
720 
721  t_pts.push_back(vec_unass_pts[i][p]);
722  hitz.push_back(vec_unass_hits[i][p]);
723  }
724 
725  }
726 
727  if(hitz.size()!=0){
728  std::cout<<"SinglePhoton::seaDBSCAN\t||\t Cluster "<<vec_clusters.size()+1<<" has "<<hitz.size()<<" hitz on plane "<<i<<std::endl;
729  vec_clusters.emplace_back(vec_clusters.size()+1,i,t_pts,hitz);
730  }
731  }
732  }
733 
734  return 0;
735  }
736 
737  std::vector<double> SEAviewer::analyzeTrackLikeClusters(double eps, const std::map<art::Ptr<recob::Shower>, art::Ptr<recob::PFParticle>> & showerToPFParticleMap, const std::map<art::Ptr<recob::PFParticle>, std::vector<art::Ptr<recob::Hit>> > & pfParticleToHitsMap,std::vector<seaview::cluster>& vec_in_clusters ){
738 
739 
740  // Grab the shower start and shower direction
741  std::vector<double> shr_start_3D= {vec_showers[0]->ShowerStart().X(), vec_showers[0]->ShowerStart().Y(),vec_showers[0]->ShowerStart().Z()};
742  std::vector<double> shr_other_3D= {vec_showers[0]->ShowerStart().X()+vec_showers[0]->Direction().X(),vec_showers[0]->ShowerStart().Y()+vec_showers[0]->Direction().Y(), vec_showers[0]->ShowerStart().Z()+vec_showers[0]->Direction().Z()};
743 
744  std::vector<std::vector<double>> shr_start_pt = this->to2D(shr_start_3D);
745  std::vector<std::vector<double>> shr_other_pt = this->to2D(shr_other_3D);
746 
747 
748 
749  //Loop over all clusters
750  for(size_t c=0; c< vec_clusters.size(); c++){
751 
752  auto hitz = vec_clusters[c].getHits(); // type of hitz: std::vector<art::Ptr<recob::Hit>>
753  int num_hits_in_cluster = vec_clusters[c].getHits().size();
754  int pl = vec_clusters[c].getPlane();
755 
756  //Need to modify this a bit
757  auto ssscorz = SeaviewScoreCluster(pl,c+1, hitz ,vertex_chan[pl], vertex_tick[pl], vec_showers.front());
758  vec_clusters[c].setScore(ssscorz);
759  vec_clusters[c].setWireTickBasedLength(sqrt(pow((ssscorz.max_wire-ssscorz.min_wire)*wire_con, 2.0) + pow((ssscorz.max_tick - ssscorz.min_tick)*tick_con, 2.0)));
761  TrackLikeClusterAnalyzer(vec_clusters[c], shr_start_pt[pl], shr_other_pt[pl]);
762 
763  //This is just checking if its in, we can do this earlier; TODO
764  //TODO: is_in_shower, get back to primary shower (at least available)
765  //Sim Stuff
766  //Draw Direction on plot
767  //Delauney on here might be good, that said, we have a LOT of things. Hmm, cap at 50 hits maybe?
768  int is_in_shower = SeaviewCompareToShowers(pl,c+1, hitz ,vertex_chan[pl], vertex_tick[pl], vec_showers, showerToPFParticleMap, pfParticleToHitsMap,eps);
769  vec_clusters[c].setShowerRemerge(is_in_shower);
770 
771  std::string sname = "Cluster "+std::to_string(c)+", Hits: "+std::to_string(num_hits_in_cluster)+", PCA "+std::to_string(ssscorz.pca_0)+", Theta:" +std::to_string(ssscorz.pca_theta)+", Wires: "+std::to_string(ssscorz.n_wires)+ ", Ticks: "+std::to_string(ssscorz.n_ticks)+", ReMerged: "+std::to_string(is_in_shower);
772  std::cout<<sname << "\n" <<std::endl;
773 
774 
775  }//cluster loop
776 
777  vec_in_clusters = vec_clusters;
778 
779  return {0};
780 
781  }
782 
783  std::vector<double> SEAviewer::analyzeShowerLikeClusters(double eps, const std::map<art::Ptr<recob::Shower>, art::Ptr<recob::PFParticle>> & showerToPFParticleMap, const std::map<art::Ptr<recob::PFParticle>, std::vector<art::Ptr<recob::Hit>> > & pfParticleToHitsMap,std::vector<seaview::cluster>& vec_in_clusters ){
784 
785  /*
786  std::vector<std::vector<double>> percent_matched(vec_clusters.size(), std::vector<double>(vec_clusters.size(),0.0));
787  for(size_t c=0; c< vec_clusters.size(); c++){
788  //Loop over all hits in this clusters
789  for(size_t c2 = 0; c2 < vec_clusters.size(); c2++){
790  int n2_hits = vec_clusters[c2].getHits().size();
791  int n2_matched = 0;
792  if(vec_clusters[c2].getPlane() == vec_clusters[c].getPlane()) continue; //ignore clusters on same plane
793  for(auto &h : vec_clusters[c].getHits()){
794  //get time spread of this hit.
795  double pp = h->PeakTimePlusRMS(1.0);
796  double pm = h->PeakTimeMinusRMS(1.0);
797  for(auto &h2 : vec_clusters[c2].getHits()){
798  if(h2->PeakTime() < pp && h2->PeakTime() > pm) n2_matched++;
799  }
800  }
801  percent_matched[c][c2] = ((double)n2_matched)/((double)n2_hits)*100.0;
802  std::cout<<" Cluster "<<c<<" on plane "<<vec_clusters[c].getPlane()<<" matches with "<<percent_matched[c][c2]<<" percent of hits of cluster "<<c2<<" on plane "<<vec_clusters[c2].getPlane()<<std::endl;
803  }
804  }
805  */
806 
807  //This is where I will copy over a lot of the old SSS codebase
808  std::vector<double> shr_start_3D= {vec_showers[0]->ShowerStart().X(), vec_showers[0]->ShowerStart().Y(),vec_showers[0]->ShowerStart().Z()};
809  std::vector<double> shr_other_3D= {vec_showers[0]->ShowerStart().X()+vec_showers[0]->Direction().X(),vec_showers[0]->ShowerStart().Y()+vec_showers[0]->Direction().Y(), vec_showers[0]->ShowerStart().Z()+vec_showers[0]->Direction().Z()};
810 
811  std::vector<std::vector<double>> shr_start_pt = this->to2D(shr_start_3D);
812  std::vector<std::vector<double>> shr_other_pt = this->to2D(shr_other_3D);
813 
814 
815 
816  //Loop over all clusters
817  for(size_t c=0; c< vec_clusters.size(); c++){
818 
819  auto hitz = vec_clusters[c].getHits(); // type of hitz: std::vector<art::Ptr<recob::Hit>>
820  int num_hits_in_cluster = vec_clusters[c].getHits().size();
821  int pl = vec_clusters[c].getPlane();
822 
823  //Need to modify this a bit
824  auto ssscorz = SeaviewScoreCluster(pl,c+1, hitz ,vertex_chan[pl], vertex_tick[pl], vec_showers.front());
825  vec_clusters[c].setScore(ssscorz);
826  vec_clusters[c].setWireTickBasedLength(sqrt(pow((ssscorz.max_wire-ssscorz.min_wire)*wire_con, 2.0) + pow((ssscorz.max_tick - ssscorz.min_tick)*tick_con, 2.0)));
828 
829  //This is just checking if its in, we can do this earlier; TODO
830  //TODO: is_in_shower, get back to primary shower (at least available)
831  //Sim Stuff
832  //Draw Direction on plot
833  //Delauney on here might be good, that said, we have a LOT of things. Hmm, cap at 50 hits maybe?
834  int is_in_shower = SeaviewCompareToShowers(pl,c+1, hitz ,vertex_chan[pl], vertex_tick[pl], vec_showers, showerToPFParticleMap, pfParticleToHitsMap,eps);
835 
836  std::string sname = "Cluster "+std::to_string(c)+" Hits: "+std::to_string(num_hits_in_cluster)+" PCA: "+std::to_string(ssscorz.pca_0)+" Theta: " +std::to_string(ssscorz.pca_theta)+" Wires: "+std::to_string(ssscorz.n_wires)+ " Ticks: "+std::to_string(ssscorz.n_ticks)+" ReMerged: "+std::to_string(is_in_shower);
837  std::cout<<sname<<std::endl;
838 
839  if(ssscorz.pass){
840 
841  if(num_hits_in_cluster>0){
842 
843 
844  TGraph * tmp = (TGraph*)vec_clusters[c].getGraph()->Clone(("tmp_"+std::to_string(pl)+std::to_string(c)).c_str());
845 
846  int Npts = 20;
847  //TODO need to write this function
848  TGraph * core = (TGraph*)SeaviewGetNearestNpts(pl,c+1,hitz,vertex_chan[pl],vertex_tick[pl],Npts);
849 
850  core->Draw("p same");
851  tmp->Draw("p same");
852 
853  double fmax = -999;
854  double fmin = 99999;
855  for(int b=0; b<core->GetN(); b++){
856  double ttx=0;
857  double tty=0;
858  core->GetPoint(b,ttx,tty);
859  fmax = std::max(fmax, ttx);
860  fmin = std::min(fmin,ttx);
861  }
862 
863  //std::cout<<"Just Before Core Fit of "<<tmp->GetN()<<" pts between "<<chan_min[pl]<<" "<<chan_max[pl]<<" or "<<fmin<<" "<<fmax<<std::endl;
864 
865  double con;
866  double slope;
867  if(fmin==fmax){
868  slope = 0;
869  con = fmin;
870  }else{
871  core->Fit("pol1","Q","same",fmin,fmax); // fit to polynomial of degree 1, and plot it on the same pad
872  con = core->GetFunction("pol1")->GetParameter(0);
873  slope = core->GetFunction("pol1")->GetParameter(1);
874  }
875 
876  double impact_parameter = 1e10;
877 
878  //rudimentary!
879  for(double k=chan_min[pl]; k< chan_max[pl];k++){
880  double y = slope*k+con;
881  double dist = dist_point_point(k, y, vertex_chan[pl], vertex_tick[pl]);
882  impact_parameter = std::min(impact_parameter,dist);
883  }
884 
885  //Lets assume its potining back to the "vertex" and calculate a kinda_angle w.r.t to the shower
886  //vertex_wire[i] vertex_tick[i] (already calcuated)
887  //cluster closest point )ssscorz.close_wire and close_tick
888  //recob::Shower start point, convered to wire tick.
889  std::vector<double> vec_c = {(double)(vertex_chan[pl]-ssscorz.close_wire), (double)(vertex_tick[pl]-ssscorz.close_tick)};
890  std::vector<double> vec_s = {(double)vertex_chan[pl]-shr_start_pt[pl][0], (double)vertex_tick[pl]-shr_start_pt[pl][1]};
891  double l_c = sqrt(pow(wire_con*vec_c[0],2)+pow(vec_c[1]*tick_con,2));
892  double l_s = sqrt(pow(wire_con*vec_s[0],2)+pow(vec_s[1]*tick_con,2));
893  double kinda_angle = acos((wire_con*vec_s[0]*wire_con*vec_c[0]+vec_c[1]*vec_s[1]*tick_con*tick_con )/(l_c*l_s));
894 
895 
896  std::cout<<"SSSNEW "<<this->tag<<std::endl;
897  std::cout<<pl<<" Num Hits "<<num_hits_in_cluster<<std::endl;
898  std::cout<<pl<<" Num Wires "<< (int)ssscorz.n_wires<<std::endl;
899  std::cout<<pl<<" Num Ticks "<< (int)ssscorz.n_ticks<<std::endl;
900  std::cout<<pl<<" Plane "<<pl<<std::endl;
901  std::cout<<pl<<" PCA "<<ssscorz.pca_0<<std::endl;
902  std::cout<<pl<<" Impact "<<impact_parameter<<std::endl;
903  std::cout<<pl<<" Fit Slope "<<slope<<std::endl;
904  std::cout<<pl<<" Fit Constant "<<con<<std::endl;
905  std::cout<<pl<<" Mean Tick "<<ssscorz.mean_tick<<std::endl;
906  std::cout<<pl<<" Max Tick "<<ssscorz.max_tick<<std::endl;
907  std::cout<<pl<<" Min Tick "<<ssscorz.min_tick<<std::endl;
908  std::cout<<pl<<" Mean Wire "<<ssscorz.mean_wire<<std::endl;
909  std::cout<<pl<<" Max Wire "<<ssscorz.max_wire<<std::endl;
910  std::cout<<pl<<" Min Wire "<<ssscorz.min_wire<<std::endl;
911  std::cout<<pl<<" Kinda Angle "<<kinda_angle<<std::endl;
912 
913  vec_clusters[c].setShowerRemerge(is_in_shower);
914  vec_clusters[c].setImpactParam(impact_parameter);
915  vec_clusters[c].setFitSlope(slope);
916  vec_clusters[c].setFitCons(con);
917  vec_clusters[c].setAngleWRTShower(kinda_angle);
918  }
919  } // if ssscorz has passed
920 
921  }//cluster loop
922 
923  vec_in_clusters = vec_clusters;
924 
925 
926 
927 
928  /*
929  //Relative to showers!
930  for(size_t s=0; s<vec_showers.size(); ++s){
931  std::vector<double> shr_start_3D= {vec_showers[s]->ShowerStart().X(), vec_showers[s]->ShowerStart().Y(),vec_showers[s]->ShowerStart().Z()};
932  std::vector<double> shr_other_3D= {vec_showers[s]->ShowerStart().X()+vec_showers[s]->Direction().X(),vec_showers[s]->ShowerStart().Y()+vec_showers[s]->Direction().Y(), vec_showers[s]->ShowerStart().Z()+vec_showers[s]->Direction().Z()};
933 
934  std::vector<std::vector<double>> start_pt = this->to2D(shr_start_3D);
935  std::vector<std::vector<double>> other_pt = this->to2D(shr_other_3D);
936 
937  for(int i=0; i<3; i++){
938  double slope = (start_pt[i][1]-other_pt[i][1])/(start_pt[i][0]-other_pt[i][0]);
939  double inter = start_pt[i][1]-slope*start_pt[i][0];
940 
941  double x1_plot = other_pt[i][0];//chan_min[i]-chan_shift;
942  double y1_plot = slope*x1_plot+inter;
943 
944  double x2_plot;
945  if(other_pt[i][0]<start_pt[i][0]){
946  x2_plot = chan_max[i]+chan_shift;
947  }else{
948  x2_plot = chan_min[i]-chan_shift;
949  }
950  double y2_plot = slope*x2_plot+inter;
951 
952  TLine *l = new TLine(x1_plot, y1_plot, x2_plot, y2_plot);
953 
954 
955  //Ok now find the min distance from this line to all clusters on this plane
956 
957  for(size_t c=0; c< vec_clusters.size(); c++){
958  int pl = vec_clusters[c].getPlane();
959  if(pl != i ) continue;
960 
961  double min_d = 1e10;
962  int min_p = -9;
963 
964  for(size_t p = 0; p< vec_clusters[c].getPts().size(); p++){
965  std::vector<double> pt = (vec_clusters[c].getPts())[p];
966  double dist = this->dist_line_point({x1_plot*wire_con,y1_plot*tick_con}, {x2_plot*wire_con,y2_plot*tick_con}, {pt[0]*wire_con, pt[1]*tick_con});
967 
968  if(dist< min_d){
969  min_p = (int)p;
970  min_d = dist;
971  }
972  }
973 
974  }
975 
976 
977 
978  }
979 
980  }
981  */
982 
983  return {0};
984 
985 
986  }
987 
988  double SEAviewer::dist_line_point( const std::vector<double>&X1, const std::vector<double>& X2, const std::vector<double>& point){
989  // convert {wire, tick} coordinate to [cm, cm] coordinate
990  double x1 =X1.at(0)*wire_con;
991  double y1 =X1.at(1)*tick_con;
992 
993  double x2 =X2.at(0)*wire_con;
994  double y2 =X2.at(1)*tick_con;
995 
996  double x0 =point.at(0)*wire_con;
997  double y0 =point.at(1)*tick_con;
998 
999  double x10 = x1-x0;
1000  double y10 = y1-y0;
1001 
1002  double x21 = x2-x1;
1003  double y21 = y2-y1;
1004 
1005  double t = -(x10*x21+y10*y21)/fabs(x21*x21+y21*y21);
1006 
1007  double d2 = pow(x1-x0,2)+pow(y1-y0,2)+2*t*((x2-x1)*(x1-x0)+(y2-y1)*(y1-y0))+t*t*( pow(x2-x1,2)+pow(y2-y1,2));
1008 
1009 
1010  return sqrt(d2);
1011 
1012  }
1013 
1014  cluster_score SEAviewer::SeaviewScoreCluster(int p, int cl, std::vector<art::Ptr<recob::Hit>> &hits, double vertex_wire, double vertex_tick, const art::Ptr<recob::Shower> &shower){
1015  cluster_score score(p,cl);
1016  score.n_hits = hits.size();
1017 
1018  std::vector<double> t_wires;
1019  std::vector<double> t_ticks;
1020 
1021  //
1022  int n_min_ticks = 4;
1023  int n_min_wires = 3;
1024  double n_max_pca = 0.9999;
1025 
1026  score.pass = true;
1027 
1028  // ************* Some simple metrics relative to study point (usually vertex) ***************
1029  score.max_dist_tick = 0;
1030  score.min_dist_tick = 1e10;
1031  score.mean_dist_tick = 0;
1032 
1033  score.max_dist_wire = 0;
1034  score.min_dist_wire = 1e10;
1035  score.mean_dist_wire = 0;
1036 
1037  score.max_dist = 0;
1038  score.min_dist = 1e10;
1039  score.mean_dist = 0;
1040 
1041  score.mean_tick =0;
1042  score.max_tick =0;
1043  score.min_tick =1e10;
1044 
1045  score.mean_wire =0;
1046  score.max_wire =0;
1047  score.min_wire =1e10;
1048 
1049  score.n_wires = 0;
1050  score.n_ticks = 0;
1051 
1052  score.impact_parameter = -99;
1053 
1054  score.close_tick = -99;
1055  score.close_wire = -99;
1056 
1057  std::map<int,bool> wire_count;
1058  std::map<int,bool> tick_count;
1059 
1060 
1061  for(auto &h: hits){
1062  double h_tick = (double)h->PeakTime();
1063  double h_wire = (double)h->WireID().Wire;
1064 
1065  score.mean_wire += h_wire;
1066  score.mean_tick += h_tick;
1067 
1068  score.max_wire = std::max(score.max_wire, h_wire);
1069  score.min_wire = std::min(score.min_wire, h_wire);
1070 
1071  score.max_tick = std::max(score.max_tick, h_tick);
1072  score.min_tick = std::min(score.min_tick, h_tick);
1073 
1074  score.max_dist_tick = std::max(score.max_dist_tick, fabs(h_tick-vertex_tick));
1075  score.min_dist_tick = std::min(score.min_dist_tick, fabs(h_tick-vertex_tick));
1076 
1077  score.max_dist_wire = std::max(score.max_dist_wire, fabs(h_wire-vertex_wire));
1078  score.min_dist_wire = std::min(score.min_dist_wire, fabs(h_wire-vertex_wire));
1079 
1080  score.mean_dist_tick += fabs(h_tick-vertex_tick);
1081  score.mean_dist_wire += fabs(h_wire-vertex_wire);
1082 
1083  //wierd dits
1084  double dd = dist_point_point(h_wire, h_tick, vertex_wire, vertex_tick);
1085  score.mean_dist += dd;
1086  if(dd< score.min_dist){
1087  score.close_wire = h_wire;
1088  score.close_tick = h_tick;
1089  }
1090 
1091  score.max_dist = std::max(dd,score.max_dist);
1092  score.min_dist = std::min(dd,score.min_dist);
1093 
1094 
1095  t_wires.push_back(h_wire);
1096  t_ticks.push_back(h_tick);
1097 
1098  if(wire_count.count((int)h_wire)<1){
1099  wire_count[((int)h_wire)] = true;
1100  score.n_wires++;
1101  }
1102  if(tick_count.count((int)h_tick)<1){
1103  tick_count[((int)h_tick)] = true;
1104  score.n_ticks++;
1105  }
1106 
1107  }
1108 
1109  // TGraph * g_pts = new TGraph(t_wires.size(),&t_ticks[0],&t_wires[0]);
1110 
1111  score.mean_tick = score.mean_tick/(double)score.n_hits;
1112  score.mean_wire = score.mean_wire/(double)score.n_hits;
1113 
1114  score.mean_dist = score.mean_dist/(double)score.n_hits;
1115 
1116  score.mean_dist_tick = score.mean_dist_tick/(double)score.n_hits;
1117  score.mean_dist_wire = score.mean_dist_wire/(double)score.n_hits;
1118 
1119  // **************** Metrics of Pointing: Does this cluster "point" back to the vertex? *************************
1120  // **************** First off, PCA
1121 
1122 
1123  TPrincipal* principal = new TPrincipal(2,"D");
1124  double mod_wire = 1.0;
1125  double mod_tick = 1.0;
1126 
1127  for(int i = 0; i < score.n_hits; i++){
1128  std::vector<double> tmp_pts = {t_wires[i]*mod_wire, t_ticks[i]/mod_tick};
1129  principal->AddRow(&tmp_pts[0]);
1130  }
1131  principal->MakePrincipals();
1132  //principal->Print();
1133 
1134  TVectorD * eigenval = (TVectorD*) principal->GetEigenValues();
1135  //TMatrixD * eigenvec = (TMatrixD*) principal->GetEigenVectors();
1136  TMatrixD * covar = (TMatrixD*) principal->GetCovarianceMatrix();
1137 
1138  score.pca_0 = (*eigenval)(0);
1139  score.pca_1 = (*eigenval)(1);
1140 
1141  //(*eigenvec).Print();
1142  //(*covar).Print();
1143  //std::cout<<"SinglePhoton::SSS\t||\tEigen: "<<score.pca_0<<" "<<score.pca_1<<std::endl;
1144 
1145  score.pca_theta = atan((*covar)[0][0]/(*covar)[0][1])*180.0/3.14159;
1146 
1147 
1148  double slope = ((*covar)[0][0]/(*covar)[0][1]);
1149  double c = score.mean_tick*mod_wire - slope*score.mean_wire/mod_tick;
1150  score.impact_parameter = fabs(slope*vertex_wire*mod_wire +vertex_tick/mod_tick+c)/sqrt(slope*slope+1.0*1.0);
1151 
1152 
1153 
1154  if(score.n_wires < n_min_wires || score.n_ticks < n_min_ticks || score.pca_0 >= n_max_pca){
1155  score.pass = false;
1156  }
1157 
1158 
1159 
1160 
1161  delete principal;
1162 
1163  return score;
1164  }
1165 
1166  int SEAviewer::SeaviewCompareToShowers(int p ,int cl, std::vector<art::Ptr<recob::Hit>>& hitz,double vertex_wire,double vertex_tick, std::vector<art::Ptr<recob::Shower>>& showers, const std::map<art::Ptr<recob::Shower>, art::Ptr<recob::PFParticle>> & showerToPFParticleMap, const std::map<art::Ptr<recob::PFParticle>, std::vector<art::Ptr<recob::Hit>> > & pfParticleToHitsMap, double eps){
1167 
1168 
1169  for(size_t s =0; s< showers.size(); s++){
1170  art::Ptr<recob::Shower> shower = showers[s];
1171  art::Ptr<recob::PFParticle> pfp = showerToPFParticleMap.at(shower); //key has to be in the map, otherwise out-of-range error
1172  std::vector<art::Ptr<recob::Hit>> showerhits = pfParticleToHitsMap.at(pfp);
1173 
1174  bool in_primary_shower = false;
1175  for(size_t h = 0; h< hitz.size(); h++){
1176  auto hit = hitz[h];
1177  double h_wire = (double)hit->WireID().Wire;
1178  double h_tick = (double)hit->PeakTime();
1179 
1180 
1181  for(auto &sh: showerhits){
1182 
1183  if(sh->View() != hit->View()) continue; //Guanqun: if not on the same plane?
1184 
1185  double sh_wire = (double)sh->WireID().Wire;
1186  double sh_tick = (double)sh->PeakTime();
1187 
1188  double dist = dist_point_point(sh_wire, sh_tick, h_wire, h_tick);
1189 
1190  if(dist<=eps){
1191  in_primary_shower = true;
1192  return (int)s;
1193  }
1194 
1195  }
1196 
1197  } // end of hitz loop
1198 
1199  if(in_primary_shower){
1200  return (int)s;
1201  }
1202  }
1203 
1204 
1205  return -1;
1206  }
1207 
1208 
1209 
1210  TGraph* SEAviewer::SeaviewGetNearestNpts(int p, int cl, std::vector<art::Ptr<recob::Hit>> &hitz, double vertex_wire, double vertex_tick, int Npts){
1211 
1212  std::vector<double>t_wire;
1213  std::vector<double>t_tick;
1214  // std::vector<double>t_dist;
1215 
1216  std::vector<double>all_wire;
1217  std::vector<double>all_tick;
1218  std::vector<double>all_dist;
1219 
1220 
1221  for(size_t h = 0; h< hitz.size(); h++){
1222  auto hit = hitz[h];
1223  double h_wire = (double)hit->WireID().Wire;
1224  double h_tick = (double)hit->PeakTime();
1225 
1226  double dd = dist_point_point(h_wire, h_tick, vertex_wire, vertex_tick);
1227  all_wire.push_back(h_wire);
1228  all_tick.push_back(h_tick);
1229  all_dist.push_back(dd);
1230  }
1231 
1232  // sorted_in has indices of elements in all_dist in descending order
1233  std::vector<size_t> sorted_in = seaview_sort_indexes(all_dist);
1234  size_t max_e = std::min((size_t)Npts,hitz.size());
1235 
1236  for(size_t i =0; i<max_e; i++){ // get the position ({wire, tick}) of the closest 'max_e' points.
1237  t_wire.push_back(all_wire[sorted_in[hitz.size()-1-i]]);
1238  t_tick.push_back(all_tick[sorted_in[hitz.size()-1-i]]);
1239  }
1240 
1241  return new TGraph(t_wire.size(),&t_wire[0],&t_tick[0]);
1242  }
1243 
1244 
1246 
1247  //grab all hits in cluster
1248  const std::vector<art::Ptr<recob::Hit>>& hitz = cl.getHits();
1249  cl.f_ADC_hist.StatOverflows(kTRUE);
1250 
1251  for(auto& h : hitz){
1252  cl.f_ADC_hist.Fill(h->SummedADC());
1253  }
1254 
1255  cl.f_meanADC = cl.f_ADC_hist.GetMean();
1256  cl.f_ADC_RMS = cl.f_ADC_hist.GetRMS();
1257  return;
1258  }
1259 
1260 
1261 
1262  void SEAviewer::SetClusterLegend(int cluster, double energy, int is_matched, int matched_pdg, double overlay_fraction){
1263 
1264  //grab the plane number, and impact parameter of the cluster
1265  int plane = vec_clusters.at(cluster).getPlane();
1266  double min_ioc_to_shower = vec_clusters.at(cluster).getMinHitIOC();
1267 
1268  //need to use stringstream to control the number of digits..
1269  std::ostringstream ss1, ss2, ss3;
1270  ss1 << std::setprecision(1) << std::fixed << energy;
1271  ss2 << std::setprecision(1) << std::fixed << min_ioc_to_shower;
1272  ss3 << std::setprecision(2) << std::fixed << overlay_fraction;
1273 
1274  std::string legend;
1275  //add the truth information to the legend if the cluster is matched to a MCParticle
1276  if(is_matched == 1){
1277  legend = "#splitline{" + std::to_string(plane) + ", " + ss1.str() + "MeV, Min IOC: "
1278  + ss2.str() + "}{#splitline{Matched: " + (is_matched == 1 ? "true" : "false") +", PDG: "
1279  + std::to_string(matched_pdg) + "}{Ovelay Frac: "+ ss3.str() + "}}";
1280  }
1281  else{
1282  legend = std::to_string(plane) + ", " + ss1.str() + "MeV, Min IOC: " + ss2.str();
1283  }
1284  vec_clusters.at(cluster).setLegend(legend);
1285  }
1286 
1287 
1288  void SEAviewer::format_legend(std::string &leg, double arg1, double arg2, double arg3){
1289  std::ostringstream ss1, ss2, ss3;
1290  ss1 << std::setprecision(1) << std::fixed << arg1;
1291  ss2 << std::setprecision(2) << std::fixed << arg2;
1292  ss3 << std::setprecision(1) << std::fixed << arg3;
1293 
1294  if(leg == "Shower"){
1295  leg = "#splitline{" + leg + ": " + ss1.str() + " MeV | " + ss2.str() + " cm }{conv. dist | "
1296  + ss3.str() + " impact par.}";
1297  //leg += ": " + ss1.str() + " MeV, " + ss2.str() + " cm conv. dist.";
1298 
1299  }else{
1300  //for tracks, 3rd argument is not used
1301  leg += ": "+ ss1.str() + " cm | " + ss2.str() + " PCA";
1302  }
1303  }
1304 }
double f_mean_ADC_second_half
Definition: SEAviewer.h:246
int loadVertex(double m_vertex_pos_x, double m_vertex_pos_y, double m_vertex_pos_z)
Definition: SEAviewer.cxx:350
std::vector< TGraph > true_vertex_graph
Definition: SEAviewer.h:410
std::vector< std::vector< TGraph > > vec_graphs
Definition: SEAviewer.h:381
std::vector< std::vector< double > > vec_all_ticks
Definition: SEAviewer.h:427
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
int addPFParticleHits(std::vector< art::Ptr< recob::Hit >> &hits, std::string leg, double arg1=0.0, double arg2=0.0, double arg3=0.0)
Definition: SEAviewer.cxx:279
BEGIN_PROLOG could also be cerr
TRandom3 * rangen
Definition: SEAviewer.h:432
std::vector< TGraph > vertex_graph
Definition: SEAviewer.h:404
std::vector< seaview::cluster > vec_clusters
Definition: SEAviewer.h:435
std::vector< std::vector< std::vector< double > > > vec_unass_pts
Definition: SEAviewer.h:421
int InNuSlice(const std::map< int, std::vector< art::Ptr< recob::Hit >> > &sliceIDToHitsMap, int nuSliceID)
Definition: SEAviewer.cxx:7
std::vector< double > analyzeShowerLikeClusters(double eps, const std::map< art::Ptr< recob::Shower >, art::Ptr< recob::PFParticle >> &showerToPFParticleMap, const std::map< art::Ptr< recob::PFParticle >, std::vector< art::Ptr< recob::Hit >> > &pfParticleToHitsMap, std::vector< seaview::cluster > &vec_c)
Definition: SEAviewer.cxx:783
std::map< art::Ptr< recob::Hit >, bool > map_unassociated_hits
Definition: SEAviewer.h:414
pdgs p
Definition: selectors.fcl:22
std::vector< art::Ptr< recob::Shower > > vec_showers
Definition: SEAviewer.h:436
double calcTime(double X, int plane, int fTPC, int fCryostat, detinfo::DetectorPropertiesData const &detprop)
Definition: SEAviewer.h:312
BEGIN_PROLOG or score(default)}sbnd_crttrackmatchingalg_crID
int setHitThreshold(double)
Definition: SEAviewer.cxx:195
std::vector< std::vector< art::Ptr< recob::Hit > > > vec_unass_hits
Definition: SEAviewer.h:422
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
int addTrack(art::Ptr< recob::Track > &trk)
Definition: SEAviewer.cxx:320
std::vector< int > num_clusters
Definition: SEAviewer.h:430
process_name hit
Definition: cheaterreco.fcl:51
std::vector< std::vector< double > > vec_all_chans
Definition: SEAviewer.h:428
bool InRange(double tick_max, double tick_min, double wire_max, double wire_min) const
Definition: SEAviewer.h:212
std::vector< art::Ptr< recob::Hit > > f_hits
Definition: SEAviewer.h:224
process_name shower
Definition: cheaterreco.fcl:51
double f_fit_chi2
Definition: SEAviewer.h:251
double f_mean_ADC_first_to_second_ratio
Definition: SEAviewer.h:247
BEGIN_PROLOG TPC
size_t start_hit_idx
Definition: SEAviewer.h:243
std::vector< std::vector< std::vector< double > > > vec_ticks
Definition: SEAviewer.h:385
geo::GeometryCore const * geom
Definition: SEAviewer.h:388
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
process_name opflash particleana ie ie y
size_t end_hit_idx
Definition: SEAviewer.h:244
cluster_score SeaviewScoreCluster(int p, int cl, std::vector< art::Ptr< recob::Hit >> &hits, double vertex_wire, double vertex_tick, const art::Ptr< recob::Shower > &shower)
Definition: SEAviewer.cxx:1014
double f_ioc_based_length
Definition: SEAviewer.h:240
double hit_threshold
Definition: SEAviewer.h:378
double f_meanADC
Definition: SEAviewer.h:253
bool f_track_treated
Definition: SEAviewer.h:221
std::string tag
Definition: SEAviewer.h:377
cluster_score f_score
Definition: SEAviewer.h:226
double f_min_ioc_to_shower_start
Definition: SEAviewer.h:239
static constexpr double wire_con
Definition: SEAviewer.h:368
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
std::vector< double > vertex_chan
Definition: SEAviewer.h:403
std::vector< TGraph > vec_all_graphs
Definition: SEAviewer.h:426
std::vector< std::pair< int, int > > m_bad_channel_list
Definition: SEAviewer.h:399
double f_angle_wrt_shower_direction
Definition: SEAviewer.h:249
detinfo::DetectorPropertiesData const & theDetector
Definition: SEAviewer.h:389
string sname
std::vector< double > analyzeTrackLikeClusters(double eps, const std::map< art::Ptr< recob::Shower >, art::Ptr< recob::PFParticle >> &showerToPFParticleMap, const std::map< art::Ptr< recob::PFParticle >, std::vector< art::Ptr< recob::Hit >> > &pfParticleToHitsMap, std::vector< seaview::cluster > &vec_c)
Definition: SEAviewer.cxx:737
std::vector< std::vector< double > > to2D(std::vector< double > &threeD)
Definition: SEAviewer.cxx:329
const std::string & getLegend() const
Definition: SEAviewer.h:169
Description of geometry of one entire detector.
double f_ADC_RMS
Definition: SEAviewer.h:252
std::vector< int > Scan2D(std::vector< std::vector< double >> &pts)
Definition: seaDBSCAN.cxx:5
int Print(double plot_distance)
Definition: SEAviewer.cxx:405
int setBadChannelList(std::vector< std::pair< int, int >> &in)
Definition: SEAviewer.cxx:159
std::vector< double > chan_max
Definition: SEAviewer.h:396
TGraph * SeaviewGetNearestNpts(int p, int cl, std::vector< art::Ptr< recob::Hit >> &hitz, double vertex_wire, double vertex_tick, int Npts)
Definition: SEAviewer.cxx:1210
double f_mean_ADC_first_half
Definition: SEAviewer.h:245
int addShower(art::Ptr< recob::Shower > &shr)
Definition: SEAviewer.cxx:312
void TrackLikeClusterAnalyzer(cluster &cl, const std::vector< double > &shower_start_pt_2D, const std::vector< double > &shower_other_pt_2D)
Definition: SEAviewer.cxx:26
int getPlane() const
Definition: SEAviewer.h:164
std::vector< std::string > vec_pfp_legend
Definition: SEAviewer.h:383
int addAllHits(std::vector< art::Ptr< recob::Hit >> &hits)
Definition: SEAviewer.cxx:200
std::vector< std::vector< double > > vec_unass_ticks
Definition: SEAviewer.h:419
std::vector< double > true_vertex_tick
Definition: SEAviewer.h:408
std::map< art::Ptr< recob::Hit >, bool > map_considered_hits
Definition: SEAviewer.h:415
if &&[-z"$BASH_VERSION"] then echo Attempting to switch to bash bash shellSwitch exit fi &&["$1"= 'shellSwitch'] shift declare a IncludeDirectives for Dir in
std::vector< std::vector< int > > cluster_labels
Definition: SEAviewer.h:431
void format_legend(std::string &leg, double arg1=0.0, double arg2=0.0, double arg3=0.0)
Definition: SEAviewer.cxx:1288
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double dist_point_point(double w1, double t1, double w2, double t2) const
Definition: SEAviewer.h:328
std::vector< double > true_vertex_chan
Definition: SEAviewer.h:409
int SeaviewCompareToShowers(int p, int cl, std::vector< art::Ptr< recob::Hit >> &hitz, double vertex_wire, double vertex_tick, std::vector< art::Ptr< recob::Shower >> &showers, const std::map< art::Ptr< recob::Shower >, art::Ptr< recob::PFParticle >> &showerToPFParticleMap, const std::map< art::Ptr< recob::PFParticle >, std::vector< art::Ptr< recob::Hit >> > &pfParticleToHitsMap, double eps)
Definition: SEAviewer.cxx:1166
double dist_line_point(const std::vector< double > &X1, const std::vector< double > &X2, const std::vector< double > &point)
Definition: SEAviewer.cxx:988
std::vector< int > f_hit_group
Definition: SEAviewer.h:225
std::string to_string(WindowPattern const &pattern)
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
std::vector< double > chan_min
Definition: SEAviewer.h:397
double calcWire(double Y, double Z, int plane, int fTPC, int fCryostat, geo::GeometryCore const &geo)
Definition: SEAviewer.h:306
void SetClusterLegend(int cluster, double energy, int is_matched, int matched_pdg, double overlay_fraction)
Definition: SEAviewer.cxx:1262
std::vector< size_t > seaview_sort_indexes(const std::vector< T > &v)
Definition: SEAviewer.h:75
std::vector< art::Ptr< recob::Track > > vec_tracks
Definition: SEAviewer.h:437
int runseaDBSCAN(double min_pts, double eps)
Definition: SEAviewer.cxx:687
static constexpr double tick_con
Definition: SEAviewer.h:369
std::vector< std::vector< double > > vec_unass_chans
Definition: SEAviewer.h:420
int addTrueVertex(double x, double y, double z)
Definition: SEAviewer.cxx:377
then echo ***************************************echo Variable FHICL_FILE_PATH not found echo You porbably haven t set up larsoft echo Try setup uboonecode vXX_XX_XX q e10
Definition: find_fhicl.sh:6
std::vector< TGraph > vec_unass_graphs
Definition: SEAviewer.h:418
const std::vector< art::Ptr< recob::Hit > > & getHits()
Definition: SEAviewer.h:170
int addHitsToConsider(std::vector< art::Ptr< recob::Hit >> &hits)
Definition: SEAviewer.cxx:164
pdgs k
Definition: selectors.fcl:22
std::size_t count(Cont const &cont)
SEAviewer(std::string tag, geo::GeometryCore const *geom, detinfo::DetectorPropertiesData const &theDetector)
Definition: SEAviewer.cxx:129
std::vector< int > calcUnassociatedHits()
Definition: SEAviewer.cxx:227
TGraph * getGraph()
Definition: SEAviewer.h:166
double f_min_conversion_dist_to_shower_start
Definition: SEAviewer.h:238
BEGIN_PROLOG could also be cout
void BasicClusterCalorimetry(cluster &cl)
Definition: SEAviewer.cxx:1245
std::vector< std::vector< std::vector< double > > > vec_chans
Definition: SEAviewer.h:386
double f_min_impact_parameter_to_shower
Definition: SEAviewer.h:236
std::vector< double > vertex_tick
Definition: SEAviewer.h:402
int filterConsideredHits(double dist_to_vertex)
Definition: SEAviewer.cxx:172