19 #include "fhiclcpp/ParameterSet.h"
26 fExponentConstant(p.
get<float>(
"ExponentConstant",0.42)),
27 fMinResRange(p.
get<float>(
"MinResRange",0)),
28 fMaxResRange(p.
get<float>(
"MaxResRange",30)),
29 fMaxPIDAValue(p.
get<float>(
"MaxPIDAValue",50)),
30 fKDEEvalMaxSigma(p.
get<float>(
"KDEEvalMaxSigma",3)),
31 fKDEEvalStepSize(p.
get<float>(
"KDEEvalStepSize",0.01)),
32 fKDEBandwidths(p.
get<
std::
vector<float> >(
"KDEBandwidths")),
33 fnormalDist(util::NormalDistribution(fKDEEvalMaxSigma,fKDEEvalStepSize)),
34 fPIDAHistNbins(p.
get<unsigned int>(
"PIDAHistNbins",100)),
35 fPIDAHistMin(p.
get<float>(
"PIDAHistMin",0.0)),
36 fPIDAHistMax(p.
get<float>(
"PIDAHistMax",50.0))
42 fpida_mean = fPIDA_BOGUS;
43 fpida_sigma = fPIDA_BOGUS;
44 fpida_integral_dedx = fPIDA_BOGUS;
45 fpida_integral_pida = fPIDA_BOGUS;
49 fpida_kde_mp = std::vector<float>(fKDEBandwidths.size(),fPIDA_BOGUS);
50 fpida_kde_fwhm = std::vector<float>(fKDEBandwidths.size(),fPIDA_BOGUS);
51 fpida_kde_b = std::vector<float>(fKDEBandwidths.size(),fPIDA_BOGUS);
52 fkde_distribution = std::vector< std::vector<float> >(fKDEBandwidths.size());
53 fkde_dist_min = std::vector<float>(fKDEBandwidths.size(),fPIDA_BOGUS);
54 fkde_dist_max = std::vector<float>(fKDEBandwidths.size(),fPIDA_BOGUS);
60 throw "Error: input histograms larger than max allowed bandwidths.";
61 if(hist_kde.size()!=fKDEBandwidths.size())
62 throw "Error: input histograms do not have same size as bandwidths.";
66 hPIDAvalues = hist_vals;
67 hPIDAvalues->SetNameTitle(
"hPIDAvalues",
"PIDA Distribution");
68 hPIDAvalues->SetBins(fPIDAHistNbins,fPIDAHistMin,fPIDAHistMax);
70 for(
size_t i_hist=0; i_hist<hist_kde.size(); i_hist++){
71 hPIDAKDE[i_hist] = hist_kde[i_hist];
73 std::stringstream hname,htitle;
74 hname <<
"hPIDAKDE_" << i_hist;
75 htitle <<
"PIDA KDE-smoothed Distribution, Bandwidth=" << fKDEBandwidths.at(i_hist);
77 hPIDAKDE[i_hist]->SetNameTitle(hname.str().c_str(),htitle.str().c_str());
78 hPIDAKDE[i_hist]->SetBins(fPIDAHistNbins,fPIDAHistMin,fPIDAHistMax);
81 fPIDATree->Branch(
"pida",&fPIDAProperties,fPIDAProperties.leaf_structure.c_str());
82 fPIDATree->Branch(
"hpida_vals",
"TH1F",hPIDAvalues);
83 fPIDATree->Branch(
"n_bandwidths",&(fPIDAProperties.n_bandwidths),
"n_bandwidths/i");
84 fPIDATree->Branch(
"kde_bandwidth",fPIDAProperties.kde_bandwidth,
"kde_bandwidth[n_bandwidths]/F");
85 fPIDATree->Branch(
"kde_mp",fPIDAProperties.kde_mp,
"kde_mp[n_bandwidths]/F");
86 fPIDATree->Branch(
"kde_fwhm",fPIDAProperties.kde_fwhm,
"kde_fwhm[n_bandwidths]/F");
87 for(
size_t i_hist=0; i_hist<hist_kde.size(); i_hist++){
88 std::stringstream bname;
89 bname <<
"hpida_kde_" << i_hist;
90 fPIDATree->Branch(bname.str().c_str(),
"TH1F",hPIDAKDE[i_hist]);
96 if(fpida_mean==fPIDA_BOGUS)
103 if(fpida_sigma==fPIDA_BOGUS)
104 calculatePIDASigma();
110 if(fpida_kde_mp[i_b]==fPIDA_BOGUS)
113 return fpida_kde_mp[i_b];
117 if(fpida_kde_fwhm[i_b]==fPIDA_BOGUS)
120 return fpida_kde_fwhm[i_b];
133 std::vector<float>
const&
dEdx = calo.
dEdx();
134 RunPIDAAlg(resRange,dEdx);
142 mean = getPIDAMean();
143 sigma = getPIDASigma();
147 std::vector<float>
const&
dEdx){
151 fpida_values.reserve( resRange.size() );
152 fpida_errors.reserve( resRange.size() );
154 std::map<double,double> range_dEdx_map;
156 for(
size_t i_r=0; i_r<resRange.size(); i_r++){
157 if(resRange[i_r]>fMaxResRange || resRange[i_r]<fMinResRange)
continue;
159 range_dEdx_map[ resRange[i_r] ] = dEdx[i_r];
161 float val = dEdx[i_r]*std::pow(resRange[i_r],fExponentConstant);
162 if(val < fMaxPIDAValue){
163 fpida_values.push_back(val);
169 calculatePIDAIntegral(range_dEdx_map);
171 if(fpida_values.size()==0)
172 fpida_values.push_back(-99);
178 unsigned int calo_index,
181 FillPIDAProperties(run,event,calo_index,calo);
186 if(fpida_values.size()==0)
187 throw "pid::PIDAAlg --- PIDA Values not filled!";
190 for(
auto const& val : fpida_values)
192 fpida_mean /= fpida_values.size();
198 if(fpida_mean==fPIDA_BOGUS)
202 for(
auto const& val : fpida_values)
203 fpida_sigma += (fpida_mean-val)*(fpida_mean-val);
205 fpida_sigma = std::sqrt(fpida_sigma)/fpida_values.size();
210 if(range_dEdx_map.size()<2)
return;
212 fpida_integral_dedx = 0;
214 for( std::map<double,double>::const_iterator map_iter = range_dEdx_map.begin();
215 map_iter != std::prev(range_dEdx_map.end());
218 double range_width = std::next(map_iter)->first - map_iter->first;
219 fpida_integral_dedx += range_width*( std::next(map_iter)->second + 0.5*(map_iter->second-std::next(map_iter)->second));
222 fpida_integral_pida = fpida_integral_dedx * (1-fExponentConstant) *
223 std::pow( (std::prev(range_dEdx_map.end())->
first - range_dEdx_map.begin()->first),(fExponentConstant-1) );
228 if(fpida_values.size()==0)
229 throw "pid::PIDAAlg --- PIDA Values not filled!";
233 if(fKDEBandwidths[i_b]<=0) {
234 calculatePIDASigma();
235 float bandwidth = fpida_sigma*1.06*std::pow((
float)(fpida_values.size()),-0.2);
236 fpida_errors = std::vector<float>(fpida_values.size(),bandwidth);
237 fpida_kde_b[i_b] = bandwidth;
240 fpida_errors = std::vector<float>(fpida_values.size(),fKDEBandwidths[i_b]);
241 fpida_kde_b[i_b] = fKDEBandwidths[i_b];
244 const auto min_pida_iterator = std::min_element(fpida_values.begin(),fpida_values.end());
245 const size_t min_pida_location =
std::distance(fpida_values.begin(),min_pida_iterator);
246 fkde_dist_min[i_b] = fpida_values[min_pida_location] - fKDEEvalMaxSigma*fpida_errors[min_pida_location];
248 const auto max_pida_iterator = std::max_element(fpida_values.begin(),fpida_values.end());
249 const size_t max_pida_location =
std::distance(fpida_values.begin(),max_pida_iterator);
250 fkde_dist_max[i_b] = fpida_values[max_pida_location] + fKDEEvalMaxSigma*fpida_errors[max_pida_location];
253 const size_t kde_dist_size = (size_t)( (fkde_dist_max[i_b] - fkde_dist_min[i_b])/fKDEEvalStepSize ) + 1;
254 fkde_distribution[i_b].resize(kde_dist_size);
257 for(
size_t i_step=0; i_step<kde_dist_size; i_step++){
258 float pida_val = fkde_dist_min[i_b] + i_step*fKDEEvalStepSize;
259 fkde_distribution[i_b][i_step]=0;
261 for(
size_t i_pida=0; i_pida<fpida_values.size(); i_pida++)
262 fkde_distribution[i_b][i_step] += fnormalDist.getValue((fpida_values[i_pida]-pida_val)/fpida_errors[i_pida])/fpida_errors[i_pida];
264 if(fkde_distribution[i_b][i_step]>kde_max){
265 kde_max = fkde_distribution[i_b][i_step];
267 fpida_kde_mp[i_b] = pida_val;
272 float half_max = 0.5*fpida_kde_mp[i_b];
274 for(
size_t i_step=step_max; i_step>0; i_step--){
275 if(fkde_distribution[i_b][i_step] < half_max)
break;
276 low_width += fKDEEvalStepSize;
279 for(
size_t i_step=step_max; i_step<kde_dist_size; i_step++){
280 if(fkde_distribution[i_b][i_step] < half_max)
break;
281 high_width += fKDEEvalStepSize;
283 fpida_kde_fwhm[i_b] = low_width+high_width;
288 for(
size_t i_b=0; i_b < fKDEBandwidths.size(); i_b++)
294 unsigned int calo_index,
297 fPIDAProperties.run = run;
298 fPIDAProperties.event = event;
299 fPIDAProperties.calo_index = calo_index;
301 fPIDAProperties.trk_range = calo.
Range();
304 fPIDAProperties.n_bandwidths = fKDEBandwidths.size();
305 for(
size_t i_b=0; i_b<fPIDAProperties.n_bandwidths; i_b++)
307 calculatePIDASigma();
308 fPIDAProperties.n_pid_pts = fpida_values.size();
309 fPIDAProperties.mean = fpida_mean;
310 fPIDAProperties.sigma = fpida_sigma;
312 fPIDAProperties.integral_dedx = fpida_integral_dedx;
313 fPIDAProperties.integral_pida = fpida_integral_pida;
316 for(
size_t i_b=0; i_b<fPIDAProperties.n_bandwidths; i_b++){
317 fPIDAProperties.kde_mp[i_b] = fpida_kde_mp[i_b];
318 fPIDAProperties.kde_fwhm[i_b] = fpida_kde_fwhm[i_b];
319 fPIDAProperties.kde_bandwidth[i_b] = fpida_kde_b[i_b];
322 hPIDAvalues->Reset();
323 for(
auto const& val: fpida_values)
324 hPIDAvalues->Fill(val);
326 for(
size_t i_b=0; i_b<fPIDAProperties.n_bandwidths; i_b++){
327 hPIDAKDE[i_b]->Reset();
328 for(
size_t i_step=0; i_step<fkde_distribution[i_b].size(); i_step++)
329 hPIDAKDE[i_b]->AddBinContent(hPIDAKDE[i_b]->FindBin(i_step*fKDEEvalStepSize+fkde_dist_min[i_b]),
330 fkde_distribution[i_b][i_step]);
337 for(
size_t i_pida=0; i_pida<fpida_values.size(); i_pida++)
338 std::cout <<
"\tPIDA --- " << i_pida <<
"\t" << fpida_values[i_pida] << std::endl;
344 throw "util::NormalDistribution --- Cannot have zero step size!";
346 const size_t vector_size = (size_t)(max_sigma / step_size);
347 fValues.resize(vector_size);
349 const float AMPLITUDE = 1. / std::sqrt(2*M_PI);
352 for(
size_t i_step=0; i_step<vector_size; i_step++){
353 float diff = i_step*step_size;
354 fValues[i_step] = AMPLITUDE *
std::exp(-0.5*diff*diff);
355 integral+= fValues[i_step];
358 for(
size_t i_step=0; i_step<vector_size; i_step++)
359 fValues[i_step] /= (integral*2);
361 fStepSize = step_size;
362 fMaxSigma = fStepSize * vector_size;
369 if(x > fMaxSigma)
return 0;
371 size_t bin_low = x / fStepSize;
372 float remainder = (x - (bin_low*fStepSize)) / fStepSize;
374 return fValues[bin_low]*(1-remainder) + remainder*fValues[bin_low+1];
void SetPIDATree(TTree *, TH1F *, std::vector< TH1F * >)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
process_name opflash particleana ie x
void FillPIDATree(unsigned int, unsigned int, unsigned int, anab::Calorimetry const &)
const geo::PlaneID & PlaneID() const
PIDAAlg(fhicl::ParameterSet const &p)
void FillPIDAProperties(unsigned int, unsigned int, unsigned int, anab::Calorimetry const &)
void createKDE(const size_t)
const std::vector< float > & ResidualRange() const
process_name can override from command line with o or output calo
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
const std::vector< float > & getPIDAValues()
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
float getPIDAKDEMostProbable(const size_t)
void RunPIDAAlg(std::vector< float > const &, std::vector< float > const &)
const unsigned int MAX_BANDWIDTHS
PlaneID_t Plane
Index of the plane within its TPC.
Definition of data types for geometry description.
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
const std::vector< float > & dEdx() const
float getPIDAKDEFullWidthHalfMax(const size_t)
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
void calculatePIDAIntegral(std::map< double, double > const &)
const float & KineticEnergy() const
const std::vector< float > & getPIDAErrors()
const float & Range() const
void calculatePIDASigma()
BEGIN_PROLOG could also be cout