REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestRawFFT.cxx
1
17
18#include "TRestRawFFT.h"
19
20#include <TComplex.h>
21#include <TVirtualFFT.h>
22
23using namespace std;
24
25ClassImp(TRestRawFFT);
26
27TRestRawFFT::TRestRawFFT() {
28 // TRestRawFFT default constructor
29}
30
31TRestRawFFT::~TRestRawFFT() {
32 // TRestRawFFT destructor
33}
34
35void TRestRawFFT::SetNfft(Int_t n) {
36 fNfft = n;
37
38 fTimeReal.Set(fNfft);
39 fTimeImg.Set(fNfft);
40 fFrequencyReal.Set(fNfft);
41 fFrequencyImg.Set(fNfft);
42}
43
44Double_t TRestRawFFT::GetFrequencyNorm2(Int_t n) {
45 Double_t norm2 = fFrequencyReal.GetArray()[n] * fFrequencyReal.GetArray()[n] +
46 fFrequencyImg.GetArray()[n] * fFrequencyImg.GetArray()[n];
47
48 return norm2;
49}
50
51void TRestRawFFT::ForwardSignalFFT(TRestRawSignal* sgnl, Int_t fNStart, Int_t fNEnd) {
52 Int_t n = sgnl->GetNumberOfPoints() - fNStart - fNEnd;
53 SetNfft(n);
54
55 for (int i = fNStart; i < sgnl->GetNumberOfPoints() - fNEnd; i++) {
56 fTimeReal[i - fNStart] = sgnl->GetData(i);
57 fTimeImg[i - fNStart] = 0;
58 }
59
60 TVirtualFFT* forward = TVirtualFFT::FFT(1, &fNfft, "R2C");
61 forward->SetPointsComplex(fTimeReal.GetArray(), fTimeImg.GetArray());
62 forward->Transform();
63
64 for (int i = 0; i < fNfft; i++)
65 forward->GetPointComplex(i, fFrequencyReal.GetArray()[i], fFrequencyImg.GetArray()[i]);
66
67 delete forward;
68}
69
70void TRestRawFFT::BackwardFFT() {
71 TVirtualFFT* backward = TVirtualFFT::FFT(1, &fNfft, "C2R");
72 backward->SetPointsComplex(fFrequencyReal.GetArray(), fFrequencyImg.GetArray());
73 backward->Transform();
74
75 for (int i = 0; i < fNfft; i++) {
76 backward->GetPointComplex(i, fTimeReal.GetArray()[i], fTimeImg.GetArray()[i]);
77 fTimeReal.GetArray()[i] /= fNfft;
78 fTimeImg.GetArray()[i] /= fNfft;
79 }
80
81 delete backward;
82}
83
84void TRestRawFFT::ProduceDelta(Int_t t_o, Int_t Nfft) {
85 SetNfft(Nfft);
86
87 for (int i = 0; i < fNfft; i++) {
88 fTimeReal[i] = 0;
89 fTimeImg[i] = 0;
90
91 if (i == t_o) fTimeReal[i] = 1;
92 }
93
94 TVirtualFFT* forward = TVirtualFFT::FFT(1, &fNfft, "R2C");
95 forward->SetPointsComplex(fTimeReal.GetArray(), fTimeImg.GetArray());
96 forward->Transform();
97
98 for (int i = 0; i < fNfft; i++)
99 forward->GetPointComplex(i, fFrequencyReal.GetArray()[i], fFrequencyImg.GetArray()[i]);
100
101 delete forward;
102}
103
104void TRestRawFFT::GetSignal(TRestRawSignal* sgnl) {
105 sgnl->Reset();
106 for (int i = 0; i < fNfft; i++) sgnl->AddPoint(fTimeReal.GetArray()[i]);
107}
108
109void TRestRawFFT::MultiplyBy(TRestRawFFT* fftInput, Int_t from, Int_t to) {
110 if (fftInput->GetNfft() != this->GetNfft()) {
111 cout << "Not the same N FFT" << endl;
112 return;
113 }
114
115 if (to == 0) to = GetNfft() / 2;
116
117 for (int i = from; i < GetNfft() / 2; i++) {
118 TComplex top(this->GetFrequencyAmplitudeReal(i), this->GetFrequencyAmplitudeImg(i));
119 TComplex bottom(fftInput->GetFrequencyAmplitudeReal(i), fftInput->GetFrequencyAmplitudeImg(i));
120 TComplex product = top * bottom;
121 fFrequencyReal.GetArray()[i] = product.Re();
122 fFrequencyImg.GetArray()[i] = product.Im();
123 fFrequencyReal.GetArray()[fNfft - i - 1] = fFrequencyReal.GetArray()[i];
124 fFrequencyImg.GetArray()[fNfft - i - 1] = fFrequencyImg.GetArray()[i];
125 }
126}
127
128void TRestRawFFT::DivideBy(TRestRawFFT* fftInput, Int_t from, Int_t to) {
129 if (fftInput->GetNfft() != this->GetNfft()) {
130 cout << "Not the same N FFT" << endl;
131 return;
132 }
133
134 if (to == 0) to = GetNfft() / 2;
135
136 for (int i = from; i < to; i++) {
137 TComplex top(this->GetFrequencyAmplitudeReal(i), this->GetFrequencyAmplitudeImg(i));
138 TComplex bottom(fftInput->GetFrequencyAmplitudeReal(i), fftInput->GetFrequencyAmplitudeImg(i));
139 TComplex cocient = top / bottom;
140 fFrequencyReal.GetArray()[i] = cocient.Re();
141 fFrequencyImg.GetArray()[i] = cocient.Im();
142 fFrequencyReal.GetArray()[fNfft - i - 1] = fFrequencyReal.GetArray()[i];
143 fFrequencyImg.GetArray()[fNfft - i - 1] = fFrequencyImg.GetArray()[i];
144 }
145}
146
147void TRestRawFFT::ApplyResponse(TRestRawFFT* fftInput, Int_t cutOff) {
148 if (cutOff <= 0) cout << "TRestRawFFT::ApplyResponse. cutOff <= 0!!!" << endl;
149 DivideBy(fftInput, 0, cutOff);
150
151 Double_t normCutOff = GetFrequencyNorm2(cutOff - 1);
152 Double_t scaleFactor = normCutOff / GetFrequencyNorm2(cutOff);
153 scaleFactor = TMath::Sqrt(scaleFactor);
154 for (int i = cutOff; i < GetNfft() / 2; i++) {
155 fFrequencyReal.GetArray()[i] *= scaleFactor;
156 fFrequencyImg.GetArray()[i] *= scaleFactor;
157 fFrequencyReal.GetArray()[fNfft - i - 1] = fFrequencyReal.GetArray()[i];
158 fFrequencyImg.GetArray()[fNfft - i - 1] = fFrequencyImg.GetArray()[i];
159 }
160}
161
162void TRestRawFFT::KillFrequencies(Int_t cutOff) {
163 for (int i = cutOff; i < GetNfft() / 2; i++) {
164 fFrequencyReal.GetArray()[i] = 0;
165 fFrequencyImg.GetArray()[i] = 0;
166 fFrequencyReal.GetArray()[fNfft - i - 1] = fFrequencyReal.GetArray()[i];
167 fFrequencyImg.GetArray()[fNfft - i - 1] = fFrequencyImg.GetArray()[i];
168 }
169}
170
171void TRestRawFFT::ButterWorthFilter(Int_t cutOff, Int_t order) //, Double_t amp, Double_t decay )
172{
173 double cOffDouble = (double)cutOff;
174 for (int i = 0; i < fNfft / 2; i++) {
175 double iDouble = (double)i;
176 if (i > cutOff) {
177 fFrequencyReal.GetArray()[i] /= sqrt(1 + pow(iDouble / cOffDouble, 2 * order));
178 fFrequencyImg.GetArray()[i] /= sqrt(1 + pow(iDouble / cOffDouble, 2 * order));
179
180 fFrequencyReal.GetArray()[fNfft - i - 1] = fFrequencyReal.GetArray()[i];
181 fFrequencyImg.GetArray()[fNfft - i - 1] = fFrequencyImg.GetArray()[i];
182 }
183 }
184}
185
186void TRestRawFFT::ApplyLowPassFilter(Int_t cutFrequency) {
187 for (int i = 0; i < fNfft; i++) {
188 if (i >= cutFrequency && i < fNfft - cutFrequency) {
189 fFrequencyReal.GetArray()[i] = 0.;
190 fFrequencyImg.GetArray()[i] = 0.;
191 }
192 }
193}
194
195void TRestRawFFT::GaussianSecondOrderResponse(Double_t f1, Double_t f2, Double_t Ao, Double_t sigma) {
196 Double_t a = TMath::Sqrt(Ao);
197 for (int i = 0; i < fNfft / 2; i++) {
198 Double_t w = (double)2. * i / 3;
199
200 TComplex* cmplx1 = new TComplex((f1 * f2 - w * w), f1 * w);
201
202 TComplex* cmplx2 = new TComplex(f1, 0);
203
204 *cmplx2 /= *cmplx1;
205
206 *cmplx2 *= a * TMath::Exp(-sigma * w * w);
207
208 fFrequencyReal.GetArray()[i] = cmplx2->Re();
209 fFrequencyImg.GetArray()[i] = cmplx2->Im();
210 }
211
212 for (int i = fNfft / 2; i < fNfft; i++) {
213 fFrequencyReal.GetArray()[i] = fFrequencyReal.GetArray()[fNfft - i - 1];
214 fFrequencyImg.GetArray()[i] = fFrequencyImg.GetArray()[fNfft - i - 1];
215 }
216
217 // WriteFrequencyToTextFile( "frequencyResponse" );
218
219 BackwardFFT();
220
221 // WriteTimeSignalToTextFile ( "timeSignal" );
222}
223
224void TRestRawFFT::SetSecondOrderAnalyticalResponse(Double_t f1, Double_t f2, Double_t to) {
225 for (int i = 0; i < fNfft / 2; i++) {
226 Double_t w = 2.59 * (double)i;
227
228 TComplex* cmplx1 = new TComplex(f1 * w, (f1 * f2 - w * w));
229
230 TComplex* cmplx2 = new TComplex(f1, 0);
231
232 *cmplx2 /= *cmplx1;
233
234 TComplex phase(TComplex::Exp(TComplex(0, -w * to)));
235
236 *cmplx2 *= phase;
237
238 fFrequencyReal.GetArray()[i] = cmplx2->Re();
239 fFrequencyImg.GetArray()[i] = cmplx2->Im();
240 }
241 for (int i = fNfft / 2; i < fNfft; i++) {
242 fFrequencyReal.GetArray()[i] = fFrequencyReal.GetArray()[fNfft - i - 1];
243 fFrequencyImg.GetArray()[i] = fFrequencyImg.GetArray()[fNfft - i - 1];
244 }
245
246 WriteFrequencyToTextFile("/home/javier/tmp/frequencyResponse");
247
248 BackwardFFT();
249
250 WriteTimeSignalToTextFile("/home/javier/tmp/timeSignal");
251}
252
253void TRestRawFFT::RemoveBaseline() {
254 Double_t real = this->GetFrequencyAmplitudeReal(1);
255 Double_t img = this->GetFrequencyAmplitudeImg(1);
256 Double_t module = sqrt(real * real + img * img);
257 this->SetNode(0, module);
258}
259
260void TRestRawFFT::RenormalizeNode(Int_t n, Double_t factor) {
261 fFrequencyReal.GetArray()[fNfft - n - 1] = fFrequencyReal.GetArray()[n] / factor;
262 fFrequencyImg.GetArray()[fNfft - n - 1] = fFrequencyImg.GetArray()[n] / factor;
263
264 fFrequencyReal.GetArray()[n] = fFrequencyReal.GetArray()[n] / factor;
265 fFrequencyImg.GetArray()[n] = fFrequencyImg.GetArray()[n] / factor;
266}
267
268void TRestRawFFT::WriteFrequencyToTextFile(TString filename) {
269 FILE* fff = fopen(filename.Data(), "w");
270 for (int i = 0; i < fNfft; i++)
271 fprintf(fff, "%d\t%17.14e\t%17.14e\n", i, fFrequencyReal.GetArray()[i], fFrequencyImg.GetArray()[i]);
272 fclose(fff);
273}
274
275void TRestRawFFT::WriteTimeSignalToTextFile(TString filename) {
276 FILE* fff = fopen(filename.Data(), "w");
277 for (int i = 0; i < fNfft; i++)
278 fprintf(fff, "%d\t%e\t%e\n", i, fTimeReal.GetArray()[i], fTimeImg.GetArray()[i]);
279 fclose(fff);
280}
It defines a Short_t array with a physical parameter that evolves in time using a fixed time bin.
void Reset()
Initializes the existing signal data and sets it to zero while keeping the array size.
Double_t GetData(Int_t n) const
It returns the data value of point n including baseline correction.
void AddPoint(Short_t)
Adds a new point to the end of the signal data array.
Int_t GetNumberOfPoints() const
Returns the actual number of points, or size of the signal.