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

Last change on this file since 392 was 392, checked in by blanch, 25 years ago
Functions to Set threshold_channel, trigger_multi and trigger_geometry, which are private members, are implemented. The threshold_file option in MTrigger.card gives a file where program reads threshold value for each pixel. Some Clear() functins have been implemented to clear trigger level by level.
File size: 27.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
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.0 ;
296 SlicesSecond[i] = -50.0 ;
297 PixelsFirst[i] = -1;
298 PixelsSecond[i] = -1;
299 }
300 cout << " end of MTrigger::MTrigger()" << endl ;
301}
302
303MTrigger::~MTrigger() {
304 // ============================================================//
305 // destructor
306 //
307 int i;
308 // delete histPmt ;
309 for(i=0;i<TRIGGER_PIXELS;i++){
310 delete [] a_sig[i];
311 delete [] d_sig[i];
312 }
313 delete GenElec;
314}
315
316
317void MTrigger::Reset() {
318 // ============================================================
319 //
320 // reset all values of the signals to zero
321 //
322 Int_t i, ii ;
323
324 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
325 used [i] = FALSE ;
326 dknt [i] = FALSE ;
327
328 nphotshow[i] = 0 ;
329 nphotnsb [i] = 0 ;
330 nphotstar[i] = 0 ;
331 }
332
333 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
334 sum_d_sig[ii] = 0. ;
335 }
336}
337
338void MTrigger::ClearZero() {
339 //
340 // set the information about the Zero Level Trigger to zero
341 //
342
343 Int_t i;
344
345 nZero = 0 ;
346
347 for (i=0 ; i<TRIGGER_TIME_SLICES; i++ ) {
348 SlicesZero[i] = FALSE;
349 }
350
351}
352
353void MTrigger::ClearFirst() {
354 //
355 // set the information about the First Level Trigger to zero
356 //
357
358 Int_t i;
359
360 nFirst = 0 ;
361
362 for ( i = 0 ; i < 5 ; i++) {
363 SlicesFirst[i] = -50.0 ;
364 PixelsFirst[i] = -1;
365 }
366}
367
368Float_t MTrigger::FillShow(Int_t iPix, Float_t time) {
369 // ============================================================
370 //
371 // Fills the information of one single Phe electron that
372 // comes from the shower
373 //
374
375 //
376 // First check the time
377 //
378
379 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
380 cout << " WARNING: time of phe out of time range: " << time << endl;
381 return 0. ;
382 }
383 else {
384 return ( Fill( iPix, time, CASE_SHOW ) ) ;
385 }
386}
387
388Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) {
389 // ============================================================
390 //
391 // Fills the information of one single Phe electron that
392 // comes from the shower
393 //
394
395 //
396 // First check the time
397 //
398
399 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
400 cout << " WARNING: time of phe out of time range: " << time << endl;
401 return 0. ;
402 }
403 else {
404 return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ;
405 }
406}
407
408Float_t MTrigger::FillStar(Int_t iPix, Float_t time) {
409 // ============================================================
410 //
411 // Fills the information of one single Phe electron that
412 // comes from the shower
413 //
414
415 //
416 // First check the time
417 //
418
419 if ( time < 0. || time > TOTAL_TRIGGER_TIME ) {
420 cout << " WARNING: time of phe out of time range: " << time << endl;
421 return 0. ;
422 }
423 else {
424 return ( Fill( iPix, time - peak_time, CASE_STAR ) ) ;
425 }
426}
427
428Float_t MTrigger::Fill( Int_t iPix, Float_t time, Int_t fall ) {
429 // ============================================================
430 //
431 // Fills the information in the array for the analog signal
432 //
433
434 Float_t PmtAmp = 0 ; // Amplitude of the PMT signal (results from noise)
435
436 if ( iPix < 0 ) {
437 cout << " ERROR: in MTrigger::Fill() " << endl ;
438 cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ;
439 exit (1) ;
440 }
441 else if ( iPix >= CAMERA_PIXELS ) {
442 cout << " ERROR: in MTrigger::Fill() " << endl ;
443 cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ;
444 exit (1) ;
445 }
446 else if ( iPix >= TRIGGER_PIXELS ) {
447 //
448 // We have not to fill information in the trigger part,
449 // but we must create the height of the puls going into
450 // the FADC simulation
451 //
452 PmtAmp = (histPmt->GetRandom()/histMean) ;
453
454 //
455 // But we fill the information in the counters of phe's
456 //
457
458 if ( fall == CASE_SHOW )
459 nphotshow[iPix]++ ;
460 else if ( fall == CASE_NSB )
461 nphotshow[iPix]++ ;
462 else if ( fall == CASE_STAR )
463 nphotstar[iPix]++ ;
464
465
466 }
467 else {
468 //
469 // we have a trigger pixel and we fill it
470 //
471 Int_t i ;
472
473 //
474 // but at the beginning we must check if this pixel is
475 // hitted the first time
476 //
477
478 if ( used[iPix] == FALSE ) {
479 used [iPix] = TRUE ;
480 // baseline[iPix] = 0. ;
481
482 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
483 a_sig[iPix][i] = 0. ;
484 d_sig[iPix][i] = 0. ;
485 }
486 }
487
488 //
489 // get the randomized amplitude
490 //
491 PmtAmp = (histPmt->GetRandom()/histMean) ;
492
493 //
494 // select the first slice to fill
495 //
496
497 Int_t ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
498
499 //
500 // look over the response signal and put it in the signal line
501 //
502
503 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
504
505 if ( (ichan+i) >= 0 &&
506 (ichan+i) < TRIGGER_TIME_SLICES ) {
507 a_sig[iPix][ichan+i] += PmtAmp * sing_resp[i] ;
508 }
509 }
510
511 //
512 // we fill the information in the counters of phe's
513 //
514
515 if ( fall == CASE_SHOW )
516 nphotshow[iPix]++ ;
517 else if ( fall == CASE_NSB )
518 nphotshow[iPix]++ ;
519 else if ( fall == CASE_STAR )
520 nphotstar[iPix]++ ;
521
522 //
523 //
524 return PmtAmp ;
525 }
526 return PmtAmp ;
527}
528
529
530
531void MTrigger::ElecNoise() {
532 // ============================================================
533 //
534 // adds the noise due to optronic and electronic
535 // to the signal
536 //
537 Float_t rausch ;
538
539 rausch = RESPONSE_AMPLITUDE * 0.3 ;
540
541 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
542 if ( used [i] == TRUE ) {
543
544 for ( Int_t ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
545
546 a_sig [i][ii] += GenElec->Gaus(0., rausch ) ;
547
548 }
549 }
550 }
551}
552
553void MTrigger::SetMultiplicity(Int_t multi){
554 //=============================================================
555 //
556 // It sets the private member trigger_multi
557
558 trigger_multi=multi;
559}
560
561void MTrigger::SetTopology(Int_t topo){
562 //=============================================================
563 //
564 // It sets the private member trigger_geometry
565
566 trigger_geometry=topo;
567}
568
569void MTrigger::SetThreshold(Float_t thres[]){
570 //=============================================================
571 //
572 // It sets the private member chan_thres[TRIGGER_PIXELS]
573
574 Int_t i;
575
576 for(i=0;i<TRIGGER_PIXELS;i++){
577 chan_thres[i]=thres[i];
578 }
579}
580
581void MTrigger::ReadThreshold(char name[]){
582 //=============================================================
583 //
584 // It reads values for threshold of each pixel from file name
585
586 FILE *unit;
587 Int_t i=0;
588
589 if ((unit=fopen(name, "r"))==0){
590 cout<<"WARNING: not able to read ..."<<name<<endl;
591 }
592 else {
593 while (i<TRIGGER_PIXELS){
594 fscanf(unit, "%f",&chan_thres[i++]);
595 }
596 fclose (unit);
597 }
598
599}
600
601void MTrigger::Diskriminate() {
602 // ============================================================
603 //
604 // Diskriminates the analog signal
605 //
606 // one very important part is the calucaltion of the baseline
607 // shift. Because of the AC coupling of the PMT, only the
608 // fluctuations are interesting. If there are a lot of phe,
609 // a so-called shift of the baseline occurs.
610 //
611
612 Int_t iM = 0 ;
613 Int_t i, ii ;
614
615
616 Int_t jmax = (Int_t) (gate_leng * SLICES_PER_NSEC ) ;
617
618 //
619 // first of all determine the integral of all signals to get
620 // the baseline shift.
621 //
622
623 for ( i=0 ; i < TRIGGER_PIXELS ; i++ ) {
624 if ( used[i] == TRUE ) {
625 baseline[i] = 0. ;
626
627 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
628 baseline[i] += a_sig[i][ii] ;
629 }
630
631 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
632
633 //
634 // now correct the baseline shift in the analog signal!!
635 //
636 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
637 a_sig[i][ii] = a_sig[i][ii] - baseline[i] ;
638 }
639 }
640 }
641
642 //
643 // now the diskrimination is coming
644 //
645 // take only that pixel which are used
646 //
647
648 for ( i=0 ; i < TRIGGER_PIXELS; i++ ) {
649 if ( used [i] == TRUE ) {
650
651 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
652 //
653 // first check if the signal is crossing the CHANNEL_THRESHOLD
654 // form low to big signals
655 //
656
657 if ( a_sig[i][ii-1] < chan_thres[i] &&
658 a_sig[i][ii] >= chan_thres[i] ) {
659 {
660 if ( dknt[i] == FALSE ) {
661 dknt [i] = TRUE ;
662 iM++ ;
663 }
664 // cout << " disk " << ii ;
665 //
666 // put the standard diskriminator signal in
667 // the diskriminated signal
668 //
669 for ( Int_t j=0 ; j < jmax ; j++ ) {
670
671 if ( ii+j < TRIGGER_TIME_SLICES ) {
672 d_sig [i][ii+j] = 1. ;
673 }
674 }
675 ii = ii + jmax ;
676 }
677 }
678 else d_sig[i][ii]=0.;
679 }
680 }
681 }
682}
683
684
685void MTrigger::ShowSignal (MMcEvt *McEvt) {
686 // ============================================================
687 //
688 // This method is used to book the histogramm to show the signal in
689 // a special gui frame (class MGTriggerSignal). After the look onto the
690 // signals for a better understanding of the things we will expect
691 // the gui frame and all histogramms will be destroyed.
692 //
693
694 //
695 // first of all create a list of the histograms to show
696 //
697 // take only that one with a entry
698
699 TH1F *hist ;
700 TH1F *dhist ;
701 Char_t dumm[10];
702 Char_t name[256];
703
704 TObjArray *AList ;
705 AList = new TObjArray(10) ;
706
707 TObjArray *DList ;
708 DList = new TObjArray(10) ;
709
710 // the list of analog signal histograms
711 // at the beginning we initalise 10 elements
712 // but this array expand automaticly if neccessay
713
714 Int_t ic = 0 ;
715 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
716 if ( used [i] == TRUE ) {
717
718 sprintf (dumm, "A_%d", i ) ;
719 sprintf (name, "analog %d", i ) ;
720
721 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
722 //
723 // fill the histogram
724 //
725
726 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
727 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
728 }
729 hist->SetMaximum(8.);
730 hist->SetMinimum(-8.);
731 hist->SetStats(kFALSE);
732
733 AList->Add(hist) ;
734
735 sprintf (dumm, "D_%d", i ) ;
736 sprintf (name, "digital %d", i ) ;
737
738 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
739 if ( dknt[i] == TRUE ) {
740 //
741 // fill the histogram of digital signal
742 //
743 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
744 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
745 dhist->SetStats(kFALSE);
746 }
747 }
748 dhist->SetMaximum(1.5);
749
750 DList->Add(dhist);
751
752 ic++ ;
753
754 }
755 }
756
757 //
758 // create the Gui Tool
759 //
760 //
761
762 new MGTriggerSignal(McEvt,
763 AList,
764 DList,
765 gClient->GetRoot(),
766 gClient->GetRoot(),
767 400, 400 ) ;
768
769 //
770 // delete the List of histogramms
771 //
772
773 AList->Delete() ;
774 DList->Delete() ;
775
776 delete AList ;
777 delete DList ;
778}
779
780
781Int_t MTrigger::ZeroLevel() {
782 // ============================================================
783 //
784 // This is a level introduced just to speed up the program.
785 // It makes sense to look for next neighbours only if there
786 // are at least trigger_multi pixels with a diskriminator
787 // signal.
788 //
789
790 //
791 // first count the pixels with a diskriminator signal
792 //
793 Int_t iMul = 0 ;
794 for ( Int_t iP =0 ; iP < TRIGGER_PIXELS; iP++ ) {
795 //
796 //
797 if ( dknt[iP] == TRUE ) {
798 iMul++ ;
799 }
800 }
801
802 //
803 // only if there are at least more pixels than requested
804 // it make sense to look into details
805 if ( iMul >= trigger_multi ) {
806 //
807 // fill the sum signal of all diskriminator signals
808 //
809 for ( Int_t iP =0 ; iP < TRIGGER_PIXELS; iP++ ) {
810 //
811 //
812 if ( dknt[iP] == TRUE ) {
813 //
814 // sum it up
815 //
816 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
817 //
818 //
819 sum_d_sig [iS] += d_sig[iP][iS] ;
820 }
821 }
822 }
823 //
824 // run over the sum_d_sig and check each time slice
825 //
826 Int_t iReturn = 0 ;
827
828 for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) {
829
830 if ( sum_d_sig[iS] >= trigger_multi ) {
831 iReturn++ ;
832 nZero++;
833 SlicesZero[iS] = TRUE ;
834
835 }
836 else SlicesZero[iS] = FALSE;
837 }
838
839 return ( iReturn ) ;
840 }
841 else {
842 return 0 ;
843 }
844}
845
846Int_t MTrigger::FirstLevel() {
847 //=================================================
848 //
849 // This is a level trigger which can look for several
850 // multiplicities (trigger_multi)
851 // and topologies (trigger_geometry)
852 //
853
854 Int_t iReturn = 0 ; // Return value for this function
855
856 // Definition of needed variables
857 Bool_t Muster[TRIGGER_PIXELS] ;
858 Bool_t Neighb[TRIGGER_PIXELS] ;
859 Int_t iMulti = 0 ;
860
861 // We put several wrong topologies which we already know that they
862 // are not possible. It can save time.
863
864 if (trigger_geometry==0 && trigger_multi>7) {
865 cout <<"You are looking for a topology that needs more than six neighbours of the same pixel"<<endl;
866 cout <<" Topology "<<trigger_geometry<<" Multiplicity "<<trigger_multi<<endl;;
867 return (kFALSE);
868 }
869
870 if (trigger_geometry==2 && trigger_multi<3) {
871 cout<<"Closed pack geometry with multiplicity "<<trigger_multi<<" does not make sense"<<endl;
872 return (kFALSE);
873 }
874 if (trigger_geometry>2) {
875 cout << "This trigger topology is not implemented"<<endl;
876 return (kFALSE);
877 }
878
879 //
880 // loop over all ZeroLevel Trigger
881 //
882 // it is only neccessary to look after a ZeroLevel Trigger for
883 // a FirstLevel (NextNeighbour) trigger.
884 //
885
886 if (nZero) {
887
888 //
889 // Then run over all slices
890 //
891
892 for ( Int_t iSli = 0;
893 iSli < TRIGGER_TIME_SLICES; iSli++ ) {
894
895 // Check if this time slice has more fired pixels than trigger_multi
896
897 if (SlicesZero[iSli]){
898 //
899 // then look in all pixel if the diskriminated signal is 1
900 //
901
902 for ( Int_t iPix = 0 ; iPix < TRIGGER_PIXELS; iPix++ ) {
903 Muster[iPix] = kFALSE ;
904 Neighb[iPix] = kFALSE ;
905 if ( used [iPix] == TRUE ) {
906 //
907 // now check the diskriminated signal
908 //
909 if ( d_sig [iPix][iSli] > 0. ) {
910 Muster[iPix] = kTRUE ;
911 }
912 }
913 } // end of loop over the pixels
914
915 //
916 // here we have to look for the topologies
917 //
918
919 switch(trigger_geometry){
920 case 0:{
921
922 // It looks for a pixel above threshold which has
923 // trigger_multi-1 neighbour pixels above threshold
924
925 Bool_t Dummy[TRIGGER_PIXELS] ;
926
927 // Loop over all pixels
928 for (int j=0;j<TRIGGER_PIXELS;j++){
929
930 //
931 // I commented out this line here
932 // Dummy=Muster;
933
934 for (int k=0; k<TRIGGER_PIXELS; k++){
935 Neighb[k]=kFALSE;
936
937 Dummy[k] = Muster[k] ;
938 }
939 if(Muster[j]){
940 // If pixel is fired, it checks how many fired neighbours it has
941 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
942 Neighb[j] = kTRUE ;
943 Dummy[j] = kTRUE ;
944 if (!PassNextNeighbour(Dummy, &Neighb[0])){
945 break;
946 }
947 for (int k=0; k<TRIGGER_PIXELS; k++){
948 if (Neighb[k]){
949 Dummy[k]=kFALSE;
950 Neighb[k]=kFALSE;
951 }
952 }
953 }
954 if (iMulti==trigger_multi ) {
955 //
956 // A NN-Trigger is detected at time Slice
957 //
958 PixelsFirst[nFirst] = j; // We save pixel that triggers
959 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
960 iReturn++ ;
961 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
962 break ;
963 }
964 }
965 }
966 break;
967 };
968
969 case 1:{
970
971 // It looks for trigger_multi neighbour pixels above the
972 // threshold.
973
974 for (int j=0;j<TRIGGER_PIXELS;j++){
975 if(Muster[j]){
976 // It checks if you can find
977 // trigger_multi fired neighbour pixels
978 Neighb[j] = kTRUE ;
979 for (iMulti=1;iMulti<trigger_multi; iMulti++) {
980 if (!PassNextNeighbour(Muster, &Neighb[0]))
981 break;
982 }
983 if (iMulti==trigger_multi ) {
984 //
985 // A NN-Trigger is detected at time Slice
986 //
987 PixelsFirst[nFirst] = j; // We save pixel that triggers
988 SlicesFirst[nFirst++] = iSli ; // We save when it triggers
989 iReturn++ ;
990 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
991 break ;
992 }
993 else {
994 // We put Neighb to kFALSE to check an other pixel
995 for (int k=0; k<TRIGGER_PIXELS; k++){
996 if (Neighb[k]){
997 Neighb[k]=kFALSE;
998 }
999 }
1000 }
1001 }
1002 }
1003 break;
1004 };
1005 case 2:{
1006
1007 // It looks for trigger_multi closed pack neighbours
1008 // above threshold
1009 // Closed pack means that you can take out any pixel
1010 // and you will still get a trigger for trigger_multi -1
1011
1012 Int_t closed_pack = 1;
1013
1014 for (int j=0;j<TRIGGER_PIXELS;j++){
1015 if(Muster[j]){
1016 // It checks if there are trigger_multi
1017 // neighbours above threshold
1018 Neighb[j] = kTRUE ;
1019 for (iMulti=1;iMulti<trigger_multi; iMulti++){
1020 if (!PassNextNeighbour(Muster, &Neighb[0]))
1021 break;
1022 }
1023 if (iMulti==trigger_multi ) {
1024 //
1025 // A NN-Trigger is detected at time Slice
1026 //
1027
1028 // Check if there is closed pack topology
1029 Bool_t Aux1[TRIGGER_PIXELS];
1030 Bool_t Aux2[TRIGGER_PIXELS];
1031 for (int jj=0;jj<TRIGGER_PIXELS;jj++)
1032 Aux2[jj]=kFALSE;
1033
1034 for (int i=0;i<TRIGGER_PIXELS;i++){
1035 if (Neighb[i]) {
1036 // Loop over pixels that achive neighbouring condition
1037
1038 // huschel
1039 // here also some corrections were neccessary
1040 //
1041 //Aux1=Neighb;
1042
1043 for (int jj=0;jj<TRIGGER_PIXELS;jj++) {
1044 Aux1[jj] = Neighb[jj] ; // huschel
1045
1046 Aux2[jj]=kFALSE;
1047 }
1048
1049 Aux1[i]=kFALSE;
1050 Aux2[j]=kTRUE;
1051 // It checks if taking any of the pixels we lose
1052 // neighbouring condition for trigger -1
1053 for (iMulti=1;iMulti<(trigger_multi-1);iMulti++){
1054 if (!PassNextNeighbour(Aux1, &Aux2[0]))
1055 break;
1056 }
1057 if (iMulti<(trigger_multi-1)){
1058 closed_pack=0;
1059 break;
1060 }
1061
1062 }
1063 }
1064 if (closed_pack){
1065 PixelsFirst[nFirst] = j; // We save pixel that triggers
1066 SlicesFirst[nFirst++] = iSli ; // We save time when it triggers
1067 iReturn++ ;
1068 iSli+=(50*SLICES_PER_NSEC); // We skip the following 50 ns (dead time)
1069 break ;
1070 }
1071 else {
1072 for (int k=0; k<TRIGGER_PIXELS; k++){
1073 if (Neighb[k]){
1074 Neighb[k]=kFALSE;
1075 }
1076 }
1077 }
1078 }
1079 else
1080 for (int k=0; k<TRIGGER_PIXELS; k++)
1081 Neighb[k]=kFALSE;
1082 }
1083 }
1084 break;
1085 };
1086 default:{
1087 cout << "This topology is not implemented yet"<<endl;
1088 break;
1089 }
1090 }
1091 }
1092 } // end of loop over the slices
1093 } // end of conditional for a trigger Zero
1094
1095 //
1096 // return the Number of FirstLevel Triggers
1097 //
1098 return iReturn ;
1099}
1100
1101
1102Bool_t MTrigger::PassNextNeighbour ( Bool_t m[], Bool_t *n) {
1103 //
1104 // This function is looking for a next neighbour of pixels in n[]
1105 // above triggers using a NNlookup table.
1106 // This table is builded by the default constructor
1107 //
1108
1109 //
1110 // loop over all trigger pixels
1111 //
1112
1113 Bool_t return_val = kFALSE;
1114
1115 for ( Int_t i=0; i<TRIGGER_PIXELS; i++) {
1116 //
1117 // check if this pixel has a diskrminator signal
1118 // (this is inside n[] )
1119 //
1120
1121 if ( n[i] && !return_val) {
1122
1123 //
1124 // look in the next neighbours from the lookuptable
1125 //
1126
1127 for ( Int_t kk=0; kk<6; kk++ ) {
1128 //
1129 // if the nextneighbour is outside the triggerarea do nothing
1130 //
1131 if (!return_val){
1132 if (NN[i][kk] >= TRIGGER_PIXELS ) {
1133
1134 }
1135 // the nextneighbour is not inside the TRIGGER_PIXELS
1136 else {
1137 //
1138 // look if the boolean of nn pixels is true
1139 //
1140
1141 if ( m[ NN[i][kk] ] && !n[NN[i][kk]] ) {
1142 n[NN[i][kk]]=kTRUE ;
1143 return_val =kTRUE;
1144 }
1145 }
1146 }
1147 else break;
1148 }
1149 }
1150 }
1151 return(return_val);
1152}
1153
1154Float_t MTrigger::GetFirstLevelTime( Int_t il ){
1155
1156 //=============================================================
1157 //
1158 // It gives the time for the il trigger at first level
1159
1160 return((Float_t) ((Float_t) SlicesFirst[il]/((Float_t) SLICES_PER_NSEC)));
1161}
1162
1163Int_t MTrigger::GetFirstLevelPixel( Int_t il ){
1164
1165 //=============================================================
1166 //
1167 // It gives the pixel that triggers for the il trigger at first level
1168 return(PixelsFirst[il]);
1169}
Note: See TracBrowser for help on using the repository browser.