ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtFilterFFT.cxx
Go to the documentation of this file.
1 #include "AtFilterFFT.h"
2 
3 #include "AtPad.h"
4 #include "AtPadBase.h"
5 #include "AtPadFFT.h"
6 #include "AtRawEvent.h"
7 
8 #include <FairLogger.h>
9 
10 #include <Rtypes.h>
11 #include <TComplex.h> // IWYU pragma: keep
12 #include <TVirtualFFT.h>
13 
14 #include <iostream>
15 #include <utility>
16 struct AtPadReference;
17 
18 void AtFilterFFT::SetLowPass(int order, int cutoff)
19 {
20  fFreqRanges.clear();
21  for (int i = 0; i < 512 / 2 + 1; ++i)
22  AddFreqRange({i, getFilterKernel(i, order, cutoff), i, getFilterKernel(i, order, cutoff)});
23 }
24 
30 double AtFilterFFT::getFilterKernel(int freq, int fFilterOrder, int fCutoffFreq)
31 {
32 
33  if (fFilterOrder == 0)
34  return 1;
35 
36  return 1.0 / (1.0 + std::pow(freq * freq / fCutoffFreq, fFilterOrder));
37 }
38 
40 {
41  auto canAdd = isValidFreqRange(range);
42  if (canAdd) {
43  fFreqRanges.push_back(std::move(range));
44 
45  if (range.fEndFreq == range.fBeginFreq) {
46  fFactors[range.fBeginFreq] = range.fBeginFact;
47  return true;
48  }
49  auto dFact = (range.fEndFact - range.fBeginFact) / (range.fEndFreq - range.fBeginFreq);
50  for (int i = range.fBeginFreq; i <= range.fEndFreq; ++i)
51  fFactors[i] = range.fBeginFact + dFact * (i - range.fBeginFreq);
52  }
53  return canAdd;
54 }
55 
57 {
58  std::vector<Int_t> dimSize = {fTransformSize};
59 
60  // Create a FFT object that we own ("K"), that will optimize the transform ("M"),
61  // and is a forward transform from real data to complex ("R2C")
62  fFFT = std::unique_ptr<TVirtualFFT>(TVirtualFFT::FFT(1, dimSize.data(), "R2C M K"));
63 
64  // Create a FFT object that we own ("K"), that will optimize the transform ("M"),
65  // and is a backwards transform from complex to Reak ("C2R")
66  fFFTbackward = std::unique_ptr<TVirtualFFT>(TVirtualFFT::FFT(1, dimSize.data(), "C2R M K"));
67 }
68 
70 {
71  fInputEvent = inputEvent;
72 }
73 
81 void AtFilterFFT::Filter(AtPad *pad, AtPadReference *padReference)
82 {
83  // Get data and transform
84  if (!pad->IsPedestalSubtracted()) {
85  LOG(error) << "Skipping FFT on pad " << pad->GetPadNum() << " at " << pad << " because not pedestal subtracted.";
86  return;
87  }
88 
89  fFFT->SetPoints(pad->GetADC().data());
90  fFFT->Transform();
91 
93 
94  // If we are saving the transform add
95  if (fSaveTransform) {
96  // Add the frequency information to the output pad
97  pad->AddAugment("fft", std::move(fft));
98 
99  // Add the freq information to the input pad
100  auto inputFFT = std::make_unique<AtPadFFT>();
101  inputFFT->GetDataFromFFT(fFFT.get());
102  fInputEvent->GetPad(pad->GetPadNum())->AddAugment("fft", std::move(inputFFT));
103  }
104 
105  fFFTbackward->Transform();
106 
107  double baseline = 0;
108  if (fSubtractBackground) {
109  for (int i = 0; i < 20; ++i)
110  baseline += fFFTbackward->GetPointReal(i);
111  baseline /= 20;
112  }
113 
114  for (int i = 0; i < pad->GetADC().size(); ++i)
115  pad->SetADC(i, fFFTbackward->GetPointReal(i) - baseline);
116 
117  // If we are saving the transform, add the
118 }
119 
120 bool AtFilterFFT::isValidFreqRange(const AtFreqRange &range)
121 {
122  bool isValid = true;
123  isValid &= range.fBeginFreq <= range.fEndFreq;
124  isValid &= range.fEndFreq <= fTransformSize / 2 + 1;
125  isValid &= range.fBeginFact >= 0 && range.fBeginFact <= 1;
126  isValid &= range.fEndFact >= 0 && range.fEndFact <= 1;
127  isValid &= !doesFreqRangeOverlap(range);
128  return isValid;
129 }
130 
131 bool AtFilterFFT::doesFreqRangeOverlap(const AtFreqRange &newRange)
132 {
133  for (auto &range : fFreqRanges) {
134  // Check to make sure the minimum frequency does not exist within the bounds
135  // of any added frequency, except for the max frequency when the factors are
136  // the same
137  if (newRange.fBeginFreq >= range.fBeginFreq && newRange.fBeginFreq < range.fEndFreq)
138  return true;
139  if (newRange.fBeginFreq == range.fEndFreq && newRange.fBeginFact != range.fEndFact)
140  return true;
141 
142  // Check to make sure the maximum frequency does not exist within the bounds of any added
143  // frequency, except for when it matches the minimum frequency with the same factor
144  if (newRange.fEndFreq > range.fBeginFreq && newRange.fEndFreq <= range.fEndFreq)
145  return true;
146  if (newRange.fEndFreq == range.fBeginFreq && newRange.fEndFact != range.fBeginFreq)
147  return true;
148  }
149 
150  return false;
151 }
152 
158 {
159  auto ret = std::make_unique<AtPadFFT>();
160  for (int i = 0; i < 512 / 2 + 1; ++i) {
161 
162  Double_t re, im;
163  fFFT->GetPointComplex(i, re, im);
164  if (fFactors.find(i) != fFactors.end()) {
165  re *= fFactors[i];
166  im *= fFactors[i];
167  }
168  ret->SetPoint(i, {re, im});
169  fFFTbackward->SetPoint(i, re / fFFT->GetN()[0], im / fFFT->GetN()[0]);
170  }
171  return ret;
172 }
173 
175 {
176  return lhs.fBeginFreq < rhs.fBeginFreq;
177 }
178 
180 {
181  for (const auto &pair : fFactors)
182  std::cout << pair.first << " " << pair.second << std::endl;
183 }
AtPad.h
AtFilterFFT::fFreqRanges
FreqRanges fFreqRanges
Definition: AtFilterFFT.h:48
AtRawEvent.h
AtRawEvent::GetPad
AtPad * GetPad(Int_t padNum)
Definition: AtRawEvent.h:124
AtFilterFFT::AtFreqRange::fEndFact
Double_t fEndFact
Definition: AtFilterFFT.h:42
AtFilterFFT::DumpFactors
void DumpFactors()
Definition: AtFilterFFT.cxx:179
AtFilterFFT::fSubtractBackground
Bool_t fSubtractBackground
Definition: AtFilterFFT.h:55
AtFilterFFT::fFFTbackward
std::unique_ptr< TVirtualFFT > fFFTbackward
Definition: AtFilterFFT.h:52
AtPad::SetADC
void SetADC(const trace &val)
Definition: AtPad.h:91
AtFilterFFT::AtFreqRange::fBeginFreq
Int_t fBeginFreq
Definition: AtFilterFFT.h:38
AtFilterFFT::fTransformSize
static constexpr Int_t fTransformSize
Definition: AtFilterFFT.h:59
AtRawEvent
Definition: AtRawEvent.h:34
AtFilterFFT::Filter
void Filter(AtPad *pad, AtPadReference *padReference) override
Definition: AtFilterFFT.cxx:81
AtFilterFFT::InitEvent
void InitEvent(AtRawEvent *event=nullptr) override
Called once for each event at the start of the Exec phase.
Definition: AtFilterFFT.cxx:69
AtFilterFFT::AtFreqRange::fBeginFact
Double_t fBeginFact
Definition: AtFilterFFT.h:39
AtFilterFFT::AtFreqRange::fEndFreq
Int_t fEndFreq
Definition: AtFilterFFT.h:41
AtFilterFFT.h
AtFilterFFT::AtFreqRange
Definition: AtFilterFFT.h:37
AtFilterFFT::AddFreqRange
bool AddFreqRange(AtFreqRange range)
Definition: AtFilterFFT.cxx:39
AtPad::GetPadNum
Int_t GetPadNum() const
Definition: AtPad.h:96
AtFilterFFT::applyFrequencyCutsAndSetInverseFFT
virtual std::unique_ptr< AtPadFFT > applyFrequencyCutsAndSetInverseFFT()
Definition: AtFilterFFT.cxx:157
AtPad::GetADC
const trace & GetADC() const
Definition: AtPad.cxx:97
AtFilterFFT::Init
void Init() override
Called at the init stage of the AtFilterTask.
Definition: AtFilterFFT.cxx:56
AtPad::IsPedestalSubtracted
Bool_t IsPedestalSubtracted() const
Definition: AtPad.h:94
AtFilterFFT::fFactors
std::map< Int_t, Double_t > fFactors
Definition: AtFilterFFT.h:49
AtPadFFT.h
AtFilterFFT::SetLowPass
void SetLowPass(int order, int cuttoff)
Definition: AtFilterFFT.cxx:18
AtFilterFFT::fFFT
std::unique_ptr< TVirtualFFT > fFFT
Definition: AtFilterFFT.h:51
AtPad
Container class for AtPadBase objects.
Definition: AtPad.h:38
AtPadBase.h
AtPadReference
Definition: AtPadReference.h:20
AtPad::AddAugment
AtPadBase * AddAugment(std::string name, std::unique_ptr< AtPadBase > augment)
Definition: AtPad.cxx:63
operator<
bool operator<(const AtFilterFFT::AtFreqRange &lhs, const AtFilterFFT::AtFreqRange &rhs)
Definition: AtFilterFFT.cxx:174
AtFilterFFT::fSaveTransform
Bool_t fSaveTransform
Definition: AtFilterFFT.h:54
AtFilterFFT::fInputEvent
AtRawEvent * fInputEvent
Definition: AtFilterFFT.h:57