ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtPSADeconv.cxx
Go to the documentation of this file.
1 #include "AtPSADeconv.h"
2 
3 #include "AtDigiPar.h"
4 #include "AtHit.h"
5 #include "AtPad.h"
6 #include "AtPadArray.h"
7 #include "AtPadBase.h" // for AtPadBase
8 #include "AtPadFFT.h"
9 
10 #include <FairLogger.h>
11 #include <FairParSet.h> // for FairParSet
12 #include <FairRun.h>
13 #include <FairRuntimeDb.h>
14 
15 #include <Math/Point3D.h>
16 #include <Math/Point3Dfwd.h> // for XYZPoint
17 #include <Rtypes.h> // for Int_t, Double_t
18 #include <TComplex.h>
19 #include <TVirtualFFT.h>
20 
21 #include <cmath> // for sqrt
22 #include <numeric>
23 #include <stdexcept> // for runtime_error
24 #include <utility> // for move, pair
25 
27 
29 {
30  initFFTs();
31 };
32 
34  : fEventResponse(r.fEventResponse), fResponse(r.fResponse), fFFT(nullptr), fFFTbackward(nullptr),
35  fFilterOrder(r.fFilterOrder), fCutoffFreq(r.fCutoffFreq), fUseSimulatedCharge(r.fUseSimulatedCharge)
36 {
37  initFFTs();
38 }
39 
41 {
42  if (order % 2 != 0)
43  LOG(error) << "We only support even order filters!";
44  fFilterOrder = order / 2;
45  initFilter();
46 }
47 
49 {
50  fCutoffFreq = freq * freq;
51  initFilter();
52 }
53 
55 {
56  std::vector<Int_t> dimSize = {512};
57  // Create a FFT object that we own ("K"), that will optimize the transform ("M"),
58  // and is a forward transform from real data to complex ("R2C")
59  fFFT = std::unique_ptr<TVirtualFFT>(TVirtualFFT::FFT(1, dimSize.data(), "R2C M K"));
60  // Create a FFT object that we own ("K"), that will optimize the transform ("M"),
61  // and is a backwards transform from complex to Reak ("C2R")
62  fFFTbackward = std::unique_ptr<TVirtualFFT>(TVirtualFFT::FFT(1, dimSize.data(), "C2R M K"));
63 }
64 
71 {
72  LOG(debug2) << "Getting pad " << padNum << " from response event.";
73  auto pad = fEventResponse.GetPad(padNum);
74  if (pad == nullptr)
75  pad = createResponsePad(padNum);
76 
77  return *pad;
78 }
79 
87 {
88  auto &pad = GetResponse(padNum);
89  auto fft = dynamic_cast<AtPadFFT *>(pad.GetAugment("fft"));
90 
91  if (fft == nullptr) {
92  LOG(debug) << "Adding FFT to pad " << padNum;
93  fFFT->SetPoints(pad.GetADC().data());
94  fFFT->Transform();
95  auto fftNew = std::make_unique<AtPadFFT>();
96  fftNew->GetDataFromFFT(fFFT.get());
97  fft = dynamic_cast<AtPadFFT *>(pad.AddAugment("fft", std::move(fftNew)));
98  }
99 
100  return *fft;
101 }
102 
110 {
111  auto &pad = GetResponse(padNum);
112  auto &fft = GetResponseFFT(padNum);
113  auto filter = dynamic_cast<AtPadFFT *>(pad.GetAugment("filter"));
114 
115  if (filter == nullptr) {
116  LOG(debug) << "Adding filter to pad " << padNum;
117  filter = dynamic_cast<AtPadFFT *>(pad.AddAugment("filter", std::make_unique<AtPadFFT>()));
118  updateFilter(fft, filter);
119  }
120  return *filter;
121 }
122 void AtPSADeconv::updateFilter(const AtPadFFT &fft, AtPadFFT *filter)
123 {
124  LOG(debug) << "Updating filter ";
125  for (int i = 0; i < 512 / 2 + 1; ++i) {
126  auto R = fft.GetPointComplex(i);
127  auto filterVal = getFilterKernel(i) / R;
128 
129  LOG(debug2) << i << " " << TComplex::Abs(R) << " " << getFilterKernel(i) << " " << filterVal;
130  filter->SetPointRe(i, filterVal.Re());
131  filter->SetPointIm(i, filterVal.Im());
132  }
133 }
134 
136 {
137  LOG(debug) << "Creating response pad for " << padNum;
138  auto fPar = dynamic_cast<AtDigiPar *>(FairRun::Instance()->GetRuntimeDb()->getContainer("AtDigiPar"));
139  auto tbTime = fPar->GetTBTime() / 1000.;
140 
141  auto pad = fEventResponse.AddPad(padNum);
142  LOG(debug) << "Filling response pad for " << padNum;
143  for (int i = 0; i < 512; ++i) {
144  auto time = (i + 0.5) * tbTime;
145  pad->SetADC(i, fResponse(padNum, time));
146  }
147  return pad;
148 }
149 
156 {
157  if (fFilterOrder == 0)
158  return 1;
159  return 1.0 / (1.0 + std::pow(freq * freq / fCutoffFreq, fFilterOrder));
160 }
161 
166 {
167  // Loop through every existing filter and update it
168  for (auto &pad : fEventResponse.GetPads()) {
169  auto filter = dynamic_cast<AtPadFFT *>(pad->GetAugment("filter"));
170  if (filter != nullptr)
171  updateFilter(GetResponseFFT(pad->GetPadNum()), filter);
172  }
173 }
174 
175 // Assumes the passed pad already has its FFT calculated
177 {
178  LOG(debug) << "Analyzing pad " << pad.GetPadNum();
179  auto padFFT = dynamic_cast<AtPadFFT *>(pad.GetAugment("fft"));
180  auto recoFFT = dynamic_cast<AtPadFFT *>(pad.AddAugment("Qreco-fft", std::make_unique<AtPadFFT>()));
181  LOG(debug) << "Getting response filter";
182  const auto &respFFT = GetResponseFilter(pad.GetPadNum());
183  LOG(debug) << "Got response filter";
184 
185  if (padFFT == nullptr)
186  throw std::runtime_error("Missing FFT information in pad");
187 
188  // Fill the inverse FFT with the input charge
189  for (int i = 0; i < 512 / 2 + 1; ++i) {
190  auto a = padFFT->GetPointComplex(i);
191  auto b = respFFT.GetPointComplex(i);
192  LOG(debug2) << i << " " << a << " " << b << " " << a * b;
193  auto z = a * b;
194 
195  recoFFT->SetPoint(i, z);
196  z /= 512;
197  fFFTbackward->SetPointComplex(i, z);
198  }
199  fFFTbackward->Transform();
200 
201  // Get baseline from the charge
202  double baseline = std::accumulate(fFFTbackward->GetPointsReal(), fFFTbackward->GetPointsReal() + 20, 0.0);
203  baseline /= 20;
204 
205  // Create the charge padcentercoord
206  auto charge = std::make_unique<AtPadArray>();
207  // Fill the charge pad
208  for (int i = 0; i < 512; ++i)
209  charge->SetArray(i, fFFTbackward->GetPointReal(i) - baseline);
210 
211  pad.AddAugment("Qreco", std::move(charge));
212 
213  return chargeToHits(pad, "Qreco");
214 }
215 
217 {
218  // If this pad has simulated charge, use that instead
219  if (fUseSimulatedCharge && pad->GetAugment<AtPadArray>("Q") != nullptr)
220  return chargeToHits(*pad, "Q");
221 
222  // If this pad already contains FFT information, then just use it as is.
223  if (dynamic_cast<AtPadFFT *>(pad->GetAugment("fft")) != nullptr)
224  return AnalyzeFFTpad(*pad);
225 
226  // Add FFT data to this pad
227  fFFT->SetPoints(pad->GetADC().data());
228  fFFT->Transform();
229  pad->AddAugment("fft", AtPadFFT::CreateFromFFT(fFFT.get()));
230 
231  // Now process the pad with its fourier transform
232  return AnalyzeFFTpad(*pad);
233 }
234 
236 {
237 
238  HitVector ret;
239  auto charge = dynamic_cast<AtPadArray *>(pad.GetAugment(qName));
240 
241  LOG(debug) << "PadNum: " << pad.GetPadNum();
242  auto hitVec = getZandQ(charge->GetArray());
243 
244  for (auto &ZandQ : hitVec) {
245  XYZPoint pos(pad.GetPadCoord().X(), pad.GetPadCoord().Y(), CalculateZGeo(ZandQ.z));
246 
247  auto posVarXY = getXYhitVariance();
248  auto posVarZ = getZhitVariance(0, ZandQ.zVar);
249 
250  LOG(debug) << "Z(tb): " << ZandQ.z << " +- " << std::sqrt(ZandQ.zVar);
251  LOG(debug) << "Z(mm): " << pos.Z() << " +- " << std::sqrt(posVarZ);
252 
253  auto hit = std::make_unique<AtHit>(pad.GetPadNum(), pos, ZandQ.q);
254  hit->SetPositionVariance({posVarXY.first, posVarXY.second, posVarZ});
255  hit->SetChargeVariance(ZandQ.qVar);
256 
257  ret.push_back(std::move(hit));
258  }
259 
260  return ret;
261 }
262 
264 {
265  // Get the mean time and total charge
266  double q = std::accumulate(charge.begin(), charge.end(), 0.0);
267  double z = 0;
268  for (int i = 0; i < charge.size(); ++i)
269  z += i * charge[i];
270  z /= q;
271 
272  // Get the variance of the time
273  double zVar = 0;
274  for (int i = 0; i < charge.size(); ++i) {
275  zVar += charge[i] * (i - z) * (i - z);
276  }
277  zVar /= (q - 1);
278 
279  // Get the variance of the charge
280  double qVar = 0;
281 
282  return {{z, zVar, q, qVar}}; // Vector containing a single ZHitData struct
283 }
284 
285 double AtPSADeconv::getZhitVariance(double zLoc, double zLocVar) const
286 {
287  // zLocVar is in TB^2
288  double time = zLocVar * fTBTime * fTBTime; // Get variance in ns^2
289  time /= 1000 * 1000; // Get variance in us^2
290  auto pos = time * fDriftVelocity * fDriftVelocity; // Get variance in cm
291  pos *= 100; // Get variance in mm
292  return pos;
293 }
AtPad.h
AtPadFFT::CreateFromFFT
static std::unique_ptr< AtPadFFT > CreateFromFFT(const TVirtualFFT *fft)
Definition: AtPadFFT.cxx:112
AtPSADeconv::initFilter
void initFilter()
Update all "filter" augments in fEventResponse with the new parameters.
Definition: AtPSADeconv.cxx:165
AtRawEvent::GetPad
AtPad * GetPad(Int_t padNum)
Definition: AtRawEvent.h:124
AtPSADeconv::SetCutoffFreq
void SetCutoffFreq(int freq)
Definition: AtPSADeconv.cxx:48
AtPSADeconv::chargeToHits
virtual HitVector chargeToHits(AtPad &charge, std::string qName)
Definition: AtPSADeconv.cxx:235
AtPSA::CalculateZGeo
Double_t CalculateZGeo(Double_t peakIdx)
Definition: AtPSA.cxx:90
AtPSADeconv::AnalyzePad
virtual HitVector AnalyzePad(AtPad *pad) override
Definition: AtPSADeconv.cxx:216
AtPSADeconv::fEventResponse
AtRawEvent fEventResponse
Definition: AtPSADeconv.h:52
AtPadFFT::SetPointIm
void SetPointIm(int i, Double_t val)
Sets the imaginary value of the ith frequency component.
Definition: AtPadFFT.cxx:63
AtPSADeconv::fFFT
std::unique_ptr< TVirtualFFT > fFFT
Definition: AtPSADeconv.h:59
AtPSADeconv::updateFilter
void updateFilter(const AtPadFFT &fft, AtPadFFT *filter)
Definition: AtPSADeconv.cxx:122
AtPSADeconv::getZandQ
virtual HitData getZandQ(const AtPad::trace &charge)
Definition: AtPSADeconv.cxx:263
AtPadFFT::SetPointRe
void SetPointRe(int i, Double_t val)
Sets the real value of the ith frequency component.
Definition: AtPadFFT.cxx:53
AtPSADeconv::getZhitVariance
virtual double getZhitVariance(double zLoc, double zLocVar) const override
Definition: AtPSADeconv.cxx:285
AtPad::trace
std::array< Double_t, 512 > trace
Definition: AtPad.h:41
AtPSA::HitVector
std::vector< std::unique_ptr< AtHit > > HitVector
Definition: AtPSA.h:50
AtPad::SetADC
void SetADC(const trace &val)
Definition: AtPad.h:91
AtPSADeconv::fFilterOrder
int fFilterOrder
Definition: AtPSADeconv.h:62
AtDigiPar::GetTBTime
Int_t GetTBTime() const
returns the time duration of a time bucket in given sampling time in ns.
Definition: AtDigiPar.cxx:17
AtPSADeconv::GetResponse
AtPad & GetResponse(int padNum)
Get the AtPad describing the response of the electronics.
Definition: AtPSADeconv.cxx:70
XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPatternCircle2D.h:18
AtPSADeconv::fFFTbackward
std::unique_ptr< TVirtualFFT > fFFTbackward
Definition: AtPSADeconv.h:60
AtPSADeconv::initFFTs
void initFFTs()
Definition: AtPSADeconv.cxx:54
AtPSADeconv::GetResponseFFT
const AtPadFFT & GetResponseFFT(int padNum)
Get the fourier transform describing the response of the electronics.
Definition: AtPSADeconv.cxx:86
AtPSA::getXYhitVariance
virtual std::pair< double, double > getXYhitVariance() const
Definition: AtPSA.cxx:200
AtPad::GetPadCoord
XYPoint GetPadCoord() const
Definition: AtPad.h:107
AtPSADeconv::SetFilterOrder
void SetFilterOrder(int order)
Definition: AtPSADeconv.cxx:40
AtRawEvent::GetPads
const PadVector & GetPads() const
Definition: AtRawEvent.h:131
AtPSADeconv::AtPSADeconv
AtPSADeconv()
Definition: AtPSADeconv.cxx:28
AtPadArray.h
AtHit.h
AtPSADeconv::getFilterKernel
double getFilterKernel(int freq)
Definition: AtPSADeconv.cxx:155
AtPSADeconv::GetResponseFilter
const AtPadFFT & GetResponseFilter(int padNum)
Get the filter in fourier space describing the response of the electronics.
Definition: AtPSADeconv.cxx:109
AtDigiPar.h
XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPSADeconv.cxx:26
AtDigiPar
Definition: AtDigiPar.h:14
AtPSA::fDriftVelocity
Double_t fDriftVelocity
Definition: AtPSA.h:47
AtPSADeconv::fUseSimulatedCharge
bool fUseSimulatedCharge
Definition: AtPSADeconv.h:64
AtPadFFT
Definition: AtPadFFT.h:19
AtPSADeconv::createResponsePad
AtPad * createResponsePad(int padNum)
Definition: AtPSADeconv.cxx:135
AtPSADeconv
Abstract base class for getting current through deconvolution.
Definition: AtPSADeconv.h:38
AtPad::GetAugment
AtPadBase * GetAugment(std::string name)
Definition: AtPad.cxx:82
AtPad::GetPadNum
Int_t GetPadNum() const
Definition: AtPad.h:96
AtPad::GetADC
const trace & GetADC() const
Definition: AtPad.cxx:97
AtRawEvent::AddPad
AtPad * AddPad(Ts &&...params)
Create a new pad in this event.
Definition: AtRawEvent.h:82
AtPSADeconv::fResponse
ResponseFunc fResponse
Definition: AtPSADeconv.h:57
AtPadFFT::GetPointComplex
TComplex GetPointComplex(int i) const
Definition: AtPadFFT.h:35
AtPSADeconv::HitData
std::vector< ZHitData > HitData
Data structure for Z loc (TB), Z variance (TB), Charge (arb), Charge variance (arb)
Definition: AtPSADeconv.h:109
AtPSADeconv::fCutoffFreq
int fCutoffFreq
Definition: AtPSADeconv.h:63
AtPadArray
Holds an addition array of doubles for an AtPad.
Definition: AtPadArray.h:24
AtPadFFT.h
AtPad
Container class for AtPadBase objects.
Definition: AtPad.h:38
AtPSA
Definition: AtPSA.h:27
AtPadBase.h
AtPSADeconv::AnalyzeFFTpad
HitVector AnalyzeFFTpad(AtPad &pad)
Assumes that the pad has it's fourier transform information filled.
Definition: AtPSADeconv.cxx:176
AtPad::AddAugment
AtPadBase * AddAugment(std::string name, std::unique_ptr< AtPadBase > augment)
Definition: AtPad.cxx:63
AtPSADeconv.h
AtPSA::fTBTime
Int_t fTBTime
Definition: AtPSA.h:45