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

Last change on this file since 427 was 410, checked in by MagicSol, 24 years ago
We itroduced a new constructor that has values for gate length and amplitud response and fhwn for one phe.
File size: 32.3 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
14
15MTrigger::MTrigger() {
16 // ============================================================
17 //
18 // default constructor
19 //
20 // The procedure is the following:
21 //
22 // 1. Allocation of some memory needed
23 // 2. some parameters of the trigger are set to default.
24 // 3. if a File MTrigger.card exists in the current directory,
25 // this parameters of the trigger may be changed
26 // 4. Then the all signals are set to zero
27
28 FILE *unit_mtrig ;
29 Int_t endflag = 1 ;
30 Int_t bthresholdpixel = FALSE;
31 char datac[256] ;
32 char dummy[50] ;
33 char input_thres[50];
34 Int_t i, ii ;
35
36 Float_t threshold ;
37
38 //
39 // allocate the memory for the 2dim arrays (a_sig, d_sig )
40 //
41
42 for( Int_t j=0; j<TRIGGER_PIXELS; j++ ) {
43
44 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
45
46 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
47 }
48
49 //
50 // set the values for the standard response pulse
51 //
52
53 fwhm_resp = RESPONSE_FWHM ;
54 ampl_resp = RESPONSE_AMPLITUDE ;
55
56 threshold = CHANNEL_THRESHOLD ;
57
58
59 gate_leng = TRIGGER_GATE ;
60 trigger_multi = TRIGGER_MULTI ;
61 trigger_geometry = TRIGGER_GEOM ;
62
63 //
64 // check if the file MTrigger.card exists
65 //
66
67 if ( (unit_mtrig = fopen ("MTrigger.card", "r")) != 0 ) {
68 cout << "[MTrigger] use the values from MTrigger.card "<< endl ;
69
70 while ( endflag == 1 ) {
71 //
72 //
73 fgets (datac, 255, unit_mtrig) ;
74 // printf ("--> %s <--", datac ) ;
75
76 //
77 // now compare the line with controlcard words
78 //
79
80 if ( strncmp (datac, "channel_threshold", 17 ) == 0 ) {
81 sscanf (datac, "%s %f", dummy, &threshold ) ;
82 }
83 else if ( strncmp (datac, "gate_length", 11 ) == 0 ) {
84 sscanf (datac, "%s %f", dummy, &gate_leng ) ;
85 }
86 else if ( strncmp (datac, "response_fwhm", 13 ) == 0 ) {
87 sscanf (datac, "%s %f", dummy, &fwhm_resp ) ;
88 }
89 else if ( strncmp (datac, "response_ampl", 13 ) == 0 ) {
90 sscanf (datac, "%s %f", dummy, &ampl_resp ) ;
91 }
92 else if ( strncmp (datac, "multiplicity", 12 ) == 0 ) {
93 sscanf (datac, "%s %f", dummy, &trigger_multi ) ;
94 }
95 else if ( strncmp (datac, "topology", 8 ) == 0 ) {
96 sscanf (datac, "%s %i", dummy, &trigger_geometry ) ;
97 }
98 else if ( strncmp (datac, "threshold_file", 14 ) == 0 ) {
99 sscanf (datac, "%s %s", dummy, input_thres ) ;
100 bthresholdpixel=TRUE;
101 }
102
103 if ( feof(unit_mtrig) != 0 ) {
104 endflag = 0 ;
105 }
106
107 }
108
109 fclose ( unit_mtrig ) ;
110 }
111 else {
112 cout << "[MTrigger] use the standard values for MTrigger "<< endl ;
113 }
114
115 cout << endl
116 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
117 if(bthresholdpixel){
118 cout<<endl
119 << "[MTrigger] ChannelThreshold from file: "<<input_thres
120 <<endl;
121 }
122 else{
123 cout << endl
124 << "[MTrigger] ChannelThreshold: " << threshold << " mV"
125 << endl ;
126 }
127 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
128 << endl ;
129 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
130 << endl ;
131 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
132 << endl ;
133 cout << "[MTrigger] Trigger Multiplicity: " << trigger_multi << " pixels"
134 << endl ;
135 cout << "[MTrigger] Trigger Topology: " << trigger_geometry
136 << endl ;
137
138 cout << endl ;
139
140
141 //
142 // we have introduced individual thresholds for all pixels
143 //
144 FILE *unit_thres;
145
146 if (bthresholdpixel == TRUE) {
147 if ((unit_thres=fopen(input_thres, "r"))==0){
148 cout<<"WARNING: not able to read ..."<<input_thres<<endl;
149 cout<<"Threshold will be set to "<<threshold<<" for all pixels"<<endl;
150 for (Int_t k=0; k<TRIGGER_PIXELS; k++ ) {
151 chan_thres[k] = threshold ;
152 }
153 }
154 else {
155 for (i=0;i<TRIGGER_PIXELS;i++){
156 fscanf(unit_thres, "%f",&chan_thres[i]);
157 }
158 fclose (unit_thres);
159 }
160 }
161 else {
162 for (Int_t k=0; k<TRIGGER_PIXELS; k++ ) {
163 chan_thres[k] = threshold ;
164 }
165 }
166
167
168 //
169 // set up the response shape
170 //
171
172 Float_t sigma ;
173 Float_t x, x0 ;
174
175 sigma = fwhm_resp / 2.35 ;
176 x0 = 3*sigma ;
177
178 for (i=0; i< RESPONSE_SLICES ; i++ ) {
179
180 x = i * (1./((Float_t)SLICES_PER_NSEC))
181 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
182
183 sing_resp[i] =
184 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
185
186 }
187
188 //
189 // look for the time between start of response function and the
190 // maximum value of the response function. This is needed by the
191 // member functions FillNSB() and FillStar()
192 //
193
194 Int_t imax = 0 ;
195 Float_t max = 0. ;
196 for (i=0; i< RESPONSE_SLICES ; i++ ) {
197 if ( sing_resp[i] > max ) {
198 imax = i ;
199 max = sing_resp[i] ;
200 }
201 }
202
203 peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ;
204
205
206 //
207 // the amplitude of one single photo electron is not a constant.
208 // There exists a measured distribution from Razmik. This distribution
209 // is used to simulate the noise of the amplitude.
210 // For this a histogramm (histPmt) is created and filled with the
211 // values.
212 //
213
214 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
215
216 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
217 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
218 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
219 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
220 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
221
222 histMean = histPmt->GetMean() ;
223
224 histPmt->SetContent( ValRazmik) ;
225
226 histMean = histPmt->GetMean() ;
227
228 //
229 // create the random generator for the Electronic Noise
230 //
231
232 GenElec = new TRandom() ;
233
234 //
235 // Read in the lookup table for NN trigger
236 //
237
238 FILE *unit ;
239 int id ;
240
241 i = 0 ;
242
243 if ( (unit = fopen("../include-MTrigger/TABLE_NEXT_NEIGHBOUR", "r" )) == 0 ) {
244 cout << "ERROR: not able to read ../include-MTrigger/TABLE_NEXT_NEIGHBOUR"
245 << endl ;
246 exit(123) ;
247 }
248 else {
249 while ( i < TRIGGER_PIXELS )
250 {
251 fscanf ( unit, " %d", &id ) ;
252
253 for ( Int_t k=0; k<6; k++ ) {
254 fscanf ( unit, "%d ", &NN[i][k] ) ;
255 }
256 i++ ;
257 }
258
259 fclose (unit) ;
260 }
261
262
263 //
264 //
265 // set all the booleans used to FALSE, indicating that the pixel is not
266 // used in this event.
267 //
268
269 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
270 used [i] = FALSE ;
271 dknt [i] = FALSE ;
272
273 nphotshow[i] = 0 ;
274 nphotnsb [i] = 0 ;
275 nphotstar[i] = 0 ;
276
277 baseline[i] = 0 ;
278 }
279
280 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
281 sum_d_sig[ii] = 0. ;
282 }
283
284 //
285 // set the information about the Different Level Triggers to zero
286 //
287
288 nZero = nFirst = nSecond = 0 ;
289
290 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
291 SlicesZero[ii] = FALSE;
292 }
293
294 for ( i = 0 ; i < 5 ; i++) {
295 SlicesFirst[i] = -50 ;
296 SlicesSecond[i] = -50 ;
297 PixelsFirst[i] = -1;
298 PixelsSecond[i] = -1;
299 }
300 cout << " end of MTrigger::MTrigger()" << endl ;
301}
302
303MTrigger::MTrigger(float gate, float ampl, float fwhm) {
304 // ============================================================
305 //
306 // constructor
307 //
308 // The procedure is the following:
309 //
310 // 1. Allocation of some memory needed
311 // 2. some parameters of the trigger are set.
312 // 3. Then the all signals are set to zero
313
314 Int_t i, ii ;
315
316 Float_t threshold ;
317
318 //
319 // allocate the memory for the 2dim arrays (a_sig, d_sig )
320 //
321
322 for( Int_t j=0; j<TRIGGER_PIXELS; j++ ) {
323
324 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
325
326 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
327 }
328
329 //
330 // set the values for the standard response pulse
331 //
332
333 fwhm_resp = fwhm ;
334 ampl_resp = ampl ;
335
336 threshold = CHANNEL_THRESHOLD ;
337
338
339 gate_leng = gate ;
340 trigger_multi = TRIGGER_MULTI ;
341 trigger_geometry = TRIGGER_GEOM ;
342
343 cout << endl
344 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
345 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
346 << endl ;
347 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
348 << endl ;
349 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
350 << endl ;
351 cout << endl ;
352
353
354 for (Int_t k=0; k<TRIGGER_PIXELS; k++ ) {
355 chan_thres[k] = threshold ;
356 }
357
358
359 //
360 // set up the response shape
361 //
362
363 Float_t sigma ;
364 Float_t x, x0 ;
365
366 sigma = fwhm_resp / 2.35 ;
367 x0 = 3*sigma ;
368
369 for (i=0; i< RESPONSE_SLICES ; i++ ) {
370
371 x = i * (1./((Float_t)SLICES_PER_NSEC))
372 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
373
374 sing_resp[i] =
375 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
376
377 }
378
379 //
380 // look for the time between start of response function and the
381 // maximum value of the response function. This is needed by the
382 // member functions FillNSB() and FillStar()
383 //
384
385 Int_t imax = 0 ;
386 Float_t max = 0. ;
387 for (i=0; i< RESPONSE_SLICES ; i++ ) {
388 if ( sing_resp[i] > max ) {
389 imax = i ;
390 max = sing_resp[i] ;
391 }
392 }
393
394 peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ;
395
396
397 //
398 // the amplitude of one single photo electron is not a constant.
399 // There exists a measured distribution from Razmik. This distribution
400 // is used to simulate the noise of the amplitude.
401 // For this a histogramm (histPmt) is created and filled with the
402 // values.
403 //
404
405 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
406
407 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
408 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
409 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
410 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
411 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
412
413 histMean = histPmt->GetMean() ;
414
415 histPmt->SetContent( ValRazmik) ;
416
417 histMean = histPmt->GetMean() ;
418
419 //
420 // create the random generator for the Electronic Noise
421 //
422
423 GenElec = new TRandom() ;
424
425 //
426 // Read in the lookup table for NN trigger
427 //
428
429 FILE *unit ;
430 int id ;
431
432 i = 0 ;
433
434 if ( (unit = fopen("../include-MTrigger/TABLE_NEXT_NEIGHBOUR", "r" )) == 0 ) {
435 cout << "ERROR: not able to read ../include-MTrigger/TABLE_NEXT_NEIGHBOUR"
436 << endl ;
437 exit(123) ;
438 }
439 else {
440 while ( i < TRIGGER_PIXELS )
441 {
442 fscanf ( unit, " %d", &id ) ;
443
444 for ( Int_t k=0; k<6; k++ ) {
445 fscanf ( unit, "%d ", &NN[i][k] ) ;
446 }
447 i++ ;
448 }
449
450 fclose (unit) ;
451 }
452
453
454 //
455 //
456 // set all the booleans used to FALSE, indicating that the pixel is not
457 // used in this event.
458 //
459
460 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
461 used [i] = FALSE ;
462 dknt [i] = FALSE ;
463
464 nphotshow[i] = 0 ;
465 nphotnsb [i] = 0 ;
466 nphotstar[i] = 0 ;
467
468 baseline[i] = 0 ;
469 }
470
471 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
472 sum_d_sig[ii] = 0. ;
473 }
474
475 //
476 // set the information about the Different Level Triggers to zero
477 //
478
479 nZero = nFirst = nSecond = 0 ;
480
481 for (ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
482 SlicesZero[ii] = FALSE;
483 }
484
485 for ( i = 0 ; i < 5 ; i++) {
486 SlicesFirst[i] = -50 ;
487 SlicesSecond[i] = -50 ;
488 PixelsFirst[i] = -1;
489 PixelsSecond[i] = -1;
490 }
491 cout << " end of MTrigger::MTrigger()" << endl ;
492}
493
494MTrigger::~MTrigger() {
495 // ============================================================//
496 // destructor
497 //
498 int i;
499 // delete histPmt ;
500 for(i=0;i<TRIGGER_PIXELS;i++){
501 delete [] a_sig[i];
502 delete [] d_sig[i];
503 }
504 delete GenElec;
505}
506
507
508void MTrigger::Reset() {
509 // ============================================================
510 //
511 // reset all values of the signals to zero
512 //
513 Int_t i, ii ;
514
515 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
516 used [i] = FALSE ;
517 dknt [i] = FALSE ;
518
519 nphotshow[i] = 0 ;
520 nphotnsb [i] = 0 ;
521 nphotstar[i] = 0 ;
522 }
523
524 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
525 sum_d_sig[ii] = 0. ;
526 }
527}
528
529void MTrigger::ClearZero() {
530 //
531 // set the information about the Zero Level Trigger to zero
532 //
533
534 Int_t i;
535
536 nZero = 0 ;
537
538 for (i=0 ; i<TRIGGER_TIME_SLICES; i++ ) {
539 SlicesZero[i] = FALSE;
540 }
541
542}
543
544void MTrigger::ClearFirst() {
545 //
546 // set the information about the First Level Trigger to zero
547 //
548
549 Int_t i;
550
551 nFirst = 0 ;
552
553 for ( i = 0 ; i < 5 ; i++) {
554 SlicesFirst[i] = -50 ;
555 PixelsFirst[i] = -1;
556 }
557}
558
559Float_t MTrigger::FillShow(Int_t iPix, Float_t time) {
560 // ============================================================
561 //
562 // Fills the information of one single Phe electron that
563 // comes from the shower
564 //
565
566 //
567 // First check the time
568 //
569
570 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
571 cout << " WARNING: time of phe out of time range: " << time << endl;
572 return 0. ;
573 }
574 else {
575 return ( Fill( iPix, time, CASE_SHOW ) ) ;
576 }
577}
578
579Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) {
580 // ============================================================
581 //
582 // Fills the information of one single Phe electron that
583 // comes from the shower
584 //
585
586 //
587 // First check the time
588 //
589
590 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
591 cout << " WARNING: time of phe out of time range: " << time << endl;
592 return 0. ;
593 }
594 else {
595 return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ;
596 }
597}
598
599Float_t MTrigger::FillStar(Int_t iPix, Float_t time) {
600 // ============================================================
601 //
602 // Fills the information of one single Phe electron that
603 // comes from the shower
604 //
605
606 //
607 // First check the time
608 //
609
610 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
611 cout << " WARNING: time of phe out of time range: " << time << endl;
612 return 0. ;
613 }
614 else {
615 return ( Fill( iPix, time - peak_time, CASE_STAR ) ) ;
616 }
617}
618
619Float_t MTrigger::Fill( Int_t iPix, Float_t time, Int_t fall ) {
620 // ============================================================
621 //
622 // Fills the information in the array for the analog signal
623 //
624
625 Float_t PmtAmp = 0 ; // Amplitude of the PMT signal (results from noise)
626
627 if ( iPix < 0 ) {
628 cout << " ERROR: in MTrigger::Fill() " << endl ;
629 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
630 exit (1) ;
631 }
632 else if ( iPix >= CAMERA_PIXELS ) {
633 cout << " ERROR: in MTrigger::Fill() " << endl ;
634 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
635 exit (1) ;
636 }
637 else if ( iPix >= TRIGGER_PIXELS ) {
638 //
639 // We have not to fill information in the trigger part,
640 // but we must create the height of the puls going into
641 // the FADC simulation
642 //
643 PmtAmp = (histPmt->GetRandom()/histMean) ;
644
645 //
646 // But we fill the information in the counters of phe's
647 //
648
649 if ( fall == CASE_SHOW )
650 nphotshow[iPix]++ ;
651 else if ( fall == CASE_NSB )
652 nphotshow[iPix]++ ;
653 else if ( fall == CASE_STAR )
654 nphotstar[iPix]++ ;
655
656
657 }
658 else {
659 //
660 // we have a trigger pixel and we fill it
661 //
662 Int_t i ;
663
664 //
665 // but at the beginning we must check if this pixel is
666 // hitted the first time
667 //
668
669 if ( used[iPix] == FALSE ) {
670 used [iPix] = TRUE ;
671 // baseline[iPix] = 0. ;
672
673 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
674 a_sig[iPix][i] = 0. ;
675 d_sig[iPix][i] = 0. ;
676 }
677 }
678
679 //
680 // get the randomized amplitude
681 //
682 PmtAmp = (histPmt->GetRandom()/histMean) ;
683
684 //
685 // select the first slice to fill
686 //
687
688 Int_t ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
689
690 //
691 // look over the response signal and put it in the signal line
692 //
693
694 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
695
696 if ( (ichan+i) >= 0 &&
697 (ichan+i) < TRIGGER_TIME_SLICES ) {
698 a_sig[iPix][ichan+i] += PmtAmp * sing_resp[i] ;
699 }
700 }
701
702 //
703 // we fill the information in the counters of phe's
704 //
705
706 if ( fall == CASE_SHOW )
707 nphotshow[iPix]++ ;
708 else if ( fall == CASE_NSB )
709 nphotshow[iPix]++ ;
710 else if ( fall == CASE_STAR )
711 nphotstar[iPix]++ ;
712
713 //
714 //
715 return PmtAmp ;
716 }
717 return PmtAmp ;
718}
719
720
721
722void MTrigger::ElecNoise() {
723 // ============================================================
724 //
725 // adds the noise due to optronic and electronic
726 // to the signal
727 //
728 Float_t rausch ;
729
730 rausch = RESPONSE_AMPLITUDE * 0.3 ;
731
732 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
733 if ( used [i] == TRUE ) {
734
735 for ( Int_t ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
736
737 a_sig [i][ii] += GenElec->Gaus(0., rausch ) ;
738
739 }
740 }
741 }
742}
743
744void MTrigger::SetMultiplicity(Int_t multi){
745 //=============================================================
746 //
747 // It sets the private member trigger_multi
748
749 trigger_multi=multi;
750}
751
752void MTrigger::SetTopology(Int_t topo){
753 //=============================================================
754 //
755 // It sets the private member trigger_geometry
756
757 trigger_geometry=topo;
758}
759
760void MTrigger::SetThreshold(Float_t thres[]){
761 //=============================================================
762 //
763 // It sets the private member chan_thres[TRIGGER_PIXELS]
764
765 Int_t i;
766
767 for(i=0;i<TRIGGER_PIXELS;i++){
768 chan_thres[i]=thres[i];
769 }
770}
771
772void MTrigger::ReadThreshold(char name[]){
773 //=============================================================
774 //
775 // It reads values for threshold of each pixel from file name
776
777 FILE *unit;
778 Int_t i=0;
779
780 if ((unit=fopen(name, "r"))==0){
781 cout<<"WARNING: not able to read ..."<<name<<endl;
782 }
783 else {
784 while (i<TRIGGER_PIXELS){
785 fscanf(unit, "%f",&chan_thres[i++]);
786 }
787 fclose (unit);
788 }
789
790}
791
792void MTrigger::Diskriminate() {
793 // ============================================================
794 //
795 // Diskriminates the analog signal
796 //
797 // one very important part is the calucaltion of the baseline
798 // shift. Because of the AC coupling of the PMT, only the
799 // fluctuations are interesting. If there are a lot of phe,
800 // a so-called shift of the baseline occurs.
801 //
802
803 Int_t iM = 0 ;
804 Int_t i, ii ;
805
806
807 Int_t jmax = (Int_t) (gate_leng * SLICES_PER_NSEC ) ;
808
809 //
810 // first of all determine the integral of all signals to get
811 // the baseline shift.
812 //
813
814 for ( i=0 ; i < TRIGGER_PIXELS ; i++ ) {
815 if ( used[i] == TRUE ) {
816 baseline[i] = 0. ;
817
818 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
819 baseline[i] += a_sig[i][ii] ;
820 }
821
822 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
823
824 //
825 // now correct the baseline shift in the analog signal!!
826 //
827 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
828 a_sig[i][ii] = a_sig[i][ii] - baseline[i] ;
829 }
830 }
831 }
832
833 //
834 // now the diskrimination is coming
835 //
836 // take only that pixel which are used
837 //
838
839 for ( i=0 ; i < TRIGGER_PIXELS; i++ ) {
840 if ( used [i] == TRUE ) {
841
842 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
843 //
844 // first check if the signal is crossing the CHANNEL_THRESHOLD
845 // form low to big signals
846 //
847
848 if ( a_sig[i][ii-1] < chan_thres[i] &&
849 a_sig[i][ii] >= chan_thres[i] ) {
850 {
851 if ( dknt[i] == FALSE ) {
852 dknt [i] = TRUE ;
853 iM++ ;
854 }
855 // cout << " disk " << ii ;
856 //
857 // put the standard diskriminator signal in
858 // the diskriminated signal
859 //
860 for ( Int_t j=0 ; j < jmax ; j++ ) {
861
862 if ( ii+j < TRIGGER_TIME_SLICES ) {
863 d_sig [i][ii+j] = 1. ;
864 }
865 }
866 ii = ii + jmax ;
867 }
868 }
869 else d_sig[i][ii]=0.;
870 }
871 }
872 }
873}
874
875
876void MTrigger::ShowSignal (MMcEvt *McEvt) {
877 // ============================================================
878 //
879 // This method is used to book the histogramm to show the signal in
880 // a special gui frame (class MGTriggerSignal). After the look onto the
881 // signals for a better understanding of the things we will expect
882 // the gui frame and all histogramms will be destroyed.
883 //
884
885 //
886 // first of all create a list of the histograms to show
887 //
888 // take only that one with a entry
889
890 TH1F *hist ;
891 TH1F *dhist ;
892 Char_t dumm[10];
893 Char_t name[256];
894
895 TObjArray *AList ;
896 AList = new TObjArray(10) ;
897
898 TObjArray *DList ;
899 DList = new TObjArray(10) ;
900
901 // the list of analog signal histograms
902 // at the beginning we initalise 10 elements
903 // but this array expand automaticly if neccessay
904
905 Int_t ic = 0 ;
906 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
907 if ( used [i] == TRUE ) {
908
909 sprintf (dumm, "A_%d", i ) ;
910 sprintf (name, "analog %d", i ) ;
911
912 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
913 //
914 // fill the histogram
915 //
916
917 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
918 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
919 }
920 hist->SetMaximum(8.);
921 hist->SetMinimum(-8.);
922 hist->SetStats(kFALSE);
923
924 AList->Add(hist) ;
925
926 sprintf (dumm, "D_%d", i ) ;
927 sprintf (name, "digital %d", i ) ;
928
929 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
930 if ( dknt[i] == TRUE ) {
931 //
932 // fill the histogram of digital signal
933 //
934 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
935 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
936 dhist->SetStats(kFALSE);
937 }
938 }
939 dhist->SetMaximum(1.5);
940
941 DList->Add(dhist);
942
943 ic++ ;
944
945 }
946 }
947
948 //
949 // create the Gui Tool
950 //
951 //
952
953 new MGTriggerSignal(McEvt,
954 AList,
955 DList,
956 gClient->GetRoot(),
957 gClient->GetRoot(),
958 400, 400 ) ;
959
960 //
961 // delete the List of histogramms
962 //
963
964 AList->Delete() ;
965 DList->Delete() ;
966
967 delete AList ;
968 delete DList ;
969}
970
971
972Int_t MTrigger::ZeroLevel() {
973 // ============================================================
974 //
975 // This is a level introduced just to speed up the program.
976 // It makes sense to look for next neighbours only if there
977 // are at least trigger_multi pixels with a diskriminator
978 // signal.
979 //
980
981 //
982 // first count the pixels with a diskriminator signal
983 //
984 Int_t iMul = 0 ;
985 for ( Int_t iP =0 ; iP < TRIGGER_PIXELS; iP++ ) {
986 //
987 //
988 if ( dknt[iP] == TRUE ) {
989 iMul++ ;
990 }
991 }
992
993 //
994 // only if there are at least more pixels than requested
995 // it make sense to look into details
996 if ( iMul >= trigger_multi ) {
997 //
998 // fill the sum signal of all diskriminator signals
999 //
1000 for ( Int_t iP =0 ; iP < TRIGGER_PIXELS; iP++ ) {
1001 //
1002 //
1003 if ( dknt[iP] == TRUE ) {
1004 //
1005 // sum it up
1006 //
1007 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1008 //
1009 //
1010 sum_d_sig [iS] += d_sig[iP][iS] ;
1011 }
1012 }
1013 }
1014 //
1015 // run over the sum_d_sig and check each time slice
1016 //
1017 Int_t iReturn = 0 ;
1018
1019 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1020
1021 if ( sum_d_sig[iS] >= trigger_multi ) {
1022 iReturn++ ;
1023 nZero++;
1024 SlicesZero[iS] = TRUE ;
1025
1026 }
1027 else SlicesZero[iS] = FALSE;
1028 }
1029
1030 return ( iReturn ) ;
1031 }
1032 else {
1033 return 0 ;
1034 }
1035}
1036
1037Int_t MTrigger::FirstLevel() {
1038 //=================================================
1039 //
1040 // This is a level trigger which can look for several
1041 // multiplicities (trigger_multi)
1042 // and topologies (trigger_geometry)
1043 //
1044
1045 Int_t iReturn = 0 ; // Return value for this function
1046
1047 // Definition of needed variables
1048 Bool_t Muster[TRIGGER_PIXELS] ;
1049 Bool_t Neighb[TRIGGER_PIXELS] ;
1050 Int_t iMulti = 0 ;
1051
1052 // We put several wrong topologies which we already know that they
1053 // are not possible. It can save time.
1054
1055 if (trigger_geometry==0 && trigger_multi>7) {
1056 cout <<"You are looking for a topology that needs more than six neighbours of the same pixel"<<endl;
1057 cout <<" Topology "<<trigger_geometry<<" Multiplicity "<<trigger_multi<<endl;;
1058 return (kFALSE);
1059 }
1060
1061 if (trigger_geometry==2 && trigger_multi<3) {
1062 cout<<"Closed pack geometry with multiplicity "<<trigger_multi<<" does not make sense"<<endl;
1063 return (kFALSE);
1064 }
1065 if (trigger_geometry>2) {
1066 cout << "This trigger topology is not implemented"<<endl;
1067 return (kFALSE);
1068 }
1069
1070 //
1071 // loop over all ZeroLevel Trigger
1072 //
1073 // it is only neccessary to look after a ZeroLevel Trigger for
1074 // a FirstLevel (NextNeighbour) trigger.
1075 //
1076
1077 if (nZero) {
1078
1079 //
1080 // Then run over all slices
1081 //
1082
1083 for ( Int_t iSli = 0;
1084 iSli < TRIGGER_TIME_SLICES; iSli++ ) {
1085
1086 // Check if this time slice has more fired pixels than trigger_multi
1087
1088 if (SlicesZero[iSli]){
1089 //
1090 // then look in all pixel if the diskriminated signal is 1
1091 //
1092
1093 for ( Int_t iPix = 0 ; iPix < TRIGGER_PIXELS; iPix++ ) {
1094 Muster[iPix] = kFALSE ;
1095 Neighb[iPix] = kFALSE ;
1096 if ( used [iPix] == TRUE ) {
1097 //
1098 // now check the diskriminated signal
1099 //
1100 if ( d_sig [iPix][iSli] > 0. ) {
1101 Muster[iPix] = kTRUE ;
1102 }
1103 }
1104 } // end of loop over the pixels
1105
1106 //
1107 // here we have to look for the topologies
1108 //
1109
1110 switch(trigger_geometry){
1111 case 0:{
1112
1113 // It looks for a pixel above threshold which has
1114 // trigger_multi-1 neighbour pixels above threshold
1115
1116 Bool_t Dummy[TRIGGER_PIXELS] ;
1117
1118 // Loop over all pixels
1119 for (int j=0;j<TRIGGER_PIXELS;j++){
1120
1121 //
1122 // I commented out this line here
1123 // Dummy=Muster;
1124
1125 for (int k=0; k<TRIGGER_PIXELS; k++){
1126 Neighb[k]=kFALSE;
1127
1128 Dummy[k] = Muster[k] ;
1129 }
1130 if(Muster[j]){
1131 // If pixel is fired, it checks how many fired neighbours it has
1132 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1133 Neighb[j] = kTRUE ;
1134 Dummy[j] = kTRUE ;
1135 if (!PassNextNeighbour(Dummy, &Neighb[0])){
1136 break;
1137 }
1138 for (int k=0; k<TRIGGER_PIXELS; k++){
1139 if (Neighb[k]){
1140 Dummy[k]=kFALSE;
1141 Neighb[k]=kFALSE;
1142 }
1143 }
1144 }
1145 if (iMulti==trigger_multi ) {
1146 //
1147 // A NN-Trigger is detected at time Slice
1148 //
1149 PixelsFirst[nFirst] = j; // We save pixel that triggers
1150 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1151 iReturn++ ;
1152 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1153 break ;
1154 }
1155 }
1156 }
1157 break;
1158 };
1159
1160 case 1:{
1161
1162 // It looks for trigger_multi neighbour pixels above the
1163 // threshold.
1164
1165 for (int j=0;j<TRIGGER_PIXELS;j++){
1166 if(Muster[j]){
1167 // It checks if you can find
1168 // trigger_multi fired neighbour pixels
1169 Neighb[j] = kTRUE ;
1170 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1171 if (!PassNextNeighbour(Muster, &Neighb[0]))
1172 break;
1173 }
1174 if (iMulti==trigger_multi ) {
1175 //
1176 // A NN-Trigger is detected at time Slice
1177 //
1178 PixelsFirst[nFirst] = j; // We save pixel that triggers
1179 SlicesFirst[nFirst++] = iSli ; // We save when it triggers
1180 iReturn++ ;
1181 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1182 break ;
1183 }
1184 else {
1185 // We put Neighb to kFALSE to check an other pixel
1186 for (int k=0; k<TRIGGER_PIXELS; k++){
1187 if (Neighb[k]){
1188 Neighb[k]=kFALSE;
1189 }
1190 }
1191 }
1192 }
1193 }
1194 break;
1195 };
1196 case 2:{
1197
1198 // It looks for trigger_multi closed pack neighbours
1199 // above threshold
1200 // Closed pack means that you can take out any pixel
1201 // and you will still get a trigger for trigger_multi -1
1202
1203 Int_t closed_pack = 1;
1204
1205 for (int j=0;j<TRIGGER_PIXELS;j++){
1206 if(Muster[j]){
1207 // It checks if there are trigger_multi
1208 // neighbours above threshold
1209 Neighb[j] = kTRUE ;
1210 for (iMulti=1;iMulti<trigger_multi; iMulti++){
1211 if (!PassNextNeighbour(Muster, &Neighb[0]))
1212 break;
1213 }
1214 if (iMulti==trigger_multi ) {
1215 //
1216 // A NN-Trigger is detected at time Slice
1217 //
1218
1219 // Check if there is closed pack topology
1220 Bool_t Aux1[TRIGGER_PIXELS];
1221 Bool_t Aux2[TRIGGER_PIXELS];
1222 for (int jj=0;jj<TRIGGER_PIXELS;jj++)
1223 Aux2[jj]=kFALSE;
1224
1225 for (int i=0;i<TRIGGER_PIXELS;i++){
1226 if (Neighb[i]) {
1227 // Loop over pixels that achive neighbouring condition
1228
1229 // huschel
1230 // here also some corrections were neccessary
1231 //
1232 //Aux1=Neighb;
1233
1234 for (int jj=0;jj<TRIGGER_PIXELS;jj++) {
1235 Aux1[jj] = Neighb[jj] ; // huschel
1236
1237 Aux2[jj]=kFALSE;
1238 }
1239
1240 Aux1[i]=kFALSE;
1241 Aux2[j]=kTRUE;
1242 // It checks if taking any of the pixels we lose
1243 // neighbouring condition for trigger -1
1244 for (iMulti=1;iMulti<(trigger_multi-1);iMulti++){
1245 if (!PassNextNeighbour(Aux1, &Aux2[0]))
1246 break;
1247 }
1248 if (iMulti<(trigger_multi-1)){
1249 closed_pack=0;
1250 break;
1251 }
1252
1253 }
1254 }
1255 if (closed_pack){
1256 PixelsFirst[nFirst] = j; // We save pixel that triggers
1257 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1258 iReturn++ ;
1259 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1260 break ;
1261 }
1262 else {
1263 for (int k=0; k<TRIGGER_PIXELS; k++){
1264 if (Neighb[k]){
1265 Neighb[k]=kFALSE;
1266 }
1267 }
1268 }
1269 }
1270 else
1271 for (int k=0; k<TRIGGER_PIXELS; k++)
1272 Neighb[k]=kFALSE;
1273 }
1274 }
1275 break;
1276 };
1277 default:{
1278 cout << "This topology is not implemented yet"<<endl;
1279 break;
1280 }
1281 }
1282 }
1283 } // end of loop over the slices
1284 } // end of conditional for a trigger Zero
1285
1286 //
1287 // return the Number of FirstLevel Triggers
1288 //
1289 return iReturn ;
1290}
1291
1292
1293Bool_t MTrigger::PassNextNeighbour ( Bool_t m[], Bool_t *n) {
1294 //
1295 // This function is looking for a next neighbour of pixels in n[]
1296 // above triggers using a NNlookup table.
1297 // This table is builded by the default constructor
1298 //
1299
1300 //
1301 // loop over all trigger pixels
1302 //
1303
1304 Bool_t return_val = kFALSE;
1305
1306 for ( Int_t i=0; i<TRIGGER_PIXELS; i++) {
1307 //
1308 // check if this pixel has a diskrminator signal
1309 // (this is inside n[] )
1310 //
1311
1312 if ( n[i] && !return_val) {
1313
1314 //
1315 // look in the next neighbours from the lookuptable
1316 //
1317
1318 for ( Int_t kk=0; kk<6; kk++ ) {
1319 //
1320 // if the nextneighbour is outside the triggerarea do nothing
1321 //
1322 if (!return_val){
1323 if (NN[i][kk] >= TRIGGER_PIXELS ) {
1324
1325 }
1326 // the nextneighbour is not inside the TRIGGER_PIXELS
1327 else {
1328 //
1329 // look if the boolean of nn pixels is true
1330 //
1331
1332 if ( m[ NN[i][kk] ] && !n[NN[i][kk]] ) {
1333 n[NN[i][kk]]=kTRUE ;
1334 return_val =kTRUE;
1335 }
1336 }
1337 }
1338 else break;
1339 }
1340 }
1341 }
1342 return(return_val);
1343}
1344
1345Float_t MTrigger::GetFirstLevelTime( Int_t il ){
1346
1347 //=============================================================
1348 //
1349 // It gives the time for the il trigger at first level
1350
1351 return((Float_t) ((Float_t) SlicesFirst[il]/((Float_t) SLICES_PER_NSEC)));
1352}
1353
1354Int_t MTrigger::GetFirstLevelPixel( Int_t il ){
1355
1356 //=============================================================
1357 //
1358 // It gives the pixel that triggers for the il trigger at first level
1359 return(PixelsFirst[il]);
1360}
Note: See TracBrowser for help on using the repository browser.