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

Last change on this file since 5083 was 5082, checked in by moralejo, 21 years ago
*** empty log message ***
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
16MTrigger::MTrigger(int pix) {
17 // ============================================================
18 //
19 // default constructor
20 //
21 // The procedure is the following:
22 //
23 // 1. Allocation of some memory needed
24 // 2. some parameters of the trigger are set to default.
25 // 3. if a File MTrigger.card exists in the current directory,
26 // this parameters of the trigger may be changed
27 // 4. Then the all signals are set to zero
28
29 FILE *unit_mtrig ;
30 Int_t endflag = 1 ;
31 Int_t bthresholdpixel = FALSE;
32 char datac[256] ;
33 char dummy[50] ;
34 char input_thres[50];
35 Int_t i, ii ;
36
37 Float_t threshold ;
38
39 // Number of pixels in the trigger region
40 pixnum=pix;
41
42 //
43 // allocate the memory for the 2dim arrays (a_sig, d_sig )
44 //
45
46 used = new Bool_t[pix];
47 nphotshow = new Int_t[pix];
48 nphotnsb = new Int_t[pix];
49 nphotstar = new Int_t[pix];
50 a_sig = new Float_t * [pix];
51 d_sig = new Float_t * [pix];
52 baseline = new Float_t[pix];
53 dknt = new Bool_t[pix];
54 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
55 chan_thres = new Float_t[pix];
56 for(Int_t j=0;j<6;j++)
57 NN[j] = new Int_t[pix];
58 for(Int_t j=0;j<TRIGGER_CELLS;j++)
59 TC[j] = new Int_t[pix];
60
61 for( Int_t j=0; j<pix; j++ ) {
62
63 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
64
65 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
66 }
67
68
69
70 //
71 // set the values for the standard response pulse
72 //
73
74 fwhm_resp = RESPONSE_FWHM ;
75 ampl_resp = RESPONSE_AMPLITUDE ;
76
77 overlaping_time = TRIGGER_OVERLAPING;
78
79 threshold = CHANNEL_THRESHOLD ;
80
81
82 gate_leng = TRIGGER_GATE ;
83 trigger_multi = TRIGGER_MULTI ;
84 trigger_geometry = TRIGGER_GEOM ;
85
86 //
87 // check if the file MTrigger.card exists
88 //
89
90 if ( (unit_mtrig = fopen ("MTrigger.card", "r")) != 0 ) {
91 cout << "[MTrigger] use the values from MTrigger.card "<< endl ;
92
93 while ( endflag == 1 ) {
94 //
95 //
96 fgets (datac, 255, unit_mtrig) ;
97 // printf ("--> %s <--", datac ) ;
98
99 //
100 // now compare the line with controlcard words
101 //
102
103 if ( strncmp (datac, "channel_threshold", 17 ) == 0 ) {
104 sscanf (datac, "%s %f", dummy, &threshold ) ;
105 }
106 else if ( strncmp (datac, "gate_length", 11 ) == 0 ) {
107 sscanf (datac, "%s %f", dummy, &gate_leng ) ;
108 }
109 else if ( strncmp (datac, "response_fwhm", 13 ) == 0 ) {
110 sscanf (datac, "%s %f", dummy, &fwhm_resp ) ;
111 }
112 else if ( strncmp (datac, "response_ampl", 13 ) == 0 ) {
113 sscanf (datac, "%s %f", dummy, &ampl_resp ) ;
114 }
115 else if ( strncmp (datac, "overlaping", 10 ) == 0 ) {
116 sscanf (datac, "%s %f", dummy, &overlaping_time ) ;
117 }
118 else if ( strncmp (datac, "multiplicity", 12 ) == 0 ) {
119 sscanf (datac, "%s %f", dummy, &trigger_multi ) ;
120 }
121 else if ( strncmp (datac, "topology", 8 ) == 0 ) {
122 sscanf (datac, "%s %i", dummy, &trigger_geometry ) ;
123 }
124 else if ( strncmp (datac, "threshold_file", 14 ) == 0 ) {
125 sscanf (datac, "%s %s", dummy, input_thres ) ;
126 bthresholdpixel=kTRUE;
127 }
128
129 if ( feof(unit_mtrig) != 0 ) {
130 endflag = 0 ;
131 }
132
133 }
134
135 fclose ( unit_mtrig ) ;
136 }
137 else {
138 cout << "[MTrigger] use the standard values for MTrigger "<< endl ;
139 }
140
141 cout << endl
142 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
143 if(bthresholdpixel){
144 cout<<endl
145 << "[MTrigger] ChannelThreshold from file: "<<input_thres
146 <<endl;
147 }
148 else{
149 cout << endl
150 << "[MTrigger] ChannelThreshold: " << threshold << " mV"
151 << endl ;
152 }
153 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
154 << endl ;
155 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
156 << endl ;
157 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
158 << endl ;
159 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
160 << endl ;
161 cout << "[MTrigger] Trigger Multiplicity: " << trigger_multi << " pixels"
162 << endl ;
163 cout << "[MTrigger] Trigger Topology: " << trigger_geometry
164 << endl ;
165
166 cout << endl ;
167
168
169 //
170 // we have introduced individual thresholds for all pixels
171 //
172 FILE *unit_thres;
173
174 if (bthresholdpixel == kTRUE) {
175 if ((unit_thres=fopen(input_thres, "r"))==0){
176 cout<<"WARNING: not able to read ..."<<input_thres<<endl;
177 cout<<"Threshold will be set to "<<threshold<<" for all pixels"<<endl;
178 for (Int_t k=0; k<pix; k++ ) {
179 chan_thres[k] = threshold ;
180 }
181 }
182 else {
183 for (i=0;i<pix;i++){
184 fscanf(unit_thres, "%f",&chan_thres[i]);
185 }
186 fclose (unit_thres);
187 }
188 }
189 else {
190 for (Int_t k=0; k<pix; k++ ) {
191 chan_thres[k] = threshold ;
192 }
193 }
194
195
196 //
197 // set up the response shape
198 //
199
200 Float_t sigma ;
201 Float_t x, x0 ;
202
203 sigma = fwhm_resp / 2.35 ;
204 x0 = 3*sigma ;
205
206 for (i=0; i< RESPONSE_SLICES ; i++ ) {
207
208 x = i * (1./((Float_t)SLICES_PER_NSEC))
209 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
210
211 sing_resp[i] =
212 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
213
214 }
215
216 //
217 // look for the time between start of response function and the
218 // maximum value of the response function. This is needed by the
219 // member functions FillNSB() and FillStar()
220 //
221
222 Int_t imax = 0 ;
223 Float_t max = 0. ;
224 for (i=0; i< RESPONSE_SLICES ; i++ ) {
225 if ( sing_resp[i] > max ) {
226 imax = i ;
227 max = sing_resp[i] ;
228 }
229 }
230
231 peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ;
232
233
234 //
235 // the amplitude of one single photo electron is not a constant.
236 // There exists a measured distribution from Razmik. This distribution
237 // is used to simulate the noise of the amplitude.
238 // For this a histogramm (histPmt) is created and filled with the
239 // values.
240 //
241
242 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
243
244 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
245 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
246 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
247 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
248 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
249
250 histMean = histPmt->GetMean() ;
251
252 for (i=0;i<41;i++){
253 histPmt->SetBinContent(i,ValRazmik[i]);
254 }
255
256 histMean = histPmt->GetMean() ;
257
258 //
259 // create the random generator for the Electronic Noise
260 //
261
262 GenElec = new TRandom() ;
263
264 GenElec->SetSeed(0);
265
266 //
267 // Read in the lookup table for NN trigger
268 //
269
270 FILE *unit ;
271 int id ;
272
273 i = 0 ;
274
275 if ( (unit = fopen("../include-MTrigger/TABLE_NEXT_NEIGHBOUR", "r" )) == 0 ) {
276 cout << "ERROR: not able to read ../include-MTrigger/TABLE_NEXT_NEIGHBOUR"
277 << endl ;
278 exit(123) ;
279 }
280 else {
281 while ( i < pix )
282 {
283 fscanf ( unit, " %d", &id ) ;
284
285 for ( Int_t k=0; k<6; k++ ) {
286 fscanf ( unit, "%d ", &NN[k][i] ) ;
287 }
288 i++ ;
289 }
290
291 fclose (unit) ;
292 }
293
294
295 //
296 // Read in the lookup table for trigger cells
297 //
298
299 i = 0 ;
300
301 if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) {
302 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
303 << endl ;
304 exit(123) ;
305 }
306 else {
307 while ( i < pix )
308 {
309 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
310 TC[k][i]=kFALSE;
311 }
312 i++ ;
313 }
314 while ( feof(unit) == 0 ) {
315 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
316 fscanf ( unit, "%d ", &i ) ;
317 if ((i-1)<pix)
318 TC[k][i-1]=kTRUE;
319 }
320 }
321 fclose (unit) ;
322 }
323
324
325 //
326 //
327 // set all the booleans used to FALSE, indicating that the pixel is not
328 // used in this event.
329 //
330
331 for ( i =0 ; i <pix ; i++ ) {
332 used [i] = kFALSE ;
333 dknt [i] = kFALSE ;
334
335 nphotshow[i] = 0 ;
336 nphotnsb [i] = 0 ;
337 nphotstar[i] = 0 ;
338
339 baseline[i] = 0 ;
340 }
341
342 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
343 sum_d_sig[ii] = 0. ;
344 }
345
346 //
347 // set the information about the Different Level Triggers to zero
348 //
349
350 nZero = nFirst = nSecond = 0 ;
351
352 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
353 SlicesZero[ii] = kFALSE;
354 }
355
356 for ( i = 0 ; i < 5 ; i++) {
357 SlicesFirst[i] = -50 ;
358 SlicesSecond[i] = -50 ;
359 PixelsFirst[i] = -1;
360 PixelsSecond[i] = -1;
361 }
362
363 cout << " end of MTrigger::MTrigger()" << endl ;
364}
365
366MTrigger::MTrigger(Int_t pix, MGeomCam *camgeom,
367 float gate, float overt, float ampl, float fwhm, int ct_id) {
368 // ============================================================
369 //
370 // constructor
371 //
372 // The procedure is the following:
373 //
374 // 1. Allocation of some memory needed
375 // 2. some parameters of the trigger are set.
376 // 3. Then the all signals are set to zero
377
378 Int_t i, ii ;
379
380 Float_t threshold ;
381
382 // Number of pixels in the trigger region
383 pixnum=pix;
384
385 //
386 // allocate the memory for the 2dim arrays (a_sig, d_sig )
387 //
388
389 used = new Bool_t[pix];
390 nphotshow = new Int_t[pix];
391 nphotnsb = new Int_t[pix];
392 nphotstar = new Int_t[pix];
393 a_sig = new Float_t * [pix];
394 d_sig = new Float_t * [pix];
395 baseline = new Float_t[pix];
396 dknt = new Bool_t[pix];
397 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
398 chan_thres = new Float_t[pix];
399 for(Int_t j=0;j<6;j++)
400 NN[j] = new Int_t[pix];
401 for(Int_t j=0;j<TRIGGER_CELLS;j++)
402 TC[j] = new Int_t[pix];
403
404 for( Int_t j=0; j<pix; j++ ) {
405
406 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
407
408 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
409 }
410
411 //
412 // set the values for the standard response pulse
413 //
414
415 fwhm_resp = fwhm ;
416 ampl_resp = ampl ;
417
418 overlaping_time = overt;
419
420
421 threshold = CHANNEL_THRESHOLD ;
422
423
424 gate_leng = gate ;
425 trigger_multi = TRIGGER_MULTI ;
426 trigger_geometry = TRIGGER_GEOM ;
427
428 cout << endl
429 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
430 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
431 << endl ;
432 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
433 << endl ;
434 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
435 << endl ;
436 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
437 << endl ;
438 cout << endl ;
439
440 for (Int_t k=0; k<pixnum; k++ ) {
441 chan_thres[k] = threshold ;
442 }
443
444 //
445 // set up the response shape
446 //
447
448 Float_t sigma ;
449 Float_t x, x0 ;
450
451 sigma = fwhm_resp / 2.35 ;
452 x0 = 3*sigma ;
453
454 for (i=0; i< RESPONSE_SLICES ; i++ ) {
455
456 x = i * (1./((Float_t)SLICES_PER_NSEC))
457 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
458
459 sing_resp[i] =
460 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
461
462 }
463
464 //
465 // look for the time between start of response function and the
466 // maximum value of the response function. This is needed by the
467 // member functions FillNSB() and FillStar()
468 //
469
470 Int_t imax = 0 ;
471 Float_t max = 0. ;
472 for (i=0; i< RESPONSE_SLICES ; i++ ) {
473 if ( sing_resp[i] > max ) {
474 imax = i ;
475 max = sing_resp[i] ;
476 }
477 }
478
479 peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ;
480
481 //
482 // the amplitude of one single photo electron is not a constant.
483 // There exists a measured distribution from Razmik. This distribution
484 // is used to simulate the noise of the amplitude.
485 // For this a histogramm (histPmt) is created and filled with the
486 // values.
487 //
488
489 char histname[32];
490 sprintf(histname, "histPmt_%d", ct_id);
491 histPmt = new TH1F (histname,"Noise of PMT", 40, 0., 40.) ;
492
493 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
494 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
495 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
496 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
497 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
498
499 histMean = histPmt->GetMean() ;
500
501 for (i=0;i<41;i++){
502 histPmt->SetBinContent(i,ValRazmik[i]);
503 }
504
505 histMean = histPmt->GetMean() ;
506
507 //
508 // create the random generator for the Electronic Noise
509 //
510
511 GenElec = new TRandom() ;
512
513 //
514 // Read in the lookup table for NN trigger
515 //
516
517#ifndef __STARRESPO__
518 for(i=0; i < pixnum;i++ )
519 {
520 MGeomPix &pixel = (*camgeom)[i];
521 for ( Int_t k=0; k<6; k++ ) {
522 NN[k][i]=pixel.GetNeighbor(k);
523 }
524 }
525#endif
526 //
527 // Read in the lookup table for trigger cells
528 //
529
530 FILE *unit;
531
532 i = 0 ;
533
534 if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) {
535 cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS"
536 << endl ;
537 exit(123) ;
538 }
539 else {
540 while ( i < pixnum )
541 {
542 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
543 TC[k][i]=kFALSE;
544 }
545 i++ ;
546 }
547 while ( feof(unit) == 0 ) {
548 for ( Int_t k=0; k<TRIGGER_CELLS; k++ ) {
549 fscanf ( unit, "%d ", &i ) ;
550 if((i-1)<pixnum)
551 TC[k][i-1]=kTRUE;
552 }
553 }
554 fclose (unit) ;
555 }
556
557 //
558 //
559 // set all the booleans used to FALSE, indicating that the pixel is not
560 // used in this event.
561 //
562
563 for ( i =0 ; i <pixnum ; i++ ) {
564 used [i] = kFALSE ;
565 dknt [i] = kFALSE ;
566
567 nphotshow[i] = 0 ;
568 nphotnsb [i] = 0 ;
569 nphotstar[i] = 0 ;
570
571 baseline[i] = 0 ;
572 }
573
574 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
575 sum_d_sig[ii] = 0. ;
576 }
577
578 //
579 // set the information about the Different Level Triggers to zero
580 //
581
582 nZero = nFirst = nSecond = 0 ;
583
584 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
585 SlicesZero[ii] = kFALSE;
586 }
587
588 for ( i = 0 ; i < 5 ; i++) {
589 SlicesFirst[i] = -50 ;
590 SlicesSecond[i] = -50 ;
591 PixelsFirst[i] = -1;
592 PixelsSecond[i] = -1;
593 }
594 cout << " end of MTrigger::MTrigger()" << endl ;
595}
596MTrigger::MTrigger(Int_t pix,
597 float gate, float overt, float ampl, float fwhm) {
598 // ============================================================
599 //
600 // constructor
601 //
602 // The procedure is the following:
603 //
604 // 1. Allocation of some memory needed
605 // 2. some parameters of the trigger are set.
606 // 3. Then the all signals are set to zero
607
608 Int_t i, ii ;
609
610 Float_t threshold ;
611
612 // Number of pixels in the trigger region
613 pixnum=pix;
614
615 //
616 // allocate the memory for the 2dim arrays (a_sig, d_sig )
617 //
618
619 used = new Bool_t[pix];
620 nphotshow = new Int_t[pix];
621 nphotnsb = new Int_t[pix];
622 nphotstar = new Int_t[pix];
623 a_sig = new Float_t * [pix];
624 d_sig = new Float_t * [pix];
625 baseline = new Float_t[pix];
626 dknt = new Bool_t[pix];
627 noise = new Float_t[TRIGGER_TIME_SLICES*1001];
628 chan_thres = new Float_t[pix];
629 for(Int_t j=0;j<6;j++)
630 NN[j] = new Int_t[pix];
631 for(Int_t j=0;j<TRIGGER_CELLS;j++)
632 TC[j] = new Int_t[pix];
633
634 for( Int_t j=0; j<pix; j++ ) {
635
636 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
637
638 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
639 }
640
641 //
642 // set the values for the standard response pulse
643 //
644
645 fwhm_resp = fwhm ;
646 ampl_resp = ampl ;
647
648 overlaping_time = overt;
649
650
651 threshold = CHANNEL_THRESHOLD ;
652
653
654 gate_leng = gate ;
655 trigger_multi = TRIGGER_MULTI ;
656 trigger_geometry = TRIGGER_GEOM ;
657
658 cout << endl
659 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
660 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
661 << endl ;
662 cout << "[MTrigger] Overlaping time: " << overlaping_time << " ns"
663 << endl ;
664 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
665 << endl ;
666 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
667 << endl ;
668 cout << endl ;
669
670 for (Int_t k=0; k<pixnum; k++ ) {
671 chan_thres[k] = threshold ;
672 }
673
674 //
675 // set up the response shape
676 //
677
678 Float_t sigma ;
679 Float_t x, x0 ;
680
681 sigma = fwhm_resp / 2.35 ;
682 x0 = 3*sigma ;
683
684 for (i=0; i< RESPONSE_SLICES ; i++ ) {
685
686 x = i * (1./((Float_t)SLICES_PER_NSEC))
687 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
688
689 sing_resp[i] =
690 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
691
692 }
693
694 //
695 // look for the time between start of response function and the
696 // maximum value of the response function. This is needed by the
697 // member functions FillNSB() and FillStar()
698 //
699
700 Int_t imax = 0 ;
701 Float_t max = 0. ;
702 for (i=0; i< RESPONSE_SLICES ; i++ ) {
703 if ( sing_resp[i] > max ) {
704 imax = i ;
705 max = sing_resp[i] ;
706 }
707 }
708
709 peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ;
710
711 //
712 // the amplitude of one single photo electron is not a constant.
713 // There exists a measured distribution from Razmik. This distribution
714 // is used to simulate the noise of the amplitude.
715 // For this a histogramm (histPmt) is created and filled with the
716 // values.
717 //
718
719 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
720
721 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
722 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
723 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
724 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
725 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
726
727 histMean = histPmt->GetMean() ;
728
729 for (i=0;i<41;i++){
730 histPmt->SetBinContent(i,ValRazmik[i]);
731 }
732
733 histMean = histPmt->GetMean() ;
734
735 //
736 // create the random generator for the Electronic Noise
737 //
738
739 GenElec = new TRandom() ;
740
741 //
742 //
743 // set all the booleans used to FALSE, indicating that the pixel is not
744 // used in this event.
745 //
746
747 for ( i =0 ; i <pixnum ; i++ ) {
748 used [i] = kFALSE ;
749 dknt [i] = kFALSE ;
750
751 nphotshow[i] = 0 ;
752 nphotnsb [i] = 0 ;
753 nphotstar[i] = 0 ;
754
755 baseline[i] = 0 ;
756 }
757
758 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
759 sum_d_sig[ii] = 0. ;
760 }
761
762 //
763 // set the information about the Different Level Triggers to zero
764 //
765
766 nZero = nFirst = nSecond = 0 ;
767
768 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
769 SlicesZero[ii] = kFALSE;
770 }
771
772 for ( i = 0 ; i < 5 ; i++) {
773 SlicesFirst[i] = -50 ;
774 SlicesSecond[i] = -50 ;
775 PixelsFirst[i] = -1;
776 PixelsSecond[i] = -1;
777 }
778 cout << " end of MTrigger::MTrigger()" << endl ;
779}
780
781MTrigger::~MTrigger() {
782 // ============================================================//
783 // destructor
784 //
785 int i;
786
787 delete histPmt ;
788
789 for(i=0;i<pixnum;i++){
790 //delete [] a_sig[i];
791 //delete [] d_sig[i];
792 }
793
794 delete GenElec;
795}
796
797
798void MTrigger::Reset() {
799 // ============================================================
800 //
801 // reset all values of the signals to zero
802 //
803 Int_t i, ii ;
804
805 for ( i =0 ; i <pixnum ; i++ ) {
806 used [i] = kFALSE ;
807 dknt [i] = kFALSE ;
808
809 nphotshow[i] = 0 ;
810 nphotnsb [i] = 0 ;
811 nphotstar[i] = 0 ;
812 }
813
814 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
815 sum_d_sig[ii] = 0. ;
816 }
817}
818
819void MTrigger::ClearZero() {
820 //
821 // set the information about the Zero Level Trigger to zero
822 //
823
824 Int_t i;
825
826 nZero = 0 ;
827
828 for (i=0 ; i<TRIGGER_TIME_SLICES; i++ ) {
829 SlicesZero[i] = kFALSE;
830 }
831
832}
833
834void MTrigger::ClearFirst() {
835 //
836 // set the information about the First Level Trigger to zero
837 //
838
839 Int_t i;
840
841 nFirst = 0 ;
842
843 for ( i = 0 ; i < 5 ; i++) {
844 SlicesFirst[i] = -50 ;
845 PixelsFirst[i] = -1;
846 }
847}
848
849Float_t MTrigger::FillShow(Int_t iPix, Float_t time) {
850 // ============================================================
851 //
852 // Fills the information of one single Phe electron that
853 // comes from the shower
854 //
855
856 //
857 // First check the time
858 //
859
860 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
861 cout << " WARNING: time of phe out of time range: " << time << endl;
862 return 0. ;
863 }
864 else {
865 return ( Fill( iPix, time, CASE_SHOW ) ) ;
866 }
867}
868
869Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) {
870 // ============================================================
871 //
872 // Fills the information of one single Phe electron that
873 // comes from the shower
874 //
875
876 //
877 // First check the time
878 //
879
880 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
881 cout << " WARNING: time of phe out of time range: " << time << endl;
882 return 0. ;
883 }
884 else {
885 return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ;
886 }
887}
888
889Float_t MTrigger::FillStar(Int_t iPix, Float_t time) {
890 // ============================================================
891 //
892 // Fills the information of one single Phe electron that
893 // comes from the shower
894 //
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) 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; 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 ; i++ ) {
1134
1135 x = i * (1./((Float_t)SLICES_PER_NSEC))
1136 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
1137
1138 sing_resp[i] =
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; 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(2,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 * 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 analisy,
1574 // therefore it is keep 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+=(50*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+=(50*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+=(50*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) 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*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}
1902
1903
1904
Note: See TracBrowser for help on using the repository browser.