source: trunk/Mars/melectronics/MAnalogSignal.cc@ 20107

Last change on this file since 20107 was 19697, checked in by tbretz, 5 years ago
Added a function to shift the signal.
File size: 8.9 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of CheObs, the Modular Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appears in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: CheObs Software Development, 2000-2009
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MAnalogSignal
28//
29// This is the equivalent to an analog signal. The signal is stored by
30// a sampling in equidistant bins.
31//
32//////////////////////////////////////////////////////////////////////////////
33#include "MAnalogSignal.h"
34
35#include <TF1.h>
36#include <TRandom.h>
37#include <TObjArray.h>
38
39#include "MLog.h"
40#include "MLogManip.h"
41
42#include "MSpline3.h"
43#include "MDigitalSignal.h"
44
45#include "MExtralgoSpline.h"
46
47ClassImp(MAnalogSignal);
48
49using namespace std;
50
51// ------------------------------------------------------------------------
52//
53// Set the array length and the length of the buffers.
54//
55void MAnalogSignal::Set(UInt_t n)
56{
57 // FIXME: Maybe we move this before initializing the spline
58 // with a check?
59 fDer1.Set(n);
60 fDer2.Set(n);
61
62 MArrayF::Set(n);
63}
64
65// ------------------------------------------------------------------------
66//
67// Evaluate the spline an add the result between t+xmin and t+xmax
68// (xmin and xmax are the limits of the spline) to the signal.
69// The spline is evaluated at the bin-center of the analog signal
70// and multiplied by f.
71//
72// Return kTRUE if the full range of the spline could be added to the
73// analog signal, kFALSE otherwise.
74//
75Bool_t MAnalogSignal::AddPulse(const MSpline3 &spline, Float_t t, Float_t f)
76{
77 // FIXME: This could be improved using a MExtralgoSpline with
78 // the identical stepping as the signal and we could use
79 // the integral instead of the pure y-value if we want.
80
81 // Both in units of the sampling frequency
82 const Float_t start = t+spline.GetXmin();
83 const Float_t end = t+spline.GetXmax();
84
85 Int_t first = TMath::CeilNint(start);
86 UInt_t last = TMath::CeilNint(end); // Ceil:< Floor:<=
87
88 Bool_t rc = kTRUE;
89 if (first<0)
90 {
91 first=0;
92 rc = kFALSE;
93 }
94 if (last>GetSize())
95 {
96 last=GetSize();
97 rc = kFALSE;
98 }
99
100 // FIXME: As soon as we have access to TSpline3::fPoly we can
101 // gain a lot in execution speed here.
102
103 Float_t *arr = GetArray();
104 for (UInt_t i=first; i<last; i++)
105 arr[i] += spline.Eval(i-t)*f;
106
107 return rc;
108}
109
110// ------------------------------------------------------------------------
111//
112// Evaluate the spline an add the result between t+xmin and t+xmax
113// (xmin and xmax are the limits of the TF1) to the signal.
114// The spline is evaluated at the bin-center of the analog signal
115// and multiplied by f.
116//
117// Return kTRUE if the full range of the function could be added to the
118// analog signal, kFALSE otherwise.
119//
120Bool_t MAnalogSignal::AddPulse(const TF1 &func, Float_t t, Float_t f)
121{
122 // Both in units of the sampling frequency
123 const Float_t start = t+func.GetXmin();
124 const Float_t end = t+func.GetXmax();
125
126 Int_t first = TMath::CeilNint(start);
127 UInt_t last = TMath::CeilNint(end); // Ceil:< Floor:<=
128
129 Bool_t rc = kTRUE;
130 if (first<0)
131 {
132 first=0;
133 rc = kFALSE;
134 }
135 if (last>GetSize())
136 {
137 last=GetSize();
138 rc = kFALSE;
139 }
140
141 // FIXME: As soon as we have access to TSpline3::fPoly we can
142 // gain a lot in execution speed here.
143
144 Float_t *arr = GetArray();
145 for (UInt_t i=first; i<last; i++)
146 arr[i] += func.Eval(i-t)*f;
147
148 return rc;
149}
150
151void MAnalogSignal::ShiftSignal(Double_t shift)
152{
153 Float_t *arr = GetArray();
154 for (UInt_t i=0; i<fN; i++)
155 arr[i] += shift;
156}
157
158
159// ------------------------------------------------------------------------
160//
161// Add a second analog signal. Just by addining it bin by bin.
162//
163void MAnalogSignal::AddSignal(const MAnalogSignal &s, Int_t delay,
164 Float_t dampingFactor )
165{
166 Add(s.GetArray(), s.fN, delay, dampingFactor);
167}
168
169void MAnalogSignal::CopySignal(const MAnalogSignal &s)
170{
171 *this = s;
172 fDer1 = s.fDer1;
173 fDer2 = s.fDer2;
174}
175
176// Deprecated. Use MSimRandomPhotons instead
177void MAnalogSignal::AddRandomPulses(const MSpline3 &spline, Float_t num)
178{
179 // Average number (1./freq) of pulses per slice
180
181 const Float_t start = 0 -spline.GetXmin();
182 const Float_t end = (fN-1)-spline.GetXmax();
183
184 const UInt_t first = TMath::CeilNint(start);
185 const UInt_t last = TMath::CeilNint(end); // Ceil:< Floor:<=
186
187 Double_t d = first;
188
189 while (d<last)
190 {
191 d += gRandom->Exp(num);
192 AddPulse(spline, d);
193 }
194}
195
196// ------------------------------------------------------------------------
197//
198// Add a random gaussian with amplitude and offset to every bin
199// of the analog signal. The default offset is 0. The default amplitude 1.
200//
201void MAnalogSignal::AddGaussianNoise(Float_t amplitude, Float_t offset)
202{
203 for (Float_t *ptr = GetArray(); ptr<GetArray()+fN; ptr++)
204 *ptr += gRandom->Gaus(offset, amplitude);
205}
206
207// ------------------------------------------------------------------------
208//
209// The signal is evaluated using the spline MExtralgoSpline.
210// Searching upwards from the beginning all points are calculated at
211// which the spline is equal to threshold. After a rising edge
212// a leading edge is searched. From this an MDigitalSignal is
213// created and added to an newly created TObjArray. If len<0 then
214// the signal length is equal to the time above threshold, otherwise
215// the length is fixed to len. The start of the digital signal is the
216// rising edge. If due to fixed length two digital signal overlap the
217// digital signals are combined into one signal.
218//
219// For numerical reasons we have to avoid to find the same x-value twice.
220// Therefor a "dead-time" of 1e-4 is implemented after each edge.
221//
222// The user is responsible of deleting the TObjArray.
223//
224TObjArray *MAnalogSignal::Discriminate(Float_t threshold, Double_t start, Double_t end, Float_t len) const
225{
226 TObjArray *ttl = new TObjArray;
227 ttl->SetOwner();
228
229 // The time after which we start searching for a falling or leading
230 // edge at threshold after a leading or falling edge respectively.
231 // This value has mainly numerical reasons. If starting the search
232 // too early we might end up in an endless loop finding the same
233 // value again and again. This just means that a glitch above or
234 // below the threshold which is shorter than this value can
235 // stay unnoticed. This shouldn't hurt.
236 const Double_t deadtime = 1e-4;
237
238 // FIXME: Are local maximum/minima handled correctly?
239
240 const MExtralgoSpline sp(GetArray(), fN, fDer1.GetArray(), fDer2.GetArray());
241
242 Double_t x1 = 0;
243 Double_t x2 = start; // Start searching at x2
244
245 while (1)
246 {
247 // Search for the next rising edge (starting at x2)
248 while (1)
249 {
250 x1 = sp.SearchYup(x2+deadtime, threshold);
251 if (x1<0 || x1>=end)
252 return ttl;
253
254 const Bool_t rising = sp.Deriv1(x1)>0;
255 if (rising)
256 break;
257
258 x2 = x1;
259 }
260
261 // Search for the next falling edge (starting at x1)
262 while (1)
263 {
264 x2 = sp.SearchYup(x1+deadtime, threshold);
265 if (x2<0)
266 x2 = end;
267 if (x2>=end)
268 break;
269
270 const Bool_t falling = sp.Deriv1(x2)<0;
271 if (falling)
272 break;
273
274 x1 = x2;
275 }
276
277 // We found a rising and a falling edge
278 MDigitalSignal *sig = new MDigitalSignal(x1, len>0?len:x2-x1);
279
280 // In case of a fixed length we have to check for possible overlapping
281 if (len>0 && ttl->GetEntriesFast()>0)
282 {
283 // FIXME: What if in such a case the electronics is just dead?
284 MDigitalSignal *last = static_cast<MDigitalSignal*>(ttl->Last());
285 // Combine both signals to one if they overlap
286 if (last->Combine(*sig))
287 {
288 // Both signals overlap and have been combined into the existing one
289 delete sig;
290 continue;
291 }
292 // The signals don't overlap we add the new signal as usual
293 }
294
295 // Add the new signal to the list of signals
296 ttl->Add(sig);
297 }
298
299 return ttl;
300}
Note: See TracBrowser for help on using the repository browser.