GamR  0.0.0
GammaROOT
Loading...
Searching...
No Matches
Efficiency.cc
Go to the documentation of this file.
1
8
9#include <sstream>
10#include <map>
11#include <string>
12#include <fstream>
13#include <vector>
14
15#include <TH1.h>
16#include <TF1.h>
17#include <TGraph.h>
18#include <TGraphErrors.h>
19#include <TMultiGraph.h>
20#include <TFile.h>
21#include <TColor.h>
22
23#include <Math/Functor.h>
24#include <Math/Factory.h>
25#include <Math/Minimizer.h>
26#include <Math/MinimizerOptions.h>
27
28
29#include "Efficiency.hh"
30
31// ignoring npar, gin, iflag in GlobalChiSquare::doit
32// TMinuit expects these extra variables that we don't use
33#pragma GCC diagnostic ignored "-Wunused-parameter"
34
35namespace GamR {
36 namespace Efficiency {
187 }
188}
189
190namespace GamR {
191 namespace Efficiency {
192
198 double EffCFunc(double *x, double *pars) {
199 //this is basically from radware
200 double x1 = log(x[0]/100.0);
201 double x2 = log(x[0]/1000.0);
202
203 double g = pars[6];
204 double f1 = pars[0] + pars[1]*x1 + pars[2]*x1*x1;
205 double f2 = pars[3] + pars[4]*x2 + pars[5]*x2*x2;
206
207 double abs_scale = pars[7];
208 double f = 0;
209 double nf = 0;
210 double r = 0;
211
212 //if both are negative we have a problem, f1^(-g) + f2^(-g) is potentially undefined
213 //--> return zero
214 if (f1 < 0 && f2 < 0) {
215 if (x[0] > 50 && x[0] < 8192) {
216 std::cerr << "Warning! Both parabolic components of efficiency are < 0 for E_gamma = " << x[0] << " keV, consider decreasing normalization for data sets" << std::endl;
217 }
218 return 0;
219 }
220
221 if (f1 <= f2 ) {
222 r = f1/f2;
223 f = f1;
224 nf = f2;
225 }
226 else {
227 r = f2/f1;
228 f = f2;
229 nf = f1;
230 }
231
232 //if one is negative, and the other positive, or both positive but one is much smaller than the other
233 //approximation where only large component matters
234 if (r <= 1e-6) {
235 double retval = exp(f)*abs_scale;
236 return retval;
237 }
238 //both are positive and approximately the same size
239 //full evaluation
240 else {
241 double y = pow(pow(r, g) + 1.0, -1.0/g);
242 double retval = exp(y*f)*abs_scale;
243 return retval;
244 }
245 }
246
248 {
249 fKeys.clear();
250 fEnergies.clear();
251 fPeakAreas.clear();
252 fPeakErrors.clear();
253 fIntensities.clear();
254 fEfficiencies.clear();
255 fEfficiencyErrors.clear();
256 fNormalisation = 1.0;
257 fAbsScale = 1.0;
258 }
259
260 DataSet::DataSet(TH1D *fHist, GamR::Nucleus::TransitionMap* fTransitionMap, std::map<std::string, std::pair<double, double> > fIntensityMap)
261 {
262 SetData(fHist, fTransitionMap, fIntensityMap);
263 }
264
265 void DataSet::SetData(TH1D *fHist, GamR::Nucleus::TransitionMap* fTransitionMap, std::map<std::string, std::pair<double, double> > fIntensityMap)
266 {
267 Clear();
268 std::map<std::string, GamR::Nucleus::Transition > *fTransMap = fTransitionMap->GetMap();
269 fNormalisation = 0.0;
270 double max = 0.0;
271 for (auto &intensity : fIntensityMap) {
272 //check if there's a corresponding transition in transitionmap
273 if (fTransMap->find(intensity.first) != fTransMap->end()) {
274 double area = (*fTransMap)[intensity.first].Apply(fHist);
275 double areaerror = (*fTransMap)[intensity.first].ApplyError(fHist);
276 double energy = intensity.second.first;
277 double intens = intensity.second.second;
278 double eff = area/intens;
279 double efferr = areaerror/intens;
280 if (area<=0) {
281 continue;
282 }
283 fKeys.push_back(intensity.first);
284 fPeakAreas.push_back(area);
285 fPeakErrors.push_back(areaerror);
286 fEnergies.push_back(energy);
287 fIntensities.push_back(intens);
288 fEfficiencies.push_back(eff);
289 fEfficiencyErrors.push_back(efferr);
290
291 if (eff > max) {
292 max = eff;
293 }
294 }
295 }
296
297 fNormalisation = max/1000.0;
298
299 }
300
301 void DataSet::SetData(std::string areaFile, std::map<std::string, std::pair<double, double> > fIntensityMap)
302 {
303 Clear();
304 std::map<std::string, std::pair<double, double> > areaMap;
305 std::ifstream area_file(areaFile);
306 std::string key;
307 double area,area_error;
308 while (area_file >> key >> area >> area_error) {
309 areaMap[key] = {area, area_error};
310 }
311
312 fNormalisation = 0.0;
313 double max = 0.0;
314 for (auto &intensity : fIntensityMap) {
315 //check if there's a corresponding transition in transitionmap
316 if (areaMap.find(intensity.first) != areaMap.end()) {
317 double area = areaMap[intensity.first].first;
318 double areaerror = areaMap[intensity.first].second;
319 double energy = intensity.second.first;
320 double intens = intensity.second.second;
321 double eff = area/intens;
322 double efferr = areaerror/intens;
323 if (area<=0) {
324 continue;
325 }
326 fKeys.push_back(intensity.first);
327 fPeakAreas.push_back(area);
328 fPeakErrors.push_back(areaerror);
329 fEnergies.push_back(energy);
330 fIntensities.push_back(intens);
331 fEfficiencies.push_back(eff);
332 fEfficiencyErrors.push_back(efferr);
333
334 if (eff > max) {
335 max = eff;
336 }
337 }
338 }
339
340 fNormalisation = max/1000.0;
341
342 }
343 void DataSet::SetData(const char *effFile)
344 {
345 Clear();
346 double area;
347 double areaerror;
348 double intens;
349 double energy;
350 double max;
351 std::string key;
352 std::string line;
353 std::ifstream eff_file(effFile);
354 std::stringstream ss;
355 if (!eff_file.is_open()) {
356 std::cerr << "Error opening " << effFile << std::endl;
357 }
358 while (getline(eff_file, line)) {
359 if (line.size()==0) { continue; }
360 if (line[0]=='#') { continue; }
361 ss.clear();
362 ss.str(line);
363 ss >> key >> energy >> intens >> area >> areaerror;
364 double eff = area/intens;
365 double efferr = areaerror/intens;
366 if (area <=0 ) {
367 continue;
368 }
369 fKeys.push_back(key);
370 fPeakAreas.push_back(area);
371 fPeakErrors.push_back(areaerror);
372 fEnergies.push_back(energy);
373 fIntensities.push_back(intens);
374 fEfficiencies.push_back(eff);
375 fEfficiencyErrors.push_back(efferr);
376
377 if (eff > max) {
378 max = eff;
379 }
380 }
381
382 fNormalisation = max/1000.0;
383 }
384
385 DataSet::DataSet(const char *effFile)
386 {
387 SetData(effFile);
388 }
389
390 DataSet::DataSet(const char *histFile, const char *histName, const char *gateFile, const char *mapName, const char *intensityFile)
391 {
392 TFile *hisFile = new TFile(histFile);
393 TH1D *fHist = (TH1D*)hisFile->Get(histName);
394
395 TFile *gatFile = new TFile(gateFile);
396 GamR::Nucleus::TransitionMap *fTransitionMap = (GamR::Nucleus::TransitionMap*)gatFile->Get(mapName);
397
398
399 std::ifstream intFile(intensityFile);
400
401 std::string key;
402 double energy;
403 double intensity;
404 std::map<std::string, std::pair<double, double> > fIntensityMap;
405 while(intFile >> key >> energy >> intensity) {
406 fIntensityMap[key] = std::pair<double, double>(energy, intensity);
407 }
408
409 SetData(fHist, fTransitionMap, fIntensityMap);
410
411 hisFile->Close();
412 gatFile->Close();
413 }
414
415 DataSet::DataSet(std::string areaFile, const char *intensityFile) {
416 std::ifstream intFile(intensityFile);
417
418 std::string key;
419 double energy;
420 double intensity;
421 std::map<std::string, std::pair<double, double> > fIntensityMap;
422 while(intFile >> key >> energy >> intensity) {
423 fIntensityMap[key] = std::pair<double, double>(energy, intensity);
424 }
425
426 SetData(areaFile, fIntensityMap);
427 }
428
429 int DataSet::GetIndex(std::string key)
430 {
431 int index = -1;
432 for (int i=0; i<GetNData(); ++i) {
433 if (fKeys[i].compare(key) == 0) {
434 index = i;
435 break;
436 }
437 }
438 if (index == -1) {
439 std::cout << "Key " << key << " not found!" << std::endl;
440 return -1;
441 }
442 return index;
443 }
444
445 void DataSet::EraseData(std::string key)
446 {
447 int index = GetIndex(key);
448
449 if (index >= 0) {
450 fKeys.erase(fKeys.begin()+index);
451 fEnergies.erase(fEnergies.begin()+index);
452 fPeakAreas.erase(fPeakAreas.begin()+index);
453 fPeakErrors.erase(fPeakErrors.begin()+index);
454 fIntensities.erase(fIntensities.begin()+index);
455 fEfficiencies.erase(fEfficiencies.begin()+index);
456 fEfficiencyErrors.erase(fEfficiencyErrors.begin()+index);
457 }
458 }
459
460 void DataSet::Print(const char *fileName)
461 {
462 FILE* file;
463 file = fopen(fileName, "wa");
464
465 fprintf(file, "Key Energy Intensity PeakArea Error \n");
466 for (int i=0; i<GetNData(); ++i) {
467 fprintf(file, "%8s %11.2f %13.4f %12.2f %10.4f\n", fKeys[i].c_str(), fEnergies[i], fIntensities[i], fPeakAreas[i], fPeakErrors[i]);
468 }
469
470 fclose(file);
471 }
472
473 TGraphErrors *DataSet::GetGraph()
474 {
475 int nPoints = fEnergies.size();
476 TGraphErrors *graph = new TGraphErrors(nPoints);
477
478 for (int i=0; i<nPoints; ++i)
479 {
480 double y = fEfficiencies[i]/fNormalisation;
481 double y_err = fEfficiencyErrors[i]/fNormalisation;
482 if (!fAbsolute) {
483 y = y * fAbsScale;
484 y_err = y_err * fAbsScale;
485 }
486 graph->SetPoint(i, fEnergies[i], y);
487 graph->SetPointError(i, 0, 0.01*fAbsScale);
488 }
489 return graph;
490 }
491
493 {
494 int nPoints = fEnergies.size();
495 TGraphErrors *graph = new TGraphErrors(nPoints);
496
497 for (int i=0; i<nPoints; ++i)
498 {
499 double y = fEfficiencies[i]/fNormalisation;
500 double y_err = fEfficiencyErrors[i]/fNormalisation;
501 if (!fAbsolute) {
502 y = y * fAbsScale;
503 y_err = y_err * fAbsScale;
504 }
505 std::cout << fEnergies[i] << " " << fEfficiencies[i] << " " << fNormalisation << " " << y << std::endl;
506 graph->SetPoint(i, fEnergies[i], y);
507 graph->SetPointError(i, 0, y_err);
508 }
509 return graph;
510 }
511
513 {
514 EffFunc = new TF1("EffFunc", EffCFunc, 1, 4096, 8);
515 EffFunc->SetNpx(1000);
516
517 //sane initial values
518 EffFunc->SetParameter(0, 1.);
519 EffFunc->SetParameter(1, 1.);
520 EffFunc->SetParameter(2, 0.);
521 EffFunc->SetParameter(3, 1.);
522 EffFunc->SetParameter(4, 1.);
523 EffFunc->SetParameter(5, 1.);
524 EffFunc->SetParameter(6, 20.);
525 EffFunc->SetParameter(7, 1.0);
526
527 for (int i=0; i<7; ++i)
528 {
529 double parmin, parmax;
530 EffFunc->GetParLimits(i, parmin, parmax);
531 EffFunc->SetParLimits(i, -1e4, 1e4);
532 EffFunc->SetParError(i, 0.1);
533 }
534 EffFunc->SetParLimits(6, 1.0, 1e4);
535
536 EffFunc->SetParLimits(7, 0, 1.0);
537 EffFunc->SetParError(7, 0.01);
538
539 EffFunc->FixParameter(2, 0.);
540 EffFunc->FixParameter(6, 20.);
541
542 fAbsScale = 1.0;
543 }
544
545
547 private:
548 static EffFit *p;
549
550 public:
551 GlobalChiSquare(EffFit *parent) { p = parent; }
552
553 double operator()(const double *par) {
554 double chisq = 0;
555
556 p->EffFunc->SetParameter(0, par[0]);
557 p->EffFunc->SetParameter(1, par[1]);
558 p->EffFunc->SetParameter(2, par[2]);
559 p->EffFunc->SetParameter(3, par[3]);
560 p->EffFunc->SetParameter(4, par[4]);
561 p->EffFunc->SetParameter(5, par[5]);
562 p->EffFunc->SetParameter(6, par[6]);
563 p->EffFunc->SetParameter(7, par[7]);
564
565 int nDataSets = p->fDataSets.size();
566 for (int i=0; i<8+nDataSets; ++i) {
567 std::cout << Form("%6.3f ", par[i]);
568 }
569
570 for (int i=0; i<nDataSets; ++i) {
571 p->fDataSets[i].SetAbsScale(par[7]);
572 p->fDataSets[i].SetNorm(par[8+i]);
573 if (p->fDataSets[i].GetNData() > 0) {
574 TGraphErrors *graph;
575 if (p->EqualWeights) {
576 graph = p->fDataSets[i].GetGraph();
577 }
578 else {
579 graph = p->fDataSets[i].GetGraphErrors();
580 }
581 if (p->fDataSets[i].GetAbsolute()) { //a bit of extra encouragement here, as for absolute normalizations we typically have a few data points with which we should achieve almost perfect agreement
582 chisq += 100.0*graph->Chisquare(p->EffFunc);
583 }
584 else {
585 chisq += graph->Chisquare(p->EffFunc);
586 }
587
588 delete graph;
589 }
590 }
591 std::cout << Form("chisq=%5.1f",chisq);
592 std::cout << std::endl;
593 return chisq;
594 }
595
596
597 /*
598 static void minuit(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
599 {
600 f = 0;
601
602 p->EffFunc->SetParameter(0, par[0]);
603 p->EffFunc->SetParameter(1, par[1]);
604 p->EffFunc->SetParameter(2, par[2]);
605 p->EffFunc->SetParameter(3, par[3]);
606 p->EffFunc->SetParameter(4, par[4]);
607 p->EffFunc->SetParameter(5, par[5]);
608 p->EffFunc->SetParameter(6, par[6]);
609 p->EffFunc->SetParameter(7, par[7]);
610
611 int nDataSets = p->fDataSets.size();
612 for (int i=0; i<nDataSets; ++i) {
613 p->fDataSets[i].SetAbsScale(par[7]);
614 p->fDataSets[i].SetNorm(par[8+i]);
615 if (p->fDataSets[i].GetNData() > 0) {
616 TGraphErrors *graph;
617 if (p->EqualWeights) {
618 graph = p->fDataSets[i].GetGraph();
619 }
620 else {
621 graph = p->fDataSets[i].GetGraphErrors();
622 }
623 f += graph->Chisquare(p->EffFunc);
624
625 delete graph;
626 }
627 }
628 }
629 */
630 };
631
632
633 EffFit *EffFit::GlobalChiSquare::p = nullptr;
634
635 void EffFit::Fit(int quiet)
636 {
637 int nDataSets = fDataSets.size();
638 if (nDataSets == 0) { return; }
639 Int_t npars = 8 + nDataSets;
640
641 ROOT::Math::Minimizer *min = NULL;
642 min=ROOT::Math::Factory::CreateMinimizer("Minuit2", "Minimize");
643
644 if (min==NULL) { std::cerr << "Minimizer failed to create!" << std::endl; exit(1); }
645
646 GlobalChiSquare func(this);
647 ROOT::Math::Functor f_init(func,npars);
648
649 min->SetErrorDef(1.);
650 min->SetMaxFunctionCalls(100000);
651 min->SetMaxIterations(100000);
652 min->SetTolerance(1e-6);
653 min->SetPrecision(1e-8);
654 min->SetFunction(f_init);
655
656 Int_t parnum = 0;
657
658 std::cout << "Starting fit with guesses: " << std::endl;
659 std::vector< std::string > parnames = {"A", "B", "C", "D", "E", "F", "G", "AbsScale"};
660 for ( int i=0; i<8; ++i ) {
661 double parmin, parmax;
662 EffFunc->GetParLimits(i, parmin, parmax);
663 if (parmin==parmax) {
664 parmin = EffFunc->GetParameter(i) - 1; //because Minuit doesn't allow equal upper and lower bounds
665 parmax = EffFunc->GetParameter(i) + 1;
666 }
667 std::cout << " " << parnames[i] << " " << EffFunc->GetParameter(i) << " (" << parmin << "," << parmax << ")" << std::endl;
668 min->SetLimitedVariable(parnum, parnames[i].c_str(), EffFunc->GetParameter(i), EffFunc->GetParError(i), parmin, parmax);
669 min->SetVariableStepSize(parnum, 0.1);
670 ++parnum;
671 }
672
673 for (int i=0; i<8; ++i) {
674 double parmin, parmax;
675 EffFunc->GetParLimits(i, parmin, parmax);
676 if (parmin*parmax != 0 && parmin >= parmax) {
677 min->FixVariable(i);
678 }
679 }
680
681 for (int i=0; i<nDataSets; ++i) {
682 std::cout << "Initial fNorm " << i << " = " << fDataSets[i].GetNorm() << std::endl;
683 min->SetLimitedVariable(parnum, ("N"+std::to_string(i)).c_str(), fDataSets[i].GetNorm(), 0.02*fDataSets[i].GetNorm(), 0.8*fDataSets[i].GetNorm(), 1.2*fDataSets[i].GetNorm());
684 if (fDataSets[i].GetNData() == 0 || fDataSets[i].GetAbsolute()) {
685 min->FixVariable(parnum);
686 }
687 ++parnum;
688 }
689
690 min->FixVariable(7); //absolute scale
691 min->FixVariable(8); //first data set
692
693 // MINIMIZE
694 min->Minimize();
695 min->PrintResults();
696
697 //get parameters + errors and put into EffFunc
698 for (int i=0; i<8; ++i) {
699 double parVal, parErr;
700 parVal = min->X()[i];
701 parErr = min->Errors()[i];
702 EffFunc->SetParameter(i, parVal);
703 EffFunc->SetParError(i, parErr);
704 if (i==7) {
705 fAbsScale = parVal;
706 }
707 }
708 //set final normalizations
709 std::cout << "Setting final normalizations" << std::endl;
710 for (int i=0; i<nDataSets; ++i) {
711 double parVal, parErr;
712 parVal = min->X()[8+i];
713 fDataSets[i].SetNorm(parVal);
714 std::cout << "Dataset " << i << ": " << parVal << std::endl;
715 }
716
717 delete min;
718
719 if (quiet==0) {
720 TCanvas *c1 = new TCanvas("cEff", "Efficiency Curve", 1280, 720);
721 this->Draw(c1);
722 }
723
724 }
725
726 /*
727 void EffFit::Fit(int quiet)
728 {
729 int nDataSets = fDataSets.size();
730 if (nDataSets == 0) { return; }
731 Int_t npars = 8 + nDataSets;
732 auto gMinuit = new TMinuit(npars);
733 //gMinuit->Command("SET PRINT -1");
734
735 GlobalChiSquare func(this);
736 gMinuit->SetFCN(func.minuit);
737
738 Double_t arglist[10];
739 arglist[0] = 1;
740
741 Int_t ierflg = 0; // some error flag ???
742
743 gMinuit->mnexcm("SET ERR", arglist, 1, ierflg);
744 arglist[0] = 2;
745 gMinuit->mnexcm("SET STR", arglist, 1, ierflg);
746
747 Int_t parnum = 0;
748
749 std::vector< std::string > parnames = {"A", "B", "C", "D", "E", "F", "G", "AbsScale"};
750 for ( int i=0; i<8; ++i ) {
751 double parmin, parmax;
752 EffFunc->GetParLimits(i, parmin, parmax);
753 //std::cout << "Setting parameter " << parnum << " : " << parnames[i].c_str() << " " << EffFunc->GetParameter(i) << " " << EffFunc->GetParError(i) << " " << parmin << " " << parmax;
754 if (parmin==parmax) {
755 parmin = EffFunc->GetParameter(i) - 1; //because Minuit doesn't allow equal upper and lower bounds
756 parmax = EffFunc->GetParameter(i) + 1;
757 }
758 gMinuit->mnparm(parnum, parnames[i].c_str(), EffFunc->GetParameter(i), EffFunc->GetParError(i), parmin, parmax, ierflg);
759 ++parnum;
760 }
761
762 for (int i=0; i<8; ++i) {
763 double parmin, parmax;
764 EffFunc->GetParLimits(i, parmin, parmax);
765 if (parmin*parmax != 0 && parmin >= parmax) {
766 gMinuit->FixParameter(i);
767 }
768 }
769
770 for (int i=0; i<nDataSets; ++i) {
771 std::cout << "Initial fNorm " << i << " = " << fDataSets[i].GetNorm() << std::endl;
772 gMinuit->mnparm(parnum, ("N"+std::to_string(i)).c_str(), fDataSets[i].GetNorm(), 0.02*fDataSets[i].GetNorm(), 0.8*fDataSets[i].GetNorm(), 1.2*fDataSets[i].GetNorm(), ierflg);
773 if (fDataSets[i].GetNData() == 0 || fDataSets[i].GetAbsolute()) {
774 gMinuit->FixParameter(parnum);
775 }
776 ++parnum;
777 }
778
779 gMinuit->FixParameter(7); //absolute scale
780
781 // MINIMIZE
782 arglist[0] = 100000; // Max Iterations
783 arglist[1] = 1; // Number of sigma max step
784 gMinuit->mnexcm("MINIGRAD", arglist, 2, ierflg);
785 gMinuit->mnimpr(); // Improve fit by searching for other minima
786 gMinuit->mnexcm("HESSE", arglist, 2, ierflg);
787 gMinuit->mnexcm("MINOS", arglist, 2, ierflg);
788
789 //get parameters + errors and put into EffFunc
790 for (int i=0; i<8; ++i) {
791 double parVal, parErr;
792 gMinuit->GetParameter(i, parVal, parErr);
793 EffFunc->SetParameter(i, parVal);
794 EffFunc->SetParError(i, parErr);
795 if (i==7) {
796 fAbsScale = parVal;
797 }
798 }
799 //set final normalizations
800 for (int i=0; i<nDataSets; ++i) {
801 double parVal, parErr;
802 gMinuit->GetParameter(8+i, parVal, parErr);
803 fDataSets[i].SetNorm(parVal);
804 }
805
806 delete gMinuit;
807
808 if (quiet==0) {
809 TCanvas *c1 = new TCanvas("cEff", "Efficiency Curve", 1280, 720);
810 this->Draw(c1);
811 }
812
813 }
814 */
815
817 for (int i=0; i<fDataSets.size(); ++i) {
818 if (fDataSets[i].GetAbsolute()) {
819 fDataSets[i].SetAbsScale(1.0);
820 }
821 else {
822 fDataSets[i].SetAbsScale(fAbsScale);
823 }
824 }
825 for (int i=0; i<params.params.size(); ++i) {
826 double plow, phigh;
827 EffFunc->GetParLimits(i, plow, phigh);
828 double parmin = params.limlow[i].Eval(plow);
829 double parmax = params.limhigh[i].Eval(phigh);
830 //EffFunc->GetParLimits(i, parmin, parmax);
831
832 if (params.fixed[i]==1) {
833 EffFunc->SetParameter(i, params.params[i].Eval(EffFunc->GetParameter(i)));
834 EffFunc->SetParLimits(i, parmin, parmax);
835 EffFunc->FixParameter(i, params.params[i].Eval(EffFunc->GetParameter(i)));
836 }
837 else {
838 EffFunc->ReleaseParameter(i);
839 EffFunc->SetParameter(i, params.params[i].Eval(EffFunc->GetParameter(i)));
840 EffFunc->SetParLimits(i, parmin, parmax);
841 if (EffFunc->GetParError(i) == 0) {
842 EffFunc->SetParError(i, 0.1);
843 }
844 }
845 }
846 EffFunc->SetParLimits(7, 0.1*fAbsScale, 10.0*fAbsScale);
847 EffFunc->SetParameter(7, fAbsScale);
848 }
849
850 TMultiGraph* EffFit::Draw(TCanvas *canvas, int detID/*=0*/, double xlow/*=-1*/, double xhigh/*=-1*/, bool log/*=false*/)
851 {
852 std::cout << "Drawing Detector " << detID << std::endl;
853 canvas->Clear();
854 canvas->cd();
855 int nDataSets = fDataSets.size();
856 TMultiGraph *graph = new TMultiGraph();
857 graph->SetTitle(("Efficiency "+std::to_string(detID)).c_str());
858 std::vector<Color_t> colors = {kRed, kBlue, kGreen, kMagenta, kCyan, kBlack, kYellow};
859 for (int i=0; i<nDataSets; ++i)
860 {
861 fDataSets[i].SetAbsScale(fAbsScale);
862 TGraphErrors *dsetgraph = fDataSets[i].GetGraphErrors();
863 std::cout << " Data Set " << i << ", nPoints " << dsetgraph->GetN() << std::endl;
864 dsetgraph->SetLineColor(colors[i]);
865 dsetgraph->SetMarkerColor(colors[i]);
866 graph->Add(dsetgraph);
867 }
868 if (log) {
869 graph->GetHistogram()->SetMinimum(0.01);
870 }
871 else {
872 graph->GetHistogram()->SetMinimum(0.0);
873 }
874 graph->Draw("A*");
875 if (xlow!=xhigh) {
876 graph->GetXaxis()->SetLimits(xlow, xhigh);
877 }
878 graph->Draw("A*");
879 EffFunc->SetParameter(7, fAbsScale);
880 EffFunc->Draw("same");
881 /*
882 std::cout << "EXPLICIT PRINT OUT" << std::endl;
883 for (int i=1; i<4096; ++i) {
884 std::cout << i << " " << EffFunc->Eval(i) << std::endl;
885 }
886 */
887 if (log) {
888 canvas->SetLogy();
889 canvas->SetLogx();
890 }
891 return graph;
892 }
893
894 void EffFit::WriteGraph(std::string outDir)
895 {
896 int nDataSets = fDataSets.size();
897
898 for (int i=0; i<nDataSets; ++i)
899 {
900 std::string fname = outDir+"/dset_"+std::to_string(i)+".dat";
901 std::ofstream dset_file(fname);
902 TGraphErrors *dsetgraph = fDataSets[i].GetGraphErrors();
903 std::cout << " Data Set " << i << ", nPoints " << dsetgraph->GetN() << std::endl;
904 std::cout << fname << std::endl;
905 for (int j=0; j<dsetgraph->GetN(); ++j) {
906 double x, y, yerr;
907 dsetgraph->GetPoint(j, x, y);
908 yerr = dsetgraph->GetErrorY(j);
909 dset_file << x << " " << y << " " << yerr << std::endl;
910 }
911 dset_file.close();
912 }
913
914 std::string fname = outDir+"/efficiency.dat";
915 std::ofstream eff_file(fname);
916 for (int i=1; i<=4096; ++i) {
917 eff_file << i << " " << EffFunc->Eval((double)i) << std::endl;
918 }
919 eff_file.close();
920 }
921
922 TMultiGraph* EffFit::DrawRes(TCanvas *canvas, int detID/*=0*/, double xlow/*=-1*/, double xhigh/*=-1*/)
923 {
924 std::cout << "Drawing Detector " << detID << std::endl;
925 canvas->Clear();
926 canvas->cd();
927 int nDataSets = fDataSets.size();
928 TMultiGraph *graph = new TMultiGraph();
929 graph->SetTitle(("Efficiency "+std::to_string(detID)).c_str());
930 std::vector<Color_t> colors = {kRed, kBlue, kGreen, kMagenta, kCyan, kBlack, kYellow};
931 double std_dev = 0;
932 int nPoints = 0;
933 for (int i=0; i<nDataSets; ++i)
934 {
935 TGraphErrors *dsetgraph = fDataSets[i].GetGraphErrors();
936 std::cout << " Data Set " << i << ", nPoints " << dsetgraph->GetN() << std::endl;
937 TGraphErrors *residuals = new TGraphErrors();
938 for (int j=0; j<dsetgraph->GetN(); ++j) {
939 ++nPoints;
940 double x,y;
941 dsetgraph->GetPoint(j, x, y);
942 y = (y - EffFunc->Eval(x))/EffFunc->Eval(x)*100.0;
943 std_dev += y*y;
944 residuals->SetPoint(j, x, y);
945 residuals->SetPointError(j, 0, dsetgraph->GetErrorY(j)/EffFunc->Eval(x)*100.0);
946 }
947
948 residuals->SetLineColor(colors[i]);
949 residuals->SetMarkerColor(colors[i]);
950 graph->Add(residuals);
951 }
952 std_dev = std::sqrt(std_dev/(double)nPoints);
953 std::cout << "Spread = " << std_dev << std::endl;
954 canvas->SetLogy(0);
955 graph->Draw("A*");
956 if (xlow!=xhigh) {
957 graph->GetXaxis()->SetLimits(xlow, xhigh);
958 }
959 graph->Draw("A*");
960 TF1 *con = new TF1("con", "0", xlow, xhigh);
961 con->Draw("same");
962 return graph;
963 }
964
965 void EffFit::Draw(const char* outFile, double xlow, double xhigh, bool log) {
966 TCanvas *c1 = new TCanvas();
967 c1->Print(((std::string)outFile+"[").c_str());
968 TMultiGraph *graph = Draw(c1, 0, xlow, xhigh, log);
969 c1->Update();
970 c1->Print(outFile);
971 TMultiGraph *res = DrawRes(c1, 0, xlow, xhigh);
972 c1->Update();
973 c1->Print(outFile);
974 c1->Print(((std::string)outFile+"]").c_str());
975 delete graph;
976 delete res;
977 }
978
979 MultiDataSet::MultiDataSet(const char *histFile, const char *histName, const char *gateFile, const char *mapName, const char *intensityFile)
980 {
981 TFile *hisFile = new TFile(histFile);
982 TH2D *fHist = (TH2D*)hisFile->Get(histName);
983
984 TFile *gatFile = new TFile(gateFile);
985 GamR::Nucleus::TransitionMap *fTransitionMap = (GamR::Nucleus::TransitionMap*)gatFile->Get(mapName);
986
987 std::ifstream intFile(intensityFile);
988
989 std::string key;
990 double energy;
991 double intensity;
992 std::map<std::string, std::pair<double, double> > fIntensityMap;
993 while(intFile >> key >> energy >> intensity) {
994 fIntensityMap[key] = std::pair<double, double>(energy, intensity);
995 }
996
997 for (int i=1; i<fHist->GetYaxis()->GetNbins()+1; ++i) {
998 TH1D *proj = (TH1D*)fHist->ProjectionX("proj", i, i);
999 std::cout << "ADDING DETECTOR " << i << ", " << proj->GetEntries() << std::endl;
1000 if (proj->GetEntries()>0) {
1001 fDataSets[i] = DataSet(proj, fTransitionMap, fIntensityMap);
1002 }
1003 delete proj;
1004
1005 }
1006
1007 hisFile->Close();
1008 gatFile->Close();
1009
1010 }
1011
1012 void FitParams::SetParams(std::vector<std::string> sParams, std::vector<std::string> sFixed, std::vector<std::string> sLimLow, std::vector<std::string> sLimHigh)
1013 {
1014 for (int i=0; i<sParams.size(); ++i) {
1015 TFormula fval("fval", sParams[i].c_str());
1016 TFormula flow("flow", sLimLow[i].c_str());
1017 TFormula fhigh("fhigh", sLimHigh[i].c_str());
1018 double parlow, parhigh;
1019 //func->GetParLimits(i, parlow, parhigh);
1020 params[i] = fval;//.Eval(func->GetParameter(i));
1021 limlow[i] = flow;//.Eval(parlow);
1022 limhigh[i] = fhigh;//.Eval(parhigh);
1023 if (atoi(sFixed[i].c_str())==1) {
1024 fixed[i] = 1;
1025 }
1026 else {
1027 fixed[i] = 0;
1028 }
1029 }
1030 }
1031
1032 void MultiEffFit::AddData(const char *histFile, const char *histName, const char *gateFile, const char *mapName, const char *intensityFile)
1033 {
1034 MultiDataSet mdataset(histFile, histName, gateFile, mapName, intensityFile);
1035 for (auto &dset : *(mdataset.GetDataSets())) {
1036 int i = dset.first;
1037 AddData(dset.second, dset.first);
1038 }
1039 }
1040
1041 void MultiEffFit::AddData(DataSet dataSet, int ID) {
1042 if (fEffFits.find(ID) == fEffFits.end()) {
1043 fEffFits[ID] = EffFit();
1044 fDetNorm[ID] = 1.0;
1045 }
1046 fEffFits[ID].AddData(dataSet);
1047 std::cout << "Added Det " << ID << " with " << dataSet.GetNData() << " efficiency calibration points" << std::endl;
1048 for (int j=0; j<dataSet.GetNData(); ++j) {
1049 std::cout << dataSet.GetEnergy(j) << " " << dataSet.GetEfficiency(j) << std::endl;
1050 }
1051 }
1052
1053 void MultiEffFit::SetData(const char *effFile, int i, int ID)
1054 {
1055 fEffFits[ID].fDataSets[i].SetData(effFile);
1056 }
1057
1059 {
1060 for (auto &efffit : fEffFits) {
1061 efffit.second.SetParams(params);
1062 }
1063 }
1064
1066 {
1067 if (fEffFits.find(ID) == fEffFits.end()) { return; }
1068 fEffFits[ID].SetParams(params);
1069 }
1070
1071 void MultiEffFit::SetDetNorms(int ID, int iDataSet, std::string key)
1072 {
1073 int index = fEffFits[ID].fDataSets[iDataSet].GetIndex(key);
1074 double normArea = fEffFits[ID].fDataSets[iDataSet].GetPeak(index);
1075
1076 for (auto &efffit : fEffFits) {
1077 if (efffit.first != ID) {
1078 index = efffit.second.fDataSets[iDataSet].GetIndex(key);
1079 fDetNorm[efffit.first] = efffit.second.fDataSets[iDataSet].GetPeak(index)/normArea;
1080 }
1081 }
1082 }
1083
1084 void MultiEffFit::SetNorm(int iDataSet, double factor) {
1085 for (auto &efffit : fEffFits) {
1086 double curNorm = efffit.second.fDataSets[iDataSet].GetNorm();
1087 efffit.second.fDataSets[iDataSet].SetNorm(curNorm*factor);
1088 }
1089 }
1090
1091 void MultiEffFit::SetNorm(int ID, int iDataSet, double factor) {
1092 double curNorm = fEffFits[ID].fDataSets[iDataSet].GetNorm();
1093 fEffFits[ID].fDataSets[iDataSet].SetNorm(curNorm*factor);
1094 }
1095
1096 void MultiEffFit::EraseData(int iDataSet, std::string key) {
1097 for (auto &efffit : fEffFits) {
1098 efffit.second.fDataSets[iDataSet].EraseData(key);
1099 }
1100 }
1101
1103 for (auto &efffit : fEffFits) {
1104 efffit.second.EqualWeights = true;
1105 }
1106 }
1107
1109 {
1110 for (auto &efffit : fEffFits) {
1111 std::cout << "=====================================================" << std::endl;
1112 std::cout << "FITTING DETECTOR " << efffit.first << std::endl;
1113 std::cout << "=====================================================" << std::endl;
1114 efffit.second.Fit(1);
1115 }
1116 }
1117
1118 void MultiEffFit::Fit(int ID)
1119 {
1120 if (fEffFits.find(ID) == fEffFits.end()) { return; }
1121 fEffFits[ID].Fit(1);
1122 }
1123
1124 void MultiEffFit::Draw(const char *outFile, double xlow/*=-1*/, double xhigh/*=-1*/, bool log/*=false*/)
1125 {
1126 std::vector<int> presentIDs;
1127 TCanvas *c1 = new TCanvas("c1", "c1", 1280, 720);
1128 c1->Print((outFile+std::string("[")).c_str());
1129 for (auto &efffit : fEffFits) {
1130 int detID = efffit.first;
1131 std::cout << "Drawing Det " << detID << std::endl;
1132 c1->Clear();
1133 TMultiGraph *graph = efffit.second.Draw(c1, detID, xlow, xhigh, log);
1134 c1->Update();
1135 c1->Print(outFile);
1136 presentIDs.push_back(detID);
1137 delete graph;
1138 }
1139 c1->Clear();
1140 c1->Print((outFile+std::string("]")).c_str());
1141 }
1142
1143 void MultiEffFit::PrintDataSet(int i, int ID, const char *fileName)
1144 {
1145 fEffFits[ID].fDataSets[i].Print(fileName);
1146 }
1147
1148 void MultiEffFit::PrintDataSet(int i, const char *fileNameBase)
1149 {
1150 for (auto &efffit : fEffFits) {
1151 std::string fileName((std::string(fileNameBase)+"."+std::to_string(efffit.first)).c_str());
1152 efffit.second.fDataSets[i].Print(fileName.c_str());
1153 }
1154 }
1155
1156 void MultiEffFit::PrintParams(const char *outFile)
1157 {
1158 FILE *file;
1159 file = fopen(outFile, "wa");
1160 fprintf(file, " ID AbsScale RelNorm A Aerr B Berr C Cerr D Derr E Eerr F Ferr G Gerr\n");
1161 for (auto &efffit : fEffFits) {
1162 int detID = efffit.first;
1163 fprintf(file, "%4i", detID);
1164 fprintf(file, " %8.7f ", efffit.second.EffFunc->GetParameter(7));
1165 fprintf(file, " %10.3f", fDetNorm[efffit.first]);
1166 for (int i=0; i<7; ++i) {
1167 fprintf(file, " %5.4f %5.4f ", efffit.second.EffFunc->GetParameter(i), efffit.second.EffFunc->GetParError(i));
1168 }
1169 fprintf(file,"\n");
1170 }
1171 fclose(file);
1172 }
1173
1174 void MultiEffFit::WriteGraphs(std::string outDir)
1175 {
1176 for ( auto &det : fEffFits) {
1177 det.second.WriteGraph(outDir+"/det"+std::to_string(det.first));
1178 }
1179 }
1180
1181 void EffFit::PrintParams(const char *outFile) {
1182 FILE *file;
1183 file = fopen(outFile, "wa");
1184 fprintf(file, "AbsScale A Aerr B Berr C Cerr D Derr E Eerr F Ferr G Gerr\n");
1185 fprintf(file, " %8.7f ", EffFunc->GetParameter(7));
1186 for (int i=0; i<7; ++i) {
1187 fprintf(file, " %5.4f %5.4f ", EffFunc->GetParameter(i), EffFunc->GetParError(i));
1188 }
1189 fprintf(file,"\n");
1190 fclose(file);
1191 }
1192 }
1193}
void ss(std::vector< int > indexes, TCanvas *canvas, Option_t *option)
void log(TVirtualPad *canvas)
double GetEfficiency(int i)
Definition Efficiency.hh:56
TGraphErrors * GetGraph()
void SetData(const char *effFile)
void Print(const char *fileName)
void EraseData(std::string key)
TGraphErrors * GetGraphErrors()
int GetIndex(std::string key)
double operator()(const double *par)
std::vector< DataSet > fDataSets
Definition Efficiency.hh:81
void PrintParams(const char *fileName)
void SetParams(FitParams params)
void Fit(int quiet=0)
void WriteGraph(std::string outDir)
TMultiGraph * Draw(TCanvas *canvas, int detID=0, double xlow=-1, double xhigh=-1, bool log=false)
TMultiGraph * DrawRes(TCanvas *canvas, int detID=0, double xlow=-1, double xhigh=-1)
void SetParams(std::vector< std::string > sParams, std::vector< std::string > sFixed, std::vector< std::string > sLimLow, std::vector< std::string > sLimHigh)
std::vector< TFormula > params
Definition Efficiency.hh:67
std::vector< TFormula > limlow
Definition Efficiency.hh:68
std::vector< int > fixed
Definition Efficiency.hh:70
std::vector< TFormula > limhigh
Definition Efficiency.hh:69
std::map< int, DataSet > * GetDataSets()
void SetParams(FitParams params)
void SetData(const char *effFile, int i, int ID)
void AddData(const char *histFile, const char *histName, const char *gateFile, const char *mapName, const char *intensityFile)
void Draw(const char *outFile, double xlow=-1, double xhigh=-1, bool log=false)
void PrintParams(const char *outFile)
void SetDetNorms(int ID, int iDataSet, std::string key)
void WriteGraphs(std::string outDir)
void SetNorm(int iDataSet, double factor)
void PrintDataSet(int i, const char *fileNameBase)
void EraseData(int ID, int iDataSet, std::string key)
std::map< std::string, Transition > * GetMap()
Definition Transition.hh:54
Library to calculate relative efficiencies for HPGe detectors.
Definition Efficiency.cc:36
double EffCFunc(double *x, double *pars)
Definition Gain.cc:19