LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
ClusterParamsAlg.cxx
Go to the documentation of this file.
1 #ifndef CLUSTERPARAMSALG_CXX
2 #define CLUSTERPARAMSALG_CXX
3 
4 #include "ClusterParamsAlg.h"
5 
6 // LArSoft includes
7 #include "lardata/Utilities/StatCollector.h" // StatCollector<>
8 #include "lardata/Utilities/SimpleFits.h" // LinearFit<>
9 
10 //-----Math-------
11 #include <math.h>
12 #define PI 3.14159265
13 
14 
15 namespace {
16 
17  template <typename T>
18  inline constexpr T sqr(T const& v) { return v*v; }
19 
20 } // local namespace
21 
22 
23 namespace cluster{
24 
26  {
27  fMinNHits = 10;
28  fGSer=nullptr;
29  enableFANN = false;
30  verbose=true;
31  Initialize();
32  }
33 
34 // ClusterParamsAlg::ClusterParamsAlg(const std::vector<const larlite::hit*> &inhitlist)
35 // {
36 // fMinNHits = 10;
37 // fGSer=nullptr;
38 // enableFANN = false;
39 // verbose=true;
40 // SetHits(inhitlist);
41 // }
42 
43  ClusterParamsAlg::ClusterParamsAlg(const std::vector<util::PxHit> &inhitlist)
44  {
45  fMinNHits = 10;
46  fGSer=nullptr;
47  enableFANN = false;
48  verbose=true;
49  SetHits(inhitlist);
50  }
51 
52  int ClusterParamsAlg::SetHits(const std::vector<util::PxHit> &inhitlist){
53 
54  Initialize();
55 
56  // Make default values
57  // Is done by the struct
58  if(!(inhitlist.size())) {
59  throw CRUException("Provided empty hit list!");
60  return -1;
61  }
62 
63  fHitVector.reserve(inhitlist.size());
64  for(auto h : inhitlist)
65 
66  fHitVector.push_back(h);
67 
68  fPlane=fHitVector[0].plane;
69 
70 
71  if (fHitVector.size() < fMinNHits)
72  {
73  if(verbose) std::cout << " the hitlist is too small. Continuing to run may result in crash!!! " <<std::endl;
74  return -1;
75  }
76  else
77  return fHitVector.size();
78 
79  }
80 
81 // int ClusterParamsAlg::SetHits(const std::vector<const larlite::hit*> &inhitlist){
82 //
83 // // Make default values
84 // // Is done by the struct
85 // if(!(inhitlist.size())) {
86 // throw CRUException("Provided empty hit list!");
87 // return -1;
88 // }
89 //
90 // Initialize();
91 //
92 // //UChar_t plane = larutil::Geometry::GetME()->ChannelToPlane((*inhitlist.begin())->Channel());
93 // UChar_t plane = (*inhitlist.begin())->WireID().Plane;
94 //
95 // fHitVector.reserve(inhitlist.size());
96 // for(auto h : inhitlist) {
97 // fHitVector.push_back(util::PxHit());
98 //
99 // (*fHitVector.rbegin()).t = h->PeakTime() * fGSer->TimeToCm();
100 // (*fHitVector.rbegin()).w = h->Wire() * fGSer->WireToCm();
101 // (*fHitVector.rbegin()).charge = h->Charge();
102 // (*fHitVector.rbegin()).peak = h->Charge(true);
103 // (*fHitVector.rbegin()).plane = plane;
104 // }
105 // fPlane=fHitVector[0].plane;
106 //
107 //
108 // if (fHitVector.size()<10)
109 // {
110 // if(verbose) std::cout << " the hitlist is too small. Continuing to run may result in crash!!! " << std::endl;
111 // return -1;
112 // }
113 // else
114 // return fHitVector.size();
115 //
116 // }
117 
119  fPlane = p;
120  for(auto& h : fHitVector) h.plane = p;
123  }
124 
125  void ClusterParamsAlg::GetFANNVector(std::vector<float> & data){
126  unsigned int length = 13;
127  if (data.size() != length)
128  data.resize(length);
129  data[0] = fParams.opening_angle / PI;
130  data[1] = fParams.opening_angle_charge_wgt / PI;
131  data[2] = fParams.closing_angle / PI;
132  data[3] = fParams.closing_angle_charge_wgt / PI;
133  data[4] = fParams.eigenvalue_principal;
134  data[5] = fParams.eigenvalue_secondary;
135  data[6] = fParams.width / fParams.length;
138  data[9] = fParams.N_Hits_HC / fParams.N_Hits;
139  data[10] = fParams.modified_hit_density;
140  data[11] = fParams.RMS_charge / fParams.mean_charge;
141  data[12] = log(fParams.sum_charge / fParams.length);
142  return;
143  }
144 
145  // std::vector<float> & ClusterParamsAlg::GetFANNVector(){
146  // std::vector<float> result;
147  // GetFANNVector(result);
148  // return result;
149  // }
150 
152  std::vector<float> data;
153  GetFANNVector(data);
154  if(verbose){
155  std::cout << "Printing FANN input vector:\n"
156  << " Opening Angle (normalized) ... : " << data[0] << "\n"
157  << " Opening Angle charge weight .. : " << data[1] << "\n"
158  << " Closing Angle (normalized) ... : " << data[2] << "\n"
159  << " Closing Angle charge weight .. : " << data[3] << "\n"
160  << " Principal Eigenvalue ......... : " << data[4] << "\n"
161  << " Secondary Eigenvalue ......... : " << data[5] << "\n"
162  << " Width / Length ............... : " << data[6] << "\n"
163  << " Hit Density / M.H.D. ......... : " << data[7] << "\n"
164  << " Percent MultiHit Wires ....... : " << data[8] << "\n"
165  << " Percent High Charge Hits ..... : " << data[9] << "\n"
166  << " Modified Hit Density ......... : " << data[10] << "\n"
167  << " Charge RMS / Mean Charge ...... : " << data[11] << "\n"
168  << " log(Sum Charge / Length) ...... : " << data[12] << "\n";
169  }
170  return;
171  }
172 
173 
174 // void ClusterParamsAlg::SetArgoneutGeometry(){
175 // util::LArUtilManager::Reconfigure(larlite::geo::kArgoNeuT);
176 // }
177 
178 
179 
180 
182  {
183 
184  fTimeRecord_ProcName.clear();
185  fTimeRecord_ProcTime.clear();
186 
187  TStopwatch localWatch;
188  localWatch.Start();
189 
190  // Set pointer attributes
192 
193  //--- Initilize attributes values ---//
194  fFinishedGetAverages = false;
195  fFinishedGetRoughAxis = false;
196  fFinishedGetProfileInfo = false;
198  fFinishedRefineDirection = false;
199  fFinishedGetFinalSlope = false;
201  fFinishedTrackShowerSep = false;
202  fFinishedGetEndCharges = false;
203 
204  fRough2DSlope=-999.999; // slope
205  fRough2DIntercept=-999.999; // slope
206 
207  fRoughBeginPoint.w=-999.999;
208  fRoughEndPoint.w=-999.999;
209 
210  fRoughBeginPoint.t=-999.999;
211  fRoughEndPoint.t=-999.999;
212 
213  fProfileIntegralForward=999.999;
214  fProfileIntegralBackward=999.999;
215  fProfileMaximumBin=-999;
216 
217  fChargeCutoffThreshold.clear();
218  fChargeCutoffThreshold.reserve(3);
219  //fChargeCutoffThreshold.resize(3,0);
220  //fChargeCutoffThreshold.at(0)=200;
221  //fChargeCutoffThreshold.at(1)=400;
222  fChargeCutoffThreshold.push_back(500);
223  fChargeCutoffThreshold.push_back(500);
224  fChargeCutoffThreshold.push_back(1000);
225 
226  fHitVector.clear();
227 
228  fParams.Clear();
229 
230  // Initialize the neural network:
231  // enableFANN = false;
232  fTimeRecord_ProcName.push_back("Initialize");
233  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
234  }
235 
237  enableFANN = true;
238  // ::cluster::FANNService::GetME()->GetFANNModule().LoadFromFile(fNeuralNetPath);
239  return;
240  }
241 
242  template <typename Stream>
243  void ClusterParamsAlg::Report(Stream& stream) const {
244  if(verbose) {
245  stream << "ClusterParamsAlg Report: " << "\n"
246  << "\tFinishedGetAverages " << fFinishedGetAverages << "\n"
247  << "\tFinishedGetRoughAxis " << fFinishedGetRoughAxis << "\n"
248  << "\tFinishedGetProfileInfo " << fFinishedGetProfileInfo << "\n"
249  << "\tFinishedRefineStartPoints " << fFinishedRefineStartPoints << "\n"
250  << "\tFinishedRefineDirection " << fFinishedRefineDirection << "\n"
251  << "\tFinishedGetFinalSlope " << fFinishedGetFinalSlope << "\n"
252  << "\tFinishedGetEndCharges " << fFinishedGetEndCharges << "\n"
253  << "--------------------------------------" << "\n";
254  fParams.Report(stream);
255  }
256  }
257 
258  void ClusterParamsAlg::FillParams(bool override_DoGetAverages ,
259  bool override_DoGetRoughAxis ,
260  bool override_DoGetProfileInfo ,
261  // bool override_DoRefineDirection ,
262  // bool override_DoRefineStartPoints,
263  bool override_DoStartPointsAndDirection,
264  bool override_DoGetFinalSlope ,
265  bool override_DoTrackShowerSep,
266  bool override_DoEndCharge){
267  GetAverages (override_DoGetAverages );
268  GetRoughAxis (override_DoGetRoughAxis );
269  GetProfileInfo (override_DoGetProfileInfo );
270  RefineStartPointAndDirection(override_DoStartPointsAndDirection);
271  // RefineDirection (override_DoRefineDirection );
272  // RefineStartPoints(override_DoRefineStartPoints);
273  GetFinalSlope (override_DoGetFinalSlope );
274  GetEndCharges (override_DoEndCharge);
275  TrackShowerSeparation(override_DoTrackShowerSep);
276  }
277 
278  void ClusterParamsAlg::GetAverages(bool override){
279  if(!override) { //Override being set, we skip all this logic.
280  //OK, no override. Stop if we're already finshed.
281  if (fFinishedGetAverages) return;
282  }
283 
284  TStopwatch localWatch;
285  localWatch.Start();
286 
287  TPrincipal fPrincipal(2,"D");
288 
289  fParams.N_Hits = fHitVector.size();
290 
291  std::map<double, int> wireMap;
292 
293  lar::util::StatCollector<double> charge, sumADC;
294 
295  int uniquewires = 0;
296  int multi_hit_wires = 0;
297  for(auto& hit : fHitVector){
298  // std::cout << "This hit has charge " << hit.charge << "\n";
299 
300  double data[2];
301  data[0] = hit.w;
302  data[1] = hit.t;
303  fPrincipal.AddRow(data);
304  fParams.charge_wgt_x += hit.w * hit.charge;
305  fParams.charge_wgt_y += hit.t * hit.charge;
306  charge.add(hit.charge);
307  sumADC.add(hit.sumADC);
308 
309 
310  if (wireMap[hit.w] == 0) {
311  uniquewires ++;
312  }
313  if (wireMap[hit.w] == 1) {
314  multi_hit_wires ++;
315  }
316  wireMap[hit.w] ++;
317 
318 
319  }
320 
321  fParams.sum_charge = charge.Sum();
322  fParams.mean_charge = charge.Average();
323  fParams.rms_charge = charge.RMS();
324 
325  fParams.sum_ADC = sumADC.Sum();
326  fParams.mean_ADC = sumADC.Average();
327  fParams.rms_ADC = sumADC.RMS();
328 
329 
330  fParams.N_Wires = uniquewires;
331  fParams.multi_hit_wires = multi_hit_wires;
332 
333  if(fPrincipal.GetMeanValues()->GetNrows()<2) {
334  throw cluster::CRUException();
335  return;
336  }
337 
338  fParams.mean_x = (* fPrincipal.GetMeanValues())[0];
339  fParams.mean_y = (* fPrincipal.GetMeanValues())[1];
341 
342  if (fParams.sum_charge != 0.) {
345  }
346  else { // "SNAFU"; use the mean
349  }
350 
351  fPrincipal.MakePrincipals();
352 
353  fParams.eigenvalue_principal = (* fPrincipal.GetEigenValues() )[0];
354  fParams.eigenvalue_secondary = (* fPrincipal.GetEigenValues() )[1];
355 
356  fFinishedGetAverages = true;
357  // Report();
358 
359  fTimeRecord_ProcName.push_back("GetAverages");
360  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
361  }
362 
363 
364  // Also does the high hitlist
365  void ClusterParamsAlg::GetRoughAxis(bool override){
366  if(!override) { //Override being set, we skip all this logic.
367  //OK, no override. Stop if we're already finshed.
368  if (fFinishedGetRoughAxis) return;
369  //Try to run the previous function if not yet done.
370  if (!fFinishedGetAverages) GetAverages(true);
371  } else {
372  //Try to run the previous function if not yet done.
373  if (!fFinishedGetAverages) GetAverages(true);
374  }
375 
376  TStopwatch localWatch;
377  localWatch.Start();
378 
379  double rmsx = 0.0;
380  double rmsy = 0.0;
381  double rmsq = 0.0;
382  //using the charge weighted coordinates find the axis from slope
383  double ncw=0;
384  double sumtime=0;//from sum averages
385  double sumwire=0;//from sum averages
386  double sumwiretime=0;//sum over (wire*time)
387  double sumwirewire=0;//sum over (wire*wire)
388  //next loop over all hits again
389 
390  for (auto& hit : fHitVector){
391  // First, abuse this loop to calculate rms in x and y
392  rmsx += pow(fParams.mean_x - hit.w, 2)/fParams.N_Hits;
393  rmsy += pow(fParams.mean_y - hit.t, 2)/fParams.N_Hits;
394  rmsq += pow(fParams.mean_charge - hit.charge, 2)/fParams.N_Hits;
395  //if charge is above avg_charge
396  // std::cout << "This hit has charge " << hit . charge << "\n";
397 
398  if(hit.charge > fParams.mean_charge){
399  ncw+=1;
400  sumwire+=hit.w;
401  sumtime+=hit.t;
402  sumwiretime+=hit.w * hit.t;
403  sumwirewire+=pow(hit.w,2);
404  }//for high charge
405  }//For hh loop
406 
407  fParams.rms_x = sqrt(rmsx);
408  fParams.rms_y = sqrt(rmsy);
409  fParams.RMS_charge = sqrt(rmsq);
410 
411  fParams.N_Hits_HC = ncw;
412  //Looking for the slope and intercept of the line above avg_charge hits
413 
414  // std::cout << " ncw, and parentheses " << ncw << " " << (ncw*sumwiretime- sumwire*sumtime) << " " <<(ncw*sumwirewire-sumwire*sumwire) << std::endl;
415  if((ncw*sumwirewire-sumwire*sumwire) > 0.00001)
416  fRough2DSlope= (ncw*sumwiretime- sumwire*sumtime)/(ncw*sumwirewire-sumwire*sumwire);//slope for cw
417  else
418  fRough2DSlope=999;
421  fParams.charge_wgt_y -fRough2DSlope*(fParams.charge_wgt_x): //intercept for cw
422  0.;
423 
424  //Getthe 2D_angle
426 
427 
428  fFinishedGetRoughAxis = true;
429  // Report();
430 
431  fTimeRecord_ProcName.push_back("GetRoughAxis");
432  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
433  return;
434  }
435 
436 
437  void ClusterParamsAlg::GetProfileInfo(bool override) {
438  if(!override) { //Override being set, we skip all this logic.
439  //OK, no override. Stop if we're already finshed.
440  if (fFinishedGetProfileInfo) return;
441  //Try to run the previous function if not yet done.
443  } else {
445  }
446 
447  TStopwatch localWatch;
448  localWatch.Start();
449 
450  bool drawOrtHistos = false;
451 
452  //these variables need to be initialized to other values?
453  if(fRough2DSlope==-999.999 || fRough2DIntercept==-999.999 )
454  GetRoughAxis(true);
455 
456  //get slope of lines orthogonal to those found crossing the shower.
457  double inv_2d_slope=0;
458  if(fabs(fRough2DSlope)>0.001)
459  inv_2d_slope=-1./fRough2DSlope;
460  else
461  inv_2d_slope=-999999.;
462  // std::cout << " N_Hits is " << fParams.N_Hits << std::endl;
463  // std::cout << " inv_2d_slope is " << inv_2d_slope << std::endl;
464  // std::cout << " fRough2DSlope is " << fRough2DSlope << std::endl;
465  // std::cout << " conversions " << fWire2Cm.at(fPlane)
466  // << " " << fTime2Cm << std::endl;
467 
468  double InterHigh=-999999;
469  double InterLow=999999;
470  double WireHigh=-999999;
471  double WireLow=999999;
472  fInterHigh_side=-999999;
473  fInterLow_side=999999;
474  double min_ortdist(999), max_ortdist(-999); // needed to calculate width
475  //loop over all hits. Create coarse and fine profiles
476  // of the charge weight to help refine the start/end
477  // points and have a first guess of direction
478 
479  //std::cout << " inv_2d_slope " << inv_2d_slope << std::endl;
480 
481  for(auto const &hit : fHitVector)
482  {
483 
484  //calculate intercepts along
485  double intercept=hit.t - inv_2d_slope * (double)(hit.w);
486  double side_intercept=hit.t - fRough2DSlope * (double)(hit.w);
487 
488  util::PxPoint OnlinePoint;
489  // get coordinates of point on axis.
491 
492  // std::cout << "normal point " << hit.w << ","<<hit.t << " online point " << OnlinePoint.w << "," << OnlinePoint.t << std::endl;
493 
494  double ortdist=fGSer->Get2DDistance(&OnlinePoint,&hit);
495  if (ortdist < min_ortdist) min_ortdist = ortdist;
496  if (ortdist > max_ortdist) max_ortdist = ortdist;
497 
498  if(inv_2d_slope!=-999999) //almost all cases
499  {
500  if(intercept > InterHigh ){
501  InterHigh=intercept;
502  }
503 
504  if(intercept < InterLow ){
505  InterLow=intercept;
506  }
507  }
508  else //slope is practically horizontal. Care only about wires.
509  {
510  if(hit.w > WireHigh ){
511  WireHigh=hit.w;
512  }
513 
514  if(hit.w < WireLow ){
515  WireLow=hit.w;
516  }
517  }
518 
519  if(side_intercept > fInterHigh_side ){
520  fInterHigh_side=side_intercept;
521  }
522 
523  if(side_intercept < fInterLow_side ){
524  fInterLow_side=side_intercept;
525  }
526 
527 
528  }
529  // end of first HitIter loop, at this point we should
530  // have the extreme intercepts
531 
533  // Second loop. Fill profiles.
535 
536  // get projected points at the beginning and end of the axis.
537 
538  util::PxPoint HighOnlinePoint, LowOnlinePoint,BeginOnlinePoint, EndOnlinePoint;
539 
540  if(inv_2d_slope!=-999999) //almost all cases
541  {
543  InterHigh,HighOnlinePoint);
545  InterLow,LowOnlinePoint);
546  }
547  else //need better treatment of horizontal events.
548  {
549  util::PxPoint ptemphigh(fPlane,WireHigh,(fInterHigh_side+fInterLow_side)/2);
550  util::PxPoint ptemplow(fPlane,WireLow,(fInterHigh_side+fInterLow_side)/2);
551  fGSer->GetPointOnLine(fRough2DSlope,fRough2DIntercept,&ptemphigh,HighOnlinePoint);
552  fGSer->GetPointOnLine(fRough2DSlope,fRough2DIntercept,&ptemplow,LowOnlinePoint);
553  }
554  if(verbose){
555 
556  // std::cout << " extreme intercepts: low: " << InterLow
557  // << " " << InterHigh << std::endl;
558  // std::cout << " extreme intercepts: side: " << fInterLow_side
559  // << " " << fInterHigh_side << std::endl;
560  // std::cout << "axis + intercept " << fRough2DSlope << " "
561  // << fRough2DIntercept << std::endl;
562  //
563  std::cout << " Low online point: " << LowOnlinePoint.w << ", " << LowOnlinePoint.t
564  << " High: " << HighOnlinePoint.w << ", " << HighOnlinePoint.t << std::endl;
565 
566  //std::cout << " max_min ortdist" << max_ortdist << " " << min_ortdist << std::endl;
567  //std::cout << " hit list size " << fHitVector.size() << std::endl;
568  //define BeginOnlinePoint as the one with lower wire number (for now), adjust intercepts accordingly
569  }
570  if(HighOnlinePoint.w >= LowOnlinePoint.w)
571  {
572  BeginOnlinePoint=LowOnlinePoint;
573  fBeginIntercept=InterLow;
574  EndOnlinePoint=HighOnlinePoint;
575  fEndIntercept=InterHigh;
576  }
577  else
578  {
579  BeginOnlinePoint=HighOnlinePoint;
580  fBeginIntercept=InterHigh;
581  EndOnlinePoint=LowOnlinePoint;
582  fEndIntercept=InterLow;
583  }
584 
585  fProjectedLength=fGSer->Get2DDistance(&BeginOnlinePoint,&EndOnlinePoint);
586 
587  // std::cout << " projected length " << fProjectedLength
588  // << " Begin Point " << BeginOnlinePoint.w << " "
589  // << BeginOnlinePoint.t << " End Point " << EndOnlinePoint.w << ","<< EndOnlinePoint.t << std::endl;
590 
592  fCoarseNbins=2;
593 
595  if(fProfileNbins<10) fProfileNbins=10;
596  //std::cout << " number of profile bins " << fProfileNbins <<std::endl;
597 
598  fChargeProfile.clear();
599  fCoarseChargeProfile.clear();
600  fChargeProfile.resize(fProfileNbins,0);
602 
603 
605  // Some fitting variables to make a histogram:
606 
607  // TODO this is nonsense for small clusters
608  std::vector<double> ort_profile;
609  const int NBINS=100;
610  ort_profile.resize(NBINS);
611 
612  std::vector<double> ort_dist_vect;
613  ort_dist_vect.reserve(fHitVector.size());
614 
615  double current_maximum=0;
616  for(auto& hit : fHitVector)
617  {
618 
619  util::PxPoint OnlinePoint;
620  // get coordinates of point on axis.
621  // std::cout << BeginOnlinePoint << std::endl;
622  //std::cout << &OnlinePoint << std::endl;
623  fGSer->GetPointOnLine(fRough2DSlope,&BeginOnlinePoint,&hit,OnlinePoint);
624  double ortdist=fGSer->Get2DDistance(&OnlinePoint,&hit);
625 
626  double linedist=fGSer->Get2DDistance(&OnlinePoint,&BeginOnlinePoint);
627  // double ortdist=fGSer->Get2DDistance(&OnlinePoint,&hit);
628  ort_dist_vect.push_back(ortdist);
629  int ortbin;
630  if (ortdist == 0)
631  ortbin = 0;
632  else if (max_ortdist == min_ortdist)
633  ortbin = 0;
634  else
635  ortbin =(int)(ortdist-min_ortdist)/(max_ortdist-min_ortdist)*(NBINS-1);
636 
637  ort_profile.at(ortbin)+=hit.charge;
638  //if (ortdist < min_ortdist) min_ortdist = ortdist;
639  //if (ortdist > max_ortdist) max_ortdist = ortdist;
640 
642  //calculate the weight along the axis, this formula is based on rough guessology.
643  // there is no physics motivation behind the particular numbers, A.S.
644  // \todo: switch to something that is motivated and easier to
645  // spell than guessology. C.A.
647  double weight= (ortdist<1.) ? 10 * (hit.charge) : 5 * (hit.charge) / ortdist;
648 
649  int fine_bin = fProjectedLength?
650  (int)(linedist/fProjectedLength*(fProfileNbins-1)): 0;
651  int coarse_bin= fProjectedLength?
652  (int)(linedist/fProjectedLength*(fCoarseNbins-1)): 0;
653  /*
654  std::cout << "linedist: " << linedist << std::endl;
655  std::cout << "fProjectedLength: " << fProjectedLength << std::endl;
656  std::cout << "fProfileNbins: " << fProfileNbins << std::endl;
657  std::cout << "fine_bin: " << fine_bin << std::endl;
658  std::cout << "coarse_bin: " << coarse_bin << std::endl;
659  */
660 
661  // std::cout << "length" << linedist << " fine_bin, coarse " << fine_bin << " " << coarse_bin << std::endl;
662 
663 
664 
665  if(fine_bin<fProfileNbins) //only fill if bin number is in range
666  {
667  fChargeProfile.at(fine_bin)+=weight;
668 
669  //find maximum bin on the fly:
670  if(fChargeProfile.at(fine_bin)>current_maximum
671  && fine_bin!=0 && fine_bin!=fProfileNbins-1)
672  {
673  current_maximum=fChargeProfile.at(fine_bin);
674  fProfileMaximumBin=fine_bin;
675  }
676  }
677 
678  if(coarse_bin<fCoarseNbins) //only fill if bin number is in range
679  fCoarseChargeProfile.at(coarse_bin)+=weight;
680 
681  } // end second loop on hits. Now should have filled profile vectors.
682 
683  if(verbose) std::cout << "end second loop " << std::endl;
684 
685  double integral=0;
686  int ix=0;
687  // int fbin=0;
688  for(ix=0;ix<NBINS;ix++)
689  {
690  integral+=ort_profile.at(ix);
691  if(integral>=0.95*fParams.sum_charge)
692  {
693  break;
694  }
695  }
696 
697  fParams.width=2*(double)ix/(double)(NBINS-1)*(double)(max_ortdist-min_ortdist); // multiply by two because ortdist is folding in both sides.
698 
699  if(verbose) std::cout << " after width " << std::endl;
700 
701 
702  if (drawOrtHistos){
703  TH1F * ortDistHist =
704  new TH1F("ortDistHist",
705  "Orthogonal Distance to axis;Distance (cm)",
706  100, min_ortdist, max_ortdist);
707  TH1F * ortDistHistCharge =
708  new TH1F("ortDistHistCharge",
709  "Orthogonal Distance to axis (Charge Weighted);Distance (cm)",
710  100, min_ortdist, max_ortdist);
711  TH1F * ortDistHistAndrzej=
712  new TH1F("ortDistHistAndrzej",
713  "Orthogonal Distance Andrzej weighting",
714  100, min_ortdist, max_ortdist);
715 
716  for (int index = 0; index < fParams.N_Hits; index++){
717  ortDistHist -> Fill(ort_dist_vect.at(index));
718  ortDistHistCharge -> Fill(ort_dist_vect.at(index), fHitVector.at(index).charge);
719  double weight= (ort_dist_vect.at(index)<1.) ?
720  10 * (fHitVector.at(index).charge) :
721  (5 * (fHitVector.at(index).charge)/ort_dist_vect.at(index));
722  ortDistHistAndrzej -> Fill(ort_dist_vect.at(index), weight);
723  }
724  ortDistHist -> Scale(1.0/ortDistHist->Integral());
725  ortDistHistCharge -> Scale(1.0/ortDistHistCharge->Integral());
726  ortDistHistAndrzej -> Scale(1.0/ortDistHistAndrzej->Integral());
727 
728  TCanvas * ortCanv = new TCanvas("ortCanv","ortCanv", 600, 600);
729  ortCanv -> cd();
730  ortDistHistAndrzej -> SetLineColor(3);
731  ortDistHistAndrzej -> Draw("");
732  ortDistHistCharge -> Draw("same");
733  ortDistHist -> SetLineColor(2);
734  ortDistHist -> Draw("same");
735 
736  TLegend * leg = new TLegend(.4,.6,.8,.9);
737  leg -> SetHeader("Charge distribution");
738  leg -> AddEntry(ortDistHist, "Unweighted Hits");
739  leg -> AddEntry(ortDistHistCharge, "Charge Weighted Hits");
740  leg -> AddEntry(ortDistHistAndrzej, "Charge Weighted by Guessology");
741  leg -> Draw();
742 
743  ortCanv -> Update();
744  }
745 
748 
749  //calculate the forward and backward integrals counting int the maximum bin.
750 
751 
752  for(int ibin=0;ibin<fProfileNbins;ibin++)
753  {
754  if(ibin<=fProfileMaximumBin)
756 
757  if(ibin>=fProfileMaximumBin)
759  }
760 
761  // now, we have the forward and backward integral so start
762  // stepping forward and backward to find the trunk of the
763  // shower. This is done making sure that the running
764  // integral until less than 1% is left and the bin is above
765  // a set theshold many empty bins.
766 
767 
768 
769  //forward loop
770  double running_integral=fProfileIntegralForward;
771  int startbin,endbin;
772  for(startbin=fProfileMaximumBin; startbin>1 && startbin < (int)(fChargeProfile.size());startbin--)
773  {
774  running_integral-=fChargeProfile.at(startbin);
775  if( fChargeProfile.at(startbin)<fChargeCutoffThreshold.at(fPlane) && running_integral/fProfileIntegralForward<0.01 )
776  break;
777  else if(fChargeProfile.at(startbin)<fChargeCutoffThreshold.at(fPlane)
778  && startbin-1>0 && fChargeProfile.at(startbin-1)<fChargeCutoffThreshold.at(fPlane)
779  && startbin-2>0 && fChargeProfile.at(startbin-2)<fChargeCutoffThreshold.at(fPlane))
780  break;
781  }
782 
783  //backward loop
784  running_integral=fProfileIntegralBackward;
785  for(endbin=fProfileMaximumBin; endbin>0 && endbin<fProfileNbins-1; endbin++)
786  {
787  running_integral-=fChargeProfile.at(endbin);
788  if( fChargeProfile.at(endbin)<fChargeCutoffThreshold.at(fPlane) && running_integral/fProfileIntegralBackward<0.01 )
789  break;
790  else if(fChargeProfile.at(endbin)<fChargeCutoffThreshold.at(fPlane)
791  && endbin+1<fProfileNbins-1 && endbin+2<fProfileNbins-1
792  && fChargeProfile.at(endbin+1)<fChargeCutoffThreshold.at(fPlane)
793  && fChargeProfile.at(endbin+2)<fChargeCutoffThreshold.at(fPlane))
794  break;
795  }
796 
797  // now have profile start and endpoints. Now translate to wire/time.
798  // Will use wire/time that are on the rough axis.
799  // fProjectedLength is the length from fInterLow to interhigh a
800  // long the rough_2d_axis on bin distance is:
801  // util::PxPoint OnlinePoint;
802 
803  if(inv_2d_slope!=-999999) //almost all cases
804  {
805  double ort_intercept_begin=fBeginIntercept+(fEndIntercept-fBeginIntercept)/fProfileNbins*startbin;
806  //std::cout << " ort_intercept_begin: " << ort_intercept_begin << std::endl;
809  ort_intercept_begin,
811 
812  double ort_intercept_end=fBeginIntercept+(fEndIntercept-fBeginIntercept)/fProfileNbins*endbin;
814 
815  //std::cout << " ort_intercept_end: " << ort_intercept_end << std::endl;
818  ort_intercept_end,
821  }
822  else
823  {
824  double wire_begin=WireLow+(WireHigh-WireLow)/fProfileNbins*startbin;
825  //std::cout << " wire_begin: " << wire_begin << std::endl;
826 
827  util::PxPoint ptemphigh(fPlane,wire_begin,(fInterHigh_side+fInterLow_side)/2);
830 
831  double wire_end=WireLow+(WireHigh-WireLow)/fProfileNbins*endbin;
832  //std::cout << " wire_end: " << wire_end << std::endl;
833 
834  util::PxPoint ptemplow(fPlane,wire_end,(fInterHigh_side+fInterLow_side)/2);
837 
838  }
839 
840  if(verbose) std::cout << " rough start points " << fRoughBeginPoint.w << ", " << fRoughBeginPoint.t << " end: " << fRoughEndPoint.w << " " << fRoughEndPoint.t << std::endl;
841 
842  // ok. now have fRoughBeginPoint and fRoughEndPoint. No decision about direction has been made yet.
845  // fRoughEndPoint
846  // fRoughEndPoint
847  // and use them to get the axis
848 
849 
851  // Report();
852 
853  fTimeRecord_ProcName.push_back("GetProfileInfo");
854  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
855 
856  return;
857  }
858 
859 
870 
871  TStopwatch localWatch;
872  localWatch.Start();
873 
874  //
875  // Why override is not used here? Kazu 05/01/2014
876  // Put a stupid line here to avoid compiler warning
877  if(!override) override = true;
878 
879  // if(!override) { //Override being set, we skip all this logic.
880  // //OK, no override. Stop if we're already finshed.
881  // if (fFinishedRefineStartPoints) return;
882  // //Try to run the previous function if not yet done.
883  // if (!fFinishedRefineDirection) RefineDirection(true);
884  // } else {
885  // if (!fFinishedRefineDirection) RefineDirection(true);
886  // }
887 
888 
889  // need to define physical direction with openind angles and pass that to Ryan's line finder.
890 
891 
892  // Direction decision has been moved entirely to Refine Direction()
893  // opening and closing angles are already set
894  // they are associated with the start and endpoints.
895  // If refine direction opted to switch the shower direction,
896  // it also switched opening and closing angles.
897 
899  // fParams.direction= ...
900 
901  // Direction is decided by RefineDirection()
902  util::PxPoint startHit,endHit;
903  startHit=fRoughBeginPoint;
904  endHit=fRoughEndPoint;
905 
906 
908  //Ryan's Shower Strip finder work here.
909  //First we need to define the strip width that we want
910  double d=0.6;//this is the width of the strip.... this needs to be tuned to something.
911  //===============================================================================================================
912  // Will need to feed in the set of hits that we want.
913  // const std::vector<util::PxHit*> whole;
914  std::vector <const util::PxHit*> subhit;
915  double linearlimit=8;
916  double ortlimit=12;
917  double lineslopetest(fRough2DSlope);
918  util::PxHit averageHit;
919  //also are we sure this is actually doing what it is supposed to???
920  //are we sure this works?
921  //is anybody even listening? Were they eaten by a grue?
922  fGSer->SelectLocalHitlist(fHitVector,subhit, startHit,
923  linearlimit,ortlimit,lineslopetest,
924  averageHit);
925 
926 
927  if(!(subhit.size()) || subhit.size()<3) {
928  if(verbose) std::cout<<"Subhit list is empty or too small. Using rough start/end points..."<<std::endl;
929  // GetOpeningAngle();
932  // fRoughEndPoint
933  // fRoughEndPoint
934  // and use them to get the axis
935 
937 
938  fTimeRecord_ProcName.push_back("RefineStartPoints");
939  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
940 
941  return;
942  }
943 
944  double avgwire= averageHit.w;
945  double avgtime= averageHit.t;
946  //vertex in tilda-space pair(x-til,y-til)
947  std::vector<std::pair<double,double>> vertil;
948  // vertil.clear();// This isn't needed?
949  vertil.reserve(subhit.size() * subhit.size());
950  //vector of the sum of the distance of a vector to every vertex in tilda-space
951  std::vector<double> vs;
952  // vs.clear();// this isn't needed?
953  // $$This needs to be corrected//this is the good hits that are between strip
954  std::vector<const util::PxHit*> ghits;
955  ghits.reserve(subhit.size());
956  int n=0;
957  double fardistcurrent=0;
958  util::PxHit startpoint;
959  double gwiretime=0;
960  double gwire=0;
961  double gtime=0;
962  double gwirewire=0;
963  //KAZU!!! I NEED this too//this will need to come from somewhere...
964  //This is some hit that is from the way far side of the entire shower cluster...
966 
967  //=============building the local vector===================
968  //this is clumsy... but just want to get something to work for now.
969  //THIS is REAL Horrible and CLUMSY... We can make things into helper functions soon.
970  std::vector<util::PxHit> returnhits;
971  std::vector<double> radiusofhit;
972  std::vector<int> closehits;
973  //unsigned int minhits=0;
974  //double maxreset=0;
975  // double avgwire=0;
976  // double avgtime=0;
977  // if(minhits<fHitVector.size()){
978  // for(auto & hit : fHitVector){
979  // std::pair<double,double> rv(fRoughEndPoint.w,fRoughEndPoint.t);
980  // closehits.clear();
981  // radiusofhit.clear();
982  // returnhits.clear();
983  // for( unsigned int a=0; a<hit.size(); a++){
984  // double d= sqrt( pow((rv.first-hit.w),2) + pow((rv.second-hit.t),2) );
985  // maxreset+=d;
986  // radiusofhit.push_back(d);}
987  // for(unsigned int b=0; b<minhits; b++){
988  // int minss= std::min_element(radiusofhit.begin(),radiusofhit.end())-radiusofhit.begin();
989  // closehits.push_back(minss);
990  // radiusofhit[minss] = maxreset;}
991  //now make the vector o just the close hits using the closehit index
992  // for( unsigned int k=0; k < closehits.size(); k++){
993  // //first find the average wire and time for each set of hits... and make that the new origin before the transpose.
994  // avgwire+=fHitVector[closehits[k]].w;
995  // avgtime+=fHitVector[closehits[k]].t;
996  // returnhits.push_back(fHitVector[closehits[k]]);}
997  // }//if fHitVector is big enough
998 
999  // avgwire=avgwire/closehits.size();
1000  // avgtime=avgtime/closehits.size();
1001  // subhit=returnhits;
1002 
1003  //==============================================================================
1004  //Now we need to do the transformation into "tilda-space"
1005  for(unsigned int a=0; a<subhit.size();a++){
1006  for(unsigned int b=a+1;b<subhit.size();b++){
1007  if(subhit.at(a)->w != subhit.at(b)->w){
1008  double xtil = ((subhit.at(a)->t - avgtime) - (subhit.at(b)->t - avgtime));
1009  xtil /= ((subhit.at(a)->w - avgwire)-(subhit.at(b)->w - avgwire));
1010  double ytil = (subhit.at(a)->w - avgwire)*xtil -(subhit.at(a)->t - avgtime);
1011  //push back the tilda vertex point on the pair
1012  std::pair<double,double> tv(xtil,ytil);
1013  vertil.push_back(tv);
1014  }//if Wires are not the same
1015  }//for over b
1016  }//for over a
1017  // look at the distance from a tilda-vertex to all other tilda-verticies
1018  for(unsigned int z=0;z<vertil.size();z++){
1019  double vd=0;//the distance for vertex... just needs to be something 0
1020  for(unsigned int c=0; c<vertil.size();c++)
1021 
1022  vd+= sqrt(pow((vertil.at(z).first - vertil.at(c).first),2)
1023  + pow((vertil.at(z).second-vertil.at(c).second),2));
1024  vs.push_back(vd);
1025  vd=0.0;
1026  }//for z loop
1027 
1028  if(vs.size()==0) //al hits on same wire?!
1029  {
1030  if(verbose) std::cout<<"vertil list is empty. all subhits are on the same wire?"<<std::endl;
1031  // GetOpeningAngle();
1034  // fRoughEndPoint
1035  // fRoughEndPoint
1036  // and use them to get the axis
1037 
1039 
1040  fTimeRecord_ProcName.push_back("RefineStartPoints");
1041  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1042  return;
1043  }
1044  //need to find the min of the distance of vertex in tilda-space
1045  //this will get me the area where things are most linear
1046  int minvs= std::min_element(vs.begin(),vs.end())-vs.begin();
1047  // now use the min position to find the vertex in tilda-space
1048  //now need to look a which hits are between the tilda lines from the points
1049  //in the tilda space everything in wire time is based on the new origin which is at the average wire/time
1050  double tilwire=vertil.at(minvs).first;//slope
1051  double tiltimet=-vertil.at(minvs).second+d*sqrt(1+pow(tilwire,2));//negative cept is accounted for top strip
1052  double tiltimeb=-vertil.at(minvs).second-d*sqrt(1+pow(tilwire,2));//negative cept is accounted for bottom strip
1053  // look over the subhit list and ask for which are inside of the strip
1054  for(unsigned int a=0; a<subhit.size(); a++){
1055  double dtstrip= (-tilwire * (subhit.at(a)->w - avgwire)
1056  +(subhit.at(a)->t - avgtime)-tiltimet)/sqrt(tilwire*tilwire+1);
1057  double dbstrip= (-tilwire * (subhit.at(a)->w - avgwire)
1058  +(subhit.at(a)->t - avgtime)-tiltimeb)/sqrt(tilwire*tilwire+1);
1059 
1060  if((dtstrip<0.0 && dbstrip>0.0)||(dbstrip<0.0 && dtstrip>0.0)){
1061  ghits.push_back(subhit.at(a));
1062  }//if between strip
1063  }//for a loop
1064  //=======================Do stuff with the good hits============================
1065 
1066  //of these small set of hits just fit a simple line.
1067  //then we will need to see which of these hits is farthest away
1068 
1069  for(unsigned int g=0; g<ghits.size();g++){
1070  // should call the helper funtion to do the fit
1071  //but for now since there is no helper function I will just write it here......again
1072  n+=1;
1073  gwiretime+= ghits.at(g)->w * ghits.at(g)->t;
1074  gwire+= ghits.at(g)->w;
1075  gtime+= ghits.at(g)->t;
1076  gwirewire+= ghits.at(g)->w * ghits.at(g)->w;
1077  // now work on calculating the distance in wire time space from the far point
1078  //farhit needs to be a hit that is given to me
1079  double fardist= sqrt(pow(ghits.at(g)->w - farhit.w,2)+pow(ghits.at(g)->t - farhit.t,2));
1080  //come back to this... there is a better way to do this probably in the loop
1081  //there should also be a check that the hit that is farthest away has subsequent hits after it on a few wires
1082  if(fardist>fardistcurrent){
1083  fardistcurrent=fardist;
1084  //if fardist... this is the point to use for the start point
1085  startpoint.t = ghits.at(g)->t;
1086  startpoint.w = ghits.at(g)->w;
1087  startpoint.plane = ghits.at(g)->plane;
1088  startpoint.charge = ghits.at(g)->charge;
1089  }
1090  }//for ghits loop
1091  //This can be the new start point
1092  // std::cout<<"Here Kazu"<<std::endl;
1093  // std::cout<<"Ryan This is the new SP ("<<startpoint.w<<" , "<<startpoint.t<<")"<<std::endl;
1094  // double gslope=(n* gwiretime- gwire*gtime)/(n*gwirewire -gwire*gwire);
1095  // double gcept= gtime/n -gslope*(gwire/n);
1096 
1097  //should this be here? Id argue this might be done once outside.
1098  fParams.length=fGSer->Get2DDistance((util::PxPoint *)&startpoint,&endHit);
1099  if(fParams.length)
1101  else
1103 
1104  if(fParams.length && fParams.width)
1106  else
1108 
1109 
1110  fParams.start_point=startpoint;
1111 
1112  static int count(0);
1113  count ++;
1114  // std::cout << "Completed refine start point " << count << " times!\n";
1115 
1117  // Report();
1118 
1119  fTimeRecord_ProcName.push_back("RefineStartPoints");
1120  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1121 
1122  return;
1123  }
1124 
1125 
1129 
1130  void ClusterParamsAlg::GetFinalSlope(bool override) {
1131  if(!override) { //Override being set, we skip all this logic.
1132  //OK, no override. Stop if we're already finshed.
1133  if (fFinishedGetFinalSlope) return;
1134  //Try to run the previous function if not yet done.
1136  } else {
1137  //Try to run the previous function if not yet done.
1139  }
1140 
1141  TStopwatch localWatch;
1142  localWatch.Start();
1150  //double xangle=Get2DAngleForHit( wstn,tstn, hitlist);
1151  const int NBINS=720;
1152  std::vector< int > fh_omega_single(NBINS,0); //720,-180., 180.
1153 
1154  // fParams.start_point
1155 
1156  double current_maximum=0;
1157  double curr_max_bin=-1;
1158 
1159  for( auto hit : fHitVector){
1160 
1161  double omx=fGSer->Get2Dangle((util::PxPoint *)&hit,&fParams.start_point); // in rad and assuming cm/cm space.
1162  int nbin=(omx+TMath::Pi())*(NBINS-1)/(2*TMath::Pi());
1163  if(nbin >= NBINS) nbin=NBINS-1;
1164  if(nbin < 0) nbin=0;
1165  fh_omega_single[nbin]+=hit.charge;
1166 
1167  if( fh_omega_single[nbin]>current_maximum )
1168  {
1169  current_maximum= fh_omega_single[nbin];
1170  curr_max_bin=nbin;
1171  }
1172 
1173 
1174  }
1175 
1176 
1177  fParams.angle_2d=(curr_max_bin/720*(2*TMath::Pi()))-TMath::Pi();
1178  fParams.angle_2d*=180/PI;
1179  if(verbose) std::cout << " Final 2D angle: " << fParams.angle_2d << " degrees " << std::endl;
1180 
1181  double mod_angle=(fabs(fParams.angle_2d)<=90) ? fabs(fParams.angle_2d) : 180 - fabs(fParams.angle_2d); //want to transfer angle to radians and from 0 to 90.
1182 
1183  if(cos(mod_angle*PI/180.))
1184  { //values here based on fit of hit_density_1D vs. mod_angle defined as above (in ArgoNeuT).
1185  if(mod_angle<=75.)
1186  fParams.modified_hit_density=fParams.hit_density_1D/(2.45*cos(mod_angle*PI/180.)+0.2595);
1187  else
1188  fParams.modified_hit_density=fParams.hit_density_1D/(1.036*mod_angle*PI/180.-0.2561);
1189 
1190  //calculate modified mean_charge:
1191  fParams.modmeancharge = fParams.mean_charge/(1264 - 780*cos(mod_angle*PI/180.));
1192 
1193  }
1194  else
1196 
1198  // do not use for now.
1199  bool drawProfileHisto=false;
1200  if (drawProfileHisto)
1201  {
1202 
1204  double corr_factor=1;
1205  if(cos(mod_angle*PI/180.))
1206  { //values here based on fit of hit_density_1D vs. mod_angle defined as above (in ArgoNeuT).
1207 
1208  if(mod_angle<=75.)
1209  corr_factor*=(2.45*cos(mod_angle*PI/180.)+0.2595);
1210  else
1211  corr_factor*=(1.036*mod_angle*PI/180.-0.2561);
1212  }
1213 
1214  fProfileNbins=(int)(fProfileNbins/2*corr_factor + 0.5); // +0.5 to round to nearest sensible value
1215  //if(fProfileNbins<10) fProfileNbins=10;
1216 
1217  if(verbose) std::cout << " number of final profile bins " << fProfileNbins <<std::endl;
1218 
1219  fChargeProfile.clear();
1220  fCoarseChargeProfile.clear();
1221  fChargeProfile.resize(fProfileNbins,0);
1223 
1224 
1225  fChargeProfileNew.clear();
1226  // fDiffChargeProfile.clear();
1227  fChargeProfileNew.resize(fProfileNbins,0);
1228  // fDiffChargeProfile.resize(fProfileNbins,0);
1229 
1230 
1231  util::PxPoint BeginOnlinePoint;
1232 
1234 
1235  for( auto hit : fHitVector){
1236 
1237  util::PxPoint OnlinePoint;
1238  // get coordinates of point on axis.
1239  // std::cout << BeginOnlinePoint << std::endl;
1240  //std::cout << &OnlinePoint << std::endl;
1241  fGSer->GetPointOnLine(fRough2DSlope,&BeginOnlinePoint,&hit,OnlinePoint);
1242 
1243  double linedist=fGSer->Get2DDistance(&OnlinePoint,&BeginOnlinePoint);
1244  // double ortdist=fGSer->Get2DDistance(&OnlinePoint,&hit);
1245 
1246 
1247  int fine_bin =(int)(linedist/fProjectedLength*(fProfileNbins-1));
1248 
1249 
1250  if(fine_bin<fProfileNbins) //only fill if bin number is in range
1251  {
1252  fChargeProfileNew.at(fine_bin)+=hit.charge;
1253  }
1254  }
1255 
1256 
1257 
1258 
1259  TH1F * charge_histo =
1260  new TH1F("charge dist","charge dist",fProfileNbins,0,fProfileNbins);
1261 
1262  TH1F * charge_diff =
1263  new TH1F("charge diff","charge diff",fProfileNbins,0,fProfileNbins);
1264 
1265  for(int ix=0;ix<fProfileNbins-1;ix++)
1266  {
1267  charge_histo->SetBinContent(ix,fChargeProfileNew[ix]);
1268 
1269  if(ix>2 && ix < fProfileNbins-3)
1270  {
1271  double diff=( 1./12.*fChargeProfileNew[ix-2]
1272  - 2./3.*fChargeProfileNew [ix-1]
1273  + 2./3.*fChargeProfileNew [ix+1]
1274  - 1./12.*fChargeProfileNew[ix+2] )
1275  /(double)fProfileNbins;
1276  charge_diff->SetBinContent(ix,diff);
1277  }
1278  }
1279 
1280  TCanvas * chCanv = new TCanvas("chCanv","chCanv", 600, 600);
1281  chCanv -> cd();
1282  charge_histo -> SetLineColor(3);
1283  charge_histo -> Draw("");
1284  charge_diff -> SetLineColor(2);
1285  charge_diff -> Draw("same");
1286  chCanv -> Update();
1287 
1288 
1289 
1290 
1291  }
1292 
1294 
1295  fTimeRecord_ProcName.push_back("GetFinalSlope");
1296  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1297 
1298  fFinishedGetFinalSlope = true;
1299  return;
1300  }
1301 
1309  //
1310  // We don't use "override"? Should we remove? 05/01/14
1311  //
1312  if(!override) override = true;
1313 
1314  TStopwatch localWatch;
1315  localWatch.Start();
1316 
1317  // if(!override) { //Override being set, we skip all this logic.
1318  // //OK, no override. Stop if we're already finshed.
1319  // if (fFinishedRefineDirection) return;
1320  // //Try to run the previous function if not yet done.
1321  // if (!fFinishedGetProfileInfo) GetProfileInfo(true);
1322  // } else {
1323  // //Try to run the previous function if not yet done.
1324  // if (!fFinishedGetProfileInfo) GetProfileInfo(true);
1325  // }
1326 
1327  // double wire_2_cm = fGSer->WireToCm();
1328  // double time_2_cm = fGSer->TimeToCm();
1329 
1330  // Removing the conversion since these points are set above in cm-cm space
1331  // -- Corey
1332 
1333  util::PxPoint this_startPoint, this_endPoint;
1334 
1336  this_startPoint = fParams.start_point;
1337  this_endPoint = fParams.end_point;
1338  }
1339  else{
1340  this_startPoint = fRoughBeginPoint;
1341  this_endPoint = fRoughEndPoint;
1342  }
1343  if(verbose) {
1344  std::cout << "Angle: Start point: (" << this_startPoint.w
1345  << ", " << this_startPoint.t << ")\n";
1346  std::cout << "Angle: End point : (" << this_endPoint.w
1347  << ", " << this_endPoint.t << ")\n";
1348  }
1349  double endStartDiff_x = (this_endPoint.w - this_startPoint.w);
1350  double endStartDiff_y = (this_endPoint.t - this_startPoint.t);
1351  double rms_forward = 0;
1352  double rms_backward = 0;
1353  double mean_forward = 0;
1354  double mean_backward = 0;
1355  //double weight_total = 0;
1356  double hit_counter_forward = 0;
1357  double hit_counter_backward = 0;
1358 
1359  if (verbose && endStartDiff_y == 0 && endStartDiff_x == 0) {
1360  std::cerr << "Error: end point and start point are the same!\n";
1361 
1362  fTimeRecord_ProcName.push_back("RefineDirection");
1363  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1364  return;
1365  }
1366 
1367  double percentage = 0.90;
1368  double percentage_HC = 0.90*fParams.N_Hits_HC/fParams.N_Hits;
1369  const int NBINS=200;
1370  const double wgt = 1.0/fParams.N_Hits;
1371 
1372  // Containers for the angle histograms
1373  std::vector<float> opening_angle_bin(NBINS,0.0 ) ;
1374  std::vector<float> closing_angle_bin(NBINS,0.0 ) ;
1375  std::vector<float> opening_angle_highcharge_bin(NBINS,0.0 ) ;
1376  std::vector<float> closing_angle_highcharge_bin(NBINS,0.0 ) ;
1377  std::vector<float> opening_angle_chargeWgt_bin(NBINS,0.0 ) ;
1378  std::vector<float> closing_angle_chargeWgt_bin(NBINS,0.0 ) ;
1379  //hard coding this for now, should use SetRefineDirectionQMin function
1380  fQMinRefDir = 25;
1381 
1382  int index = -1;
1383  for(auto& hit : fHitVector) {
1384  index ++;
1385  //skip this hit if below minimum cutoff param
1386  if(hit.charge < fQMinRefDir) continue;
1387 
1388  //weight_total = hit.charge;
1389 
1390  // Compute forward mean
1391  double hitStartDiff_x = (hit.w - this_startPoint.w) ;
1392  double hitStartDiff_y = (hit.t - this_startPoint.t) ;
1393 
1394  if (hitStartDiff_x == 0 && hitStartDiff_y == 0) continue;
1395 
1396  double cosangle_start = (endStartDiff_x*hitStartDiff_x +
1397  endStartDiff_y*hitStartDiff_y);
1398  cosangle_start /= ( pow(pow(endStartDiff_x,2)+pow(endStartDiff_y,2),0.5)
1399  * pow(pow(hitStartDiff_x,2)+pow(hitStartDiff_y,2),0.5));
1400 
1401  if(cosangle_start>0) {
1402  // Only take into account for hits that are in "front"
1403  //no weighted average, works better as flat average w/ min charge cut
1404  mean_forward += cosangle_start;
1405  rms_forward += pow(cosangle_start,2);
1406  hit_counter_forward++;
1407  }
1408 
1409  // Compute backward mean
1410  double hitEndDiff_x = (hit.w - this_endPoint.w);
1411  double hitEndDiff_y = (hit.t - this_endPoint.t);
1412  if (hitEndDiff_x == 0 && hitEndDiff_y == 0) continue;
1413 
1414  double cosangle_end = (endStartDiff_x*hitEndDiff_x +
1415  endStartDiff_y*hitEndDiff_y) * (-1.);
1416  cosangle_end /= ( pow(pow(endStartDiff_x,2)+pow(endStartDiff_y,2),0.5)
1417  * pow(pow(hitEndDiff_x,2)+pow(hitEndDiff_y,2),0.5));
1418 
1419  if(cosangle_end>0) {
1420  //no weighted average, works better as flat average w/ min charge cut
1421  mean_backward += cosangle_end;
1422  rms_backward += pow(cosangle_end,2);
1423  hit_counter_backward++;
1424  }
1425 
1426  int N_bins_OPEN = (NBINS-1) * acos(cosangle_start)/PI;
1427  int N_bins_CLOSE = (NBINS-1) * acos(cosangle_end)/PI;
1428  if (N_bins_OPEN < 0) N_bins_OPEN = 0;
1429  if (N_bins_CLOSE < 0) N_bins_CLOSE = 0;
1430  // std::cout << "endStartDiff_x :" << endStartDiff_x << std::endl;
1431  // std::cout << "endStartDiff_y :" << endStartDiff_y << std::endl;
1432  // std::cout << "cosangle_start :" << cosangle_start << std::endl;
1433  // std::cout << "cosangle_end :" << cosangle_end << std::endl;
1434  // std::cout << "N_bins_OPEN :" << N_bins_OPEN << std::endl;
1435  // std::cout << "N_bins_CLOSE :" << N_bins_CLOSE << std::endl;
1436 
1437  opening_angle_chargeWgt_bin[N_bins_OPEN ]
1438  += hit.charge/fParams.sum_charge;
1439  closing_angle_chargeWgt_bin[N_bins_CLOSE]
1440  += hit.charge/fParams.sum_charge;
1441  opening_angle_bin[N_bins_OPEN] += wgt;
1442  closing_angle_bin[N_bins_CLOSE] += wgt;
1443 
1444  //Also fill bins for high charge hits
1445  if(hit.charge > fParams.mean_charge){
1446  opening_angle_highcharge_bin[N_bins_OPEN] += wgt;
1447  closing_angle_highcharge_bin[N_bins_CLOSE] += wgt;
1448  }
1449 
1450  }
1451 
1452  //initialize iterators for the angles
1453  int iBin(0), jBin(0), kBin(0), lBin(0), mBin(0), nBin(0);
1454  double percentage_OPEN(0.0),
1455  percentage_CLOSE(0.0),
1456  percentage_OPEN_HC(0.0),
1457  percentage_CLOSE_HC(0.0), //The last 2 are for High Charge (HC)
1458  percentage_OPEN_CHARGEWGT(0.0),
1459  percentage_CLOSE_CHARGEWGT(0.0);
1460 
1461  for(iBin = 0; percentage_OPEN<= percentage && iBin < NBINS; iBin++)
1462  {
1463  percentage_OPEN += opening_angle_bin[iBin];
1464  }
1465 
1466  for(jBin = 0; percentage_CLOSE<= percentage && jBin < NBINS; jBin++)
1467  {
1468  percentage_CLOSE += closing_angle_bin[jBin];
1469  }
1470 
1471  for(kBin = 0; percentage_OPEN_HC<= percentage_HC && kBin < NBINS; kBin++)
1472  {
1473  percentage_OPEN_HC += opening_angle_highcharge_bin[kBin];
1474  }
1475 
1476  for(lBin = 0; percentage_CLOSE_HC<= percentage_HC && lBin < NBINS; lBin++)
1477  {
1478  percentage_CLOSE_HC += closing_angle_highcharge_bin[lBin];
1479  }
1480 
1481  for(mBin = 0; percentage_OPEN_CHARGEWGT<= percentage && mBin < NBINS; mBin++)
1482  {
1483  percentage_OPEN_CHARGEWGT += opening_angle_chargeWgt_bin[mBin];
1484  }
1485 
1486  for(nBin = 0; percentage_CLOSE_CHARGEWGT<= percentage && nBin < NBINS; nBin++)
1487  {
1488  percentage_CLOSE_CHARGEWGT += closing_angle_chargeWgt_bin[nBin];
1489  }
1490 
1491  double opening_angle = iBin * PI /NBINS ;
1492  double closing_angle = jBin * PI /NBINS ;
1493  double opening_angle_highcharge = kBin * PI /NBINS ;
1494  double closing_angle_highcharge = lBin * PI /NBINS ;
1495  double opening_angle_charge_wgt = mBin * PI /NBINS ;
1496  double closing_angle_charge_wgt = nBin * PI /NBINS ;
1497 
1498  // std::cout<<"opening angle: "<<opening_angle<<std::endl;
1499  // std::cout<<"closing angle: "<<closing_angle<<std::endl;
1500  // std::cout<<"opening high charge angle: "<<opening_angle_highcharge<<std::endl;
1501  // std::cout<<"closing high charge angle: "<<closing_angle_highcharge<<std::endl;
1502  // std::cout<<"opening high charge wgt : "<<opening_angle_charge_wgt<<std::endl;
1503  // std::cout<<"closing high charge wgt : "<<closing_angle_charge_wgt<<std::endl;
1504  // std::cout<<"fCoarseChargeProfile : "<<fCoarseChargeProfile[0]
1505  // << ", " << fCoarseChargeProfile[1] << std::endl;
1506 
1507  double value_1 = closing_angle/opening_angle -1;
1508  // if (fCoarseChargeProfile.size() != 2) std::cout <<" !!!!!!!!!!!!!!!!!! \n\n\n\n";
1509  double value_2 = (fCoarseChargeProfile[0]/fCoarseChargeProfile[1]);
1510  if (value_2 < 100.0 && value_2 > 0.01)
1511  value_2 = log(value_2);
1512  else
1513  value_2 = 0.0;
1514  double value_3 = closing_angle_charge_wgt/opening_angle_charge_wgt -1;
1515 
1516  // if (value_1 > 1.0) value_1 = -1.0/value_1;
1517  // if (value_2 < 1.0) value_2 = -1.0/value_2;
1518  // if (value_3 > 1.0) value_3 = -1.0/value_3;
1519 
1520  // std::cout << "value_1 : " << value_1 << std::endl;
1521  // std::cout << "value_2 : " << value_2 << std::endl;
1522  // std::cout << "value_3 : " << value_3 << std::endl;
1523 
1524  // Using a sigmoid function to determine flipping.
1525  // I am going to weigh all of the values above (1, 2, 3) equally.
1526  // But, since value 2 in particular, I'm going to cut things off at 5.
1527 
1528  if (value_1 > 3 ) value_1 = 3.0;
1529  if (value_1 < -3 ) value_1 = -3.0;
1530  if (value_2 > 3 ) value_2 = 3.0;
1531  if (value_2 < -3 ) value_2 = -3.0;
1532  if (value_3 > 3 ) value_3 = 3.0;
1533  if (value_3 < -3 ) value_3 = -3.0;
1534 
1535  double Exp = exp(value_1 + value_2 + value_3);
1536  double sigmoid = (Exp - 1)/(Exp + 1);
1537 
1538  // std::cout << "sigmoid: " << sigmoid << std::endl;
1539 
1540  bool flip = false;
1541  if (sigmoid < 0) flip = true;
1542  if (flip){
1543  if(verbose) std::cout << "Flipping!" << std::endl;
1544  std::swap(opening_angle,closing_angle);
1545  std::swap(opening_angle_highcharge,closing_angle_highcharge);
1546  std::swap(opening_angle_charge_wgt,closing_angle_charge_wgt);
1547  std::swap(fParams.start_point,fParams.end_point);
1548  std::swap(fRoughBeginPoint,fRoughEndPoint);
1549  }
1550  else if(verbose){
1551  std::cout << "Not Flipping!\n";
1552  }
1553 
1554  fParams.opening_angle = opening_angle;
1555  fParams.opening_angle_charge_wgt = opening_angle_charge_wgt;
1556  fParams.closing_angle = closing_angle;
1557  fParams.closing_angle_charge_wgt = closing_angle_charge_wgt;
1558 
1559  fFinishedRefineDirection = true;
1560 
1561  fTimeRecord_ProcName.push_back("RefineDirection");
1562  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1563 
1564  // return;
1565  } //end RefineDirection
1566 
1567 
1569  {
1570 
1571  TStopwatch localWatch;
1572  localWatch.Start();
1573 
1574  if(fHitVector.size()) {
1575  std::vector<const util::PxHit*> container_polygon;
1576  fGSer->SelectPolygonHitList(fHitVector,container_polygon);
1577  //now making Polygon Object
1578  std::pair<float,float> tmpvertex;
1579  //make Polygon Object as in mac/PolyOverlap.cc
1580  std::vector<std::pair<float,float> > vertices;
1581  for (unsigned int i=0; i<container_polygon.size(); i++){
1582  tmpvertex = std::make_pair( container_polygon.at(i)->w,
1583  container_polygon.at(i)->t );
1584  vertices.push_back( tmpvertex );
1585  }
1586  fParams.PolyObject = Polygon2D( vertices );
1587  }
1588 
1589  fTimeRecord_ProcName.push_back("FillPolygon");
1590  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1591  }
1592 
1593 
1595 
1597  // This function is meant to pick the direction.
1598  // It refines both the start and end point, and then asks
1599  // if it should flip.
1600 
1601  TStopwatch localWatch;
1602  localWatch.Start();
1603 
1604  if(verbose) std::cout << " here!!! " << std::endl;
1605 
1606  if(!override) { //Override being set, we skip all this logic.
1607  //OK, no override. Stop if we're already finshed.
1609  fTimeRecord_ProcName.push_back("RefineStartPointAndDirection");
1610  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1611  return;
1612  }
1613  //Try to run the previous function if not yet done.
1615  } else {
1616  //Try to run the previous function if not yet done.
1618  }
1619  if(verbose){
1620  std::cout << "REFINING .... " << std::endl;
1621  std::cout << " Rough start and end point: " << std::endl;
1622  std::cout << " s: (" << fParams.start_point.w << ", "
1623  << fParams.start_point.t << ")" << std::endl;
1624  std::cout << " e: (" << fParams.end_point.w << ", "
1625  << fParams.end_point.t << ")" << std::endl;
1626  }
1628  if(verbose){
1629  std::cout << " Once Refined start and end point: " << std::endl;
1630  std::cout << " s: (" << fParams.start_point.w << ", "
1631  << fParams.start_point.t << ")" << std::endl;
1632  std::cout << " e: (" << fParams.end_point.w << ", "
1633  << fParams.end_point.t << ")" << std::endl;
1634  std::swap(fParams.start_point,fParams.end_point);
1635  std::swap(fRoughBeginPoint,fRoughEndPoint);
1636  }
1638  if(verbose) {
1639  std::cout << " Twice Refined start and end point: " << std::endl;
1640  std::cout << " s: (" << fParams.start_point.w << ", "
1641  << fParams.start_point.t << ")" << std::endl;
1642  std::cout << " e: (" << fParams.end_point.w << ", "
1643  << fParams.end_point.t << ")" << std::endl;
1644  std::swap(fParams.start_point,fParams.end_point);
1645  std::swap(fRoughBeginPoint,fRoughEndPoint);
1646  }
1647  RefineDirection();
1648  if(verbose) {
1649  std::cout << " Final start and end point: " << std::endl;
1650  std::cout << " s: (" << fParams.start_point.w << ", "
1651  << fParams.start_point.t << ")" << std::endl;
1652  std::cout << " e: (" << fParams.end_point.w << ", "
1653  << fParams.end_point.t << ")" << std::endl;
1654  }
1656 
1657  fTimeRecord_ProcName.push_back("RefineStartPointAndDirection");
1658  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1659  return;
1660  }
1661 
1663  if(!override) return;
1664  if(verbose) std::cout << " ---- Trying T/S sep. ------ \n";
1665  if (enableFANN){
1666  if(verbose) std::cout << " ---- Doing T/S sep. ------- \n";
1667  std::vector<float> FeatureVector, outputVector;
1668  GetFANNVector(FeatureVector);
1669 // ::cluster::FANNService::GetME()->GetFANNModule().run(FeatureVector,outputVector);
1670  // fParams.trackness = outputVector[1];
1671  // fParams.showerness = outputVector[0];
1672  }
1673  else{
1674  if(verbose) std::cout << " ---- Failed T/S sep. ------ \n";
1675  }
1676  }
1677 
1678 
1679  //----------------------------------------------------------------------------
1680  void ClusterParamsAlg::GetEndCharges(bool override_ /* = false */ ) {
1681  if(!override_) { //Override being set, we skip all this logic.
1682  //OK, no override. Stop if we're already finshed.
1683  if (fFinishedGetEndCharges) return;
1684  }
1685 
1686  TStopwatch localWatch;
1687  localWatch.Start();
1688 
1691 
1692  fFinishedGetEndCharges = true;
1693  // Report();
1694 
1695  fTimeRecord_ProcName.push_back("GetEndCharges");
1696  fTimeRecord_ProcTime.push_back(localWatch.RealTime());
1697  } // ClusterParamsAlg::GetEndCharges()
1698 
1699 
1700  //----------------------------------------------------------------------------
1702  (double m, double q, double x1, double x2)
1703  {
1704  return m / 2. * (sqr(x2) - sqr(x1)) + q * (x2 - x1);
1705  } // ClusterParamsAlg::LinearIntegral()
1706 
1707 
1708  //----------------------------------------------------------------------------
1710  double from_length, double to_length,
1711  unsigned int fit_first_bin, unsigned int fit_end_bin
1712  ) {
1713  // first compute the information on the charge profile
1714  GetProfileInfo();
1715 
1716  // first things first
1717  if (fit_first_bin > fit_end_bin) std::swap(fit_first_bin, fit_end_bin);
1718 
1719  // how many bins can we use?
1720  const unsigned int nbins = std::min
1721  (fit_end_bin - fit_first_bin, (unsigned int) fChargeProfile.size());
1722  if (nbins == 0) return 0;
1723 
1724  // move the specified range within reason
1725  if (fit_end_bin > fChargeProfile.size()) {
1726  fit_end_bin = fChargeProfile.size();
1727  fit_first_bin = fit_end_bin - nbins;
1728  }
1729 
1730  // if we have to use only one bin, so be it
1731  if (nbins < 2) return fChargeProfile[fit_first_bin];
1732 
1733  // fit the charge profile vs. bin number;
1734  // we assume that the first bin (#0) starts from the very beginning of the
1735  // cluster, that is at axis coordinate 0.
1737  for (unsigned int iBin = fit_first_bin; iBin < fit_end_bin; ++iBin) {
1738  // should we use a Poisson error instead of no error?
1739  fitter.add((double) iBin, fChargeProfile[iBin]);
1740  } // for
1741 
1742  // get the linear fit parameters; [0] intercept [1] slope
1744  try {
1745  fit = fitter.FitParameters();
1746  }
1747  catch (std::range_error) { // oops...
1748  // this is actually unexpected, since the only reason for the fit to fail
1749  // would be a singular fit matrix, that should be pretty much impossible
1750  // given that the bin coordinates are well behaved and there are at least
1751  // two of them
1752  std::cerr << "IntegrateFitCharge(): linear fit failed!" << std::endl;
1753  return 0.;
1754  }
1755 
1756  // now determine the bins corresponding to the length to integrate;
1757  // note that length can be pathologic (0, negative...); not our problem!
1758  const double length_to_bin
1759  = (double(fChargeProfile.size() - 1) / fProjectedLength);
1760  const double from_bin = from_length * length_to_bin,
1761  to_bin = to_length * length_to_bin;
1762 
1763  // we want the integral between from_bin and to_bin now:
1764  return LinearIntegral(fit[1] /* m */, fit[0] /* q */, from_bin, to_bin);
1765  } // ClusterParamsAlg::IntegrateFitCharge()
1766 
1767 
1768  //----------------------------------------------------------------------------
1770  (float length /* = 1. */, unsigned int nbins /* = 10 */)
1771  {
1772  switch (fHitVector.size()) {
1773  case 0: return 0.;
1774  case 1: return fHitVector.back().charge;
1775  // the "default" is the rest of the function
1776  } // switch
1777 
1778  // this is the range of the fit:
1779  const unsigned int fit_first_bin = 0, fit_last_bin = nbins;
1780 
1781  return IntegrateFitCharge(0., length, fit_first_bin, fit_last_bin);
1782  } // ClusterParamsAlg::StartCharge()
1783 
1784 
1785  //----------------------------------------------------------------------------
1787  (float length /* = 1. */, unsigned int nbins /* = 10 */)
1788  {
1789  switch (fHitVector.size()) {
1790  case 0: return 0.;
1791  case 1: return fHitVector.back().charge;
1792  // the "default" is the rest of the function
1793  } // switch
1794 
1795 
1796  // need the available number of bins and the axis length
1797  GetProfileInfo();
1798  const unsigned int MaxBins = fChargeProfile.size();
1799 
1800  // this is the range of the fit:
1801  const unsigned int fit_first_bin = MaxBins > nbins? MaxBins - nbins: 0,
1802  fit_last_bin = MaxBins;
1803 
1804  // now determine the integration range, in bin units;
1805  // get to the end, and go length backward;
1806  // note that length can be pathologic (0, negative...); not our problem!
1807  const double from = fProjectedLength -length, to = fProjectedLength;
1808 
1809  return IntegrateFitCharge(from, to, fit_first_bin, fit_last_bin);
1810  } // ClusterParamsAlg::EndCharge()
1811 
1812 
1813  //------------------------------------------------------------------------------
1815  if (fHitVector.size() < 2) return 0.0F;
1816 
1817  // compute all the averages
1818  GetAverages();
1819 
1820  // return the relevant information
1821  return std::isnormal(fParams.N_Wires)?
1823  } // ClusterParamsAlg::MultipleHitWires()
1824 
1825 
1826  //------------------------------------------------------------------------------
1828  if (fHitVector.size() < 2) return 0.0F;
1829 
1830  // compute all the averages
1831  GetAverages();
1832  RefineStartPoints(); // fParams.length
1833 
1834  // return the relevant information
1835  return std::isnormal(fParams.length)?
1837  } // ClusterParamsAlg::MultipleHitDensity()
1838 
1839 
1840 } //end namespace
1841 
1842 
1843 #endif
double rms_ADC
RMS (standard deviation of sample) of ADC counts of hits in ADC.
Definition: ClusterParams.h:32
util::GeometryUtilities * fGSer
void GetRoughAxis(bool override=false)
std::vector< double > fChargeProfileNew
static const GeometryUtilities * GetME()
void GetProfileInfo(bool override=false)
double closing_angle_charge_wgt
Same for charge_wgt.
Definition: ClusterParams.h:44
std::vector< std::string > fTimeRecord_ProcName
double charge_wgt_y
Mean of hits along y, charge weighted.
Definition: ClusterParams.h:38
Double_t Get2DDistance(Double_t wire1, Double_t time1, Double_t wire2, Double_t time2) const
void RefineStartPoints(bool override=false)
Double_t Get2Dangle(Double_t deltawire, Double_t deltatime) const
double mean_x
Mean of hits along x, peaks only.
Definition: ClusterParams.h:33
double start_charge
Charge at the start of the cluster.
Definition: ClusterParams.h:45
double EndCharge(float length=1., unsigned int nbins=10)
Returns the expected charge at the end of the cluster.
Float_t x1[n_points_granero]
Definition: compare.C:5
TNtupleSim Fill(f1, f2, f3, f4)
void GetFinalSlope(bool override=false)
Double_t z
Definition: plot.C:279
double rms_charge
RMS (standard deviation of sample) of charge of hits in ADC.
Definition: ClusterParams.h:29
double StartCharge(float length=1., unsigned int nbins=10)
Returns the expected charge at the beginning of the cluster.
Polygon2D PolyObject
Polygon Object...see Polygon2D.hh.
Definition: ClusterParams.h:22
TLegend * leg
Definition: compare.C:67
ClusterParamsAlg()
Default constructor.
std::vector< util::PxHit > fHitVector
double eigenvalue_principal
the principal eigenvalue from PCA
Definition: ClusterParams.h:47
double mean_ADC
Mean (average) of ADC counts of hits, in ADC.
Definition: ClusterParams.h:31
Cluster finding and building.
gr2 SetLineColor(2)
double mean_y
Mean of hits along y, peaks only.
Definition: ClusterParams.h:34
Classes gathering simple statistics.
void FillParams(bool override_DoGetAverages=false, bool override_DoGetRoughAxis=false, bool override_DoGetProfileInfo=false, bool override_DoRefineStartPointsAndDirection=false, bool override_DoGetFinalSlope=false, bool override_DoTrackShowerSep=false, bool override_DoEndCharge=false)
Weight_t RMS() const
Returns the root mean square.
Classes performing simple fits.
float MultipleHitDensity()
Returns the number of multiple hits per wire.
Performs a linear regression of data.
Definition: SimpleFits.h:849
Weight_t Average() const
Returns the value average.
void Report(Stream &os) const
T sqr(T v)
double eigenvalue_secondary
the secondary eigenvalue from PCA
Definition: ClusterParams.h:48
c1 Update()
double sum_charge
Sum charge of hits in ADC.
Definition: ClusterParams.h:27
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
cluster::cluster_params fParams
Weight_t Sum() const
Returns the weighted sum of the values.
double t
Definition: PxUtils.h:11
Float_t d
Definition: plot.C:237
void TrackShowerSeparation(bool override=false)
std::vector< double > fTimeRecord_ProcTime
util::PxPoint start_point
start point
Definition: ClusterParams.h:24
void SelectLocalHitlist(const std::vector< util::PxHit > &hitlist, std::vector< const util::PxHit * > &hitlistlocal, util::PxPoint &startHit, Double_t &linearlimit, Double_t &ortlimit, Double_t &lineslopetest)
double angle_2d
Angle of axis in wire/hit view.
Definition: ClusterParams.h:40
std::array< Data_t, NParams > FitParameters_t
type of set of fit parameters
Definition: SimpleFits.h:866
void GetAverages(bool override=false)
Detector simulation of raw signals on wires.
double w
Definition: PxUtils.h:10
void RefineStartPointAndDirection(bool override=false)
void RefineDirection(bool override=false)
Int_t GetPointOnLine(Double_t slope, Double_t intercept, Double_t wire1, Double_t time1, Double_t &wireout, Double_t &timeout) const
virtual FitParameters_t FitParameters() const override
Computes and returns all the parameters of the fit result.
leg AddEntry(gr1,"Reference data","lp")
double weight
Definition: plottest35.C:25
double sum_ADC
Sum charge of ADC counts of hits, in ADC.
Definition: ClusterParams.h:30
std::vector< double > fCoarseChargeProfile
util::PxPoint end_point
end point
Definition: ClusterParams.h:25
size_t fMinNHits
Cut value for # hits: below this value clusters are not evaluated.
Int_t min
Definition: plot.C:26
double mean_charge
Mean (average) charge of hits in ADC.
Definition: ClusterParams.h:28
int SetHits(const std::vector< util::PxHit > &)
double charge_wgt_x
Mean of hits along x, charge weighted.
Definition: ClusterParams.h:37
double opening_angle_charge_wgt
Same for charge_wgt.
Definition: ClusterParams.h:42
hist1 Draw("HIST")
double charge
area charge
Definition: PxUtils.h:39
void GetEndCharges(bool override_=false)
Char_t n[5]
double opening_angle
Width of angular distubtion wrt vertx.
Definition: ClusterParams.h:41
Int_t GetPointOnLineWSlopes(Double_t slope, Double_t intercept, Double_t ort_intercept, Double_t &wireout, Double_t &timeout) const
c1 cd(1)
Float_t x2[n_points_geant4]
Definition: compare.C:26
void Report(Stream &stream) const
double IntegrateFitCharge(double from_length, double to_length, unsigned int fit_first_bin, unsigned int fit_end_bin)
Integrates the charge between two positions in the cluster axis.
double cluster_angle_2d
Linear best fit to high-charge hits in the cluster.
Definition: ClusterParams.h:39
double rms_x
rms of hits along x (wires)
Definition: ClusterParams.h:35
simulatedPeak Scale(1/simulationNormalisationFactor)
double rms_y
rms of hits along y, (time)
Definition: ClusterParams.h:36
Collects statistics on a single quantity (weighted)
bool add(Data_t x, Data_t y, Data_t sy=Data_t(1.0))
Definition: SimpleFits.h:366
static double LinearIntegral(double m, double q, double x1, double x2)
Returns the integral of f(x) = mx + q defined in [x1, x2].
void SelectPolygonHitList(const std::vector< util::PxHit > &hitlist, std::vector< const util::PxHit * > &hitlistlocal)
#define PI
double closing_angle
Width of angular distubtion wrt endpoint.
Definition: ClusterParams.h:43
std::vector< double > fChargeProfile
unsigned int plane
Definition: PxUtils.h:12
std::vector< double > fChargeCutoffThreshold
float MultipleHitWires()
Returns the number of multiple hits per wire.
void add(Data_t value, Weight_t weight=Weight_t(1.0))
Adds one entry with specified value and weight.
void GetFANNVector(std::vector< float > &data)
double end_charge
Charge at the (other) end of the cluster.
Definition: ClusterParams.h:46