ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtPSADeconvFit.cxx
Go to the documentation of this file.
1 #include "AtPSADeconvFit.h"
2 
3 #include "AtContainerManip.h"
4 #include "AtDigiPar.h"
5 
6 #include <FairLogger.h> // for Logger, LOG
7 #include <FairParSet.h> // for FairParSet
8 #include <FairRun.h>
9 #include <FairRuntimeDb.h>
10 
11 #include <Math/WrappedMultiTF1.h>
12 #include <TF1.h>
13 #include <TH1.h> // for TH1D
14 #include <TMath.h> // for Pi
15 #include <TString.h> // for TString
16 
17 #include <HFitInterface.h>
18 
19 #include <Fit/BinData.h>
20 #include <Fit/DataOptions.h> // for DataOptions
21 #include <Fit/DataRange.h> // for DataRange
22 #include <Fit/FitConfig.h> // for FitConfig
23 #include <Fit/Fitter.h>
24 #include <algorithm> // for max_element
25 #include <cmath> // for sqrt
26 #include <functional> // for hash
27 #include <iterator> // for begin, distance, end
28 #include <memory> // for allocator, unique_ptr
29 #include <thread>
30 thread_local std::unique_ptr<TH1F> AtPSADeconvFit::fHist = nullptr;
31 
33 {
35  auto fPar = dynamic_cast<AtDigiPar *>(FairRun::Instance()->GetRuntimeDb()->getContainer("AtDigiPar"));
36  fDiffLong = fPar->GetCoefDiffusionLong();
37 }
38 
40 {
41  // Get initial guess for hit. Z loc is max and std dev is estimated from diffusion
42  auto maxTB = std::max_element(begin(charge), end(charge));
43  auto zTB = static_cast<double>(std::distance(begin(charge), maxTB));
44 
45  auto zPos = CalculateZGeo(zTB); // [mm]
46  auto driftTime = zPos / fDriftVelocity / 10.; // [us] drift velocity is cm/us
47  if (driftTime < 0)
48  driftTime = 0;
49  auto longDiff = std::sqrt(2 * fDiffLong * driftTime); // [cm] longitudal diff sigma
50  auto sigTime = longDiff / fDriftVelocity; // [us] longitudal diff sigma
51  auto sigTB = sigTime / fTBTime * 1000.; // [TB] sigTime is us, TBTime is ns.
52  if (sigTB < 0.1)
53  sigTB = 0.1;
54  LOG(debug) << "zTB: " << zTB << " zTime " << driftTime << " sigTB: " << sigTB << " Amp: " << *maxTB;
55 
56  if (*maxTB < getThreshold() || zTB < 20 || zTB > 500) {
57  LOG(debug) << "Skipping pad: " << *maxTB << " below threshold or " << zTB
58  << " outside initial guess for hit TB is outside valid range (20,500).";
59  return {};
60  }
61 
62  // Create a historgram to fit and fit to range mean +- 4 sigma.
63  auto id = std::hash<std::thread::id>{}(std::this_thread::get_id());
64  if (fHist)
66  else
67  fHist = ContainerManip::CreateHistFromData<TH1F>(TString::Format("%lu", id).Data(), charge);
68 
69  // Add an addition +-2 for when we are close to the pad plane and diffusion is small
70  auto fitRange = 3 * sigTB + 2;
71  if (fitRange < 3)
72  fitRange = 3;
73 
74  TF1 gauss(TString::Format("fitGauss%lu", id), "gaus(0)", zTB - fitRange, zTB + fitRange, TF1::EAddToList::kNo);
75  gauss.SetParameter(0, *maxTB); // Set initial height of gaussian
76  gauss.SetParameter(1, zTB); // Set initial position of gaussian
77  gauss.SetParameter(2, sigTB); // Set initial sigma of gaussian
78 
79  // Fit without graphics and saving everything in the result ptr
80  // auto resultPtr = hist->Fit(&gauss, "SQNR");
81  auto result = FitHistorgramParallel(*fHist, gauss);
82  if (!result.IsValid()) {
83  LOG(info) << "Fit did not converge using initial conditions:"
84  << " mean: " << zTB << " sig:" << sigTB << " max:" << *maxTB;
85  return {};
86  }
87 
88  auto amp = result.GetParams()[0];
89  auto z = result.GetParams()[1];
90  auto sig = result.GetParams()[2];
91 
92  auto Q = amp * sig * std::sqrt(2 * TMath::Pi());
93  LOG(debug) << "Initial: " << *maxTB << " " << zTB << " " << sigTB;
94  LOG(debug) << "Fit: " << amp << " " << z << " " << sig;
95 
96  return {{z, sig * sig, Q, 0}};
97 }
98 
99 const ROOT::Fit::FitResult AtPSADeconvFit::FitHistorgramParallel(TH1F &hist, TF1 &func)
100 {
101  // Create the data to fit
102  double xmin = 0, xmax = 0;
103  func.GetRange(xmin, xmax);
104  ROOT::Fit::DataOptions opt;
105 
106  ROOT::Fit::DataRange range(xmin, xmax);
107  ROOT::Fit::BinData d(opt, range);
108  ROOT::Fit::FillData(d, &hist);
109 
110  // Create the function to fit (just a wrapper)
111  ROOT::Math::WrappedMultiTF1 wf(func);
112 
113  ROOT::Fit::Fitter fFitter;
114  fFitter.Config().SetMinimizer("Minuit2");
115  fFitter.SetFunction(wf, false);
116 
117  bool goodFit = fFitter.Fit(d);
118  if (goodFit)
119  return fFitter.Result();
120  else
121  return {};
122 }
AtPSADeconvFit.h
AtPSA::CalculateZGeo
Double_t CalculateZGeo(Double_t peakIdx)
Definition: AtPSA.cxx:90
AtPSADeconvFit::getZandQ
HitData getZandQ(const AtPad::trace &charge) override
Definition: AtPSADeconvFit.cxx:39
AtPad::trace
std::array< Double_t, 512 > trace
Definition: AtPad.h:41
AtPSA::getThreshold
Double_t getThreshold(int padSize=-1)
Definition: AtPSA.cxx:179
gauss
double gauss(double x, const double *p)
Definition: lmfit.cxx:21
AtDigiPar.h
AtDigiPar
Definition: AtDigiPar.h:14
AtPSADeconvFit::FitHistorgramParallel
const ROOT::Fit::FitResult FitHistorgramParallel(TH1F &hist, TF1 &func)
Definition: AtPSADeconvFit.cxx:99
AtPSA::fDriftVelocity
Double_t fDriftVelocity
Definition: AtPSA.h:47
ContainerManip::SetHistFromData
void SetHistFromData(TH1 &hist, const T &data, double xMin=0, double xMax=0)
Use contents of data to set the bin contents of hist.
Definition: AtContainerManip.h:24
AtPSADeconvFit::Init
virtual void Init() override
Definition: AtPSADeconvFit.cxx:32
AtContainerManip.h
AtPSADeconv::HitData
std::vector< ZHitData > HitData
Data structure for Z loc (TB), Z variance (TB), Charge (arb), Charge variance (arb)
Definition: AtPSADeconv.h:109
AtPSADeconvFit::fDiffLong
double fDiffLong
Definition: AtPSADeconvFit.h:15
AtPSADeconvFit::fHist
static thread_local std::unique_ptr< TH1F > fHist
Definition: AtPSADeconvFit.h:16
AtPSA::Init
virtual void Init()
Definition: AtPSA.cxx:30
AtPSA::fTBTime
Int_t fTBTime
Definition: AtPSA.h:45