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

Last change on this file since 17199 was 9274, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 8.6 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
151// ------------------------------------------------------------------------
152//
153// Add a second analog signal. Just by addining it bin by bin.
154//
155void MAnalogSignal::AddSignal(const MAnalogSignal &s)
156{
157 Add(s.GetArray(), s.fN);
158}
159
160// Deprecated. Use MSimRandomPhotons instead
161void MAnalogSignal::AddRandomPulses(const MSpline3 &spline, Float_t num)
162{
163 // Average number (1./freq) of pulses per slice
164
165 const Float_t start = 0 -spline.GetXmin();
166 const Float_t end = (fN-1)-spline.GetXmax();
167
168 const UInt_t first = TMath::CeilNint(start);
169 const UInt_t last = TMath::CeilNint(end); // Ceil:< Floor:<=
170
171 Double_t d = first;
172
173 while (d<last)
174 {
175 d += gRandom->Exp(num);
176 AddPulse(spline, d);
177 }
178}
179
180// ------------------------------------------------------------------------
181//
182// Add a random gaussian with amplitude and offset to every bin
183// of the analog signal. The default offset is 0. The default amplitude 1.
184//
185void MAnalogSignal::AddGaussianNoise(Float_t amplitude, Float_t offset)
186{
187 for (Float_t *ptr = GetArray(); ptr<GetArray()+fN; ptr++)
188 *ptr += gRandom->Gaus(offset, amplitude);
189}
190
191// ------------------------------------------------------------------------
192//
193// The signal is evaluated using the spline MExtralgoSpline.
194// Searching upwards from the beginning all points are calculated at
195// which the spline is equal to threshold. After a rising edge
196// a leading edge is searched. From this an MDigitalSignal is
197// created and added to an newly created TObjArray. If len<0 then
198// the signal length is equal to the time above threshold, otherwise
199// the length is fixed to len. The start of the digital signal is the
200// rising edge. If due to fixed length two digital signal overlap the
201// digital signals are combined into one signal.
202//
203// For numerical reasons we have to avoid to find the same x-value twice.
204// Therefor a "dead-time" of 1e-4 is implemented after each edge.
205//
206// The user is responsible of deleting the TObjArray.
207//
208TObjArray *MAnalogSignal::Discriminate(Float_t threshold, Double_t start, Double_t end, Float_t len) const
209{
210 TObjArray *ttl = new TObjArray;
211 ttl->SetOwner();
212
213 // The time after which we start searching for a falling or leading
214 // edge at threshold after a leading or falling edge respectively.
215 // This value has mainly numerical reasons. If starting the search
216 // too early we might end up in an endless loop finding the same
217 // value again and again. This just means that a glitch above or
218 // below the threshold which is shorter than this value can
219 // stay unnoticed. This shouldn't hurt.
220 const Double_t deadtime = 1e-4;
221
222 // FIXME: Are local maximum/minima handled correctly?
223
224 const MExtralgoSpline sp(GetArray(), fN, fDer1.GetArray(), fDer2.GetArray());
225
226 Double_t x1 = 0;
227 Double_t x2 = start; // Start searching at x2
228
229 while (1)
230 {
231 // Search for the next rising edge (starting at x2)
232 while (1)
233 {
234 x1 = sp.SearchYup(x2+deadtime, threshold);
235 if (x1<0 || x1>=end)
236 return ttl;
237
238 const Bool_t rising = sp.Deriv1(x1)>0;
239 if (rising)
240 break;
241
242 x2 = x1;
243 }
244
245 // Search for the next falling edge (starting at x1)
246 while (1)
247 {
248 x2 = sp.SearchYup(x1+deadtime, threshold);
249 if (x2<0)
250 x2 = end;
251 if (x2>=end)
252 break;
253
254 const Bool_t falling = sp.Deriv1(x2)<0;
255 if (falling)
256 break;
257
258 x1 = x2;
259 }
260
261 // We found a rising and a falling edge
262 MDigitalSignal *sig = new MDigitalSignal(x1, len>0?len:x2-x1);
263
264 // In case of a fixed length we have to check for possible overlapping
265 if (len>0 && ttl->GetEntriesFast()>0)
266 {
267 // FIXME: What if in such a case the electronics is just dead?
268 MDigitalSignal *last = static_cast<MDigitalSignal*>(ttl->Last());
269 // Combine both signals to one if they overlap
270 if (last->Combine(*sig))
271 {
272 // Both signals overlap and have been combined into the existing one
273 delete sig;
274 continue;
275 }
276 // The signals don't overlap we add the new signal as usual
277 }
278
279 // Add the new signal to the list of signals
280 ttl->Add(sig);
281 }
282
283 return ttl;
284}
Note: See TracBrowser for help on using the repository browser.