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

Last change on this file since 5099 was 5099, checked in by moralejo, 21 years ago
Adapted headers to current c++ style, removed -Wno-deprecated from compilation options.
File size: 43.8 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 ; i++ ) {
209
210 x = i * (1./((Float_t)SLICES_PER_NSEC))
211 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
212
213 sing_resp[i] =
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 ; 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) 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] = -50 ;
360 SlicesSecond[i] = -50 ;
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 ; i++ ) {
457
458 x = i * (1./((Float_t)SLICES_PER_NSEC))
459 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
460
461 sing_resp[i] =
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 ; 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) 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#ifndef __STARRESPO__
520 for(i=0; i < pixnum;i++ )
521 {
522 MGeomPix &pixel = (*camgeom)[i];
523 for ( Int_t k=0; k<6; k++ ) {
524 NN[k][i]=pixel.GetNeighbor(k);
525 }
526 }
527#endif
528 //
529 // Read in the lookup table for trigger cells
530 //
531
532 FILE *unit;
533
534 i = 0 ;
535
536 if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) {
537 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
538 << endl ;
539 exit(123) ;
540 }
541 else {
542 while ( i < pixnum )
543 {
544 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
545 TC[k][i]=kFALSE;
546 }
547 i++ ;
548 }
549 while ( feof(unit) == 0 ) {
550 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
551 fscanf ( unit, "%d ", &i ) ;
552 if((i-1)<pixnum)
553 TC[k][i-1]=kTRUE;
554 }
555 }
556 fclose (unit) ;
557 }
558
559 //
560 //
561 // set all the booleans used to FALSE, indicating that the pixel is not
562 // used in this event.
563 //
564
565 for ( i =0 ; i <pixnum ; i++ ) {
566 used [i] = kFALSE ;
567 dknt [i] = kFALSE ;
568
569 nphotshow[i] = 0 ;
570 nphotnsb [i] = 0 ;
571 nphotstar[i] = 0 ;
572
573 baseline[i] = 0 ;
574 }
575
576 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
577 sum_d_sig[ii] = 0. ;
578 }
579
580 //
581 // set the information about the Different Level Triggers to zero
582 //
583
584 nZero = nFirst = nSecond = 0 ;
585
586 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
587 SlicesZero[ii] = kFALSE;
588 }
589
590 for ( i = 0 ; i < 5 ; i++) {
591 SlicesFirst[i] = -50 ;
592 SlicesSecond[i] = -50 ;
593 PixelsFirst[i] = -1;
594 PixelsSecond[i] = -1;
595 }
596 cout << " end of MTrigger::MTrigger()" << endl ;
597}
598MTrigger::MTrigger(Int_t pix,
599 float gate, float overt, float ampl, float fwhm) {
600 // ============================================================
601 //
602 // constructor
603 //
604 // The procedure is the following:
605 //
606 // 1. Allocation of some memory needed
607 // 2. some parameters of the trigger are set.
608 // 3. Then the all signals are set to zero
609
610 Int_t i, ii ;
611
612 Float_t threshold ;
613
614 // Number of pixels in the trigger region
615 pixnum=pix;
616
617 //
618 // allocate the memory for the 2dim arrays (a_sig, d_sig )
619 //
620
621 used = new Bool_t[pix];
622 nphotshow = new Int_t[pix];
623 nphotnsb = new Int_t[pix];
624 nphotstar = new Int_t[pix];
625 a_sig = new Float_t * [pix];
626 d_sig = new Float_t * [pix];
627 baseline = new Float_t[pix];
628 dknt = new Bool_t[pix];
629 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
630 chan_thres = new Float_t[pix];
631 for(Int_t j=0;j<6;j++)
632 NN[j] = new Int_t[pix];
633 for(Int_t j=0;j<TRIGGER_CELLS;j++)
634 TC[j] = new Int_t[pix];
635
636 for( Int_t j=0; j<pix; j++ ) {
637
638 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
639
640 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
641 }
642
643 //
644 // set the values for the standard response pulse
645 //
646
647 fwhm_resp = fwhm ;
648 ampl_resp = ampl ;
649
650 overlaping_time = overt;
651
652
653 threshold = CHANNEL_THRESHOLD ;
654
655
656 gate_leng = gate ;
657 trigger_multi = TRIGGER_MULTI ;
658 trigger_geometry = TRIGGER_GEOM ;
659
660 cout << endl
661 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
662 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
663 << endl ;
664 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
665 << endl ;
666 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
667 << endl ;
668 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
669 << endl ;
670 cout << endl ;
671
672 for (Int_t k=0; k<pixnum; k++ ) {
673 chan_thres[k] = threshold ;
674 }
675
676 //
677 // set up the response shape
678 //
679
680 Float_t sigma ;
681 Float_t x, x0 ;
682
683 sigma = fwhm_resp / 2.35 ;
684 x0 = 3*sigma ;
685
686 for (i=0; i< RESPONSE_SLICES ; i++ ) {
687
688 x = i * (1./((Float_t)SLICES_PER_NSEC))
689 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
690
691 sing_resp[i] =
692 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
693
694 }
695
696 //
697 // look for the time between start of response function and the
698 // maximum value of the response function. This is needed by the
699 // member functions FillNSB() and FillStar()
700 //
701
702 Int_t imax = 0 ;
703 Float_t max = 0. ;
704 for (i=0; i< RESPONSE_SLICES ; i++ ) {
705 if ( sing_resp[i] > max ) {
706 imax = i ;
707 max = sing_resp[i] ;
708 }
709 }
710
711 peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ;
712
713 //
714 // the amplitude of one single photo electron is not a constant.
715 // There exists a measured distribution from Razmik. This distribution
716 // is used to simulate the noise of the amplitude.
717 // For this a histogramm (histPmt) is created and filled with the
718 // values.
719 //
720
721 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
722
723 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
724 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
725 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
726 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
727 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
728
729 histMean = histPmt->GetMean() ;
730
731 for (i=0;i<41;i++){
732 histPmt->SetBinContent(i,ValRazmik[i]);
733 }
734
735 histMean = histPmt->GetMean() ;
736
737 //
738 // create the random generator for the Electronic Noise
739 //
740
741 GenElec = new TRandom() ;
742
743 //
744 //
745 // set all the booleans used to FALSE, indicating that the pixel is not
746 // used in this event.
747 //
748
749 for ( i =0 ; i <pixnum ; i++ ) {
750 used [i] = kFALSE ;
751 dknt [i] = kFALSE ;
752
753 nphotshow[i] = 0 ;
754 nphotnsb [i] = 0 ;
755 nphotstar[i] = 0 ;
756
757 baseline[i] = 0 ;
758 }
759
760 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
761 sum_d_sig[ii] = 0. ;
762 }
763
764 //
765 // set the information about the Different Level Triggers to zero
766 //
767
768 nZero = nFirst = nSecond = 0 ;
769
770 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
771 SlicesZero[ii] = kFALSE;
772 }
773
774 for ( i = 0 ; i < 5 ; i++) {
775 SlicesFirst[i] = -50 ;
776 SlicesSecond[i] = -50 ;
777 PixelsFirst[i] = -1;
778 PixelsSecond[i] = -1;
779 }
780 cout << " end of MTrigger::MTrigger()" << endl ;
781}
782
783MTrigger::~MTrigger() {
784 // ============================================================//
785 // destructor
786 //
787 int i;
788
789 delete histPmt ;
790
791 for(i=0;i<pixnum;i++){
792 //delete [] a_sig[i];
793 //delete [] d_sig[i];
794 }
795
796 delete GenElec;
797}
798
799
800void MTrigger::Reset() {
801 // ============================================================
802 //
803 // reset all values of the signals to zero
804 //
805 Int_t i, ii ;
806
807 for ( i =0 ; i <pixnum ; i++ ) {
808 used [i] = kFALSE ;
809 dknt [i] = kFALSE ;
810
811 nphotshow[i] = 0 ;
812 nphotnsb [i] = 0 ;
813 nphotstar[i] = 0 ;
814 }
815
816 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
817 sum_d_sig[ii] = 0. ;
818 }
819}
820
821void MTrigger::ClearZero() {
822 //
823 // set the information about the Zero Level Trigger to zero
824 //
825
826 Int_t i;
827
828 nZero = 0 ;
829
830 for (i=0 ; i<TRIGGER_TIME_SLICES; i++ ) {
831 SlicesZero[i] = kFALSE;
832 }
833
834}
835
836void MTrigger::ClearFirst() {
837 //
838 // set the information about the First Level Trigger to zero
839 //
840
841 Int_t i;
842
843 nFirst = 0 ;
844
845 for ( i = 0 ; i < 5 ; i++) {
846 SlicesFirst[i] = -50 ;
847 PixelsFirst[i] = -1;
848 }
849}
850
851Float_t MTrigger::FillShow(Int_t iPix, Float_t time) {
852 // ============================================================
853 //
854 // Fills the information of one single Phe electron that
855 // comes from the shower
856 //
857
858 //
859 // First check the time
860 //
861
862 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
863 cout << " WARNING: time of phe out of time range: " << time << endl;
864 return 0. ;
865 }
866 else {
867 return ( Fill( iPix, time, CASE_SHOW ) ) ;
868 }
869}
870
871Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) {
872 // ============================================================
873 //
874 // Fills the information of one single Phe electron that
875 // comes from the shower
876 //
877
878 //
879 // First check the time
880 //
881
882 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
883 cout << " WARNING: time of phe out of time range: " << time << endl;
884 return 0. ;
885 }
886 else {
887 return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ;
888 }
889}
890
891Float_t MTrigger::FillStar(Int_t iPix, Float_t time) {
892 // ============================================================
893 //
894 // Fills the information of one single Phe electron that
895 // comes from the shower
896 //
897
898 //
899 // First check the time
900 //
901
902 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
903 cout << " WARNING: time of phe out of time range: " << time << endl;
904 return 0. ;
905 }
906 else {
907 return ( Fill( iPix, time - peak_time, CASE_STAR ) ) ;
908 }
909}
910
911Float_t MTrigger::Fill( Int_t iPix, Float_t time, Int_t fall ) {
912 // ============================================================
913 //
914 // Fills the information in the array for the analog signal
915 //
916
917 Float_t PmtAmp = 0 ; // Amplitude of the PMT signal (results from noise)
918
919 if ( iPix < 0 ) {
920 cout << " ERROR: in MTrigger::Fill() " << endl ;
921 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
922 exit (1) ;
923 }
924 else if ( iPix >= CAMERA_PIXELS ) {
925 cout << " ERROR: in MTrigger::Fill() " << endl ;
926 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
927 exit (1) ;
928 }
929 else if ( iPix >= pixnum ) {
930 //
931 // We do not have to fill information in the trigger part,
932 // but we must create the height of the pulse going into
933 // the FADC simulation
934 //
935 PmtAmp = (histPmt->GetRandom()/histMean) ;
936
937 // AM April 2004: removed updating of counters nphotshow, nphotnsb,
938 // nphotstar for outer pixels... these arrays (see constructors) are
939 // initialized only with as many elements as trigger pixels!! This
940 // made the camera crash at random in some ocassions.
941 }
942 else {
943 //
944 // we have a trigger pixel and we fill it
945 //
946 Int_t i ;
947
948 //
949 // but at the beginning we must check if this pixel is
950 // hitted the first time
951 //
952
953 if ( used[iPix] == kFALSE ) {
954 used [iPix] = kTRUE ;
955 // baseline[iPix] = 0. ;
956
957 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
958 a_sig[iPix][i] = 0. ;
959 d_sig[iPix][i] = 0. ;
960 }
961 }
962
963 //
964 // get the randomized amplitude
965 //
966 PmtAmp = (histPmt->GetRandom()/histMean) ;
967
968 //
969 // select the first slice to fill
970 //
971
972 Int_t ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
973
974 //
975 // look over the response signal and put it in the signal line
976 //
977
978 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
979
980 if ( (ichan+i) >= 0 &&
981 (ichan+i) < TRIGGER_TIME_SLICES ) {
982 a_sig[iPix][ichan+i] += PmtAmp * sing_resp[i] ;
983 }
984 }
985
986 //
987 // we fill the information in the counters of phe's
988 //
989
990 if ( fall == CASE_SHOW )
991 nphotshow[iPix]++ ;
992 else if ( fall == CASE_NSB )
993 nphotnsb[iPix]++ ;
994 else if ( fall == CASE_STAR )
995 nphotstar[iPix]++ ;
996
997 //
998 //
999 return PmtAmp ;
1000 }
1001 return PmtAmp ;
1002}
1003
1004
1005void MTrigger::AddNSB( Int_t iPix, Float_t resp[TRIGGER_TIME_SLICES]){
1006 // ================================================================
1007 //
1008 // Sets the information in the array for the analog signal
1009 // from a given array
1010 //
1011
1012
1013 if ( iPix < 0 ) {
1014 cout << " ERROR: in MTrigger::SetNSB() " << endl ;
1015 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
1016 exit (1) ;
1017 }
1018 else if ( iPix >= CAMERA_PIXELS ) {
1019 cout << " ERROR: in MTrigger::SetNSB() " << endl ;
1020 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
1021 exit (1) ;
1022 }
1023 else if ( iPix >= pixnum ) {
1024 //
1025 // We have not to fill information in the trigger part.
1026 //
1027 }
1028 else {
1029 //
1030 // we have a trigger pixel and we fill it
1031 //
1032 Int_t i ;
1033
1034 //
1035 // but at the beginning we must check if this pixel is
1036 // hitted the first time
1037 //
1038
1039 if ( used[iPix] == kFALSE ) {
1040 used [iPix] = kTRUE ;
1041
1042 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
1043 a_sig[iPix][i] = 0. ;
1044 d_sig[iPix][i] = 0. ;
1045 }
1046 }
1047
1048 //
1049 // look over the response signal and put it in the signal line
1050 //
1051
1052 for ( i = 0 ; i<TRIGGER_TIME_SLICES; i++ ) {
1053
1054 a_sig[iPix][i] += resp[i];
1055 }
1056
1057 }
1058}
1059
1060void MTrigger::SetElecNoise(Float_t factor){
1061
1062 UInt_t i;
1063 Float_t rausch ;
1064
1065 rausch = RESPONSE_AMPLITUDE * factor ;
1066
1067 cout<<"MTrigger::SetElecNoise ... generating database for electronic noise."
1068 <<endl;
1069
1070 for (i=0;i<TRIGGER_TIME_SLICES*1001;i++){
1071 noise[i]=GenElec->Gaus(0., rausch );
1072 }
1073
1074 cout<<"MTrigger::SetElecNoise ... done"<<endl;
1075
1076}
1077
1078void MTrigger::ElecNoise(Float_t factor) {
1079 // ============================================================
1080 //
1081 // adds the noise due to optronic and electronic
1082 // to the signal
1083 //
1084 Float_t rausch ;
1085
1086 rausch = RESPONSE_AMPLITUDE * factor ;
1087
1088 UInt_t startslice;
1089
1090 for ( Int_t i=0 ; i < pixnum; i++ ) {
1091 //
1092 // but at the beginning we must check if this pixel is
1093 // hitted the first time
1094 //
1095 startslice=GenElec->Integer(TRIGGER_TIME_SLICES*1000);
1096
1097 if ( used[i] == kFALSE ) {
1098 used [i] = kTRUE ;
1099
1100 memcpy( (Float_t*)a_sig[i],
1101 (Float_t*)&noise[startslice],
1102 TRIGGER_TIME_SLICES*sizeof(Float_t));
1103 memset( (Float_t*)d_sig[i],
1104 0,
1105 TRIGGER_TIME_SLICES*sizeof(Float_t));
1106
1107 }
1108 //
1109 // Then the noise is introduced for each time slice
1110 //
1111 else
1112 for ( Int_t ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
1113
1114 a_sig [i][ii] += noise[startslice+ii] ;
1115
1116 }
1117 }
1118}
1119
1120void MTrigger::SetFwhm(Float_t fwhm){
1121 //===========================================================
1122 //
1123 // It sets the fwhm for the single phe signal and
1124 // updates the sing_resp for it
1125
1126 Float_t sigma ;
1127 Float_t x, x0 ;
1128 Int_t i;
1129
1130 fwhm_resp = fwhm;
1131
1132 sigma = fwhm_resp / 2.35 ;
1133 x0 = 3*sigma ;
1134
1135 for (i=0; i< RESPONSE_SLICES ; i++ ) {
1136
1137 x = i * (1./((Float_t)SLICES_PER_NSEC))
1138 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
1139
1140 sing_resp[i] =
1141 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
1142
1143 }
1144
1145
1146}
1147
1148void MTrigger::SetMultiplicity(Int_t multi){
1149 //=============================================================
1150 //
1151 // It sets the private member trigger_multi
1152
1153 trigger_multi=multi;
1154}
1155
1156void MTrigger::SetTopology(Int_t topo){
1157 //=============================================================
1158 //
1159 // It sets the private member trigger_geometry
1160
1161 trigger_geometry=topo;
1162}
1163
1164void MTrigger::SetThreshold(Float_t thres[]){
1165 //=============================================================
1166 //
1167 // It sets the private member chan_thres[pixnum]
1168
1169 Int_t i;
1170
1171 for(i=0;i<pixnum;i++){
1172 chan_thres[i]=thres[i];
1173 }
1174}
1175
1176
1177void MTrigger::CheckThreshold(float *thres, int cells){
1178 //=============================================================
1179 //
1180 // Set Right Discriminator threshold, taking into account trigger pixels
1181
1182 FILE *unit;
1183
1184 float thres_aux[CAMERA_PIXELS];
1185 int id;
1186
1187 for (int i=0;i<CAMERA_PIXELS;i++){
1188 if(i<pixnum){
1189 thres_aux[i]=999999.99;
1190 thres[i]=thres[i];
1191 }
1192 else{
1193 thres_aux[i]=-10.0;
1194 thres[i]=-10.0;
1195 }
1196 }
1197
1198 if (cells==1){
1199 if((unit =fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ){
1200 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
1201 << endl ;
1202 exit(123) ;
1203 }
1204 else {
1205 while ( feof(unit) == 0 ) {
1206 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
1207 fscanf ( unit, "%d ", &id ) ;
1208 if ((id-1)<pixnum)
1209 thres_aux[id-1]=thres[id-1];
1210 }
1211 }
1212 }
1213 fclose (unit) ;
1214
1215 for (int i=0;i<CAMERA_PIXELS;i++){
1216 thres[i]=thres_aux[i];
1217 }
1218 }
1219
1220}
1221
1222void MTrigger::ReadThreshold(char name[]){
1223 //=============================================================
1224 //
1225 // It reads values for threshold of each pixel from file name
1226
1227 FILE *unit;
1228 Int_t i=0;
1229
1230 if ((unit=fopen(name, "r"))==0){
1231 cout<<"WARNING: not able to read ..."<<name<<endl;
1232 }
1233 else {
1234 while (i<pixnum){
1235 fscanf(unit, "%f",&chan_thres[i++]);
1236 }
1237 fclose (unit);
1238 }
1239
1240}
1241
1242void MTrigger::GetResponse(Float_t *resp) {
1243 // ============================================================
1244 //
1245 // puts the standard response function into the array resp
1246
1247 for ( Int_t i=0; i< RESPONSE_SLICES; i++ ) {
1248
1249 resp[i] = sing_resp[i] ;
1250 }
1251
1252}
1253
1254void MTrigger::GetMapDiskriminator(Byte_t *map){
1255 //=============================================================
1256 //
1257 // Gives a map of the fired pixels (Bool_t dknt [pixnum])
1258 // in an array of Byte_t (each byte has the information for 8 pixels)
1259 //
1260
1261 Int_t i,ii;
1262
1263 for(i=0;i<pixnum/8+1;i++){
1264 map[i]=0;
1265 }
1266
1267 for(i=0;i<pixnum;i++){
1268 ii=(Int_t)i/8;
1269 if (dknt[i]==kTRUE){
1270 map[ii]=map[ii]+(Int_t)pow((double)2, (double)i-ii*8);
1271 }
1272 }
1273}
1274
1275
1276void MTrigger::Diskriminate() {
1277 // ============================================================
1278 //
1279 // Diskriminates the analog signal
1280 //
1281 // one very important part is the calucaltion of the baseline
1282 // shift. Because of the AC coupling of the PMT, only the
1283 // fluctuations are interesting. If there are a lot of phe,
1284 // a so-called shift of the baseline occurs.
1285 //
1286
1287 Int_t iM = 0 ;
1288 Int_t i, ii ;
1289
1290
1291 Int_t jmax = (Int_t) (gate_leng * SLICES_PER_NSEC ) ;
1292
1293 //
1294 // first of all determine the integral of all signals to get
1295 // the baseline shift.
1296 //
1297
1298 for ( i=0 ; i < pixnum ; i++ ) {
1299 if ( used[i] == kTRUE ) {
1300 baseline[i] = 0. ;
1301
1302 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
1303 baseline[i] += a_sig[i][ii] ;
1304 }
1305
1306 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
1307
1308 //
1309 // now correct the baseline shift in the analog signal!!
1310 //
1311 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
1312 a_sig[i][ii] = a_sig[i][ii] - baseline[i] ;
1313 }
1314 }
1315 }
1316
1317 //
1318 // now the diskrimination is coming
1319 //
1320 // take only that pixel which are used
1321 //
1322
1323 for ( i=0 ; i < pixnum; i++ ) {
1324 if ( used [i] == kTRUE ) {
1325
1326 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
1327 //
1328 // first check if the signal is crossing the CHANNEL_THRESHOLD
1329 // form low to big signals
1330 //
1331
1332 if ( a_sig[i][ii-1] < chan_thres[i] &&
1333 a_sig[i][ii] >= chan_thres[i] ) {
1334 {
1335 if ( dknt[i] == kFALSE ) {
1336 dknt [i] = kTRUE ;
1337 iM++ ;
1338 }
1339 // cout << " disk " << ii ;
1340 //
1341 // put the standard diskriminator signal in
1342 // the diskriminated signal
1343 //
1344 for ( Int_t j=0 ; j < jmax ; j++ ) {
1345
1346 if ( ii+j < TRIGGER_TIME_SLICES ) {
1347 d_sig [i][ii+j] = 1. ;
1348 }
1349 }
1350 ii = ii + jmax ;
1351 }
1352 }
1353 else d_sig[i][ii]=0.;
1354 }
1355 }
1356 }
1357}
1358
1359
1360void MTrigger::ShowSignal (MMcEvt *McEvt) {
1361 // ============================================================
1362 //
1363 // This method is used to book the histogramm to show the signal in
1364 // a special gui frame (class MGTriggerSignal). After the look onto the
1365 // signals for a better understanding of the things we will expect
1366 // the gui frame and all histogramms will be destroyed.
1367 //
1368
1369 //
1370 // first of all create a list of the histograms to show
1371 //
1372 // take only that one with a entry
1373
1374 TH1F *hist ;
1375 TH1F *dhist ;
1376 Char_t dumm[10];
1377 Char_t name[256];
1378
1379 TObjArray *AList ;
1380 AList = new TObjArray(10) ;
1381
1382 TObjArray *DList ;
1383 DList = new TObjArray(10) ;
1384
1385 // the list of analog signal histograms
1386 // at the beginning we initalise 10 elements
1387 // but this array expand automaticly if neccessay
1388
1389 Int_t ic = 0 ;
1390 for ( Int_t i=0 ; i < pixnum; i++ ) {
1391 if ( used [i] == kTRUE ) {
1392
1393 sprintf (dumm, "A_%d", i ) ;
1394 sprintf (name, "analog %d", i ) ;
1395
1396 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
1397 //
1398 // fill the histogram
1399 //
1400
1401 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
1402 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
1403 }
1404 hist->SetMaximum(8.);
1405 hist->SetMinimum(-8.);
1406 hist->SetStats(kFALSE);
1407
1408 AList->Add(hist) ;
1409
1410 sprintf (dumm, "D_%d", i ) ;
1411 sprintf (name, "digital %d", i ) ;
1412
1413 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
1414 if ( dknt[i] == kTRUE ) {
1415 //
1416 // fill the histogram of digital signal
1417 //
1418 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
1419 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
1420 dhist->SetStats(kFALSE);
1421 }
1422 }
1423 dhist->SetMaximum(1.5);
1424
1425 DList->Add(dhist);
1426
1427 ic++ ;
1428
1429 }
1430 }
1431
1432 //
1433 // create the Gui Tool
1434 //
1435 //
1436
1437 new MGTriggerSignal(McEvt,
1438 AList,
1439 DList,
1440 gClient->GetRoot(),
1441 gClient->GetRoot(),
1442 400, 400 ) ;
1443
1444 //
1445 // delete the List of histogramms
1446 //
1447
1448 AList->Delete() ;
1449 DList->Delete() ;
1450
1451 delete AList ;
1452 delete DList ;
1453}
1454
1455
1456Int_t MTrigger::ZeroLevel() {
1457 // ============================================================
1458 //
1459 // This is a level introduced just to speed up the program.
1460 // It makes sense to look for next neighbours only if there
1461 // are at least trigger_multi pixels with a diskriminator
1462 // signal.
1463 //
1464
1465 //
1466 // first count the pixels with a diskriminator signal
1467 //
1468 Int_t iMul = 0 ;
1469 for ( Int_t iP =0 ; iP < pixnum; iP++ ) {
1470 //
1471 //
1472
1473 if ( dknt[iP] == kTRUE ) {
1474 iMul++ ;
1475 }
1476 }
1477
1478
1479 //
1480 // only if there are at least more pixels than requested
1481 // it make sense to look into details
1482 if ( iMul >= trigger_multi ) {
1483 //
1484 // fill the sum signal of all diskriminator signals
1485 //
1486 for ( Int_t iP =0 ; iP < pixnum; iP++ ) {
1487 //
1488 //
1489 if ( dknt[iP] == kTRUE ) {
1490 //
1491 // sum it up
1492 //
1493 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1494 //
1495 //
1496 sum_d_sig [iS] += d_sig[iP][iS] ;
1497 }
1498 }
1499 }
1500 //
1501 // run over the sum_d_sig and check each time slice
1502 //
1503 Int_t iReturn = 0 ;
1504
1505 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1506
1507 if ( sum_d_sig[iS] >= trigger_multi ) {
1508 iReturn++ ;
1509 nZero++;
1510 SlicesZero[iS] = kTRUE ;
1511
1512 }
1513 else SlicesZero[iS] = kFALSE;
1514 }
1515 return ( iReturn ) ;
1516 }
1517 else {
1518 return 0 ;
1519 }
1520}
1521
1522Int_t MTrigger::FirstLevel() {
1523 //=================================================
1524 //
1525 // This is a level trigger which can look for several
1526 // multiplicities (trigger_multi)
1527 // and topologies (trigger_geometry)
1528 //
1529
1530 Int_t iReturn = 0 ; // Return value for this function
1531
1532 // Definition of needed variables
1533 Bool_t Muster[pixnum] ;
1534 Bool_t Neighb[pixnum] ;
1535 Int_t iMulti = 0 ;
1536
1537 // We put several wrong topologies which we already know that they
1538 // are not possible. It can save time.
1539
1540 if (trigger_geometry==0 && trigger_multi>7) {
1541 cout <<"You are looking for a topology that needs more than six neighbours of the same pixel"<<endl;
1542 cout <<" Topology "<<trigger_geometry<<" Multiplicity "<<trigger_multi<<endl;;
1543 return (kFALSE);
1544 }
1545
1546 if (trigger_geometry==2 && trigger_multi<3) {
1547 cout<<"Closed pack geometry with multiplicity "<<trigger_multi<<" does not make sense, I'll check simple neihgbour condition"<<endl;
1548 trigger_geometry=1;
1549 }
1550 if (trigger_geometry>2) {
1551 cout << "This trigger topology is not implemented"<<endl;
1552 return (kFALSE);
1553 }
1554
1555 //
1556 // loop over all ZeroLevel Trigger
1557 //
1558 // it is only neccessary to look after a ZeroLevel Trigger for
1559 // a FirstLevel (NextNeighbour) trigger.
1560 //
1561
1562 if (nZero) {
1563
1564 //
1565 // Then run over all slices
1566 //
1567
1568 for ( Int_t iSli = 0;
1569 iSli < TRIGGER_TIME_SLICES; iSli++ ) {
1570
1571 // Check if this time slice has more fired pixels than trigger_multi
1572
1573 if (SlicesZero[iSli]){
1574 //
1575 // Loop over trigger cells. It is topology analisy,
1576 // therefore it is keep here after multiplicity and
1577 // threshold checks.
1578 //
1579
1580 for(Int_t iCell=0; iCell<TRIGGER_CELLS; iCell++){
1581 //
1582 // then look in all pixel of that cell if the
1583 // diskriminated signal is 1
1584 //
1585 for ( Int_t iPix = 0 ; iPix < pixnum; iPix++ ) {
1586 Muster[iPix] = kFALSE ;
1587 Neighb[iPix] = kFALSE ;
1588 // Select pixels which are used and it the current cell
1589 if ( used [iPix] == kTRUE && TC[iCell][iPix]==kTRUE) {
1590 //
1591 // now check the diskriminated signal
1592 //
1593 if ( d_sig [iPix][iSli] > 0. ) {
1594 Muster[iPix] = kTRUE ;
1595 }
1596 }
1597 } // end of loop over the pixels
1598
1599 //
1600 // Here we check which of the "muster" pixels will be fired for
1601 // the minimum required overlaping time
1602 //
1603
1604 OverlapingTime(Muster, &Muster[0],iSli);
1605
1606 //
1607 // here we have to look for the topologies
1608 //
1609
1610 switch(trigger_geometry){
1611 case 0:{
1612
1613 // It looks for a pixel above threshold which has
1614 // trigger_multi-1 neighbour pixels above threshold
1615
1616 Bool_t Dummy[pixnum] ;
1617
1618 // Loop over all pixels
1619 for (int j=0;j<pixnum;j++){
1620
1621 for (int k=0; k<pixnum; k++){
1622 Neighb[k]=kFALSE;
1623
1624 Dummy[k] = Muster[k] ;
1625 }
1626 if(Muster[j]){
1627 // If pixel is fired, it checks how many fired neighbours it has
1628 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1629 Neighb[j] = kTRUE ;
1630 Dummy[j] = kTRUE ;
1631 if (!PassNextNeighbour(Dummy, &Neighb[0])){
1632 break;
1633 }
1634 for (int k=0; k<pixnum; k++){
1635 if (Neighb[k]){
1636 Dummy[k]=kFALSE;
1637 Neighb[k]=kFALSE;
1638 }
1639 }
1640 }
1641 if (iMulti==trigger_multi ) {
1642 //
1643 // A NN-Trigger is detected at time Slice
1644 //
1645 PixelsFirst[nFirst] = j; // We save pixel that triggers
1646 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1647 iReturn++ ;
1648 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1649 iCell=TRIGGER_CELLS; // We skip the remaining trigger cells
1650 break ;
1651 }
1652 }
1653 }
1654 break;
1655 };
1656
1657 case 1:{
1658
1659 // It looks for trigger_multi neighbour pixels above the
1660 // threshold.
1661
1662 for (int j=0;j<pixnum;j++){
1663 if(Muster[j]){
1664 // It checks if you can find
1665 // trigger_multi fired neighbour pixels
1666 Neighb[j] = kTRUE ;
1667 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1668 if (!PassNextNeighbour(Muster, &Neighb[0]))
1669 break;
1670 }
1671 if (iMulti==trigger_multi ) {
1672 //
1673 // A NN-Trigger is detected at time Slice
1674 //
1675 PixelsFirst[nFirst] = j; // We save pixel that triggers
1676 SlicesFirst[nFirst++] = iSli ; // We save when it triggers
1677 iReturn++ ;
1678 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1679 iCell=TRIGGER_CELLS; // We skip the remaining trigger cells
1680 break ;
1681 }
1682 else {
1683 // We put Neighb to kFALSE to check an other pixel
1684 for (int k=0; k<pixnum; k++){
1685 if (Neighb[k]){
1686 Neighb[k]=kFALSE;
1687 }
1688 }
1689 }
1690 }
1691 }
1692 break;
1693 };
1694 case 2:{
1695
1696 // It looks for trigger_multi closed pack neighbours
1697 // above threshold
1698 // Closed pack means that you can take out any pixel
1699 // and you will still get a trigger for trigger_multi -1
1700 // The algorithm is not perfect, there still somes cases
1701 // that are not really well treated
1702
1703 Int_t closed_pack = 1;
1704
1705 for (int j=0;j<pixnum;j++){
1706 if(Muster[j]){
1707 // It checks if there are trigger_multi
1708 // neighbours above threshold
1709
1710 Neighb[j] = kTRUE ;
1711 iMulti=1;
1712
1713 //while(PassNextNeighbour(Muster, &Neighb[0])) iMulti++;
1714 for (iMulti=1;iMulti<trigger_multi;iMulti++){
1715 if (!PassNextNeighbour(Muster, &Neighb[0]))
1716 break;
1717 }
1718
1719 if (iMulti==trigger_multi ) {
1720 //
1721 // A NN-Trigger is detected at time Slice
1722 //
1723
1724 // Check if there is closed pack topology
1725
1726 Bool_t Aux1[pixnum];
1727 Bool_t Aux2[pixnum];
1728 for (int jj=0;jj<pixnum;jj++)
1729 Aux2[jj]=kFALSE;
1730
1731 for (int i=0;i<pixnum;i++){
1732 if (Neighb[i]) {
1733 // Loop over pixels that achive neighbouring condition
1734
1735 for (int jj=0;jj<pixnum;jj++) {
1736
1737 Aux1[jj] = Neighb[jj] ; // huschel
1738 Aux2[jj]=kFALSE;
1739 }
1740
1741 // It checks if taking out any of the pixels we lose
1742 // neighbouring condition for trigger_multi -1
1743
1744 Aux1[i]=kFALSE;
1745 closed_pack=0;
1746 for (int jj=0;jj<pixnum;jj++) {
1747 if (Aux1[jj]==kTRUE){
1748 Aux2[jj]=kTRUE;
1749 for (iMulti=1;iMulti<(trigger_multi-1);iMulti++){
1750 if (!PassNextNeighbour(Aux1, &Aux2[0]))
1751 break;
1752 }
1753 if (iMulti==(trigger_multi-1)){
1754 // We found a NN trigger for trigger_multi -1
1755 // taking out pixel jj
1756 closed_pack=1;
1757 break;
1758 }
1759 Aux2[jj]=kFALSE;
1760 }
1761 }
1762 if (!closed_pack) break;
1763 // For some pixell we did not found NN condition
1764 // for trigger_multi -1
1765 }
1766 }
1767 if (closed_pack){
1768 PixelsFirst[nFirst] = j; // We save pixel that triggers
1769 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1770 iReturn++ ;
1771 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1772 iCell=TRIGGER_CELLS; // We skip the remaining trigger cells
1773 break ;
1774 }
1775 else {
1776 for (int k=0; k<pixnum; k++){
1777 if (Neighb[k]){
1778 Neighb[k]=kFALSE;
1779 }
1780 }
1781 }
1782 } // end if trigger multiplicity achived
1783 else{
1784 for (int k=0; k<pixnum; k++)
1785 Neighb[k]=kFALSE;
1786 }
1787 } // end if pixel fired
1788 } // end loop trigger pixels
1789 break;
1790 }; // end case 2:
1791 default:{
1792 cout << "This topology is not implemented yet"<<endl;
1793 break;
1794 }
1795 }
1796 } //end loop over trigger cells.
1797 }
1798 } // end of loop over the slices
1799 } // end of conditional for a trigger Zero
1800
1801 //
1802 // return the Number of FirstLevel Triggers
1803 //
1804 return iReturn ;
1805}
1806
1807
1808Bool_t MTrigger::PassNextNeighbour ( Bool_t m[], Bool_t *n) {
1809 //
1810 // This function is looking for a next neighbour of pixels in n[]
1811 // above triggers using a NNlookup table.
1812 // This table is builded by the default constructor
1813 //
1814
1815 //
1816 // loop over all trigger pixels
1817 //
1818
1819 Bool_t return_val = kFALSE;
1820
1821 for ( Int_t i=0; i<pixnum; i++) {
1822 //
1823 // check if this pixel has a diskrminator signal
1824 // (this is inside n[] )
1825 //
1826
1827 if ( n[i] && !return_val) {
1828
1829 //
1830 // look in the next neighbours from the lookuptable
1831 //
1832
1833 for ( Int_t kk=0; kk<6; kk++ ) {
1834 //
1835 // if the nextneighbour is outside the triggerarea do nothing
1836 //
1837 if (!return_val){
1838 if (NN[kk][i] >= pixnum ) {
1839
1840 }
1841 // the nextneighbour is not inside the pixnum
1842 else {
1843 //
1844 // look if the boolean of nn pixels is true
1845 //
1846
1847 if ( m[ NN[kk][i] ] && !n[NN[kk][i]] ) {
1848 n[NN[kk][i]]=kTRUE ;
1849 return_val =kTRUE;
1850 }
1851 }
1852 }
1853 else break;
1854 }
1855 }
1856 }
1857 return(return_val);
1858}
1859
1860Float_t MTrigger::GetFirstLevelTime( Int_t il ){
1861
1862 //=============================================================
1863 //
1864 // It gives the time for the il trigger at first level
1865
1866 return((Float_t) ((Float_t) SlicesFirst[il]/((Float_t) SLICES_PER_NSEC)));
1867}
1868
1869Int_t MTrigger::GetFirstLevelPixel( Int_t il ){
1870
1871 //=============================================================
1872 //
1873 // It gives the pixel that triggers for the il trigger at first level
1874 return(PixelsFirst[il]);
1875}
1876
1877void MTrigger::OverlapingTime ( Bool_t m[], Bool_t *n, Int_t ifSli){
1878
1879 //============================================================
1880 //
1881 // It returns in n the pixels of m that are fired during the
1882 // required overlaping time for trigger after ifSli
1883
1884 int i,j;
1885 int iNumSli;
1886
1887 // Translation from ns to slices
1888 iNumSli=(int) (overlaping_time*SLICES_PER_NSEC);
1889 if (iNumSli<1) iNumSli=1;
1890
1891 // Put pixels that fulfill the requirement in n
1892 for (i=0;i<pixnum;i++){
1893 if (m[i]==kTRUE){
1894 for(j=ifSli;j<ifSli+iNumSli;j++){
1895 if(!d_sig[i][j]){
1896 n[i]=kFALSE;
1897 break;
1898 }
1899 }
1900 }
1901 }
1902
1903}
1904
1905
1906
Note: See TracBrowser for help on using the repository browser.