source: trunk/MagicSoft/Simulation/Detector/include-MTrigger/MTrigger.cxx@ 5258

Last change on this file since 5258 was 5248, checked in by moralejo, 21 years ago
*** empty log message ***
File size: 44.0 KB
Line 
1/////////////////////////////////////////////////////////////////
2//
3// MTrigger
4//
5//
6#include "MTrigger.hxx"
7
8#include "TROOT.h"
9#include "TFile.h"
10#include "TH1.h"
11#include "TObjArray.h"
12#include "MGTriggerSignal.hxx"
13#include "MGeomCam.h"
14#include "MGeomPix.h"
15
16using namespace std;
17
18MTrigger::MTrigger(int pix) {
19 // ============================================================
20 //
21 // default constructor
22 //
23 // The procedure is the following:
24 //
25 // 1. Allocation of some memory needed
26 // 2. some parameters of the trigger are set to default.
27 // 3. if a File MTrigger.card exists in the current directory,
28 // this parameters of the trigger may be changed
29 // 4. Then the all signals are set to zero
30
31 FILE *unit_mtrig ;
32 Int_t endflag = 1 ;
33 Int_t bthresholdpixel = FALSE;
34 char datac[256] ;
35 char dummy[50] ;
36 char input_thres[50];
37 Int_t i, ii ;
38
39 Float_t threshold ;
40
41 // Number of pixels in the trigger region
42 pixnum=pix;
43
44 //
45 // allocate the memory for the 2dim arrays (a_sig, d_sig )
46 //
47
48 used = new Bool_t[pix];
49 nphotshow = new Int_t[pix];
50 nphotnsb = new Int_t[pix];
51 nphotstar = new Int_t[pix];
52 a_sig = new Float_t * [pix];
53 d_sig = new Float_t * [pix];
54 baseline = new Float_t[pix];
55 dknt = new Bool_t[pix];
56 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
57 chan_thres = new Float_t[pix];
58 for(Int_t j=0;j<6;j++)
59 NN[j] = new Int_t[pix];
60 for(Int_t j=0;j<TRIGGER_CELLS;j++)
61 TC[j] = new Int_t[pix];
62
63 for( Int_t j=0; j<pix; j++ ) {
64
65 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
66
67 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
68 }
69
70
71
72 //
73 // set the values for the standard response pulse
74 //
75
76 fwhm_resp = RESPONSE_FWHM ;
77 ampl_resp = RESPONSE_AMPLITUDE ;
78
79 overlaping_time = TRIGGER_OVERLAPING;
80
81 threshold = CHANNEL_THRESHOLD ;
82
83
84 gate_leng = TRIGGER_GATE ;
85 trigger_multi = TRIGGER_MULTI ;
86 trigger_geometry = TRIGGER_GEOM ;
87
88 //
89 // check if the file MTrigger.card exists
90 //
91
92 if ( (unit_mtrig = fopen ("MTrigger.card", "r")) != 0 ) {
93 cout << "[MTrigger] use the values from MTrigger.card "<< endl ;
94
95 while ( endflag == 1 ) {
96 //
97 //
98 fgets (datac, 255, unit_mtrig) ;
99 // printf ("--> %s <--", datac ) ;
100
101 //
102 // now compare the line with controlcard words
103 //
104
105 if ( strncmp (datac, "channel_threshold", 17 ) == 0 ) {
106 sscanf (datac, "%s %f", dummy, &threshold ) ;
107 }
108 else if ( strncmp (datac, "gate_length", 11 ) == 0 ) {
109 sscanf (datac, "%s %f", dummy, &gate_leng ) ;
110 }
111 else if ( strncmp (datac, "response_fwhm", 13 ) == 0 ) {
112 sscanf (datac, "%s %f", dummy, &fwhm_resp ) ;
113 }
114 else if ( strncmp (datac, "response_ampl", 13 ) == 0 ) {
115 sscanf (datac, "%s %f", dummy, &ampl_resp ) ;
116 }
117 else if ( strncmp (datac, "overlaping", 10 ) == 0 ) {
118 sscanf (datac, "%s %f", dummy, &overlaping_time ) ;
119 }
120 else if ( strncmp (datac, "multiplicity", 12 ) == 0 ) {
121 sscanf (datac, "%s %f", dummy, &trigger_multi ) ;
122 }
123 else if ( strncmp (datac, "topology", 8 ) == 0 ) {
124 sscanf (datac, "%s %i", dummy, &trigger_geometry ) ;
125 }
126 else if ( strncmp (datac, "threshold_file", 14 ) == 0 ) {
127 sscanf (datac, "%s %s", dummy, input_thres ) ;
128 bthresholdpixel=kTRUE;
129 }
130
131 if ( feof(unit_mtrig) != 0 ) {
132 endflag = 0 ;
133 }
134
135 }
136
137 fclose ( unit_mtrig ) ;
138 }
139 else {
140 cout << "[MTrigger] use the standard values for MTrigger "<< endl ;
141 }
142
143 cout << endl
144 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
145 if(bthresholdpixel){
146 cout<<endl
147 << "[MTrigger] ChannelThreshold from file: "<<input_thres
148 <<endl;
149 }
150 else{
151 cout << endl
152 << "[MTrigger] ChannelThreshold: " << threshold << " mV"
153 << endl ;
154 }
155 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
156 << endl ;
157 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
158 << endl ;
159 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
160 << endl ;
161 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
162 << endl ;
163 cout << "[MTrigger] Trigger Multiplicity: " << trigger_multi << " pixels"
164 << endl ;
165 cout << "[MTrigger] Trigger Topology: " << trigger_geometry
166 << endl ;
167
168 cout << endl ;
169
170
171 //
172 // we have introduced individual thresholds for all pixels
173 //
174 FILE *unit_thres;
175
176 if (bthresholdpixel == kTRUE) {
177 if ((unit_thres=fopen(input_thres, "r"))==0){
178 cout<<"WARNING: not able to read ..."<<input_thres<<endl;
179 cout<<"Threshold will be set to "<<threshold<<" for all pixels"<<endl;
180 for (Int_t k=0; k<pix; k++ ) {
181 chan_thres[k] = threshold ;
182 }
183 }
184 else {
185 for (i=0;i<pix;i++){
186 fscanf(unit_thres, "%f",&chan_thres[i]);
187 }
188 fclose (unit_thres);
189 }
190 }
191 else {
192 for (Int_t k=0; k<pix; k++ ) {
193 chan_thres[k] = threshold ;
194 }
195 }
196
197
198 //
199 // set up the response shape
200 //
201
202 Float_t sigma ;
203 Float_t x, x0 ;
204
205 sigma = fwhm_resp / 2.35 ;
206 x0 = 3*sigma ;
207
208 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
209
210 x = i * (1./((Float_t)TRIG_SLICES_PER_NSEC))
211 + (1./( 2 * (Float_t)TRIG_SLICES_PER_NSEC )) ;
212
213 sing_resp[i] = (Float_t)
214 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
215
216 }
217
218 //
219 // look for the time between start of response function and the
220 // maximum value of the response function. This is needed by the
221 // member functions FillNSB() and FillStar()
222 //
223
224 Int_t imax = 0 ;
225 Float_t max = 0. ;
226 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
227 if ( sing_resp[i] > max ) {
228 imax = i ;
229 max = sing_resp[i] ;
230 }
231 }
232
233 peak_time = ( (Float_t) imax ) / ( (Float_t) TRIG_SLICES_PER_NSEC ) ;
234
235
236 //
237 // the amplitude of one single photo electron is not a constant.
238 // There exists a measured distribution from Razmik. This distribution
239 // is used to simulate the noise of the amplitude.
240 // For this a histogramm (histPmt) is created and filled with the
241 // values.
242 //
243
244 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
245
246 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
247 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
248 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
249 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
250 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
251
252 histMean = histPmt->GetMean() ;
253
254 for (i=0;i<41;i++){
255 histPmt->SetBinContent(i,ValRazmik[i]);
256 }
257
258 histMean = histPmt->GetMean() ;
259
260 //
261 // create the random generator for the Electronic Noise
262 //
263
264 GenElec = new TRandom() ;
265
266 GenElec->SetSeed(0);
267
268 //
269 // Read in the lookup table for NN trigger
270 //
271
272 FILE *unit ;
273 int id ;
274
275 i = 0 ;
276
277 if ( (unit = fopen("../include-MTrigger/TABLE_NEXT_NEIGHBOUR", "r" )) == 0 ) {
278 cout << "ERROR: not able to read ../include-MTrigger/TABLE_NEXT_NEIGHBOUR"
279 << endl ;
280 exit(123) ;
281 }
282 else {
283 while ( i < pix )
284 {
285 fscanf ( unit, " %d", &id ) ;
286
287 for ( Int_t k=0; k<6; k++ ) {
288 fscanf ( unit, "%d ", &NN[k][i] ) ;
289 }
290 i++ ;
291 }
292
293 fclose (unit) ;
294 }
295
296
297 //
298 // Read in the lookup table for trigger cells
299 //
300
301 i = 0 ;
302
303 if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) {
304 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
305 << endl ;
306 exit(123) ;
307 }
308 else {
309 while ( i < pix )
310 {
311 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
312 TC[k][i]=kFALSE;
313 }
314 i++ ;
315 }
316 while ( feof(unit) == 0 ) {
317 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
318 fscanf ( unit, "%d ", &i ) ;
319 if ((i-1)<pix)
320 TC[k][i-1]=kTRUE;
321 }
322 }
323 fclose (unit) ;
324 }
325
326
327 //
328 //
329 // set all the booleans used to FALSE, indicating that the pixel is not
330 // used in this event.
331 //
332
333 for ( i =0 ; i <pix ; i++ ) {
334 used [i] = kFALSE ;
335 dknt [i] = kFALSE ;
336
337 nphotshow[i] = 0 ;
338 nphotnsb [i] = 0 ;
339 nphotstar[i] = 0 ;
340
341 baseline[i] = 0 ;
342 }
343
344 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
345 sum_d_sig[ii] = 0. ;
346 }
347
348 //
349 // set the information about the Different Level Triggers to zero
350 //
351
352 nZero = nFirst = nSecond = 0 ;
353
354 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
355 SlicesZero[ii] = kFALSE;
356 }
357
358 for ( i = 0 ; i < 5 ; i++) {
359 SlicesFirst[i] = 0;
360 SlicesSecond[i] = 0;
361 PixelsFirst[i] = -1;
362 PixelsSecond[i] = -1;
363 }
364
365 cout << " end of MTrigger::MTrigger()" << endl ;
366}
367
368MTrigger::MTrigger(Int_t pix, MGeomCam *camgeom,
369 float gate, float overt, float ampl, float fwhm, int ct_id) {
370 // ============================================================
371 //
372 // constructor
373 //
374 // The procedure is the following:
375 //
376 // 1. Allocation of some memory needed
377 // 2. some parameters of the trigger are set.
378 // 3. Then the all signals are set to zero
379
380 Int_t i, ii ;
381
382 Float_t threshold ;
383
384 // Number of pixels in the trigger region
385 pixnum=pix;
386
387 //
388 // allocate the memory for the 2dim arrays (a_sig, d_sig )
389 //
390
391 used = new Bool_t[pix];
392 nphotshow = new Int_t[pix];
393 nphotnsb = new Int_t[pix];
394 nphotstar = new Int_t[pix];
395 a_sig = new Float_t * [pix];
396 d_sig = new Float_t * [pix];
397 baseline = new Float_t[pix];
398 dknt = new Bool_t[pix];
399 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
400 chan_thres = new Float_t[pix];
401 for(Int_t j=0;j<6;j++)
402 NN[j] = new Int_t[pix];
403 for(Int_t j=0;j<TRIGGER_CELLS;j++)
404 TC[j] = new Int_t[pix];
405
406 for( Int_t j=0; j<pix; j++ ) {
407
408 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
409
410 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
411 }
412
413 //
414 // set the values for the standard response pulse
415 //
416
417 fwhm_resp = fwhm ;
418 ampl_resp = ampl ;
419
420 overlaping_time = overt;
421
422
423 threshold = CHANNEL_THRESHOLD ;
424
425
426 gate_leng = gate ;
427 trigger_multi = TRIGGER_MULTI ;
428 trigger_geometry = TRIGGER_GEOM ;
429
430 cout << endl
431 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
432 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
433 << endl ;
434 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
435 << endl ;
436 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
437 << endl ;
438 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
439 << endl ;
440 cout << endl ;
441
442 for (Int_t k=0; k<pixnum; k++ ) {
443 chan_thres[k] = threshold ;
444 }
445
446 //
447 // set up the response shape
448 //
449
450 Float_t sigma ;
451 Float_t x, x0 ;
452
453 sigma = fwhm_resp / 2.35 ;
454 x0 = 3*sigma ;
455
456 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
457
458 x = i * (1./((Float_t)TRIG_SLICES_PER_NSEC))
459 + (1./( 2 * (Float_t)TRIG_SLICES_PER_NSEC )) ;
460
461 sing_resp[i] = (Float_t)
462 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
463
464 }
465
466 //
467 // look for the time between start of response function and the
468 // maximum value of the response function. This is needed by the
469 // member functions FillNSB() and FillStar()
470 //
471
472 Int_t imax = 0 ;
473 Float_t max = 0. ;
474 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
475 if ( sing_resp[i] > max ) {
476 imax = i ;
477 max = sing_resp[i] ;
478 }
479 }
480
481 peak_time = ( (Float_t) imax ) / ( (Float_t) TRIG_SLICES_PER_NSEC ) ;
482
483 //
484 // the amplitude of one single photo electron is not a constant.
485 // There exists a measured distribution from Razmik. This distribution
486 // is used to simulate the noise of the amplitude.
487 // For this a histogramm (histPmt) is created and filled with the
488 // values.
489 //
490
491 char histname[32];
492 sprintf(histname, "histPmt_%d", ct_id);
493 histPmt = new TH1F (histname,"Noise of PMT", 40, 0., 40.) ;
494
495 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
496 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
497 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
498 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
499 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
500
501 histMean = histPmt->GetMean() ;
502
503 for (i=0;i<41;i++){
504 histPmt->SetBinContent(i,ValRazmik[i]);
505 }
506
507 histMean = histPmt->GetMean() ;
508
509 //
510 // create the random generator for the Electronic Noise
511 //
512
513 GenElec = new TRandom() ;
514
515 //
516 // Read in the lookup table for NN trigger
517 //
518
519 for(i=0; i < pixnum;i++ )
520 {
521 MGeomPix &pixel = (*camgeom)[i];
522 for ( Int_t k=0; k<6; k++ ) {
523 NN[k][i]=pixel.GetNeighbor(k);
524 }
525 }
526
527 //
528 // Read in the lookup table for trigger cells
529 //
530
531 FILE *unit;
532
533 i = 0 ;
534
535 if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) {
536 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
537 << endl ;
538 exit(123) ;
539 }
540 else {
541 while ( i < pixnum )
542 {
543 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
544 TC[k][i]=kFALSE;
545 }
546 i++ ;
547 }
548 while ( feof(unit) == 0 ) {
549 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
550 fscanf ( unit, "%d ", &i ) ;
551 if((i-1)<pixnum)
552 TC[k][i-1]=kTRUE;
553 }
554 }
555 fclose (unit) ;
556 }
557
558 //
559 //
560 // set all the booleans used to FALSE, indicating that the pixel is not
561 // used in this event.
562 //
563
564 for ( i =0 ; i <pixnum ; i++ ) {
565 used [i] = kFALSE ;
566 dknt [i] = kFALSE ;
567
568 nphotshow[i] = 0 ;
569 nphotnsb [i] = 0 ;
570 nphotstar[i] = 0 ;
571
572 baseline[i] = 0 ;
573 }
574
575 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
576 sum_d_sig[ii] = 0. ;
577 }
578
579 //
580 // set the information about the Different Level Triggers to zero
581 //
582
583 nZero = nFirst = nSecond = 0 ;
584
585 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
586 SlicesZero[ii] = kFALSE;
587 }
588
589 for ( i = 0 ; i < 5 ; i++) {
590 SlicesFirst[i] = 0 ;
591 SlicesSecond[i] = 0 ;
592 PixelsFirst[i] = -1;
593 PixelsSecond[i] = -1;
594 }
595 cout << " end of MTrigger::MTrigger()" << endl ;
596}
597MTrigger::MTrigger(Int_t pix,
598 float gate, float overt, float ampl, float fwhm) {
599 // ============================================================
600 //
601 // constructor
602 //
603 // The procedure is the following:
604 //
605 // 1. Allocation of some memory needed
606 // 2. some parameters of the trigger are set.
607 // 3. Then the all signals are set to zero
608
609 Int_t i, ii ;
610
611 Float_t threshold ;
612
613 // Number of pixels in the trigger region
614 pixnum=pix;
615
616 //
617 // allocate the memory for the 2dim arrays (a_sig, d_sig )
618 //
619
620 used = new Bool_t[pix];
621 nphotshow = new Int_t[pix];
622 nphotnsb = new Int_t[pix];
623 nphotstar = new Int_t[pix];
624 a_sig = new Float_t * [pix];
625 d_sig = new Float_t * [pix];
626 baseline = new Float_t[pix];
627 dknt = new Bool_t[pix];
628 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
629 chan_thres = new Float_t[pix];
630 for(Int_t j=0;j<6;j++)
631 NN[j] = new Int_t[pix];
632 for(Int_t j=0;j<TRIGGER_CELLS;j++)
633 TC[j] = new Int_t[pix];
634
635 for( Int_t j=0; j<pix; j++ ) {
636
637 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
638
639 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
640 }
641
642 //
643 // set the values for the standard response pulse
644 //
645
646 fwhm_resp = fwhm ;
647 ampl_resp = ampl ;
648
649 overlaping_time = overt;
650
651
652 threshold = CHANNEL_THRESHOLD ;
653
654
655 gate_leng = gate ;
656 trigger_multi = TRIGGER_MULTI ;
657 trigger_geometry = TRIGGER_GEOM ;
658
659 cout << endl
660 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
661 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
662 << endl ;
663 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
664 << endl ;
665 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
666 << endl ;
667 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
668 << endl ;
669 cout << endl ;
670
671 for (Int_t k=0; k<pixnum; k++ ) {
672 chan_thres[k] = threshold ;
673 }
674
675 //
676 // set up the response shape
677 //
678
679 Float_t sigma ;
680 Float_t x, x0 ;
681
682 sigma = fwhm_resp / 2.35 ;
683 x0 = 3*sigma ;
684
685 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
686
687 x = i * (1./((Float_t)TRIG_SLICES_PER_NSEC))
688 + (1./( 2 * (Float_t)TRIG_SLICES_PER_NSEC )) ;
689
690 sing_resp[i] = (Float_t)
691 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
692
693 }
694
695 //
696 // look for the time between start of response function and the
697 // maximum value of the response function. This is needed by the
698 // member functions FillNSB() and FillStar()
699 //
700
701 Int_t imax = 0 ;
702 Float_t max = 0. ;
703 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
704 if ( sing_resp[i] > max ) {
705 imax = i ;
706 max = sing_resp[i] ;
707 }
708 }
709
710 peak_time = ( (Float_t) imax ) / ( (Float_t) TRIG_SLICES_PER_NSEC ) ;
711
712 //
713 // the amplitude of one single photo electron is not a constant.
714 // There exists a measured distribution from Razmik. This distribution
715 // is used to simulate the noise of the amplitude.
716 // For this a histogramm (histPmt) is created and filled with the
717 // values.
718 //
719
720 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
721
722 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
723 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
724 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
725 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
726 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
727
728 histMean = histPmt->GetMean() ;
729
730 for (i=0;i<41;i++){
731 histPmt->SetBinContent(i,ValRazmik[i]);
732 }
733
734 histMean = histPmt->GetMean() ;
735
736 //
737 // create the random generator for the Electronic Noise
738 //
739
740 GenElec = new TRandom() ;
741
742 //
743 //
744 // set all the booleans used to FALSE, indicating that the pixel is not
745 // used in this event.
746 //
747
748 for ( i =0 ; i <pixnum ; i++ ) {
749 used [i] = kFALSE ;
750 dknt [i] = kFALSE ;
751
752 nphotshow[i] = 0 ;
753 nphotnsb [i] = 0 ;
754 nphotstar[i] = 0 ;
755
756 baseline[i] = 0 ;
757 }
758
759 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
760 sum_d_sig[ii] = 0. ;
761 }
762
763 //
764 // set the information about the Different Level Triggers to zero
765 //
766
767 nZero = nFirst = nSecond = 0 ;
768
769 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
770 SlicesZero[ii] = kFALSE;
771 }
772
773 for ( i = 0 ; i < 5 ; i++) {
774 SlicesFirst[i] = 0 ;
775 SlicesSecond[i] = 0 ;
776 PixelsFirst[i] = -1;
777 PixelsSecond[i] = -1;
778 }
779 cout << " end of MTrigger::MTrigger()" << endl ;
780}
781
782MTrigger::~MTrigger() {
783 // ============================================================//
784 // destructor
785 //
786 int i;
787
788 delete histPmt ;
789
790 for(i=0;i<pixnum;i++){
791 //delete [] a_sig[i];
792 //delete [] d_sig[i];
793 }
794
795 delete GenElec;
796}
797
798
799void MTrigger::Reset() {
800 // ============================================================
801 //
802 // reset all values of the signals to zero
803 //
804 Int_t i, ii ;
805
806 for ( i =0 ; i <pixnum ; i++ ) {
807 used [i] = kFALSE ;
808 dknt [i] = kFALSE ;
809
810 nphotshow[i] = 0 ;
811 nphotnsb [i] = 0 ;
812 nphotstar[i] = 0 ;
813 }
814
815 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
816 sum_d_sig[ii] = 0. ;
817 }
818}
819
820void MTrigger::ClearZero() {
821 //
822 // set the information about the Zero Level Trigger to zero
823 //
824
825 Int_t i;
826
827 nZero = 0 ;
828
829 for (i=0 ; i<TRIGGER_TIME_SLICES; i++ ) {
830 SlicesZero[i] = kFALSE;
831 }
832
833}
834
835void MTrigger::ClearFirst() {
836 //
837 // set the information about the First Level Trigger to zero
838 //
839
840 Int_t i;
841
842 nFirst = 0 ;
843
844 for ( i = 0 ; i < 5 ; i++) {
845 SlicesFirst[i] = 0 ;
846 PixelsFirst[i] = -1;
847 }
848}
849
850Float_t MTrigger::FillShow(Int_t iPix, Float_t time) {
851 // ============================================================
852 //
853 // Fills the information of one single Phe electron that
854 // comes from the shower
855 //
856
857 //
858 // First check the time
859 //
860
861 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
862 cout << " WARNING: time of phe out of time range: " << time << endl;
863 return 0. ;
864 }
865 else {
866 return ( Fill( iPix, time, CASE_SHOW ) ) ;
867 }
868}
869
870Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) {
871 // ============================================================
872 //
873 // Fills the information of one single Phe electron that
874 // comes from the NSB
875 //
876
877 //
878 // First check the time
879 //
880
881 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
882 cout << " WARNING: time of phe out of time range: " << time << endl;
883 return 0. ;
884 }
885 else {
886 return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ;
887 }
888}
889
890Float_t MTrigger::FillStar(Int_t iPix, Float_t time) {
891 // ============================================================
892 //
893 // Fills the information of one single Phe electron that
894 // comes from a star
895
896 //
897 // First check the time
898 //
899
900 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
901 cout << " WARNING: time of phe out of time range: " << time << endl;
902 return 0. ;
903 }
904 else {
905 return ( Fill( iPix, time - peak_time, CASE_STAR ) ) ;
906 }
907}
908
909Float_t MTrigger::Fill( Int_t iPix, Float_t time, Int_t fall ) {
910 // ============================================================
911 //
912 // Fills the information in the array for the analog signal
913 //
914
915 Float_t PmtAmp = 0 ; // Amplitude of the PMT signal (results from noise)
916
917 if ( iPix < 0 ) {
918 cout << " ERROR: in MTrigger::Fill() " << endl ;
919 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
920 exit (1) ;
921 }
922 else if ( iPix >= CAMERA_PIXELS ) {
923 cout << " ERROR: in MTrigger::Fill() " << endl ;
924 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
925 exit (1) ;
926 }
927 else if ( iPix >= pixnum ) {
928 //
929 // We do not have to fill information in the trigger part,
930 // but we must create the height of the pulse going into
931 // the FADC simulation
932 //
933 PmtAmp = (histPmt->GetRandom()/histMean) ;
934
935 // AM April 2004: removed updating of counters nphotshow, nphotnsb,
936 // nphotstar for outer pixels... these arrays (see constructors) are
937 // initialized only with as many elements as trigger pixels!! This
938 // made the camera crash at random in some ocassions.
939 }
940 else {
941 //
942 // we have a trigger pixel and we fill it
943 //
944 Int_t i ;
945
946 //
947 // but at the beginning we must check if this pixel is
948 // hitted the first time
949 //
950
951 if ( used[iPix] == kFALSE ) {
952 used [iPix] = kTRUE ;
953 // baseline[iPix] = 0. ;
954
955 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
956 a_sig[iPix][i] = 0. ;
957 d_sig[iPix][i] = 0. ;
958 }
959 }
960
961 //
962 // get the randomized amplitude
963 //
964 PmtAmp = (histPmt->GetRandom()/histMean) ;
965
966 //
967 // select the first slice to fill
968 //
969
970 Int_t ichan = (Int_t) ( time * ((Float_t) TRIG_SLICES_PER_NSEC) ) ;
971
972 //
973 // look over the response signal and put it in the signal line
974 //
975
976 for ( i = 0 ; i<RESPONSE_SLICES_TRIG; i++ ) {
977
978 if ( (ichan+i) >= 0 &&
979 (ichan+i) < TRIGGER_TIME_SLICES ) {
980 a_sig[iPix][ichan+i] += PmtAmp * sing_resp[i] ;
981 }
982 }
983
984 //
985 // we fill the information in the counters of phe's
986 //
987
988 if ( fall == CASE_SHOW )
989 nphotshow[iPix]++ ;
990 else if ( fall == CASE_NSB )
991 nphotnsb[iPix]++ ;
992 else if ( fall == CASE_STAR )
993 nphotstar[iPix]++ ;
994
995 //
996 //
997 return PmtAmp ;
998 }
999 return PmtAmp ;
1000}
1001
1002
1003void MTrigger::AddNSB( Int_t iPix, Float_t resp[TRIGGER_TIME_SLICES]){
1004 // ================================================================
1005 //
1006 // Sets the information in the array for the analog signal
1007 // from a given array
1008 //
1009
1010
1011 if ( iPix < 0 ) {
1012 cout << " ERROR: in MTrigger::SetNSB() " << endl ;
1013 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
1014 exit (1) ;
1015 }
1016 else if ( iPix >= CAMERA_PIXELS ) {
1017 cout << " ERROR: in MTrigger::SetNSB() " << endl ;
1018 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
1019 exit (1) ;
1020 }
1021 else if ( iPix >= pixnum ) {
1022 //
1023 // We have not to fill information in the trigger part.
1024 //
1025 }
1026 else {
1027 //
1028 // we have a trigger pixel and we fill it
1029 //
1030 Int_t i ;
1031
1032 //
1033 // but at the beginning we must check if this pixel is
1034 // hitted the first time
1035 //
1036
1037 if ( used[iPix] == kFALSE ) {
1038 used [iPix] = kTRUE ;
1039
1040 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
1041 a_sig[iPix][i] = 0. ;
1042 d_sig[iPix][i] = 0. ;
1043 }
1044 }
1045
1046 //
1047 // look over the response signal and put it in the signal line
1048 //
1049
1050 for ( i = 0 ; i<TRIGGER_TIME_SLICES; i++ ) {
1051
1052 a_sig[iPix][i] += resp[i];
1053 }
1054
1055 }
1056}
1057
1058void MTrigger::SetElecNoise(Float_t factor){
1059
1060 UInt_t i;
1061 Float_t rausch ;
1062
1063 rausch = RESPONSE_AMPLITUDE * factor ;
1064
1065 cout<<"MTrigger::SetElecNoise ... generating database for electronic noise."
1066 <<endl;
1067
1068 for (i=0;i<TRIGGER_TIME_SLICES*1001;i++){
1069 noise[i]=GenElec->Gaus(0., rausch );
1070 }
1071
1072 cout<<"MTrigger::SetElecNoise ... done"<<endl;
1073
1074}
1075
1076void MTrigger::ElecNoise(Float_t factor) {
1077 // ============================================================
1078 //
1079 // adds the noise due to optronic and electronic
1080 // to the signal
1081 //
1082 Float_t rausch ;
1083
1084 rausch = RESPONSE_AMPLITUDE * factor ;
1085
1086 UInt_t startslice;
1087
1088 for ( Int_t i=0 ; i < pixnum; i++ ) {
1089 //
1090 // but at the beginning we must check if this pixel is
1091 // hitted the first time
1092 //
1093 startslice=GenElec->Integer(TRIGGER_TIME_SLICES*1000);
1094
1095 if ( used[i] == kFALSE ) {
1096 used [i] = kTRUE ;
1097
1098 memcpy( (Float_t*)a_sig[i],
1099 (Float_t*)&noise[startslice],
1100 TRIGGER_TIME_SLICES*sizeof(Float_t));
1101 memset( (Float_t*)d_sig[i],
1102 0,
1103 TRIGGER_TIME_SLICES*sizeof(Float_t));
1104
1105 }
1106 //
1107 // Then the noise is introduced for each time slice
1108 //
1109 else
1110 for ( Int_t ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
1111
1112 a_sig [i][ii] += noise[startslice+ii] ;
1113
1114 }
1115 }
1116}
1117
1118void MTrigger::SetFwhm(Float_t fwhm){
1119 //===========================================================
1120 //
1121 // It sets the fwhm for the single phe signal and
1122 // updates the sing_resp for it
1123
1124 Float_t sigma ;
1125 Float_t x, x0 ;
1126 Int_t i;
1127
1128 fwhm_resp = fwhm;
1129
1130 sigma = fwhm_resp / 2.35 ;
1131 x0 = 3*sigma ;
1132
1133 for (i=0; i< RESPONSE_SLICES_TRIG ; i++ ) {
1134
1135 x = i * (1./((Float_t)TRIG_SLICES_PER_NSEC))
1136 + (1./( 2 * (Float_t)TRIG_SLICES_PER_NSEC )) ;
1137
1138 sing_resp[i] = (Float_t)
1139 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
1140
1141 }
1142
1143
1144}
1145
1146void MTrigger::SetMultiplicity(Int_t multi){
1147 //=============================================================
1148 //
1149 // It sets the private member trigger_multi
1150
1151 trigger_multi=multi;
1152}
1153
1154void MTrigger::SetTopology(Int_t topo){
1155 //=============================================================
1156 //
1157 // It sets the private member trigger_geometry
1158
1159 trigger_geometry=topo;
1160}
1161
1162void MTrigger::SetThreshold(Float_t thres[]){
1163 //=============================================================
1164 //
1165 // It sets the private member chan_thres[pixnum]
1166
1167 Int_t i;
1168
1169 for(i=0;i<pixnum;i++){
1170 chan_thres[i]=thres[i];
1171 }
1172}
1173
1174
1175void MTrigger::CheckThreshold(float *thres, int cells){
1176 //=============================================================
1177 //
1178 // Set Right Discriminator threshold, taking into account trigger pixels
1179
1180 FILE *unit;
1181
1182 float thres_aux[CAMERA_PIXELS];
1183 int id;
1184
1185 for (int i=0;i<CAMERA_PIXELS;i++){
1186 if(i<pixnum){
1187 thres_aux[i]=999999.99;
1188 thres[i]=thres[i];
1189 }
1190 else{
1191 thres_aux[i]=-10.0;
1192 thres[i]=-10.0;
1193 }
1194 }
1195
1196 if (cells==1){
1197 if((unit =fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ){
1198 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
1199 << endl ;
1200 exit(123) ;
1201 }
1202 else {
1203 while ( feof(unit) == 0 ) {
1204 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
1205 fscanf ( unit, "%d ", &id ) ;
1206 if ((id-1)<pixnum)
1207 thres_aux[id-1]=thres[id-1];
1208 }
1209 }
1210 }
1211 fclose (unit) ;
1212
1213 for (int i=0;i<CAMERA_PIXELS;i++){
1214 thres[i]=thres_aux[i];
1215 }
1216 }
1217
1218}
1219
1220void MTrigger::ReadThreshold(char name[]){
1221 //=============================================================
1222 //
1223 // It reads values for threshold of each pixel from file name
1224
1225 FILE *unit;
1226 Int_t i=0;
1227
1228 if ((unit=fopen(name, "r"))==0){
1229 cout<<"WARNING: not able to read ..."<<name<<endl;
1230 }
1231 else {
1232 while (i<pixnum){
1233 fscanf(unit, "%f",&chan_thres[i++]);
1234 }
1235 fclose (unit);
1236 }
1237
1238}
1239
1240void MTrigger::GetResponse(Float_t *resp) {
1241 // ============================================================
1242 //
1243 // puts the standard response function into the array resp
1244
1245 for ( Int_t i=0; i< RESPONSE_SLICES_TRIG; i++ ) {
1246
1247 resp[i] = sing_resp[i] ;
1248 }
1249
1250}
1251
1252void MTrigger::GetMapDiskriminator(Byte_t *map){
1253 //=============================================================
1254 //
1255 // Gives a map of the fired pixels (Bool_t dknt [pixnum])
1256 // in an array of Byte_t (each byte has the information for 8 pixels)
1257 //
1258
1259 Int_t i,ii;
1260
1261 for(i=0;i<pixnum/8+1;i++){
1262 map[i]=0;
1263 }
1264
1265 for(i=0;i<pixnum;i++){
1266 ii=(Int_t)i/8;
1267 if (dknt[i]==kTRUE){
1268 map[ii]=map[ii]+(Int_t)pow((double)2, (double)i-ii*8);
1269 }
1270 }
1271}
1272
1273
1274void MTrigger::Diskriminate() {
1275 // ============================================================
1276 //
1277 // Diskriminates the analog signal
1278 //
1279 // one very important part is the calucaltion of the baseline
1280 // shift. Because of the AC coupling of the PMT, only the
1281 // fluctuations are interesting. If there are a lot of phe,
1282 // a so-called shift of the baseline occurs.
1283 //
1284
1285 Int_t iM = 0 ;
1286 Int_t i, ii ;
1287
1288
1289 Int_t jmax = (Int_t) (gate_leng * TRIG_SLICES_PER_NSEC ) ;
1290
1291 //
1292 // first of all determine the integral of all signals to get
1293 // the baseline shift.
1294 //
1295
1296 for ( i=0 ; i < pixnum ; i++ ) {
1297 if ( used[i] == kTRUE ) {
1298 baseline[i] = 0. ;
1299
1300 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
1301 baseline[i] += a_sig[i][ii] ;
1302 }
1303
1304 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
1305
1306 //
1307 // now correct the baseline shift in the analog signal!!
1308 //
1309 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
1310 a_sig[i][ii] = a_sig[i][ii] - baseline[i] ;
1311 }
1312 }
1313 }
1314
1315 //
1316 // now the diskrimination is coming
1317 //
1318 // take only that pixel which are used
1319 //
1320
1321 for ( i=0 ; i < pixnum; i++ ) {
1322 if ( used [i] == kTRUE ) {
1323
1324 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
1325 //
1326 // first check if the signal is crossing the CHANNEL_THRESHOLD
1327 // form low to big signals
1328 //
1329
1330 if ( a_sig[i][ii-1] < chan_thres[i] &&
1331 a_sig[i][ii] >= chan_thres[i] ) {
1332 {
1333 if ( dknt[i] == kFALSE ) {
1334 dknt [i] = kTRUE ;
1335 iM++ ;
1336 }
1337 // cout << " disk " << ii ;
1338 //
1339 // put the standard diskriminator signal in
1340 // the diskriminated signal
1341 //
1342 for ( Int_t j=0 ; j < jmax ; j++ ) {
1343
1344 if ( ii+j < TRIGGER_TIME_SLICES ) {
1345 d_sig [i][ii+j] = 1. ;
1346 }
1347 }
1348 ii = ii + jmax ;
1349 }
1350 }
1351 else d_sig[i][ii]=0.;
1352 }
1353 }
1354 }
1355}
1356
1357
1358void MTrigger::ShowSignal (MMcEvt *McEvt) {
1359 // ============================================================
1360 //
1361 // This method is used to book the histogramm to show the signal in
1362 // a special gui frame (class MGTriggerSignal). After the look onto the
1363 // signals for a better understanding of the things we will expect
1364 // the gui frame and all histogramms will be destroyed.
1365 //
1366
1367 //
1368 // first of all create a list of the histograms to show
1369 //
1370 // take only that one with a entry
1371
1372 TH1F *hist ;
1373 TH1F *dhist ;
1374 Char_t dumm[10];
1375 Char_t name[256];
1376
1377 TObjArray *AList ;
1378 AList = new TObjArray(10) ;
1379
1380 TObjArray *DList ;
1381 DList = new TObjArray(10) ;
1382
1383 // the list of analog signal histograms
1384 // at the beginning we initalise 10 elements
1385 // but this array expand automaticly if neccessay
1386
1387 Int_t ic = 0 ;
1388 for ( Int_t i=0 ; i < pixnum; i++ ) {
1389 if ( used [i] == kTRUE ) {
1390
1391 sprintf (dumm, "A_%d", i ) ;
1392 sprintf (name, "analog %d", i ) ;
1393
1394 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
1395 //
1396 // fill the histogram
1397 //
1398
1399 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
1400 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
1401 }
1402 hist->SetMaximum(8.);
1403 hist->SetMinimum(-8.);
1404 hist->SetStats(kFALSE);
1405
1406 AList->Add(hist) ;
1407
1408 sprintf (dumm, "D_%d", i ) ;
1409 sprintf (name, "digital %d", i ) ;
1410
1411 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
1412 if ( dknt[i] == kTRUE ) {
1413 //
1414 // fill the histogram of digital signal
1415 //
1416 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
1417 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
1418 dhist->SetStats(kFALSE);
1419 }
1420 }
1421 dhist->SetMaximum(1.5);
1422
1423 DList->Add(dhist);
1424
1425 ic++ ;
1426
1427 }
1428 }
1429
1430 //
1431 // create the Gui Tool
1432 //
1433 //
1434
1435 new MGTriggerSignal(McEvt,
1436 AList,
1437 DList,
1438 gClient->GetRoot(),
1439 gClient->GetRoot(),
1440 400, 400 ) ;
1441
1442 //
1443 // delete the List of histogramms
1444 //
1445
1446 AList->Delete() ;
1447 DList->Delete() ;
1448
1449 delete AList ;
1450 delete DList ;
1451}
1452
1453
1454Int_t MTrigger::ZeroLevel() {
1455 // ============================================================
1456 //
1457 // This is a level introduced just to speed up the program.
1458 // It makes sense to look for next neighbours only if there
1459 // are at least trigger_multi pixels with a diskriminator
1460 // signal.
1461 //
1462
1463 //
1464 // first count the pixels with a diskriminator signal
1465 //
1466 Int_t iMul = 0 ;
1467 for ( Int_t iP =0 ; iP < pixnum; iP++ ) {
1468 //
1469 //
1470
1471 if ( dknt[iP] == kTRUE ) {
1472 iMul++ ;
1473 }
1474 }
1475
1476
1477 //
1478 // only if there are at least more pixels than requested
1479 // it make sense to look into details
1480 if ( iMul >= trigger_multi ) {
1481 //
1482 // fill the sum signal of all diskriminator signals
1483 //
1484 for ( Int_t iP =0 ; iP < pixnum; iP++ ) {
1485 //
1486 //
1487 if ( dknt[iP] == kTRUE ) {
1488 //
1489 // sum it up
1490 //
1491 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1492 //
1493 //
1494 sum_d_sig [iS] += d_sig[iP][iS] ;
1495 }
1496 }
1497 }
1498 //
1499 // run over the sum_d_sig and check each time slice
1500 //
1501 Int_t iReturn = 0 ;
1502
1503 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1504
1505 if ( sum_d_sig[iS] >= trigger_multi ) {
1506 iReturn++ ;
1507 nZero++;
1508 SlicesZero[iS] = kTRUE ;
1509
1510 }
1511 else SlicesZero[iS] = kFALSE;
1512 }
1513 return ( iReturn ) ;
1514 }
1515 else {
1516 return 0 ;
1517 }
1518}
1519
1520Int_t MTrigger::FirstLevel() {
1521 //=================================================
1522 //
1523 // This is a level trigger which can look for several
1524 // multiplicities (trigger_multi)
1525 // and topologies (trigger_geometry)
1526 //
1527
1528 Int_t iReturn = 0 ; // Return value for this function
1529
1530 // Definition of needed variables
1531 Bool_t Muster[pixnum] ;
1532 Bool_t Neighb[pixnum] ;
1533 Int_t iMulti = 0 ;
1534
1535 // We put several wrong topologies which we already know that they
1536 // are not possible. It can save time.
1537
1538 if (trigger_geometry==0 && trigger_multi>7) {
1539 cout <<"You are looking for a topology that needs more than six neighbours of the same pixel"<<endl;
1540 cout <<" Topology "<<trigger_geometry<<" Multiplicity "<<trigger_multi<<endl;;
1541 return (kFALSE);
1542 }
1543
1544 if (trigger_geometry==2 && trigger_multi<3) {
1545 cout<<"Closed pack geometry with multiplicity "<<trigger_multi<<" does not make sense, I'll check simple neihgbour condition"<<endl;
1546 trigger_geometry=1;
1547 }
1548 if (trigger_geometry>2) {
1549 cout << "This trigger topology is not implemented"<<endl;
1550 return (kFALSE);
1551 }
1552
1553 //
1554 // loop over all ZeroLevel Trigger
1555 //
1556 // it is only neccessary to look after a ZeroLevel Trigger for
1557 // a FirstLevel (NextNeighbour) trigger.
1558 //
1559
1560 if (nZero) {
1561
1562 //
1563 // Then run over all slices
1564 //
1565
1566 for ( Int_t iSli = 0;
1567 iSli < TRIGGER_TIME_SLICES; iSli++ ) {
1568
1569 // Check if this time slice has more fired pixels than trigger_multi
1570
1571 if (SlicesZero[iSli]){
1572 //
1573 // Loop over trigger cells. It is topology analysis,
1574 // therefore it is kept here after multiplicity and
1575 // threshold checks.
1576 //
1577
1578 for(Int_t iCell=0; iCell<TRIGGER_CELLS; iCell++){
1579 //
1580 // then look in all pixel of that cell if the
1581 // diskriminated signal is 1
1582 //
1583 for ( Int_t iPix = 0 ; iPix < pixnum; iPix++ ) {
1584 Muster[iPix] = kFALSE ;
1585 Neighb[iPix] = kFALSE ;
1586 // Select pixels which are used and it the current cell
1587 if ( used [iPix] == kTRUE && TC[iCell][iPix]==kTRUE) {
1588 //
1589 // now check the diskriminated signal
1590 //
1591 if ( d_sig [iPix][iSli] > 0. ) {
1592 Muster[iPix] = kTRUE ;
1593 }
1594 }
1595 } // end of loop over the pixels
1596
1597 //
1598 // Here we check which of the "muster" pixels will be fired for
1599 // the minimum required overlaping time
1600 //
1601
1602 OverlapingTime(Muster, &Muster[0],iSli);
1603
1604 //
1605 // here we have to look for the topologies
1606 //
1607
1608 switch(trigger_geometry){
1609 case 0:{
1610
1611 // It looks for a pixel above threshold which has
1612 // trigger_multi-1 neighbour pixels above threshold
1613
1614 Bool_t Dummy[pixnum] ;
1615
1616 // Loop over all pixels
1617 for (int j=0;j<pixnum;j++){
1618
1619 for (int k=0; k<pixnum; k++){
1620 Neighb[k]=kFALSE;
1621
1622 Dummy[k] = Muster[k] ;
1623 }
1624 if(Muster[j]){
1625 // If pixel is fired, it checks how many fired neighbours it has
1626 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1627 Neighb[j] = kTRUE ;
1628 Dummy[j] = kTRUE ;
1629 if (!PassNextNeighbour(Dummy, &Neighb[0])){
1630 break;
1631 }
1632 for (int k=0; k<pixnum; k++){
1633 if (Neighb[k]){
1634 Dummy[k]=kFALSE;
1635 Neighb[k]=kFALSE;
1636 }
1637 }
1638 }
1639 if (iMulti==trigger_multi ) {
1640 //
1641 // A NN-Trigger is detected at time Slice
1642 //
1643 PixelsFirst[nFirst] = j; // We save pixel that triggers
1644 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1645 iReturn++ ;
1646 iSli+=(LEVEL1_DEAD_TIME*TRIG_SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1647 iCell=TRIGGER_CELLS; // We skip the remaining trigger cells
1648 break ;
1649 }
1650 }
1651 }
1652 break;
1653 };
1654
1655 case 1:{
1656
1657 // It looks for trigger_multi neighbour pixels above the
1658 // threshold.
1659
1660 for (int j=0;j<pixnum;j++){
1661 if(Muster[j]){
1662 // It checks if you can find
1663 // trigger_multi fired neighbour pixels
1664 Neighb[j] = kTRUE ;
1665 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1666 if (!PassNextNeighbour(Muster, &Neighb[0]))
1667 break;
1668 }
1669 if (iMulti==trigger_multi ) {
1670 //
1671 // A NN-Trigger is detected at time Slice
1672 //
1673 PixelsFirst[nFirst] = j; // We save pixel that triggers
1674 SlicesFirst[nFirst++] = iSli ; // We save when it triggers
1675 iReturn++ ;
1676 iSli+=(LEVEL1_DEAD_TIME*TRIG_SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1677 iCell=TRIGGER_CELLS; // We skip the remaining trigger cells
1678 break ;
1679 }
1680 else {
1681 // We put Neighb to kFALSE to check an other pixel
1682 for (int k=0; k<pixnum; k++){
1683 if (Neighb[k]){
1684 Neighb[k]=kFALSE;
1685 }
1686 }
1687 }
1688 }
1689 }
1690 break;
1691 };
1692 case 2:{
1693
1694 // It looks for trigger_multi closed pack neighbours
1695 // above threshold
1696 // Closed pack means that you can take out any pixel
1697 // and you will still get a trigger for trigger_multi -1
1698 // The algorithm is not perfect, there still somes cases
1699 // that are not really well treated
1700
1701 Int_t closed_pack = 1;
1702
1703 for (int j=0;j<pixnum;j++){
1704 if(Muster[j]){
1705 // It checks if there are trigger_multi
1706 // neighbours above threshold
1707
1708 Neighb[j] = kTRUE ;
1709 iMulti=1;
1710
1711 //while(PassNextNeighbour(Muster, &Neighb[0])) iMulti++;
1712 for (iMulti=1;iMulti<trigger_multi;iMulti++){
1713 if (!PassNextNeighbour(Muster, &Neighb[0]))
1714 break;
1715 }
1716
1717 if (iMulti==trigger_multi ) {
1718 //
1719 // A NN-Trigger is detected at time Slice
1720 //
1721
1722 // Check if there is closed pack topology
1723
1724 Bool_t Aux1[pixnum];
1725 Bool_t Aux2[pixnum];
1726 for (int jj=0;jj<pixnum;jj++)
1727 Aux2[jj]=kFALSE;
1728
1729 for (int i=0;i<pixnum;i++){
1730 if (Neighb[i]) {
1731 // Loop over pixels that achive neighbouring condition
1732
1733 for (int jj=0;jj<pixnum;jj++) {
1734
1735 Aux1[jj] = Neighb[jj] ; // huschel
1736 Aux2[jj]=kFALSE;
1737 }
1738
1739 // It checks if taking out any of the pixels we lose
1740 // neighbouring condition for trigger_multi -1
1741
1742 Aux1[i]=kFALSE;
1743 closed_pack=0;
1744 for (int jj=0;jj<pixnum;jj++) {
1745 if (Aux1[jj]==kTRUE){
1746 Aux2[jj]=kTRUE;
1747 for (iMulti=1;iMulti<(trigger_multi-1);iMulti++){
1748 if (!PassNextNeighbour(Aux1, &Aux2[0]))
1749 break;
1750 }
1751 if (iMulti==(trigger_multi-1)){
1752 // We found a NN trigger for trigger_multi -1
1753 // taking out pixel jj
1754 closed_pack=1;
1755 break;
1756 }
1757 Aux2[jj]=kFALSE;
1758 }
1759 }
1760 if (!closed_pack) break;
1761 // For some pixell we did not found NN condition
1762 // for trigger_multi -1
1763 }
1764 }
1765 if (closed_pack){
1766 PixelsFirst[nFirst] = j; // We save pixel that triggers
1767 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1768 iReturn++ ;
1769 iSli+=(LEVEL1_DEAD_TIME*TRIG_SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1770 iCell=TRIGGER_CELLS; // We skip the remaining trigger cells
1771 break ;
1772 }
1773 else {
1774 for (int k=0; k<pixnum; k++){
1775 if (Neighb[k]){
1776 Neighb[k]=kFALSE;
1777 }
1778 }
1779 }
1780 } // end if trigger multiplicity achived
1781 else{
1782 for (int k=0; k<pixnum; k++)
1783 Neighb[k]=kFALSE;
1784 }
1785 } // end if pixel fired
1786 } // end loop trigger pixels
1787 break;
1788 }; // end case 2:
1789 default:{
1790 cout << "This topology is not implemented yet"<<endl;
1791 break;
1792 }
1793 }
1794 } //end loop over trigger cells.
1795 }
1796 } // end of loop over the slices
1797 } // end of conditional for a trigger Zero
1798
1799 //
1800 // return the Number of FirstLevel Triggers
1801 //
1802 return iReturn ;
1803}
1804
1805
1806Bool_t MTrigger::PassNextNeighbour ( Bool_t m[], Bool_t *n) {
1807 //
1808 // This function is looking for a next neighbour of pixels in n[]
1809 // above triggers using a NNlookup table.
1810 // This table is builded by the default constructor
1811 //
1812
1813 //
1814 // loop over all trigger pixels
1815 //
1816
1817 Bool_t return_val = kFALSE;
1818
1819 for ( Int_t i=0; i<pixnum; i++) {
1820 //
1821 // check if this pixel has a diskrminator signal
1822 // (this is inside n[] )
1823 //
1824
1825 if ( n[i] && !return_val) {
1826
1827 //
1828 // look in the next neighbours from the lookuptable
1829 //
1830
1831 for ( Int_t kk=0; kk<6; kk++ ) {
1832 //
1833 // if the nextneighbour is outside the triggerarea do nothing
1834 //
1835 if (!return_val){
1836 if (NN[kk][i] >= pixnum ) {
1837
1838 }
1839 // the nextneighbour is not inside the pixnum
1840 else {
1841 //
1842 // look if the boolean of nn pixels is true
1843 //
1844
1845 if ( m[ NN[kk][i] ] && !n[NN[kk][i]] ) {
1846 n[NN[kk][i]]=kTRUE ;
1847 return_val =kTRUE;
1848 }
1849 }
1850 }
1851 else break;
1852 }
1853 }
1854 }
1855 return(return_val);
1856}
1857
1858Float_t MTrigger::GetFirstLevelTime( Int_t il ){
1859
1860 //=============================================================
1861 //
1862 // It gives the time for the il trigger at first level
1863
1864 return((Float_t) ((Float_t) SlicesFirst[il]/((Float_t) TRIG_SLICES_PER_NSEC)));
1865}
1866
1867Int_t MTrigger::GetFirstLevelPixel( Int_t il ){
1868
1869 //=============================================================
1870 //
1871 // It gives the pixel that triggers for the il trigger at first level
1872 return(PixelsFirst[il]);
1873}
1874
1875void MTrigger::OverlapingTime ( Bool_t m[], Bool_t *n, Int_t ifSli){
1876
1877 //============================================================
1878 //
1879 // It returns in n the pixels of m that are fired during the
1880 // required overlaping time for trigger after ifSli
1881
1882 int i,j;
1883 int iNumSli;
1884
1885 // Translation from ns to slices
1886 iNumSli=(int) (overlaping_time*TRIG_SLICES_PER_NSEC);
1887 if (iNumSli<1) iNumSli=1;
1888
1889 // Put pixels that fulfill the requirement in n
1890 for (i=0;i<pixnum;i++){
1891 if (m[i]==kTRUE){
1892 for(j=ifSli;j<ifSli+iNumSli;j++){
1893 if(!d_sig[i][j]){
1894 n[i]=kFALSE;
1895 break;
1896 }
1897 }
1898 }
1899 }
1900
1901}
Note: See TracBrowser for help on using the repository browser.