LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ShowerRecoAlg.cxx
Go to the documentation of this file.
1 #ifndef RECOTOOL_SHOWERRECOALG_CXX
2 #define RECOTOOL_SHOWERRECOALG_CXX
3 
4 #include "ShowerRecoAlg.h"
5 
6 namespace showerreco {
7 
9  {
10 
12 
13  fcalodEdxlength=1000;
14  fdEdxlength=2.4;
15  fUseArea = true;
16  fVerbosity = true;
17  _Ecorrection = true;
18  }
19 
20 
21  ::recob::Shower ShowerRecoAlg::RecoOneShower(const std::vector< ::showerreco::ShowerCluster_t>& clusters)
22  {
23 
24  ::recob::Shower result;
25  //
26  // Reconstruct and store
27  //
28  std::vector < util::PxPoint > fStartPoint; // for each plane
29  std::vector < util::PxPoint > fEndPoint; // for each plane
30  std::vector < double > fOmega2D; // for each plane
31 
32  std::vector < double > fEnergy (fGSer->Nplanes(),-1); // for each plane
33  std::vector < double > fMIPEnergy(fGSer->Nplanes(),-1); // for each plane
34  std::vector < double > fdEdx (fGSer->Nplanes(),-1);
35  std::vector <unsigned char> fPlaneID;
36 
37  // First Get Start Points
38  for(auto const & cl : clusters)
39  {
40  fStartPoint.push_back(cl.start_point); // for each plane
41  fEndPoint.push_back(cl.end_point); // for each plane
42  fOmega2D.push_back(cl.angle_2d);
43  fPlaneID.push_back(cl.plane_id);
44  if(fVerbosity) {
45  std::cout << " planes : " << cl.plane_id
46  << " " << cl.start_point.t
47  << " " << cl.start_point.w
48  << " " << cl.end_point.t
49  << " " << cl.end_point.w
50  <<" angle2d "<< cl.angle_2d
51  << std::endl;
52  }
53  }
54 
55 
56  //decide best two planes. for now, using length in wires - flatter is better.
57  int index_to_use[2]={0,1};
58  int best_plane=-1;
59  //int good_plane=-1;
60  double best_length=0;
61  double good_length=0;
62  for (size_t ip=0;ip<fPlaneID.size();ip++)
63  {
64  double dist = fabs( fEndPoint[ip].w - fStartPoint[ip].w );
65  if(dist > best_length )
66  {
67  good_length = best_length;
68  //good_plane = best_plane;
69  index_to_use[1] = index_to_use[0];
70 
71  best_length = dist;
72  best_plane = fPlaneID.at(ip);
73  index_to_use[0] = ip;
74  }
75  else if(dist > good_length)
76  {
77  good_length = dist;
78  //good_plane = fPlaneID.at(ip);
79  index_to_use[1] = ip;
80  }
81  }
82 
83  // Second Calculate 3D angle and effective pitch and start point
84  double xphi=0,xtheta=0;
85 
86 
87  fGSer->Get3DaxisN(fPlaneID[index_to_use[0]],
88  fPlaneID[index_to_use[1]],
89  fOmega2D[index_to_use[0]]*TMath::Pi()/180.,
90  fOmega2D[index_to_use[1]]*TMath::Pi()/180.,
91  xphi,
92  xtheta);
93 
94  if(fVerbosity)
95  std::cout << " new angles: " << xphi << " " << xtheta << std::endl;
96 
97 
98 
99  double xyz[3];
100  // calculate start point here?
101  fGSer-> GetXYZ(&(fStartPoint[index_to_use[0]]),&(fStartPoint[index_to_use[1]]),xyz);
102 
103  if(fVerbosity)
104  std::cout << " XYZ: " << xyz[0] << " " << xyz[1] << " " << xyz[2] << std::endl;
105 
106  // Third calculate dE/dx and total energy for all planes, because why not?
107  //for(auto const &clustit : clusters)
108  for(size_t cl_index=0; cl_index < fPlaneID.size(); ++cl_index)
109  {
110  int plane = fPlaneID.at(cl_index);
111  double newpitch=fGSer->PitchInView(plane,xphi,xtheta);
112  if(plane == best_plane) best_length *= newpitch / fGSer->WireToCm();
113 
114  if(fVerbosity)
115  std::cout << std::endl << " Plane: " << plane << std::endl;
116 
117  double totEnergy=0;
118  double totLowEnergy=0;
119  double totHighEnergy=0;
120  double totMIPEnergy=0;
121  int direction=-1;
122  //double RMS_dedx=0;
123  double dEdx_av=0,dedx_final=0;
124  int npoints_first=0, npoints_sec=0;
125 
126  //override direction if phi (XZ angle) is less than 90 degrees
127  // this is shady, and needs to be rethought.
128  if(fabs(fOmega2D.at(cl_index)) < 90)
129  direction=1;
130 
131  auto const& hitlist = clusters.at(cl_index).hit_vector;
132  std::vector<util::PxHit> local_hitlist;
133  local_hitlist.reserve(hitlist.size());
134 
135  for(const auto& theHit : hitlist){
136 
137  double dEdx_new=0;
138  double hitElectrons = 0;
139  //double Bcorr_half;
140  //double dEdx_sub;
141  // double dEdx_MIP;
142 
143  // dEdx_new = fCaloAlg->dEdx_AREA(theHit, newpitch );
144  //Bcorr_half = 2.*fCaloAlg->dEdx_AREA(theHit->Charge()/2.,theHit->PeakTime(), newpitch, plane); ;
145  //dEdx_sub = fCaloAlg->dEdx_AREA(theHit->Charge()-PION_CORR,theHit->PeakTime(), newpitch, plane); ;
146  // dEdx_MIP = fCaloAlg->dEdx_AREA_forceMIP(theHit, newpitch );
147  if(!fUseArea)
148  {
149  dEdx_new = fCaloAlg->dEdx_AMP(theHit.peak / newpitch, theHit.t / fGSer->TimeToCm(), theHit.plane);
150  hitElectrons = fCaloAlg->ElectronsFromADCPeak(theHit.peak, plane);
151  }
152  else
153  {
154  dEdx_new = fCaloAlg->dEdx_AREA(theHit.charge / newpitch, theHit.t / fGSer->TimeToCm(), theHit.plane);
155  hitElectrons = fCaloAlg->ElectronsFromADCArea(theHit.charge, plane);
156  }
157 
158  hitElectrons *= fCaloAlg->LifetimeCorrection(theHit.t / fGSer->TimeToCm());
159 
160  totEnergy += hitElectrons * 1.e3 / (::util::kGeVToElectrons);
161 
162  //totNewCnrg+=dEdx_MIP;
163  // if(dEdx_new < 3.5 && dEdx_new >0 )
164  // {
165  // totLowEnergy +=dEdx_new*newpitch;
166  // totMIPEnergy += dEdx_new*newpitch;
167  // }
168  // else
169  // {
170  // totHighEnergy += dEdx_new*newpitch;
171  int multiplier=1;
172  if(plane < 2) multiplier =2 ;
173  if(!fUseArea){
174  totMIPEnergy += theHit.peak * 0.0061*multiplier;
175  }
176  else{
177  totMIPEnergy += theHit.charge * 0.00336*multiplier;
178  }
179  // }
180 
181  if(fVerbosity && dEdx_new >1.9 && dEdx_new <2.1)
182  std::cout << "dEdx_new " << dEdx_new << " " <<dEdx_new/theHit.charge*newpitch << " "<< theHit.charge *0.0033*multiplier/newpitch << std::endl;
183 
184  util::PxPoint OnlinePoint;
185  // calculate the wire,time coordinates of the hit projection on to the 2D shower axis
186  fGSer->GetPointOnLine(fOmega2D.at(cl_index),
187  &(fStartPoint.at(cl_index)),
188  &theHit,
189  OnlinePoint);
190 
191  double ortdist=fGSer->Get2DDistance(&OnlinePoint,&theHit);
192  double linedist=fGSer->Get2DDistance(&OnlinePoint,&(fStartPoint.at(cl_index)));
193 
194 
195  //calculate the distance from the vertex using the effective pitch metric
196  double wdist=((theHit.w-fStartPoint.at(cl_index).w)*newpitch)*direction; //wdist is always positive
197 
198  if(fVerbosity && dEdx_new < 3.5 )
199  std::cout << " CALORIMETRY:"
200  << " Pitch " <<newpitch
201  << " dist: " << wdist
202  << " dE/dx: " << dEdx_new << "MeV/cm "
203  << " average: " << totEnergy
204  << "hit: wire, time " << theHit.w/fGSer->WireToCm() << " " << theHit.t/fGSer->TimeToCm()
205  << "total energy" << totEnergy
206  << std::endl;
207 
208  // if( (fabs(wdist)<fcalodEdxlength)&&(fabs(wdist)>0.2)){
209  if( (wdist<fcalodEdxlength)&&(wdist>0.2)){
210 
211  //vdEdx.push_back(dEdx_new);
212  //vresRange.push_back(fabs(wdist));
213  //vdQdx.push_back(theHit->Charge(true)/newpitch);
214  //Trk_Length=wdist;
215 
216  //fTrkPitchC=fNPitch[set][plane];
217  //Kin_En+=dEdx_new*newpitch;
218  //npoints_calo++;
219  //sum+=dEdx_new;
220 
221 
222 
223  //fDistribChargeADC[set].push_back(ch_adc); //vector with the first De/Dx points
224  // fDistribChargeMeV[set].push_back(dEdx_new); //vector with the first De/Dx points
225  // fDistribHalfChargeMeV[set].push_back(Bcorr_half);
226  // fDistribChargeposition[set].push_back(wdist); //vector with the first De/Dx points' positions
227  // fDistribChargeMeVMIPsub[set].push_back(dEdx_sub);
228  //
229 
230 
231  //first pass at average dE/dx
232  if(wdist<fdEdxlength
233  //take no hits before vertex (depending on direction)
234  && ((direction==1 && theHit.w > fStartPoint.at(cl_index).w) || (direction==-1 && theHit.w < fStartPoint.at(cl_index).w) )
235  && ortdist<3.5
236  && linedist < fdEdxlength ){
237 
238  dEdx_av+= dEdx_new;
239  local_hitlist.push_back(theHit);
240 
241  npoints_first++;
242  if(fVerbosity)
243  std::cout << " CALORIMETRY:" << " Pitch " <<newpitch
244  << " dist: " << wdist
245  << " dE/dx: " << dEdx_new << "MeV/cm "
246  << " average: " << dEdx_av/npoints_first
247  << " hit: wire, time " << theHit.w << " " << theHit.t
248  << " line,ort " << linedist << " " << ortdist
249  << " direction " << direction
250  << std::endl;
251  }
252 
253  }//end inside range if statement
254 
255  }// end first loop on hits.
256 
257 
258 
259  double mevav2cm=0;
260  double fRMS_corr=0;
261 
262  //calculate average dE/dx
263  if(npoints_first>0) {
264  mevav2cm=dEdx_av/npoints_first;
265 
266  }
267 
268  //loop only on subset of hits
269  for(auto const & theHit : local_hitlist){
270  double dEdx=0;
271  if(fUseArea)
272  {
273  dEdx = fCaloAlg->dEdx_AREA(theHit.charge / newpitch, theHit.t / fGSer->TimeToCm(), theHit.plane);
274  }
275  else //this will hopefully go away, once all of the calibration factors are calculated.
276  {
277  dEdx = fCaloAlg->dEdx_AMP(theHit.peak / newpitch, theHit.t / fGSer->TimeToCm(), theHit.plane);
278  }
279  //fDistribAfterMin[set].push_back(MinBefore);
280  //fDistribBeforeMin[set].push_back(MinAfter);
281  // auto position = hitIter - local_hitlist.begin() ;
282 
283  fRMS_corr+=(dEdx-mevav2cm)*(dEdx-mevav2cm);
284 
285  }
286 
287 
288 
289  if(npoints_first>0)
290  {
291  fRMS_corr=TMath::Sqrt(fRMS_corr/npoints_first);
292  }
293 
295  //loop only on subset of hits
296 
297  for(auto const & theHit : local_hitlist){
298  double dEdx=0;
299  if(fUseArea)
300  {
301  dEdx = fCaloAlg->dEdx_AREA(theHit.charge / newpitch, theHit.t / fGSer->TimeToCm(), theHit.plane);
302  }
303  else //this will hopefully go away, once all of the calibration factors are calculated.
304  {
305  dEdx = fCaloAlg->dEdx_AMP(theHit.peak / newpitch, theHit.t / fGSer->TimeToCm(), theHit.plane);
306  }
307  //fDistribAfterMin[set].push_back(MinBefore);
308  //fDistribBeforeMin[set].push_back(MinAfter);
309 
310  if( ((dEdx > (mevav2cm-fRMS_corr) ) && (dEdx < (mevav2cm+fRMS_corr) ))
311  ||
312  (newpitch > 0.3*fdEdxlength )
313  ) {
314  dedx_final+= dEdx;
315  npoints_sec++;
316  }
317  }
318 
319  if(npoints_sec>0){
320  dedx_final/=npoints_sec;
321  }
322 
323  if(fVerbosity){
325  std::cout << " total ENERGY, birks: " << totEnergy << " MeV "
326  << " |average: " << dedx_final << std::endl
327  << " Energy: lo:" << totLowEnergy << " hi: " << totHighEnergy
328  << " MIP corrected " << totMIPEnergy << std::endl;
329  }
330  // if Energy correction factor to be used
331  // then get it from ShowerCalo.h
332  if (_Ecorrection) { totEnergy *= showerreco::energy::DEFAULT_ECorr; }
333  fEnergy[plane] = totEnergy; // for each plane
334  fMIPEnergy[plane] = totMIPEnergy;
335  fdEdx[plane] = dedx_final;
336 
337  // break;
338  } // end loop on clusters
339 
340  result.set_total_MIPenergy(fMIPEnergy);
341  result.set_total_best_plane(best_plane);
342  result.set_length(best_length);
343  result.set_total_energy(fEnergy);
344  //result.set_total_energy_err (std::vector< Double_t > q) { fSigmaTotalEnergy = q; }
345 
346  double dirs[3]={0};
347  fGSer->GetDirectionCosines(xphi,xtheta,dirs);
348  TVector3 vdirs(dirs[0],dirs[1],dirs[2]);
349 
350  TVector3 vxyz(xyz[0], xyz[1], xyz[2]);
351 
352  result.set_direction(vdirs);
353  //result.set_direction_err (TVector3 dir_e) { fSigmaDCosStart = dir_e; }
354  result.set_start_point(vxyz);
355  //result.set_start_point_err (TVector3 xyz_e) { fSigmaXYZstart = xyz_e; }
356  result.set_dedx (fdEdx);
357  //result.set_dedx_err (std::vector< Double_t > q) { fSigmadEdx = q; }
358 
359  // done
360  return result;
361  }
362 
363 }
364 
365 #endif
virtual ::recob::Shower RecoOneShower(const std::vector< ::showerreco::ShowerCluster_t > &)
Function to reconstruct a shower.
Class def header for a class ShowerRecoAlg.
static const GeometryUtilities * GetME()
Double_t Get2DDistance(Double_t wire1, Double_t time1, Double_t wire2, Double_t time2) const
double dEdx_AREA(art::Ptr< recob::Hit > hit, double pitch, double T0=0) const
::calo::CalorimetryAlg * fCaloAlg
Calorimetry algorithm.
bool _Ecorrection
Boolean -> decide if to use energy correction or not.
Definition: ShowerRecoAlg.h:62
static const double DEFAULT_ECorr
Definition: ShowerCalo.h:30
void set_total_energy(const std::vector< double > &q)
Definition: Shower.h:129
Double_t TimeToCm() const
Double_t WireToCm() const
util::GeometryUtilities * fGSer
Definition: ShowerRecoAlg.h:57
Double_t PitchInView(UInt_t plane, Double_t phi, Double_t theta) const
double ElectronsFromADCArea(double area, unsigned short plane) const
double ElectronsFromADCPeak(double adc, unsigned short plane) const
constexpr double kGeVToElectrons
23.6eV per ion pair, 1e9 eV/GeV
void set_direction(const TVector3 &dir)
Definition: Shower.h:135
bool fVerbosity
Verbosity flag.
void set_length(const double &l)
Definition: Shower.h:141
void set_total_best_plane(const int q)
Definition: Shower.h:133
void set_total_MIPenergy(const std::vector< double > &q)
Definition: Shower.h:131
Int_t GetPointOnLine(Double_t slope, Double_t intercept, Double_t wire1, Double_t time1, Double_t &wireout, Double_t &timeout) const
void GetDirectionCosines(Double_t phi, Double_t theta, Double_t *dirs) const
void set_start_point(const TVector3 &xyz)
Definition: Shower.h:137
double LifetimeCorrection(double time, double T0=0) const
Float_t w
Definition: plot.C:23
ShowerRecoAlg()
Default constructor.
Int_t Get3DaxisN(Int_t iplane0, Int_t iplane1, Double_t omega0, Double_t omega1, Double_t &phi, Double_t &theta) const
double dEdx_AMP(art::Ptr< recob::Hit > hit, double pitch, double T0=0) const
void set_dedx(const std::vector< double > &q)
Definition: Shower.h:139