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

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