LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Chi2PIDAlg.cxx
Go to the documentation of this file.
1 //
3 // Chi2PIDAlg class
4 //
5 // tjyang@fnal.gov
6 //
8 
9 //#include "RecoBase/Track.h"
13 
14 // ROOT includes
15 #include "TFile.h"
16 #include "TMath.h"
17 #include "TProfile.h"
18 
19 // Framework includes
21 #include "cetlib/search_path.h"
22 #include "fhiclcpp/ParameterSet.h"
24 
25 #include "cetlib/pow.h"
26 
27 //------------------------------------------------------------------------------
29 {
30  fTemplateFile = pset.get<std::string>("TemplateFile");
31  fUseMedian = pset.get<bool>("UseMedian");
32  //fCalorimetryModuleLabel = pset.get< std::string >("CalorimetryModuleLabel");
33 
34  cet::search_path sp("FW_SEARCH_PATH");
35 
36  if (!sp.find_file(fTemplateFile, fROOTfile))
37  throw cet::exception("Chi2ParticleID") << "cannot find the root template file: \n"
38  << fTemplateFile << "\n bail ungracefully.\n";
39  TFile* file = TFile::Open(fROOTfile.c_str());
40  dedx_range_pro = (TProfile*)file->Get("dedx_range_pro");
41  dedx_range_ka = (TProfile*)file->Get("dedx_range_ka");
42  dedx_range_pi = (TProfile*)file->Get("dedx_range_pi");
43  dedx_range_mu = (TProfile*)file->Get("dedx_range_mu");
44 
45  // std::cout<<"Chi2PIDAlg configuration:"<<std::endl;
46  // std::cout<<"Template file: "<<fROOTfile<<std::endl;
47  // std::cout<<"fUseMedian: "<<fUseMedian<<std::endl;
48 }
49 
50 //------------------------------------------------------------------------------
52 {
53 
54  std::bitset<8> thisBitset;
55 
56  thisBitset.set(planeID.Plane);
57 
58  return thisBitset;
59 }
60 
61 //------------------------------------------------------------------------------
64 {
65 
66  std::vector<anab::sParticleIDAlgScores> AlgScoresVec;
67  geo::PlaneID plid;
68 
69  for (size_t i_calo = 0; i_calo < calos.size(); i_calo++) {
70 
71  art::Ptr<anab::Calorimetry> calo = calos.at(i_calo);
72  if (i_calo == 0)
73  plid = calo->PlaneID();
74  else if (plid != calo->PlaneID())
75  throw cet::exception("Chi2PIDAlg") << "PlaneID mismatch: " << plid << ", " << calo->PlaneID();
76  int npt = 0;
77  double chi2pro = 0;
78  double chi2ka = 0;
79  double chi2pi = 0;
80  double chi2mu = 0;
81  double PIDA = 0; //by Bruce Baller
82  std::vector<double> vpida;
83  std::vector<float> trkdedx = calo->dEdx();
84  std::vector<float> trkres = calo->ResidualRange();
85  std::vector<float> deadwireresrc = calo->DeadWireResRC();
86 
87  int used_trkres = 0;
88  int nbins_dedx_range = dedx_range_pro->GetNbinsX();
89  for (unsigned i = 0; i < trkdedx.size(); ++i) { //hits
90  //ignore the first and the last point
91  if (i == 0 || i == trkdedx.size() - 1) continue;
92  if (trkres[i] < 30) {
93  double PIDAi = trkdedx[i] * pow(trkres[i], 0.42);
94  PIDA += PIDAi;
95  vpida.push_back(PIDAi);
96  used_trkres++;
97  }
98  if (trkdedx[i] > 1000) continue; //protect against large pulse height
99  int bin = dedx_range_pro->FindBin(trkres[i]);
100  if (bin >= 1 && bin <= nbins_dedx_range) {
101  double bincpro = dedx_range_pro->GetBinContent(bin);
102  if (bincpro < 1e-6) { //for 0 bin content, using neighboring bins
103  bincpro =
104  (dedx_range_pro->GetBinContent(bin - 1) + dedx_range_pro->GetBinContent(bin + 1)) / 2;
105  }
106  double bincka = dedx_range_ka->GetBinContent(bin);
107  if (bincka < 1e-6) {
108  bincka =
109  (dedx_range_ka->GetBinContent(bin - 1) + dedx_range_ka->GetBinContent(bin + 1)) / 2;
110  }
111  double bincpi = dedx_range_pi->GetBinContent(bin);
112  if (bincpi < 1e-6) {
113  bincpi =
114  (dedx_range_pi->GetBinContent(bin - 1) + dedx_range_pi->GetBinContent(bin + 1)) / 2;
115  }
116  double bincmu = dedx_range_mu->GetBinContent(bin);
117  if (bincmu < 1e-6) {
118  bincmu =
119  (dedx_range_mu->GetBinContent(bin - 1) + dedx_range_mu->GetBinContent(bin + 1)) / 2;
120  }
121  double binepro = dedx_range_pro->GetBinError(bin);
122  if (binepro < 1e-6) {
123  binepro =
124  (dedx_range_pro->GetBinError(bin - 1) + dedx_range_pro->GetBinError(bin + 1)) / 2;
125  }
126  double bineka = dedx_range_ka->GetBinError(bin);
127  if (bineka < 1e-6) {
128  bineka = (dedx_range_ka->GetBinError(bin - 1) + dedx_range_ka->GetBinError(bin + 1)) / 2;
129  }
130  double binepi = dedx_range_pi->GetBinError(bin);
131  if (binepi < 1e-6) {
132  binepi = (dedx_range_pi->GetBinError(bin - 1) + dedx_range_pi->GetBinError(bin + 1)) / 2;
133  }
134  double binemu = dedx_range_mu->GetBinError(bin);
135  if (binemu < 1e-6) {
136  binemu = (dedx_range_mu->GetBinError(bin - 1) + dedx_range_mu->GetBinError(bin + 1)) / 2;
137  }
138  //double errke = 0.05*trkdedx[i]; //5% KE resolution
139  double errdedx = 0.04231 + 0.0001783 * trkdedx[i] * trkdedx[i]; //resolution on dE/dx
140  errdedx *= trkdedx[i];
141 
142  double errdedx_square = errdedx * errdedx;
143  chi2pro += cet::square(trkdedx[i] - bincpro) / (binepro * binepro + errdedx_square);
144  chi2ka += cet::square(trkdedx[i] - bincka) / (bineka * bineka + errdedx_square);
145  chi2pi += cet::square(trkdedx[i] - bincpi) / (binepi * binepi + errdedx_square);
146  chi2mu += cet::square(trkdedx[i] - bincmu) / (binemu * binemu + errdedx_square);
147 
148  //std::cout<<i<<" "<<trkdedx[i]<<" "<<trkres[i]<<" "<<bincpro<<std::endl;
149  ++npt;
150  }
151  }
152 
153  anab::sParticleIDAlgScores chi2proton;
157  anab::sParticleIDAlgScores pida_mean;
158  anab::sParticleIDAlgScores pida_median;
159 
160  //anab::ParticleID pidOut;
161  if (npt) {
162 
163  chi2proton.fAlgName = "Chi2";
164  chi2proton.fVariableType = anab::kGOF;
165  chi2proton.fTrackDir = anab::kForward;
166  chi2proton.fAssumedPdg = 2212;
167  chi2proton.fPlaneMask = GetBitset(calo->PlaneID());
168  chi2proton.fNdf = npt;
169  chi2proton.fValue = chi2pro / npt;
170 
171  chi2muon.fAlgName = "Chi2";
172  chi2muon.fVariableType = anab::kGOF;
173  chi2muon.fTrackDir = anab::kForward;
174  chi2muon.fAssumedPdg = 13;
175  chi2muon.fPlaneMask = GetBitset(calo->PlaneID());
176  chi2muon.fNdf = npt;
177  chi2muon.fValue = chi2mu / npt;
178 
179  chi2kaon.fAlgName = "Chi2";
180  chi2kaon.fVariableType = anab::kGOF;
181  chi2kaon.fTrackDir = anab::kForward;
182  chi2kaon.fAssumedPdg = 321;
183  chi2kaon.fPlaneMask = GetBitset(calo->PlaneID());
184  chi2kaon.fNdf = npt;
185  chi2kaon.fValue = chi2ka / npt;
186 
187  chi2pion.fAlgName = "Chi2";
188  chi2pion.fVariableType = anab::kGOF;
189  chi2pion.fTrackDir = anab::kForward;
190  chi2pion.fAssumedPdg = 211;
191  chi2pion.fPlaneMask = GetBitset(calo->PlaneID());
192  chi2pion.fNdf = npt;
193  chi2pion.fValue = chi2pi / npt;
194 
195  AlgScoresVec.push_back(chi2proton);
196  AlgScoresVec.push_back(chi2muon);
197  AlgScoresVec.push_back(chi2kaon);
198  AlgScoresVec.push_back(chi2pion);
199  }
200 
201  //if (trkdedx.size()) pidOut.fPIDA = PIDA/trkdedx.size();
202  if (used_trkres > 0) {
203  if (fUseMedian) {
204  pida_median.fAlgName = "PIDA_median";
205  pida_median.fVariableType = anab::kPIDA;
206  pida_median.fTrackDir = anab::kForward;
207  pida_median.fValue = TMath::Median(vpida.size(), &vpida[0]);
208  pida_median.fPlaneMask = GetBitset(calo->PlaneID());
209  AlgScoresVec.push_back(pida_median);
210  }
211  else { // use mean
212  pida_mean.fAlgName = "PIDA_mean";
213  pida_mean.fVariableType = anab::kPIDA;
214  pida_mean.fTrackDir = anab::kForward;
215  pida_mean.fValue = PIDA / used_trkres;
216  pida_mean.fPlaneMask = GetBitset(calo->PlaneID());
217  AlgScoresVec.push_back(pida_mean);
218  }
219  }
220  }
221 
222  anab::ParticleID pidOut(AlgScoresVec, plid);
223 
224  return pidOut;
225 }
Chi2PIDAlg(fhicl::ParameterSet const &pset)
Definition: Chi2PIDAlg.cxx:28
TProfile * dedx_range_mu
muon template
Definition: Chi2PIDAlg.h:51
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
const geo::PlaneID & PlaneID() const
Definition: Calorimetry.h:140
TProfile * dedx_range_pro
proton template
Definition: Chi2PIDAlg.h:48
TProfile * dedx_range_pi
pion template
Definition: Chi2PIDAlg.h:50
float fValue
Result of Particle ID algorithm/test.
Definition: ParticleID.h:33
const std::vector< float > & DeadWireResRC() const
Definition: Calorimetry.h:109
std::bitset< 8 > fPlaneMask
Bitset for PlaneID used by algorithm, allowing for multiple planes and up to 8 total planes...
Definition: ParticleID.h:35
const std::vector< float > & ResidualRange() const
Definition: Calorimetry.h:105
std::string fAlgName
< determined particle ID
Definition: ParticleID.h:24
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
int fNdf
Number of degrees of freedom used by algorithm, if applicable. Set to -9999 by default.
Definition: ParticleID.h:30
kTrackDir fTrackDir
Track direction enum: defined in ParticleID_VariableTypeEnums.h. Set to kNoDirection by default...
Definition: ParticleID.h:28
kVariableType fVariableType
Variable type enum: defined in ParticleID_VariableTypeEnums.h. Set to kNotSet by default.
Definition: ParticleID.h:26
T get(std::string const &key) const
Definition: ParameterSet.h:314
std::string fROOTfile
Definition: Chi2PIDAlg.h:46
std::bitset< 8 > GetBitset(geo::PlaneID planeID)
Definition: Chi2PIDAlg.cxx:51
std::string fTemplateFile
Definition: Chi2PIDAlg.h:43
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
float bin[41]
Definition: plottest35.C:14
const std::vector< float > & dEdx() const
Definition: Calorimetry.h:97
anab::ParticleID DoParticleID(const std::vector< art::Ptr< anab::Calorimetry >> &calo)
Definition: Chi2PIDAlg.cxx:62
TFile * file
TProfile * dedx_range_ka
kaon template
Definition: Chi2PIDAlg.h:49
Float_t e
Definition: plot.C:35
Definition: fwd.h:26
calorimetry
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
int fAssumedPdg
PDG of particle hypothesis assumed by algorithm, if applicable. Set to 0 by default.
Definition: ParticleID.h:32