Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
ShowerBayesianTrucatingdEdx_tool.cc
Go to the documentation of this file.
1//############################################################################
2//### Name: ShowerBayesianTrucatingdEdx ###
3//### Author: Dominic Barker ###
4//### Date: 13.05.19 ###
5//### Description: Recursively adds values from the dEdx vectors and stops ###
6//### when the probability of getting that dEdx value is too ###
7//### low. This is done for both the a electron prior and ###
8//### photon prior. The posterior is calculated and the prior ###
9//### with the highest posterior is taken. Currently can ###
10//### only be used with the sliding calo dEdx ###
11//############################################################################
12
13//Framework Includes
14#include "art/Utilities/ToolMacros.h"
15
16//LArSoft Includes
18
19//ROOT Includes
20#include "TAxis.h"
21#include "TFile.h"
22#include "TH1.h"
23
24namespace ShowerRecoTools {
25
27
28 public:
29 ShowerBayesianTrucatingdEdx(const fhicl::ParameterSet& pset);
30
31 //Generic Direction Finder
32 int CalculateElement(const art::Ptr<recob::PFParticle>& pfparticle,
33 art::Event& Event,
34 reco::shower::ShowerElementHolder& ShowerEleHolder) override;
35
36 private:
37 double CalculatePosterior(std::string priorname,
38 std::vector<double>& values,
39 int& minprob,
40 float& mean,
41 float& likelihood);
42 double CalculatePosterior(std::string priorname, std::vector<double>& values);
43
44 bool isProbabilityGood(float& old_prob, float& new_prob)
45 {
46 return (old_prob - new_prob) < fProbSeedCut;
47 }
48
49 bool isPosteriorProbabilityGood(double& prob, double& old_posteior)
50 {
51 return (old_posteior - prob) < fPostiorCut;
52 }
53
54 bool CheckPoint(std::string priorname, double& value);
55
56 std::vector<double> GetLikelihooddEdxVec(double& electronprob,
57 double& photonprob,
58 std::string prior,
59 std::vector<double>& dEdxVec);
60
61 std::vector<double> MakeSeed(std::vector<double>& dEdxVec);
62
63 void ForceSeedToFit(std::vector<double>& SeedTrack,
64 std::string& prior,
65 float& mean,
66 double& posterior);
67
68 void RecurivelyAddHit(std::vector<double>& SeedTrack,
69 std::vector<double>& dEdxVec,
70 std::string& prior,
71 int& SkippedHitsNum,
72 float& old_mean,
73 double& old_posteior);
74
77
78 //fcl params
80 std::string fdEdxInputLabel;
89 };
90
92 : IShowerTool(pset.get<fhicl::ParameterSet>("BaseTools"))
93 , fVerbose(pset.get<int>("Verbose"))
94 , fdEdxInputLabel(pset.get<std::string>("dEdxInputLabel"))
95 , fNumSeedHits(pset.get<int>("NumSeedHits"))
96 , fProbSeedCut(pset.get<float>("ProbSeedCut"))
97 , fProbPointCut(pset.get<float>("ProbPointCut"))
98 , fPostiorCut(pset.get<float>("PostiorCut"))
99 , fnSkipHits(pset.get<int>("nSkipHits"))
100 , fShowerdEdxOutputLabel(pset.get<std::string>("ShowerdEdxOutputLabel"))
101 , fDefineBestPlane(pset.get<bool>("DefineBestPlane"))
102 , fShowerBestPlaneOutputLabel(pset.get<std::string>("ShowerBestPlaneOutputLabel"))
103 {
104
105 //Get the prior file name
106 std::string fname;
107 cet::search_path sp("FW_SEARCH_PATH");
108 auto PriorPath = pset.get<std::string>("PriorFname");
109 if (!sp.find_file(PriorPath, fname)) {
110 throw cet::exception("ShowerBayesianTrucatingdEdx") << "Could not find the prior file";
111 }
112 std::string electron_histoname = pset.get<std::string>("PriorElectronHistoName");
113 std::string photon_histoname = pset.get<std::string>("PriorPhotonHistoName");
114
115 TFile fin(fname.c_str(), "READ");
116 if (!fin.IsOpen()) {
117 throw cet::exception("ShowerBayesianTrucatingdEdx") << "Could read the prior file. Stopping";
118 }
119
120 //Get the histograms.
121 electronpriorHist = dynamic_cast<TH1F*>(fin.Get(electron_histoname.c_str()));
122 if (!electronpriorHist) {
123 throw cet::exception("ShowerBayesianTrucatingdEdx") << "Could not read the electron hist";
124 }
125 photonpriorHist = dynamic_cast<TH1F*>(fin.Get(photon_histoname.c_str()));
126 if (!photonpriorHist) {
127 throw cet::exception("ShowerBayesianTrucatingdEdx") << "Could not read the photon hist ";
128 }
129
130 if (electronpriorHist->GetNbinsX() != photonpriorHist->GetNbinsX()) {
131 throw cet::exception("ShowerBayesianTrucatingdEdx") << "Histrogram bins do not match";
132 }
133
134 //Normalise the histograms.
135 electronpriorHist->Scale(1 / electronpriorHist->Integral());
136 photonpriorHist->Scale(1 / photonpriorHist->Integral());
137 }
138
140 const art::Ptr<recob::PFParticle>& pfparticle,
141 art::Event& Event,
142 reco::shower::ShowerElementHolder& ShowerEleHolder)
143 {
144
145 //The idea , to some peoples distaste, is to attempt to improve the dEdx value by assuming
146 //The particle is either a) electron b) a e-e+ pair.
147 //We will take the start of track and work down until a few hits destory our postier probability.
148
149 //Note: tried takeing the postior with the highest sum of the probabilitys on all three
150 // planes and on the 2 planes with the most hits. Made things worse.
151
152 //Get the vectors of the dEdx Elements
153 if (!ShowerEleHolder.CheckElement(fdEdxInputLabel)) {
154 if (fVerbose)
155 mf::LogError("ShowerBayesianTrucatingdEdx")
156 << "Start position not set, returning " << std::endl;
157 return 1;
158 }
159
160 std::map<int, std::vector<double>> dEdx_plane_final;
161 std::map<int, std::vector<double>> dEdx_vec_planes;
162 ShowerEleHolder.GetElement(fdEdxInputLabel, dEdx_vec_planes);
163
164 //Do this for each plane;
165 for (auto const& dEdx_vec_plane : dEdx_vec_planes) {
166
167 //Set up out final value if we don't have any points.
168 if (dEdx_vec_plane.second.size() < 1) {
169 dEdx_plane_final[dEdx_vec_plane.first] = {};
170 continue;
171 }
172
173 std::vector<double> dEdx_vec = dEdx_vec_plane.second;
174
175 double electronprob_eprior = 0;
176 double photonprob_eprior = 0;
177
178 double electronprob_pprior = 0;
179 double photonprob_pprior = 0;
180
181 std::vector<double> dEdx_electronprior =
182 GetLikelihooddEdxVec(electronprob_eprior, photonprob_eprior, "electron", dEdx_vec);
183 std::vector<double> dEdx_photonprior =
184 GetLikelihooddEdxVec(electronprob_pprior, photonprob_pprior, "photon", dEdx_vec);
185
186 //Use the vector which maximises both priors.
187 if (electronprob_eprior < photonprob_pprior) {
188 dEdx_plane_final[dEdx_vec_plane.first] = dEdx_photonprior;
189 }
190 else {
191 dEdx_plane_final[dEdx_vec_plane.first] = dEdx_electronprior;
192 }
193
194 } //Plane Loop
195
196 //Calculate the median of the of dEdx.
197 std::vector<double> dEdx_final;
198 std::vector<double> dEdx_finalErr;
199
200 int max_hits = -999;
201 int best_plane = -999;
202
203 bool check = false;
204 for (auto const& dEdx_plane : dEdx_plane_final) {
205
206 //Redefine the best plane
207 if ((int)(dEdx_plane.second).size() > max_hits) {
208 best_plane = dEdx_plane.first;
209 max_hits = (dEdx_plane.second).size();
210 }
211
212 if ((dEdx_plane.second).empty()) {
213 dEdx_final.push_back(-999);
214 dEdx_finalErr.push_back(-999);
215 continue;
216 }
217
218 dEdx_final.push_back(TMath::Median((dEdx_plane.second).size(), &(dEdx_plane.second)[0]));
219 dEdx_finalErr.push_back(-999);
220 check = true;
221 }
222
223 //Check at least one plane has the information
224 if (!check) return 1;
225
226 if (fDefineBestPlane) { ShowerEleHolder.SetElement(best_plane, fShowerBestPlaneOutputLabel); }
227
228 ShowerEleHolder.SetElement(dEdx_final, dEdx_finalErr, fShowerdEdxOutputLabel);
229
230 return 0;
231 }
232
234 std::vector<double>& values)
235 {
236 int minprob_iter = -999;
237 float mean = -999;
238 float likelihood = -999;
239 return CalculatePosterior(priorname, values, minprob_iter, mean, likelihood);
240 }
241
243 std::vector<double>& values,
244 int& minprob_iter,
245 float& mean,
246 float& likelihood)
247 {
248
249 //Posterior prob;
250 float posterior = 1;
251 float meanprob = 0;
252 float likelihood_other = 1;
253 likelihood = 1;
254
255 //Minimum probability temp
256 float minprob_temp = 9999;
257 minprob_iter = 0;
258
259 TH1F* prior_hist = nullptr;
260 TH1F* other_hist = nullptr;
261
262 if (priorname == "electron") {
263 prior_hist = electronpriorHist;
264 other_hist = photonpriorHist;
265 }
266 if (priorname == "photon") {
267 prior_hist = photonpriorHist;
268 other_hist = electronpriorHist;
269 }
270
271 TAxis* xaxis = prior_hist->GetXaxis();
272
273 //Loop over the hits and calculate the probability
274 for (int i = 0; i < (int)values.size(); ++i) {
275
276 float value = values[i];
277
278 Int_t bin = xaxis->FindBin(value);
279
280 float prob = -9999;
281 float other_prob = -9999;
282
283 if (bin != xaxis->GetNbins() || bin == 0) {
284 //Calculate the likelihood
285 prob = prior_hist->GetBinContent(bin);
286 other_prob = other_hist->GetBinContent(bin);
287 }
288 else {
289 prob = 0;
290 other_prob = 0;
291 }
292
293 if (prob < minprob_temp) {
294 minprob_temp = prob;
295 minprob_iter = i;
296 }
297
298 if (prob == 0 && other_prob == 0) { continue; }
299
300 //Calculate the posterior the mean probability and liklihood
301 meanprob += prior_hist->GetBinContent(bin);
302 likelihood *= prob;
303 likelihood_other *= other_prob;
304 }
305
306 posterior = likelihood / (likelihood + likelihood_other);
307
308 meanprob /= values.size();
309 mean = meanprob;
310 return posterior;
311 }
312
313 bool ShowerBayesianTrucatingdEdx::CheckPoint(std::string priorname, double& value)
314 {
315
316 TH1F* prior_hist = nullptr;
317
318 if (priorname == "electron") { prior_hist = electronpriorHist; }
319 if (priorname == "photon") { prior_hist = photonpriorHist; }
320
321 TAxis* xaxis = prior_hist->GetXaxis();
322
323 Int_t bin = xaxis->FindBin(value);
324
325 float prob = -9999;
326
327 if (bin != xaxis->GetNbins() + 1 || bin == 0) {
328 //Calculate the likelihood
329 prob = prior_hist->GetBinContent(bin);
330 }
331 else {
332 prob = 0;
333 }
334
335 //Return the probability of getting that point.
336 return prob > fProbPointCut;
337 }
338
340 double& electronprob,
341 double& photonprob,
342 std::string prior,
343 std::vector<double>& dEdxVec)
344 {
345
346 //have a pool
347 std::vector<double> dEdxVec_temp = dEdxVec;
348
349 //Get The seed track.
350 std::vector<double> SeedTrack = MakeSeed(dEdxVec_temp);
351 // if(SeedTrack.size() < 1){
352 // return SeedTrack;
353 // }
354
355 //Force the seed the be a good likelihood.
356 float mean = 999;
357 double posterior = 999;
358 ForceSeedToFit(SeedTrack, prior, mean, posterior);
359
360 //Recursively add dEdx
361 int SkippedHitsNum = 0;
362 RecurivelyAddHit(SeedTrack, dEdxVec_temp, prior, SkippedHitsNum, mean, posterior);
363
364 //Calculate the likelihood of the vector with the photon and electron priors.
365 electronprob = CalculatePosterior("electron", SeedTrack);
366 photonprob = CalculatePosterior("photon", SeedTrack);
367
368 return SeedTrack;
369 }
370
371 std::vector<double> ShowerBayesianTrucatingdEdx::MakeSeed(std::vector<double>& dEdxVec)
372 {
373
374 std::vector<double> seed_vector;
375
376 //Add the first hits to the seed
377 int MaxHit = fNumSeedHits;
378 if (fNumSeedHits > (int)dEdxVec.size()) { MaxHit = (int)dEdxVec.size(); }
379
380 // if(MaxHit == 0){
381 // mf::LogError("ShowerBayesianTrucatingdEdx") << "Size of the vector is 0 cannot perform the dEdx cutting "<< std::endl;
382 //}
383
384 for (int hit_iter = 0; hit_iter < MaxHit; ++hit_iter) {
385 seed_vector.push_back(dEdxVec[0]);
386 dEdxVec.erase(dEdxVec.begin());
387 }
388
389 return seed_vector;
390 }
391
392 void ShowerBayesianTrucatingdEdx::ForceSeedToFit(std::vector<double>& SeedTrack,
393 std::string& prior,
394 float& mean,
395 double& posterior)
396 {
397
398 int minprob_iter = 999;
399 float likelihood = -999;
400 float prob = CalculatePosterior(prior, SeedTrack, minprob_iter, mean, likelihood);
401 while ((mean < fProbSeedCut || prob <= 0) && SeedTrack.size() > 1) {
402
403 //Remove the the worse point.
404 // std::cout << "removing hit with dEdx: " << SeedTrack.at(minprob_iter) << std::endl;
405 SeedTrack.erase(SeedTrack.begin() + minprob_iter);
406 minprob_iter = 999;
407
408 //Recalculate
409 prob = CalculatePosterior(prior, SeedTrack, minprob_iter, mean, likelihood);
410 }
411 posterior = prob;
412 // std::cout << "seed has been fit with size: " << SeedTrack.size() << std::endl;
413 return;
414 }
415
416 void ShowerBayesianTrucatingdEdx::RecurivelyAddHit(std::vector<double>& SeedTrack,
417 std::vector<double>& dEdxVec,
418 std::string& prior,
419 int& SkippedHitsNum,
420 float& old_mean,
421 double& old_posteior)
422 {
423
424 //If we have no more hits to add then lets finish.
425 if (dEdxVec.size() < 1) { return; }
426
427 bool ok = CheckPoint(prior, dEdxVec[0]);
428 // int minprob_iter=999;
429 // float mean = -999;
430 // float likelihood =999;
431 // if(ok){std::cout << "passed first cut" << std::endl;}
432 // else{std::cout << "failed first cut" << std::endl;}
433 // double prob = CalculatePosterior(prior,SeedTrack,minprob_iter,mean,likelihood);
434 // ok *= isProbabilityGood(mean,old_mean);
435 // if(ok){std::cout << "passed second cut" << std::endl;}
436 // else{std::cout << "failed second cut" << std::endl;}
437 // ok *= isPosteriorProbabilityGood(prob,old_posteior);
438 // if(ok){std::cout << "passed this cut" << std::endl;}
439 // else{std::cout << "failed third cut" << std::endl;}
440
441 //If we failed lets try the next hits
442 if (!ok) {
443 // std::cout << "failed the pass point: " << dEdxVec[0] << " trying another hit" << SkippedHitsNum << std::endl;
444 //if(SeedTrack.size() > 1){SeedTrack.pop_back();}
445 ++SkippedHitsNum;
446 if (SkippedHitsNum > fnSkipHits) { return; }
447 }
448 else {
449 //Add the next point in question.
450 // std::cout << "adding value: " << dEdxVec[0] << std::endl;
451 //Reset the skip number
452 SkippedHitsNum = 0;
453 SeedTrack.push_back(dEdxVec[0]);
454 }
455
456 //We have analysed this hit now lets remove it.
457 dEdxVec.erase(dEdxVec.begin());
458
459 RecurivelyAddHit(SeedTrack, dEdxVec, prior, SkippedHitsNum, old_mean, old_posteior);
460
461 return;
462 }
463}
464
std::vector< double > MakeSeed(std::vector< double > &dEdxVec)
bool CheckPoint(std::string priorname, double &value)
int CalculateElement(const art::Ptr< recob::PFParticle > &pfparticle, art::Event &Event, reco::shower::ShowerElementHolder &ShowerEleHolder) override
bool isPosteriorProbabilityGood(double &prob, double &old_posteior)
void RecurivelyAddHit(std::vector< double > &SeedTrack, std::vector< double > &dEdxVec, std::string &prior, int &SkippedHitsNum, float &old_mean, double &old_posteior)
std::vector< double > GetLikelihooddEdxVec(double &electronprob, double &photonprob, std::string prior, std::vector< double > &dEdxVec)
double CalculatePosterior(std::string priorname, std::vector< double > &values, int &minprob, float &mean, float &likelihood)
void ForceSeedToFit(std::vector< double > &SeedTrack, std::string &prior, float &mean, double &posterior)
int GetElement(const std::string &Name, T &Element) const
void SetElement(T &dataproduct, const std::string &Name, bool checktag=false)
bool CheckElement(const std::string &Name) const