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

Last change on this file since 459 was 459, checked in by harald, 24 years ago
For the development of the StarResponse program, some smaller changes in the class MTrigger are neccessary. Be carefull, perhaps a change in the destructor of MTrigger can effect other programs. Be aware of that!!
File size: 32.6 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 // cout << "destructor of MTrigger" << endl ;
499
500 delete histPmt ;
501
502 for(Int_t i=0;i<TRIGGER_PIXELS;i++){
503 // delete [] a_sig[i];
504 // delete [] d_sig[i];
505 }
506
507 delete GenElec;
508
509}
510
511
512void MTrigger::Reset() {
513 // ============================================================
514 //
515 // reset all values of the signals to zero
516 //
517 Int_t i, ii ;
518
519 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
520 used [i] = FALSE ;
521 dknt [i] = FALSE ;
522
523 nphotshow[i] = 0 ;
524 nphotnsb [i] = 0 ;
525 nphotstar[i] = 0 ;
526 }
527
528 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
529 sum_d_sig[ii] = 0. ;
530 }
531}
532
533void MTrigger::ClearZero() {
534 //
535 // set the information about the Zero Level Trigger to zero
536 //
537
538 Int_t i;
539
540 nZero = 0 ;
541
542 for (i=0 ; i<TRIGGER_TIME_SLICES; i++ ) {
543 SlicesZero[i] = FALSE;
544 }
545
546}
547
548void MTrigger::ClearFirst() {
549 //
550 // set the information about the First Level Trigger to zero
551 //
552
553 Int_t i;
554
555 nFirst = 0 ;
556
557 for ( i = 0 ; i < 5 ; i++) {
558 SlicesFirst[i] = -50 ;
559 PixelsFirst[i] = -1;
560 }
561}
562
563Float_t MTrigger::FillShow(Int_t iPix, Float_t time) {
564 // ============================================================
565 //
566 // Fills the information of one single Phe electron that
567 // comes from the shower
568 //
569
570 //
571 // First check the time
572 //
573
574 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
575 cout << " WARNING: time of phe out of time range: " << time << endl;
576 return 0. ;
577 }
578 else {
579 return ( Fill( iPix, time, CASE_SHOW ) ) ;
580 }
581}
582
583Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) {
584 // ============================================================
585 //
586 // Fills the information of one single Phe electron that
587 // comes from the shower
588 //
589
590 //
591 // First check the time
592 //
593
594 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
595 cout << " WARNING: time of phe out of time range: " << time << endl;
596 return 0. ;
597 }
598 else {
599 return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ;
600 }
601}
602
603Float_t MTrigger::FillStar(Int_t iPix, Float_t time) {
604 // ============================================================
605 //
606 // Fills the information of one single Phe electron that
607 // comes from the shower
608 //
609
610 //
611 // First check the time
612 //
613
614 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
615 cout << " WARNING: time of phe out of time range: " << time << endl;
616 return 0. ;
617 }
618 else {
619 return ( Fill( iPix, time - peak_time, CASE_STAR ) ) ;
620 }
621}
622
623Float_t MTrigger::Fill( Int_t iPix, Float_t time, Int_t fall ) {
624 // ============================================================
625 //
626 // Fills the information in the array for the analog signal
627 //
628
629 Float_t PmtAmp = 0 ; // Amplitude of the PMT signal (results from noise)
630
631 if ( iPix < 0 ) {
632 cout << " ERROR: in MTrigger::Fill() " << endl ;
633 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
634 exit (1) ;
635 }
636 else if ( iPix >= CAMERA_PIXELS ) {
637 cout << " ERROR: in MTrigger::Fill() " << endl ;
638 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
639 exit (1) ;
640 }
641 else if ( iPix >= TRIGGER_PIXELS ) {
642 //
643 // We have not to fill information in the trigger part,
644 // but we must create the height of the puls going into
645 // the FADC simulation
646 //
647 PmtAmp = (histPmt->GetRandom()/histMean) ;
648
649 //
650 // But we fill the information in the counters of phe's
651 //
652
653 if ( fall == CASE_SHOW )
654 nphotshow[iPix]++ ;
655 else if ( fall == CASE_NSB )
656 nphotshow[iPix]++ ;
657 else if ( fall == CASE_STAR )
658 nphotstar[iPix]++ ;
659
660
661 }
662 else {
663 //
664 // we have a trigger pixel and we fill it
665 //
666 Int_t i ;
667
668 //
669 // but at the beginning we must check if this pixel is
670 // hitted the first time
671 //
672
673 if ( used[iPix] == FALSE ) {
674 used [iPix] = TRUE ;
675 // baseline[iPix] = 0. ;
676
677 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
678 a_sig[iPix][i] = 0. ;
679 d_sig[iPix][i] = 0. ;
680 }
681 }
682
683 //
684 // get the randomized amplitude
685 //
686 PmtAmp = (histPmt->GetRandom()/histMean) ;
687
688 //
689 // select the first slice to fill
690 //
691
692 Int_t ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
693
694 //
695 // look over the response signal and put it in the signal line
696 //
697
698 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
699
700 if ( (ichan+i) >= 0 &&
701 (ichan+i) < TRIGGER_TIME_SLICES ) {
702 a_sig[iPix][ichan+i] += PmtAmp * sing_resp[i] ;
703 }
704 }
705
706 //
707 // we fill the information in the counters of phe's
708 //
709
710 if ( fall == CASE_SHOW )
711 nphotshow[iPix]++ ;
712 else if ( fall == CASE_NSB )
713 nphotshow[iPix]++ ;
714 else if ( fall == CASE_STAR )
715 nphotstar[iPix]++ ;
716
717 //
718 //
719 return PmtAmp ;
720 }
721 return PmtAmp ;
722}
723
724
725
726void MTrigger::ElecNoise() {
727 // ============================================================
728 //
729 // adds the noise due to optronic and electronic
730 // to the signal
731 //
732 Float_t rausch ;
733
734 rausch = RESPONSE_AMPLITUDE * 0.3 ;
735
736 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
737 if ( used [i] == TRUE ) {
738
739 for ( Int_t ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
740
741 a_sig [i][ii] += GenElec->Gaus(0., rausch ) ;
742
743 }
744 }
745 }
746}
747
748void MTrigger::SetMultiplicity(Int_t multi){
749 //=============================================================
750 //
751 // It sets the private member trigger_multi
752
753 trigger_multi=multi;
754}
755
756void MTrigger::SetTopology(Int_t topo){
757 //=============================================================
758 //
759 // It sets the private member trigger_geometry
760
761 trigger_geometry=topo;
762}
763
764void MTrigger::SetThreshold(Float_t thres[]){
765 //=============================================================
766 //
767 // It sets the private member chan_thres[TRIGGER_PIXELS]
768
769 Int_t i;
770
771 for(i=0;i<TRIGGER_PIXELS;i++){
772 chan_thres[i]=thres[i];
773 }
774}
775
776void MTrigger::ReadThreshold(char name[]){
777 //=============================================================
778 //
779 // It reads values for threshold of each pixel from file name
780
781 FILE *unit;
782 Int_t i=0;
783
784 if ((unit=fopen(name, "r"))==0){
785 cout<<"WARNING: not able to read ..."<<name<<endl;
786 }
787 else {
788 while (i<TRIGGER_PIXELS){
789 fscanf(unit, "%f",&chan_thres[i++]);
790 }
791 fclose (unit);
792 }
793
794}
795
796void MTrigger::GetResponse(Float_t *resp) {
797 // ============================================================
798 //
799 // puts the standard response function into the array resp
800
801 for ( Int_t i=0; i< RESPONSE_SLICES; i++ ) {
802
803 resp[i] = sing_resp[i] ;
804 }
805
806}
807
808void MTrigger::Diskriminate() {
809 // ============================================================
810 //
811 // Diskriminates the analog signal
812 //
813 // one very important part is the calucaltion of the baseline
814 // shift. Because of the AC coupling of the PMT, only the
815 // fluctuations are interesting. If there are a lot of phe,
816 // a so-called shift of the baseline occurs.
817 //
818
819 Int_t iM = 0 ;
820 Int_t i, ii ;
821
822
823 Int_t jmax = (Int_t) (gate_leng * SLICES_PER_NSEC ) ;
824
825 //
826 // first of all determine the integral of all signals to get
827 // the baseline shift.
828 //
829
830 for ( i=0 ; i < TRIGGER_PIXELS ; i++ ) {
831 if ( used[i] == TRUE ) {
832 baseline[i] = 0. ;
833
834 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
835 baseline[i] += a_sig[i][ii] ;
836 }
837
838 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
839
840 //
841 // now correct the baseline shift in the analog signal!!
842 //
843 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
844 a_sig[i][ii] = a_sig[i][ii] - baseline[i] ;
845 }
846 }
847 }
848
849 //
850 // now the diskrimination is coming
851 //
852 // take only that pixel which are used
853 //
854
855 for ( i=0 ; i < TRIGGER_PIXELS; i++ ) {
856 if ( used [i] == TRUE ) {
857
858 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
859 //
860 // first check if the signal is crossing the CHANNEL_THRESHOLD
861 // form low to big signals
862 //
863
864 if ( a_sig[i][ii-1] < chan_thres[i] &&
865 a_sig[i][ii] >= chan_thres[i] ) {
866 {
867 if ( dknt[i] == FALSE ) {
868 dknt [i] = TRUE ;
869 iM++ ;
870 }
871 // cout << " disk " << ii ;
872 //
873 // put the standard diskriminator signal in
874 // the diskriminated signal
875 //
876 for ( Int_t j=0 ; j < jmax ; j++ ) {
877
878 if ( ii+j < TRIGGER_TIME_SLICES ) {
879 d_sig [i][ii+j] = 1. ;
880 }
881 }
882 ii = ii + jmax ;
883 }
884 }
885 else d_sig[i][ii]=0.;
886 }
887 }
888 }
889}
890
891
892void MTrigger::ShowSignal (MMcEvt *McEvt) {
893 // ============================================================
894 //
895 // This method is used to book the histogramm to show the signal in
896 // a special gui frame (class MGTriggerSignal). After the look onto the
897 // signals for a better understanding of the things we will expect
898 // the gui frame and all histogramms will be destroyed.
899 //
900
901 //
902 // first of all create a list of the histograms to show
903 //
904 // take only that one with a entry
905
906 TH1F *hist ;
907 TH1F *dhist ;
908 Char_t dumm[10];
909 Char_t name[256];
910
911 TObjArray *AList ;
912 AList = new TObjArray(10) ;
913
914 TObjArray *DList ;
915 DList = new TObjArray(10) ;
916
917 // the list of analog signal histograms
918 // at the beginning we initalise 10 elements
919 // but this array expand automaticly if neccessay
920
921 Int_t ic = 0 ;
922 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
923 if ( used [i] == TRUE ) {
924
925 sprintf (dumm, "A_%d", i ) ;
926 sprintf (name, "analog %d", i ) ;
927
928 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
929 //
930 // fill the histogram
931 //
932
933 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
934 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
935 }
936 hist->SetMaximum(8.);
937 hist->SetMinimum(-8.);
938 hist->SetStats(kFALSE);
939
940 AList->Add(hist) ;
941
942 sprintf (dumm, "D_%d", i ) ;
943 sprintf (name, "digital %d", i ) ;
944
945 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
946 if ( dknt[i] == TRUE ) {
947 //
948 // fill the histogram of digital signal
949 //
950 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
951 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
952 dhist->SetStats(kFALSE);
953 }
954 }
955 dhist->SetMaximum(1.5);
956
957 DList->Add(dhist);
958
959 ic++ ;
960
961 }
962 }
963
964 //
965 // create the Gui Tool
966 //
967 //
968
969 new MGTriggerSignal(McEvt,
970 AList,
971 DList,
972 gClient->GetRoot(),
973 gClient->GetRoot(),
974 400, 400 ) ;
975
976 //
977 // delete the List of histogramms
978 //
979
980 AList->Delete() ;
981 DList->Delete() ;
982
983 delete AList ;
984 delete DList ;
985}
986
987
988Int_t MTrigger::ZeroLevel() {
989 // ============================================================
990 //
991 // This is a level introduced just to speed up the program.
992 // It makes sense to look for next neighbours only if there
993 // are at least trigger_multi pixels with a diskriminator
994 // signal.
995 //
996
997 //
998 // first count the pixels with a diskriminator signal
999 //
1000 Int_t iMul = 0 ;
1001 for ( Int_t iP =0 ; iP < TRIGGER_PIXELS; iP++ ) {
1002 //
1003 //
1004 if ( dknt[iP] == TRUE ) {
1005 iMul++ ;
1006 }
1007 }
1008
1009 //
1010 // only if there are at least more pixels than requested
1011 // it make sense to look into details
1012 if ( iMul >= trigger_multi ) {
1013 //
1014 // fill the sum signal of all diskriminator signals
1015 //
1016 for ( Int_t iP =0 ; iP < TRIGGER_PIXELS; iP++ ) {
1017 //
1018 //
1019 if ( dknt[iP] == TRUE ) {
1020 //
1021 // sum it up
1022 //
1023 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1024 //
1025 //
1026 sum_d_sig [iS] += d_sig[iP][iS] ;
1027 }
1028 }
1029 }
1030 //
1031 // run over the sum_d_sig and check each time slice
1032 //
1033 Int_t iReturn = 0 ;
1034
1035 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
1036
1037 if ( sum_d_sig[iS] >= trigger_multi ) {
1038 iReturn++ ;
1039 nZero++;
1040 SlicesZero[iS] = TRUE ;
1041
1042 }
1043 else SlicesZero[iS] = FALSE;
1044 }
1045
1046 return ( iReturn ) ;
1047 }
1048 else {
1049 return 0 ;
1050 }
1051}
1052
1053Int_t MTrigger::FirstLevel() {
1054 //=================================================
1055 //
1056 // This is a level trigger which can look for several
1057 // multiplicities (trigger_multi)
1058 // and topologies (trigger_geometry)
1059 //
1060
1061 Int_t iReturn = 0 ; // Return value for this function
1062
1063 // Definition of needed variables
1064 Bool_t Muster[TRIGGER_PIXELS] ;
1065 Bool_t Neighb[TRIGGER_PIXELS] ;
1066 Int_t iMulti = 0 ;
1067
1068 // We put several wrong topologies which we already know that they
1069 // are not possible. It can save time.
1070
1071 if (trigger_geometry==0 && trigger_multi>7) {
1072 cout <<"You are looking for a topology that needs more than six neighbours of the same pixel"<<endl;
1073 cout <<" Topology "<<trigger_geometry<<" Multiplicity "<<trigger_multi<<endl;;
1074 return (kFALSE);
1075 }
1076
1077 if (trigger_geometry==2 && trigger_multi<3) {
1078 cout<<"Closed pack geometry with multiplicity "<<trigger_multi<<" does not make sense"<<endl;
1079 return (kFALSE);
1080 }
1081 if (trigger_geometry>2) {
1082 cout << "This trigger topology is not implemented"<<endl;
1083 return (kFALSE);
1084 }
1085
1086 //
1087 // loop over all ZeroLevel Trigger
1088 //
1089 // it is only neccessary to look after a ZeroLevel Trigger for
1090 // a FirstLevel (NextNeighbour) trigger.
1091 //
1092
1093 if (nZero) {
1094
1095 //
1096 // Then run over all slices
1097 //
1098
1099 for ( Int_t iSli = 0;
1100 iSli < TRIGGER_TIME_SLICES; iSli++ ) {
1101
1102 // Check if this time slice has more fired pixels than trigger_multi
1103
1104 if (SlicesZero[iSli]){
1105 //
1106 // then look in all pixel if the diskriminated signal is 1
1107 //
1108
1109 for ( Int_t iPix = 0 ; iPix < TRIGGER_PIXELS; iPix++ ) {
1110 Muster[iPix] = kFALSE ;
1111 Neighb[iPix] = kFALSE ;
1112 if ( used [iPix] == TRUE ) {
1113 //
1114 // now check the diskriminated signal
1115 //
1116 if ( d_sig [iPix][iSli] > 0. ) {
1117 Muster[iPix] = kTRUE ;
1118 }
1119 }
1120 } // end of loop over the pixels
1121
1122 //
1123 // here we have to look for the topologies
1124 //
1125
1126 switch(trigger_geometry){
1127 case 0:{
1128
1129 // It looks for a pixel above threshold which has
1130 // trigger_multi-1 neighbour pixels above threshold
1131
1132 Bool_t Dummy[TRIGGER_PIXELS] ;
1133
1134 // Loop over all pixels
1135 for (int j=0;j<TRIGGER_PIXELS;j++){
1136
1137 //
1138 // I commented out this line here
1139 // Dummy=Muster;
1140
1141 for (int k=0; k<TRIGGER_PIXELS; k++){
1142 Neighb[k]=kFALSE;
1143
1144 Dummy[k] = Muster[k] ;
1145 }
1146 if(Muster[j]){
1147 // If pixel is fired, it checks how many fired neighbours it has
1148 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1149 Neighb[j] = kTRUE ;
1150 Dummy[j] = kTRUE ;
1151 if (!PassNextNeighbour(Dummy, &Neighb[0])){
1152 break;
1153 }
1154 for (int k=0; k<TRIGGER_PIXELS; k++){
1155 if (Neighb[k]){
1156 Dummy[k]=kFALSE;
1157 Neighb[k]=kFALSE;
1158 }
1159 }
1160 }
1161 if (iMulti==trigger_multi ) {
1162 //
1163 // A NN-Trigger is detected at time Slice
1164 //
1165 PixelsFirst[nFirst] = j; // We save pixel that triggers
1166 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1167 iReturn++ ;
1168 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1169 break ;
1170 }
1171 }
1172 }
1173 break;
1174 };
1175
1176 case 1:{
1177
1178 // It looks for trigger_multi neighbour pixels above the
1179 // threshold.
1180
1181 for (int j=0;j<TRIGGER_PIXELS;j++){
1182 if(Muster[j]){
1183 // It checks if you can find
1184 // trigger_multi fired neighbour pixels
1185 Neighb[j] = kTRUE ;
1186 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
1187 if (!PassNextNeighbour(Muster, &Neighb[0]))
1188 break;
1189 }
1190 if (iMulti==trigger_multi ) {
1191 //
1192 // A NN-Trigger is detected at time Slice
1193 //
1194 PixelsFirst[nFirst] = j; // We save pixel that triggers
1195 SlicesFirst[nFirst++] = iSli ; // We save when it triggers
1196 iReturn++ ;
1197 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1198 break ;
1199 }
1200 else {
1201 // We put Neighb to kFALSE to check an other pixel
1202 for (int k=0; k<TRIGGER_PIXELS; k++){
1203 if (Neighb[k]){
1204 Neighb[k]=kFALSE;
1205 }
1206 }
1207 }
1208 }
1209 }
1210 break;
1211 };
1212 case 2:{
1213
1214 // It looks for trigger_multi closed pack neighbours
1215 // above threshold
1216 // Closed pack means that you can take out any pixel
1217 // and you will still get a trigger for trigger_multi -1
1218
1219 Int_t closed_pack = 1;
1220
1221 for (int j=0;j<TRIGGER_PIXELS;j++){
1222 if(Muster[j]){
1223 // It checks if there are trigger_multi
1224 // neighbours above threshold
1225 Neighb[j] = kTRUE ;
1226 for (iMulti=1;iMulti<trigger_multi; iMulti++){
1227 if (!PassNextNeighbour(Muster, &Neighb[0]))
1228 break;
1229 }
1230 if (iMulti==trigger_multi ) {
1231 //
1232 // A NN-Trigger is detected at time Slice
1233 //
1234
1235 // Check if there is closed pack topology
1236 Bool_t Aux1[TRIGGER_PIXELS];
1237 Bool_t Aux2[TRIGGER_PIXELS];
1238 for (int jj=0;jj<TRIGGER_PIXELS;jj++)
1239 Aux2[jj]=kFALSE;
1240
1241 for (int i=0;i<TRIGGER_PIXELS;i++){
1242 if (Neighb[i]) {
1243 // Loop over pixels that achive neighbouring condition
1244
1245 // huschel
1246 // here also some corrections were neccessary
1247 //
1248 //Aux1=Neighb;
1249
1250 for (int jj=0;jj<TRIGGER_PIXELS;jj++) {
1251 Aux1[jj] = Neighb[jj] ; // huschel
1252
1253 Aux2[jj]=kFALSE;
1254 }
1255
1256 Aux1[i]=kFALSE;
1257 Aux2[j]=kTRUE;
1258 // It checks if taking any of the pixels we lose
1259 // neighbouring condition for trigger -1
1260 for (iMulti=1;iMulti<(trigger_multi-1);iMulti++){
1261 if (!PassNextNeighbour(Aux1, &Aux2[0]))
1262 break;
1263 }
1264 if (iMulti<(trigger_multi-1)){
1265 closed_pack=0;
1266 break;
1267 }
1268
1269 }
1270 }
1271 if (closed_pack){
1272 PixelsFirst[nFirst] = j; // We save pixel that triggers
1273 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1274 iReturn++ ;
1275 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1276 break ;
1277 }
1278 else {
1279 for (int k=0; k<TRIGGER_PIXELS; k++){
1280 if (Neighb[k]){
1281 Neighb[k]=kFALSE;
1282 }
1283 }
1284 }
1285 }
1286 else
1287 for (int k=0; k<TRIGGER_PIXELS; k++)
1288 Neighb[k]=kFALSE;
1289 }
1290 }
1291 break;
1292 };
1293 default:{
1294 cout << "This topology is not implemented yet"<<endl;
1295 break;
1296 }
1297 }
1298 }
1299 } // end of loop over the slices
1300 } // end of conditional for a trigger Zero
1301
1302 //
1303 // return the Number of FirstLevel Triggers
1304 //
1305 return iReturn ;
1306}
1307
1308
1309Bool_t MTrigger::PassNextNeighbour ( Bool_t m[], Bool_t *n) {
1310 //
1311 // This function is looking for a next neighbour of pixels in n[]
1312 // above triggers using a NNlookup table.
1313 // This table is builded by the default constructor
1314 //
1315
1316 //
1317 // loop over all trigger pixels
1318 //
1319
1320 Bool_t return_val = kFALSE;
1321
1322 for ( Int_t i=0; i<TRIGGER_PIXELS; i++) {
1323 //
1324 // check if this pixel has a diskrminator signal
1325 // (this is inside n[] )
1326 //
1327
1328 if ( n[i] && !return_val) {
1329
1330 //
1331 // look in the next neighbours from the lookuptable
1332 //
1333
1334 for ( Int_t kk=0; kk<6; kk++ ) {
1335 //
1336 // if the nextneighbour is outside the triggerarea do nothing
1337 //
1338 if (!return_val){
1339 if (NN[i][kk] >= TRIGGER_PIXELS ) {
1340
1341 }
1342 // the nextneighbour is not inside the TRIGGER_PIXELS
1343 else {
1344 //
1345 // look if the boolean of nn pixels is true
1346 //
1347
1348 if ( m[ NN[i][kk] ] && !n[NN[i][kk]] ) {
1349 n[NN[i][kk]]=kTRUE ;
1350 return_val =kTRUE;
1351 }
1352 }
1353 }
1354 else break;
1355 }
1356 }
1357 }
1358 return(return_val);
1359}
1360
1361Float_t MTrigger::GetFirstLevelTime( Int_t il ){
1362
1363 //=============================================================
1364 //
1365 // It gives the time for the il trigger at first level
1366
1367 return((Float_t) ((Float_t) SlicesFirst[il]/((Float_t) SLICES_PER_NSEC)));
1368}
1369
1370Int_t MTrigger::GetFirstLevelPixel( Int_t il ){
1371
1372 //=============================================================
1373 //
1374 // It gives the pixel that triggers for the il trigger at first level
1375 return(PixelsFirst[il]);
1376}
Note: See TracBrowser for help on using the repository browser.