source: trunk/MagicSoft/Simulation/Detector/include-MFadc/MFadc.cxx@ 6695

Last change on this file since 6695 was 6695, checked in by moralejo, 20 years ago
Set more precise values of the parameters for the shape of the low gain pulse in the FADC. H. Bartko provided the low gain pulse from the real data.
File size: 31.3 KB
Line 
1////////////////////////////////////////////////////////////////
2//
3// MFadc
4//
5//
6#include "MFadc.hxx"
7
8#include "MMcEvt.hxx"
9
10#include "TROOT.h"
11#include <TApplication.h>
12#include <TVirtualX.h>
13#include <TGClient.h>
14
15#include "TH1.h"
16#include "TObjArray.h"
17
18#include "MGFadcSignal.hxx"
19
20using namespace std;
21
22MFadc::MFadc(Int_t pix, Int_t shape, Float_t integral, Float_t fwhm,
23 Int_t shapeout, Float_t integralout, Float_t fwhmout,
24 Float_t trigger_delay, Float_t fadc_slices_per_ns,
25 Int_t fadc_slices_written, Int_t gainswitchamp,
26 Int_t shiftfromswitch2lowgain, Int_t hi2logainpeak) {
27 //
28 // Constructor overloaded II
29 //
30 // Input variables:
31 // 1. integral(out) = integration of the single phe response for inner
32 // (outer) pixels.
33 // 2. fwhm(out) = width at half high of the single phe response for
34 // inner (outer) pixels.
35 //
36 // trigger_delay: shift of signals towards later times in FADC, in order
37 // to center the signals in a good range. It acts as a sort of delay of
38 // the signals (before being sent to the FADC) with respect to the trigger.
39 //
40 // The procedure is the following:
41 // 1. some parameters of the trigger are set to default.
42 // this parameters of the trigger may be changed
43 // 3. Then the all signals are set to zero
44
45 numpix=pix;
46
47 fwhm_resp = fwhm;
48 integ_resp = integral;
49 fwhm_resp_outer = fwhmout;
50 integ_resp_outer = integralout;
51 shape_resp = shape;
52 shape_resp_outer = shapeout;
53 fFadcSlicesPerNanosec = fadc_slices_per_ns;
54 fFadcSlices = fadc_slices_written;
55 fGainSwitchAmp = gainswitchamp;
56 fShiftFromSwitch2LowGain = shiftfromswitch2lowgain;
57 fHi2LoGainPeak = hi2logainpeak;
58
59 fSlices_mFadc = (Int_t)(TOTAL_TRIGGER_TIME*fFadcSlicesPerNanosec);
60
61 for (Int_t i = 0; i < CAMERA_PIXELS; i++)
62 {
63 sig[i] = new Float_t[fSlices_mFadc];
64 sig_LG[i] = new Float_t[fSlices_mFadc];
65 }
66
67 noise = new Float_t[fSlices_mFadc*1001];
68 noise_outer = new Float_t[fSlices_mFadc*1001];
69 digital_noise = new Float_t[fSlices_mFadc*1001];
70
71 for (Int_t i = 0; i < CAMERA_PIXELS; i++)
72 {
73 output[i] = new Float_t[fFadcSlices];
74 output_lowgain[i] = new Float_t[fFadcSlices];
75 }
76
77 cout<< "[MFadc] Setting up the MFadc with this values "<< endl ;
78 cout<< "[MFadc] FADC sampling frequency: " << fFadcSlicesPerNanosec << " GHz" << endl ;
79 cout<< "[MFadc] - Inner pixels : "<< endl ;
80
81 switch(shape_resp){
82 case 0:
83 cout<< "[MFadc] Pulse shape : Gaussian ("<<shape_resp<<")"<< endl ;
84 cout<< "[MFadc] Response Area : "<<integ_resp<<" adc counts"<< endl ;
85 cout<< "[MFadc] Response FWHM : "<<fwhm_resp<<" ns"<< endl ;
86 break;
87 case 1:
88 cout<< "[MFadc] Pulse shape : From Pulpo ("<<shape_resp<<")"<< endl ;
89 cout<< "[MFadc] Response Area : "<<integ_resp<<" adc counts"<< endl ;
90 break;
91 default:
92 cout<< "[MFadc] Pulse shape unknown"<<endl;
93 }
94 cout<< "[MFadc] - Outer pixels : "<< endl ;
95 switch(shape_resp_outer){
96 case 0:
97 cout<< "[MFadc] Pulse shape : Gaussian ("<<shape_resp_outer<<")"<<endl;
98 cout<< "[MFadc] Response Area : "<<integ_resp_outer<<" adc counts"<<endl;
99 cout<< "[MFadc] Response FWHM : "<<fwhm_resp_outer<<" ns"<< endl ;
100 break;
101 case 1:
102 cout<< "[MFadc] Pulse shape : From Pulpo ("<<shape_resp_outer<<")"<<endl;
103 cout<< "[MFadc] Response Area : "<<integ_resp_outer<<" adc counts"<< endl ;
104 break;
105 default:
106 cout<< "[MFadc] Pulse shape unknown ("<<shape_resp_outer<<")"<<endl;
107 }
108
109
110 //
111 // set up the response shape
112 //
113
114 //
115 // First select number of bins for the histogram which will contain the single
116 // photoelectron response of the FADC. The width of these bins is smaller than that
117 // of the real FADC slices by a factor SUBBINS (see MFadcDefine.h):
118 //
119 if (shape_resp == 1)
120 fResponseSlicesFadc = (Int_t)(50.*fFadcSlicesPerNanosec*SUBBINS);
121 // 50 ns range
122
123 else
124 fResponseSlicesFadc = (Int_t)(7*fwhm_resp/2.35*fFadcSlicesPerNanosec*SUBBINS);
125 // 7 sigma range
126
127 sing_resp = new Float_t[fResponseSlicesFadc];
128 sing_resp_outer = new Float_t[fResponseSlicesFadc];
129
130 sing_resp_lowgain = new Float_t[fResponseSlicesFadc];
131 sing_resp_outer_lowgain = new Float_t[fResponseSlicesFadc];
132
133
134 // Parameters for real pulse shaped as measured with the Pulpo device:
135 fPulseParameters[0] = 2.066;
136 fPulseParameters[1] = 1.568;
137 fPulseParameters[2] = 3; // This will set the peak of the pulse at x ~ 3*3.3 = 10 ns
138 // It is just a safe value so that the pulse is well contained.
139 fPulseParameters[3] = 0.00282;
140 fPulseParameters[4] = 0.04093;
141 fPulseParameters[5] = 0.2411;
142 fPulseParameters[6] = -0.009442;
143
144 // Now for the low gain:
145 fPulseParametersLG[0] = 6.88031e-01;
146 fPulseParametersLG[1] = 1.19492e+00;
147 fPulseParametersLG[2] = 3.; // Same as above
148 fPulseParametersLG[3] = 8.10590e-03;
149 fPulseParametersLG[4] = 1.92851e-01;
150 fPulseParametersLG[5] = 3.30315e-01;
151 fPulseParametersLG[6] = 1.12980e-03;
152
153 Int_t i ;
154
155 Float_t sigma ;
156 Float_t x, x0 ;
157 Float_t dX, dX2 ;
158
159 Float_t response_sum_inner, response_sum_outer;
160 Float_t response_sum_inner_LG, response_sum_outer_LG;
161
162 response_sum_inner = 0.;
163 response_sum_outer = 0.;
164 response_sum_inner_LG = 0.;
165 response_sum_outer_LG = 0.;
166
167 dX = 1. / fFadcSlicesPerNanosec / SUBBINS ; // Units: ns
168 dX2 = dX/2. ;
169
170 switch(shape_resp){
171
172 case 0:
173 sigma = fwhm_resp / 2.35 ;
174 x0 = 3*sigma;
175 fadc_time_offset = trigger_delay-x0; // ns
176
177 for (i = 0; i < fResponseSlicesFadc ; i++ )
178 {
179 x = i * dX + dX2 ;
180
181 sing_resp[i] = (Float_t)(expf(-0.5*(x-x0)*(x-x0)/(sigma*sigma)));
182 sing_resp_lowgain[i] = sing_resp[i];
183
184 // Use the same pulse for high and low gain in case of gaussian shape
185 // FIXME: it would be nice to be able to choose a different shape for
186 // high and low gain:
187 response_sum_inner += sing_resp[i];
188 response_sum_inner_LG += sing_resp_lowgain[i];
189 }
190
191 break;
192 case 1:
193 float p0,p1,p2,p3,p4,p5,p6;
194 float d;
195 float zed_slices;
196 // Parameters values extracted from fitting a real FADC response
197 // gaussian electronic pulse passed through the whole chain from
198 // transmitter boards to FADC.
199 p0 = fPulseParameters[0];
200 p1 = fPulseParameters[1];
201 p2 = fPulseParameters[2];
202 p3 = fPulseParameters[3];
203 p4 = fPulseParameters[4];
204 p5 = fPulseParameters[5];
205 p6 = fPulseParameters[6];
206
207 float p0_LG, p1_LG, p2_LG, p3_LG, p4_LG, p5_LG, p6_LG;
208 p0_LG = fPulseParametersLG[0];
209 p1_LG = fPulseParametersLG[1];
210 p2_LG = fPulseParametersLG[2];
211 p3_LG = fPulseParametersLG[3];
212 p4_LG = fPulseParametersLG[4];
213 p5_LG = fPulseParametersLG[5];
214 p6_LG = fPulseParametersLG[6];
215
216
217 // Now define the time before trigger to read FADC signal when it
218 // has to be written. Here FADC_SLICES_PER_NSEC (=0.3) is the value
219 // for the 300 MHz MAGIC FADCs and must NOT be changed, even if you
220 // use a faster sampling in the simulation (through the input card
221 // command "fadc_GHz"), because this is just a conversion of units. The
222 // parameters of the "pulpo" pulse shape were obtained with the 300 MHz
223 // FADC and so we convert the time parameter to units of 3.3 ns slices
224 // just to use the provided parametrization, and no matter what sampling
225 // frequency we are simulating!
226
227 fadc_time_offset = trigger_delay - p2 / FADC_SLICES_PER_NSEC; // ns
228
229 for (i=0; i< fResponseSlicesFadc ; i++ )
230 {
231 x = i * dX + dX2;
232
233 // x has to be converted from ns to units FADC slices of the default
234 // FADC of 300 MHz (these are just units, and must be these even if you
235 // are using another sampling frequency!):
236 //
237 zed_slices = x * FADC_SLICES_PER_NSEC - p2;
238 d = (zed_slices>0)? 0.5 : -0.5;
239
240 sing_resp[i] = (Float_t) (p0*exp(-p1*(exp(-p1*zed_slices)+zed_slices))+
241 p3+p4*exp(-p1*(exp(-p1*zed_slices)+
242 p5*zed_slices))+p6*d);
243
244 zed_slices = x * FADC_SLICES_PER_NSEC - p2_LG;
245 d = (zed_slices>0)? 0.5 : -0.5;
246 sing_resp_lowgain[i] = (Float_t) (p0_LG*exp(-p1_LG*(exp(-p1_LG*zed_slices)+zed_slices))+
247 p3+p4*exp(-p1_LG*(exp(-p1_LG*zed_slices)+
248 p5*zed_slices))+p6*d);
249
250 response_sum_inner += sing_resp[i];
251 response_sum_inner_LG += sing_resp_lowgain[i];
252 }
253
254 break;
255 default:
256 cout<<"[MFadc] MFadc::MFadc : Shape of FADC pulse for inner pixel unknown."
257 <<endl;
258 cout<<"[MFadc] MFadc::MFadc : Exiting Camera ..."
259 <<endl;
260 exit(1);
261 }
262
263 // Response for outer pixels
264
265 switch(shape_resp_outer){
266
267 case 0:
268 sigma = fwhm_resp_outer / 2.35 ;
269 x0 = 3*sigma ;
270 fadc_time_offset = trigger_delay-x0; // ns
271
272 for (i = 0; i < fResponseSlicesFadc ; i++ )
273 {
274 x = i * dX + dX2 ;
275
276 //
277 // the value 1/sqrt(2*Pi*sigma^2) was introduced to normalize
278 // the area at the input value After this, the integral
279 // of the response will be integ_resp.
280 //
281 sing_resp_outer[i] = (Float_t) (expf(-0.5 * (x-x0)*(x-x0) /
282 (sigma*sigma)) ) ;
283 response_sum_outer += sing_resp_outer[i];
284 }
285 break;
286 case 1:
287 float p0,p1,p2,p3,p4,p5,p6;
288 float d;
289 float zed_slices;
290 // Parameters values extracted from fitting a real FADC response
291 // gaussian electronic pulse passed through the whole chain from
292 // transmitter boards to FADC.
293
294 p0 = fPulseParameters[0];
295 p1 = fPulseParameters[1];
296 p2 = fPulseParameters[2];
297 p3 = fPulseParameters[3];
298 p4 = fPulseParameters[4];
299 p5 = fPulseParameters[5];
300 p6 = fPulseParameters[6];
301
302 float p0_LG, p1_LG, p2_LG, p3_LG, p4_LG, p5_LG, p6_LG;
303 p0_LG = fPulseParametersLG[0];
304 p1_LG = fPulseParametersLG[1];
305 p2_LG = fPulseParametersLG[2];
306 p3_LG = fPulseParametersLG[3];
307 p4_LG = fPulseParametersLG[4];
308 p5_LG = fPulseParametersLG[5];
309 p6_LG = fPulseParametersLG[6];
310
311 // Now define the time before trigger to read FADC signal when it
312 // has to be written. Here FADC_SLICES_PER_NSEC (=0.3) is the value
313 // for the 300 MHz MAGIC FADCs and must NOT be changed, even if you
314 // use a faster sampling in the simulation (through the input card
315 // command "fadc_GHz"), because this is just a conversion of units. The
316 // parameters of the "pulpo" pulse shape were obtained with the 300 MHz
317 // FADC and so we convert the time parameter to units of 3.3 ns slices
318 // just to use the provided parametrization, and no matter what sampling
319 // frequency we are simulating!
320
321 fadc_time_offset = trigger_delay - p2 / FADC_SLICES_PER_NSEC; // ns
322
323 for (i=0; i< fResponseSlicesFadc ; i++ )
324 {
325 x = i * dX + dX2;
326
327 // x has to be converted from ns to units FADC slices of the default
328 // FADC of 300 MHz (these are just units, and must be these even if you
329 // are using another sampling frequency!):
330 //
331 zed_slices = x * FADC_SLICES_PER_NSEC - p2;
332 d = (zed_slices>0)? 0.5 : -0.5;
333
334 sing_resp_outer[i] = (Float_t) (p0*exp(-p1*(exp(-p1*zed_slices)+
335 zed_slices))+p3+
336 p4*exp(-p1*(exp(-p1*zed_slices)+
337 p5*zed_slices))+p6*d);
338
339 zed_slices = x * FADC_SLICES_PER_NSEC - p2_LG;
340 d = (zed_slices>0)? 0.5 : -0.5;
341 sing_resp_outer_lowgain[i] = (Float_t) (p0_LG*exp(-p1_LG*(exp(-p1_LG*zed_slices)+zed_slices))+
342 p3+p4*exp(-p1_LG*(exp(-p1_LG*zed_slices)+
343 p5*zed_slices))+p6*d);
344
345 response_sum_outer += sing_resp_outer[i];
346 response_sum_outer_LG += sing_resp_outer_lowgain[i];
347 }
348 break;
349 default:
350 cout<<"[MFadc] MFadc::MFadc : Shape of FADC pulse for inner pixel unknown."
351 <<endl;
352 cout<<"[MFadc] MFadc::MFadc : Exiting Camera ..."
353 <<endl;
354 exit(1);
355 }
356
357 //
358 // Normalize responses to values set through input card: (= set gain of electronic chain)
359 // Take into account that only 1 of every SUBBINS bins of sing_resp[] will be "sampled" by
360 // the FADC, so we have to correct for this to get the right "FADC integral" (=integ_resp)
361 // per photoelectron:
362 //
363
364 for (i = 0; i < fResponseSlicesFadc ; i++ )
365 {
366 sing_resp[i] *= integ_resp / response_sum_inner * SUBBINS;
367 sing_resp_outer[i] *= integ_resp_outer / response_sum_outer * SUBBINS;
368
369 // The low gain will be further scaled down later; for now we normalize it with to same
370 // integral as the high gain.
371 sing_resp_lowgain[i] *= integ_resp / response_sum_inner_LG * SUBBINS;
372 sing_resp_outer_lowgain[i] *= integ_resp_outer / response_sum_outer_LG * SUBBINS;
373 }
374
375 //
376 // init the Random Generator for Electronic Noise
377 //
378
379 GenElec = new TRandom () ;
380
381 Reset();
382
383 //
384 // set all pedestals to 0
385 //
386
387 for ( i =0 ; i <CAMERA_PIXELS ; i++ ) {
388 pedestal[i] = 0.0 ;
389 }
390
391 cout<<" end of MFadc::MFadc()"<<endl;
392}
393
394void MFadc::Reset() {
395 //
396 // set all values of the signals to zero
397 // set the values of FADC slices that would be read after trigger to zero
398 //
399 memset(used, 0, CAMERA_PIXELS*sizeof(Bool_t));
400
401 for (Int_t i = 0; i < CAMERA_PIXELS; i++)
402 {
403 memset(output[i], 0, fFadcSlices*sizeof(Float_t));
404 memset(output_lowgain[i], 0, fFadcSlices*sizeof(Float_t));
405 }
406
407 //
408
409 //
410 for (Int_t i = 0; i < CAMERA_PIXELS; i++)
411 {
412 memset(sig[i], 0, (Int_t)(fSlices_mFadc*sizeof(Float_t))); // Added 15 01 2004, AM
413 memset(sig_LG[i], 0, (Int_t)(fSlices_mFadc*sizeof(Float_t))); // Added 01 03 2005, AM
414 }
415}
416void MFadc::Fill( Int_t iPix, Float_t time,
417 Float_t amplitude, Int_t isinner ) {
418
419 // AM, Jan 2004 : added delay to shift the signal peak to the desired
420 // range in the FADC window (indicated through the trigger_delay command
421 // in the camera input card.
422
423 time += fadc_time_offset;
424
425 if(isinner)
426 Fill(iPix, time, amplitude);
427 else
428 FillOuter(iPix, time, amplitude);
429
430}
431void MFadc::Fill( Int_t iPix, Float_t time, Float_t amplitude ) {
432
433 //
434 // fills the information about one single Phe in the Trigger class
435 //
436 // Parameters are the number of the pixel and the time-difference to the
437 // first photon.
438 //
439 //
440 // AM, Jan 2004: Replaced former FADC simulation (integration of signal)
441 // with a more realistic one (measuring signal height at discrete points).
442 //
443
444
445 Int_t i, ichan, ichanfadc ;
446
447 //
448 // first we have to check if the pixel iPix is used or not until now
449 // if this is the first use, reset all signal for that pixel
450 //
451 if ( iPix > numpix )
452 {
453 cout << " WARNING: MFadc::Fill() : iPix greater than Pixels in Camera = "
454 << numpix
455 << endl;
456 exit(987);
457 }
458
459 if ( used[iPix] == FALSE )
460 {
461 used [iPix] = TRUE;
462
463 for (i=0; i < (Int_t) fSlices_mFadc; i++ )
464 {
465 sig[iPix][i] = 0.;
466 sig_LG[iPix][i] = 0.;
467 }
468 }
469
470 //
471 // then select the time slice to use (ichan)
472 //
473
474 if ( time < TOTAL_TRIGGER_TIME+fadc_time_offset ) {
475 //
476 // Convert time into units of the width of the analog
477 // signal histogram, sing_resp:
478 //
479 ichan = (Int_t) ( time * fFadcSlicesPerNanosec * SUBBINS);
480
481 //
482 // putting the response slices in the right sig slices.
483 // Be careful, because both slices have different widths.
484 //
485
486 // We want to put the single phe response given by sing_resp into the
487 // array sig[][], but only one of each SUBBINS bins, since the binning
488 // of sing_resp is finer than that of sig[][]. We want that the start of
489 // sing_resp coincides with the time "time" with respect to the begining
490 // of sig[][]
491
492 // We take the pulse height in the middle of FADC slices, we start in the
493 // first such point after the time "time" (=ichan in response bins). Each
494 // FADC slice corresponds to SUBBINS response bins (SUBBINS=5 by default).
495
496 Int_t first_i = Int_t(SUBBINS/2) - ichan%(Int_t)SUBBINS;
497 first_i = first_i < 0 ? (Int_t)SUBBINS+first_i : first_i; //
498 //
499 // first_i is the first bin of sing_resp which matches the center of one
500 // bin of sig[][]
501 //
502
503 for ( i = first_i ; i < (Int_t)fResponseSlicesFadc; i += (Int_t)SUBBINS)
504 {
505 ichanfadc = (Int_t) ((ichan+i)/SUBBINS) ;
506 if ( ichanfadc < 0 )
507 continue;
508
509 //
510 // fSlices_mFadc is by default 48. sig[][] is not the final FADC output; that
511 // will be later filled (from sig[][]) in MFadc::TriggeredFadc()
512 //
513 if ( (ichanfadc) < (Int_t) fSlices_mFadc )
514 {
515 sig[iPix][ichanfadc] += (amplitude * sing_resp[i] );
516 sig_LG[iPix][ichanfadc] += (amplitude * sing_resp_lowgain[i] );
517 }
518 }
519 }
520 else
521 cout << " WARNING! Fadc::Fill " << time << " out of TriggerTimeRange "
522 << TOTAL_TRIGGER_TIME+fadc_time_offset << endl ;
523
524}
525
526void MFadc::FillOuter( Int_t iPix, Float_t time, Float_t amplitude ) {
527
528 //
529 // fills the information about one single Phe in the Trigger class
530 // for an outer pixel
531 //
532 // See explanations of the code in function Fill() above
533 //
534
535 Int_t i, ichan, ichanfadc ;
536
537 if ( iPix > numpix )
538 {
539 cout << " WARNING: MFadc::FillOuter() : iPix greater than CAMERA_PIXELS"
540 << endl ;
541 exit(987) ;
542 }
543
544 if ( used[iPix] == FALSE )
545 {
546 used [iPix] = TRUE ;
547
548 for (i=0; i < (Int_t) fSlices_mFadc; i++)
549 {
550 sig[iPix][i] = 0.;
551 sig_LG[iPix][i] = 0.;
552 }
553 }
554
555
556 if ( time < TOTAL_TRIGGER_TIME+fadc_time_offset ) {
557
558 ichan = (Int_t) ( time * fFadcSlicesPerNanosec * SUBBINS);
559
560 Int_t first_i = Int_t(SUBBINS/2) - ichan%(Int_t)SUBBINS;
561 first_i = first_i < 0 ? (Int_t)SUBBINS+first_i : first_i;
562
563 for ( i = first_i ; i < (Int_t)fResponseSlicesFadc; i += (Int_t)SUBBINS)
564 {
565 ichanfadc = (Int_t) ((ichan+i)/SUBBINS);
566
567 if ( ichanfadc < 0 )
568 continue;
569
570 if ( (ichanfadc) < (Int_t)fSlices_mFadc )
571 {
572 sig[iPix][ichanfadc] += (amplitude * sing_resp_outer[i] );
573 sig_LG[iPix][ichanfadc] += (amplitude * sing_resp_outer_lowgain[i] );
574 }
575
576 }
577
578 }
579 else {
580 cout << " WARNING! Fadc::FillOuter " << time << " out of TriggerTimeRange "
581 << TOTAL_TRIGGER_TIME+fadc_time_offset << endl ;
582 }
583
584}
585
586void MFadc::AddSignal( Int_t iPix, Float_t *resp) {
587
588 //
589 // Adds signals to the fadc reponse from a given array
590 // Parameters are the number of the pixel and the values to be added
591 // With add the signal equally to the high and low gain branch. The low
592 // gain branch is not yet scaled down!!
593 //
594
595 Int_t i ;
596
597 //
598 // first we have to check if the pixel iPix is used or not until now
599 // if this is the first use, reset all signal for that pixels
600 //
601 if ( iPix > numpix )
602 {
603 cout << " WARNING: MFadc::Fill() : iPix greater than CAMERA_PIXELS"
604 << endl ;
605 exit(987) ;
606 }
607
608 if ( used[iPix] == FALSE )
609 {
610 used [iPix] = TRUE ;
611
612 for (i=0; i < (Int_t)fSlices_mFadc; i++ )
613 {
614 sig[iPix][i] = 0. ;
615 sig_LG[iPix][i] = 0. ;
616 }
617 }
618 for ( i = 0 ; i<(Int_t)fSlices_mFadc; i++ )
619 {
620 sig[iPix][i] += resp[i] ;
621 sig_LG[iPix][i] += resp[i] ;
622 }
623
624}
625
626void MFadc::SetPedestals( Int_t ped) {
627 // It sets pedestal for each pixel flat randomly dstributed between 0 and ped
628 // It uses the instance of TRandom GenElec.
629
630 Int_t i;
631
632 for(i=0;i<numpix;i++){
633 pedestal[i]= (Float_t)(ped* GenElec->Rndm());
634 }
635}
636
637void MFadc::SetPedestals( Float_t *ped) {
638 // It sets pedestal for each pixel from ped array
639
640 Int_t i;
641
642 for(i=0;i<numpix;i++){
643 pedestal[i]= ped[i];
644 }
645}
646
647
648void MFadc::Pedestals(){
649 //
650 // It shifts the FADC contents their pedestal values
651 // It shifts the values in the analog signal,
652 // therefore it has to be done before getting FADC output
653 //
654
655 Int_t i, j;
656
657 for(i=0;i<numpix;i++)
658 for(j=0;j<(Int_t)fSlices_mFadc;j++)
659 {
660 sig[i][j] += pedestal[i];
661 sig_LG[i][j] += pedestal[i];
662 }
663
664 //
665 // AM 15 01 2003: Formerly the above operation was performed only
666 // for pixels in which used[] was true. But to run camera with no noise
667 // and get the right baseline on the pixels with no C-photons, we have
668 // to do it for all pixels.
669 //
670}
671
672
673void MFadc::SetElecNoise(Float_t value1, Float_t value2, UInt_t n_in_pix){
674
675 UInt_t i;
676
677 fInnerPixelsNum = n_in_pix;
678
679 cout<<"MFadc::SetElecNoise ... generating database for electronic noise."
680 <<endl;
681
682 for (i=0;i<(UInt_t (fSlices_mFadc))*1001;i++){
683 noise[i]=GenElec->Gaus(0., value1 );
684 noise_outer[i]=GenElec->Gaus(0., value2 );
685 }
686
687 cout<<"MFadc::SetElecNoise ... done"<<endl;
688
689}
690
691void MFadc::ElecNoise() {
692 // ============================================================
693 //
694 // adds the noise due to optronics and electronics
695 // to the signal. This is noise which comes before the FADC,
696 // so it will be later scaled down in the low gain branch, if
697 // the switch to low gain occurs.
698 //
699 UInt_t startslice;
700
701 for ( Int_t i = 0 ; i < numpix; i++) {
702 //
703 // but at the beginning we must check if this pixel is
704 // hitted the first time
705 //
706
707 startslice = GenElec->Integer(((Int_t)fSlices_mFadc)*1000);
708
709 if ( used[i] == FALSE )
710 {
711 used [i] = TRUE ;
712 if (i < fInnerPixelsNum)
713 {
714 memcpy( (Float_t*)&sig[i][0],
715 (Float_t*)&noise[startslice],
716 ((Int_t) fSlices_mFadc)*sizeof(Float_t));
717 memcpy( (Float_t*)&sig_LG[i][0],
718 (Float_t*)&noise[startslice],
719 ((Int_t) fSlices_mFadc)*sizeof(Float_t));
720 }
721
722 else
723 {
724 memcpy( (Float_t*)&sig[i][0],
725 (Float_t*)&noise_outer[startslice],
726 ((Int_t) fSlices_mFadc)*sizeof(Float_t));
727 memcpy( (Float_t*)&sig_LG[i][0],
728 (Float_t*)&noise_outer[startslice],
729 ((Int_t) fSlices_mFadc)*sizeof(Float_t));
730 }
731 }
732
733 //
734 // If pixel already in use, the noise is added each time slice
735 //
736 else
737 {
738 if (i < fInnerPixelsNum)
739 for ( Int_t is = 0 ; is < (Int_t)fSlices_mFadc ; is++ )
740 {
741 sig[i][is] += noise[startslice+is];
742 sig_LG[i][is] += noise[startslice+is];
743 }
744 else
745 for ( Int_t is = 0 ; is < (Int_t)fSlices_mFadc ; is++ )
746 {
747 sig[i][is] += noise_outer[startslice+is];
748 sig_LG[i][is] += noise_outer[startslice+is];
749 }
750 }
751 }
752}
753
754void MFadc::SetDigitalNoise(Float_t value){
755
756 UInt_t i;
757 Float_t xrdm;
758
759 cout<<"MFadc::SetDigitalNoise ... generating database for electronic noise."
760 <<endl;
761
762 for (i=0;i<UInt_t(fSlices_mFadc*1001);i++){
763 xrdm=GenElec->Gaus(0., value);
764 digital_noise[i]=(xrdm>0?Int_t(xrdm+0.5):Int_t(xrdm-0.5));
765 }
766
767 cout<<"MFadc::SetDigitalNoise ... done"<<endl;
768
769}
770
771void MFadc::DigitalNoise() {
772 // ============================================================
773 //
774 // adds the noise due to FADC electronics to the signal. This
775 // noise affects equally the high and low gain branches, that is,
776 // it is not scaled down in the low gain branch.
777 //
778 UInt_t startslice;
779
780 for ( Int_t i = 0 ; i < numpix; i++)
781 {
782 if ( used[i] == FALSE )
783 continue;
784
785 startslice=GenElec->Integer((Int_t) fSlices_mFadc*999);
786 //
787 // Then the noise is introduced for each time slice
788 //
789 for ( Int_t is = 0 ; is < fFadcSlices; is++ )
790 {
791 output[i][is] += digital_noise[startslice+is];
792 output_lowgain[i][is] += digital_noise[startslice+fFadcSlices+is];
793 }
794 }
795}
796
797void MFadc::Scan() {
798
799
800 for ( Int_t ip=0; ip<numpix; ip++ ) {
801
802 if ( used[ip] == kTRUE ) {
803
804 printf ("Pid %3d", ip ) ;
805
806 for ( Int_t is=0 ; is < (Int_t)fSlices_mFadc; is++ ) {
807
808 if ( sig[ip][is] > 0. ) {
809 printf (" %4.1f/", sig[ip][is] ) ;
810 }
811 else {
812 printf ("----/" ) ;
813 }
814 }
815
816 printf ("\n");
817
818 }
819 }
820
821}
822
823void MFadc::Scan(Float_t time) {
824
825 //
826 // first of all we subtract from the time a offset (8 ns)
827 //
828
829 Float_t t ;
830
831 (0 > time - TIME_BEFORE_TRIGGER)? t=fadc_time_offset: t=(time-TIME_BEFORE_TRIGGER+fadc_time_offset) ; // to show also the start of the pulse before the trigger time
832
833 if ( t < 0. ) {
834 cout << " WARNING!! FROM MFADC::SCAN(t) " << endl ;
835 exit (776) ;
836 }
837
838 //
839 // calculate the first slice to write out
840 //
841
842 Int_t iFirstSlice ;
843
844 iFirstSlice = (Int_t) ( t * fFadcSlicesPerNanosec ) ;
845
846 for ( Int_t ip=0; ip<numpix; ip++ ) {
847
848 if ( used[ip] == kTRUE ) {
849
850 printf ("Pid %3d", ip ) ;
851
852 for ( Int_t is=iFirstSlice ; is < (iFirstSlice+15); is++ ) {
853 printf (" %5.2f /", sig[ip][is] ) ;
854 }
855
856 printf ("\n");
857
858 }
859 }
860}
861
862void MFadc::GetResponse( Float_t *resp ) {
863 // ============================================================
864 //
865 // puts the standard response function into the array resp
866
867 for ( Int_t i=0; i< fResponseSlicesFadc; i++ )
868 resp[i] = sing_resp[i];
869
870}
871
872void MFadc::GetPedestals( Float_t *offset) {
873 // ============================================================
874 //
875 // puts the pedestal values into the array offset
876
877 for ( Int_t i=0; i< numpix; i++ ) {
878
879 offset[i] = pedestal[i] ;
880 }
881}
882
883//===========================================================================
884//
885// Next function adds up the noise in pixel "pix", scaling down the part
886// of it which comes from before the receivers in the case we are dealing with
887// low gain (ishigh=0). The output is the sum of the readouts of a number
888// n_slices of FADC slices. For the case of low gain, the FADC contents we add
889// are not what we would have in a real pedestal event, but nevertheless this
890// is useful in the camera simulation to obtain what the pedestal fluctuations
891// are for the low gain. This will be written to the camera output, in the
892// MMcFadcHeader.
893//
894Float_t MFadc::AddNoiseInSlices( Int_t pix, Int_t ishigh, Int_t n_slices) {
895
896 Float_t sum = 0;
897 Float_t fvalue = 0.;
898 UChar_t value = 0;
899 UInt_t startslice;
900
901 //
902 // Get at random a point in the FADC presimulated digital noise:
903 //
904 startslice=GenElec->Integer((Int_t) fSlices_mFadc*999);
905
906 for ( Int_t is=0; is < n_slices ; is++ )
907 {
908 if (ishigh)
909 fvalue = sig[pix][is];
910 else
911 // If we deal with low gain, we have to scale the values in sig_LG[][] by
912 // the gain ratio (high2low_gain), since "sig_LG" contains at this point the
913 // noise produced before the receiver boards (for instance NSB noise).
914 //
915 fvalue = pedestal[pix]+(sig_LG[pix][is]-pedestal[pix]) / high2low_gain;
916
917 fvalue += digital_noise[startslice+is]; // We add the noise intrinsic to FADC
918
919 fvalue = fvalue < 0? fvalue-0.5 : fvalue+0.5;
920
921 value = fvalue < 0.? (UChar_t) 0 :
922 (fvalue > 255.? 255 : (UChar_t) fvalue);
923
924 // Add up slices:
925 sum += value - pedestal[pix];
926 }
927
928 return sum;
929}
930
931//=======================================================================
932
933void MFadc::TriggeredFadc(Float_t time) {
934
935 //
936 // Here the slices to write out are calculated. Warning: the digitalization
937 // is NOT done here (it is already done in MFadc::Fill). This procedure only
938 // selects which FADC slices to write out, out of those contained in the sig[][]
939 // and sig_LG[][] arrays.
940 //
941
942 //
943 // calculate the first slice to write out, according to trigger time:
944 //
945
946 Int_t iFirstSlice ;
947 Int_t i;
948
949 //
950 // We had 0.5 for the correct rounding:
951 //
952 iFirstSlice = (Int_t) ( 0.5 + time * fFadcSlicesPerNanosec ) ;
953
954 for ( Int_t ip = 0; ip < numpix; ip++ )
955 {
956
957 if ( used[ip] == kFALSE)
958 // Pixels with no C-photons, in the case that camera is being run with
959 // no noise (nor NSB neither electronic). We then set the mean pedestal as
960 // signal, since when analyzing the camera output file, MARS will subtract
961 // it anyway!
962 {
963 for ( Int_t i=0 ; i < fFadcSlices ; i++ )
964 {
965 output[ip][i] = pedestal[ip];
966 output_lowgain[ip][i] = pedestal[ip];
967 }
968 continue;
969 }
970
971
972 // First put the high gain in the output slices:
973 i = 0;
974 Int_t switch_i = 0;
975 for ( Int_t is = iFirstSlice; is < (iFirstSlice+fFadcSlices); is++ )
976 {
977 if (is < (Int_t)fSlices_mFadc)
978 {
979 output[ip][i] = sig[ip][is];
980
981 if (switch_i == 0) // Hi gain limit not yet surpassed before.
982 {
983 if (output[ip][i] > fGainSwitchAmp)
984 switch_i = i + fShiftFromSwitch2LowGain;
985 }
986 }
987
988 else // We are beyond the simulated signal history in sig[][]! Put just mean pedestal!
989 output[ip][i] = pedestal[ip];
990
991 i++;
992 }
993
994 // Now put the low gain:
995 // FIXME: for now, the shift between the high and low gain peaks has to be an integer number
996 // of FADC slices. But in the data the shift is ~16.5 slices. This has to be implemented.
997 i=0;
998 for ( Int_t is = iFirstSlice; is < (iFirstSlice+fFadcSlices); is++ )
999 {
1000 if (is < (Int_t)fSlices_mFadc)
1001 {
1002 if (switch_i > 0 && (i+fFadcSlices) >= switch_i)
1003 output_lowgain[ip][i] = pedestal[ip] +
1004 (sig_LG[ip][is-(fHi2LoGainPeak-fFadcSlices)]-pedestal[ip])/high2low_gain;
1005 // Once the shift occurs, low gain is filled with the high
1006 // gain signal scaled down by the factor high2low_gain
1007
1008 else
1009 output_lowgain[ip][i] = sig[ip][is+fFadcSlices];
1010 // Write out high gain into low gain slices if there was no
1011 // switch, or before the switch occurs.
1012 }
1013
1014 else // We are beyond the simulated signal history in sig[][]! Put just mean pedestal!
1015 {
1016 output_lowgain[ip][i] = pedestal[ip];
1017 }
1018 i++;
1019 }
1020
1021 }
1022}
1023
1024
1025void MFadc::ShowSignal (MMcEvt *McEvt, Float_t trigTime) {
1026 // ============================================================
1027 //
1028 // This method is used to book the histogram to show the signal in
1029 // a special gui frame (class MGTriggerSignal). After the look onto the
1030 // signals for a better understanding of the things we will expect
1031 // the gui frame and all histogramms will be destroyed.
1032 //
1033
1034 //
1035 // first of all create a list of the histograms to show
1036 //
1037 // take only that one with a entry
1038
1039 TH1F *hist ;
1040 Char_t dumm[10];
1041 Char_t name[256];
1042
1043 TObjArray *AList ;
1044 AList = new TObjArray(10) ;
1045
1046 // the list of analog signal histograms
1047 // at the beginning we initalise 10 elements
1048 // but this array expand automatically if neccessay
1049
1050 Int_t ic = 0 ;
1051 for ( Int_t i=0 ; i < numpix; i++ ) {
1052 if ( used [i] == TRUE ) {
1053
1054 sprintf (dumm, "FADC_%d", i ) ;
1055 sprintf (name, "fadc signal %d", i ) ;
1056
1057 hist = new TH1F(dumm, name, (Int_t)fSlices_mFadc, fadc_time_offset, TOTAL_TRIGGER_TIME+fadc_time_offset);
1058 //
1059 // fill the histogram
1060 //
1061
1062 for (Int_t ibin = 1; ibin <= (Int_t)fSlices_mFadc; ibin++)
1063 hist->SetBinContent (ibin, sig[i][ibin-1]);
1064
1065
1066 // hist->SetMaximum( 5.);
1067 // hist->SetMinimum(-10.);
1068 hist->SetStats(kFALSE);
1069
1070 // hist->SetAxisRange(0., 80. ) ;
1071
1072 AList->Add(hist) ;
1073
1074 ic++ ;
1075 }
1076 }
1077
1078 //
1079 // create the Gui Tool
1080 //
1081 //
1082
1083 new MGFadcSignal(McEvt,
1084 AList,
1085 trigTime,
1086 gClient->GetRoot(),
1087 gClient->GetRoot(),
1088 400, 400 ) ;
1089
1090 //
1091 // delete the List of histogramms
1092 //
1093 AList->Delete() ;
1094
1095 delete AList ;
1096}
1097
1098UChar_t MFadc::GetFadcSignal(Int_t pixel, Int_t slice){
1099
1100 // It returns the analog signal for a given pixel and a given FADC
1101 // time slice which would be read.
1102
1103 // Since May 1 2004, we do the rounding and the truncation to the range
1104 // 0-255 counts here. (A. Moralejo)
1105
1106 Float_t out = output[pixel][slice] > 0. ?
1107 output[pixel][slice]+0.5 : output[pixel][slice]-0.5;
1108 // (add or subtract 0.5 for correct rounding)
1109
1110 return (out < 0.? (UChar_t) 0 :
1111 (out > 255.? (UChar_t) 255 :
1112 (UChar_t) out));
1113}
1114
1115
1116UChar_t MFadc::GetFadcLowGainSignal(Int_t pixel, Int_t slice){
1117
1118 // It returns the analog signal for a given pixel and a given FADC
1119 // time slice which would be read. Same comment as above.
1120
1121 Float_t outlow = output_lowgain[pixel][slice] > 0. ?
1122 output_lowgain[pixel][slice]+0.5 :
1123 output_lowgain[pixel][slice]-0.5;
1124 // (add or subtract 0.5 for correct rounding)
1125
1126 return (outlow < 0.? (UChar_t) 0 :
1127 (outlow > 255.? (UChar_t) 255 :
1128 (UChar_t) outlow));
1129}
1130
1131
1132
Note: See TracBrowser for help on using the repository browser.