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

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