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

Last change on this file since 351 was 351, checked in by harald, 25 years ago
This is the version of the class MTrigger that was presented at the general MAGIC in BARCELONA at the beginning of February. It is inside the repository for further development. Especially for a better implementation of diskriminator, NN, secondLevelTrigger, and NSB simulations.
File size: 17.1 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 FILE *unit_mtrig ;
18 Int_t endflag = 1 ;
19 char datac[256] ;
20 char dummy[50] ;
21 //
22 // default constructor
23 //
24 // The procedure is the following:
25 //
26 // 1. Allocation of some memory needed
27 // 2. some parameters of the trigger are set to default.
28 // 3. if a File MTrigger.card exists in the current directory,
29 // this parameters of the trigger may be changed
30 // 4. Then the all signals are set to zero
31
32 //
33 // allocate the memory for the 2dim arrays (a_sig, d_sig )
34 //
35
36 for( Int_t j=0; j<TRIGGER_PIXELS; j++ ) {
37
38 a_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
39
40 d_sig[j] = new Float_t[TRIGGER_TIME_SLICES] ;
41 }
42
43 //
44 // set the values for the standard response pulse
45 //
46
47 fwhm_resp = RESPONSE_FWHM ;
48 ampl_resp = RESPONSE_AMPLITUDE ;
49
50 chan_thres = CHANNEL_THRESHOLD ;
51 gate_leng = TRIGGER_GATE ;
52 trigger_multi = TRIGGER_MULTI ;
53
54 //
55 // check if the file MTrigger.card exists
56 //
57
58 if ( (unit_mtrig = fopen ("MTrigger.card", "r")) != 0 ) {
59 cout << "[MTrigger] use the values from MTrigger.card "<< endl ;
60
61 while ( endflag == 1 ) {
62 //
63 //
64 fgets (datac, 255, unit_mtrig) ;
65 // printf ("--> %s <--", datac ) ;
66
67 //
68 // now compare the line with controlcard words
69 //
70
71 if ( strncmp (datac, "channel_threshold", 17 ) == 0 ) {
72 sscanf (datac, "%s %f", dummy, &chan_thres ) ;
73 }
74 else if ( strncmp (datac, "gate_length", 11 ) == 0 ) {
75 sscanf (datac, "%s %f", dummy, &gate_leng ) ;
76 }
77 else if ( strncmp (datac, "response_fwhm", 13 ) == 0 ) {
78 sscanf (datac, "%s %f", dummy, &fwhm_resp ) ;
79 }
80 else if ( strncmp (datac, "response_ampl", 13 ) == 0 ) {
81 sscanf (datac, "%s %f", dummy, &ampl_resp ) ;
82 }
83
84 if ( feof(unit_mtrig) != 0 ) {
85 endflag = 0 ;
86 }
87
88 }
89
90 fclose ( unit_mtrig ) ;
91 }
92 else {
93 cout << "[MTrigger] use the standard values for MTrigger "<< endl ;
94 }
95
96 cout << endl
97 << "[MTrigger] Setting up the MTrigger with this values "<< endl ;
98 cout << endl
99 << "[MTrigger] ChannelThreshold: " << chan_thres << " mV"
100 << endl ;
101
102 cout << "[MTrigger] Gate Length: " << gate_leng << " ns"
103 << endl ;
104 cout << "[MTrigger] Response FWHM: " << fwhm_resp << " ns"
105 << endl ;
106 cout << "[MTrigger] Response Amplitude: " << ampl_resp << " mV"
107 << endl ;
108
109 cout << endl ;
110 //
111 // set up the response shape
112 //
113 Int_t i, ii ;
114
115 Float_t sigma ;
116 Float_t x, x0 ;
117
118 sigma = fwhm_resp / 2.35 ;
119 x0 = 3*sigma ;
120
121 for (i=0; i< RESPONSE_SLICES ; i++ ) {
122
123 x = i * (1./((Float_t)SLICES_PER_NSEC))
124 + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ;
125
126 sing_resp[i] =
127 ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ;
128
129 // cout << i << " "
130 // << x << " "
131 // << sing_resp[i]
132 // << endl ;
133
134 }
135
136 //
137 // the amplitude of one single photo electron is not a constant.
138 // There exists a measured distribution from Razmik. This distribution
139 // is used to simulate the noise of the amplitude.
140 // For this a histogramm (histPmt) is created and filled with the
141 // values.
142 //
143
144 histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ;
145
146 Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15,
147 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10,
148 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50,
149 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10,
150 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ;
151
152 histMean = histPmt->GetMean() ;
153
154 histPmt->SetContent( ValRazmik) ;
155
156 histMean = histPmt->GetMean() ;
157
158 //
159 // create the random generator for the Electronic Noise
160 //
161
162 GenElec = new TRandom() ;
163
164
165 //
166 // Read in the lookup table for NN trigger
167 //
168
169 FILE *unit ;
170 int id ;
171 float y ;
172
173 i = 0 ;
174
175 if ( (unit = fopen("../include-MTrigger/TABLE_NEXT_NEIGHBOUR", "r" )) == 0 ) {
176 cout << "ERROR: not able to read ../include-MTrigger/TABLE_NEXT_NEIGHBOUR"
177 << endl ;
178 exit(123) ;
179 }
180 else {
181 while ( i < TRIGGER_PIXELS )
182 {
183 fscanf ( unit, " %d", &id ) ;
184
185 for ( Int_t k=0; k<6; k++ ) {
186 fscanf ( unit, "%d ", &NN[i][k] ) ;
187 }
188 i++ ;
189 }
190
191 fclose (unit) ;
192 }
193
194
195 //
196 //
197 // set all the booleans used to FALSE, indicating that the pixel is not
198 // used in this event.
199 //
200
201 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
202 used [i] = FALSE ;
203
204 nphot[i] = 0 ;
205 }
206
207 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
208 sum_d_sig[ii] = 0. ;
209 }
210
211 //
212 // set the information about the Different Level Triggers to zero
213 //
214
215 nZero = nFirst = nSecond = 0 ;
216
217 for ( i = 0 ; i < 5 ; i++) {
218 SlicesZero[i] = 0 ;
219 SlicesFirst[i] = 0 ;
220 SlicesSecond[i] = 0 ;
221 }
222
223 cout << " end of MTrigger::MTrigger()" << endl ;
224}
225
226MTrigger::~MTrigger() {
227
228 delete histPmt ;
229}
230
231void MTrigger::Reset() {
232 //
233 // set all values of the signals to zero
234 //
235 Int_t i, ii ;
236
237 for ( i =0 ; i <TRIGGER_PIXELS ; i++ ) {
238 used [i] = FALSE ;
239 dknt [i] = FALSE ;
240
241 nphot[i] = 0 ;
242 }
243
244 for ( ii=0 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
245 sum_d_sig[ii] = 0. ;
246 }
247
248 //
249 // set the information about the Different Level Triggers to zero
250 //
251
252 nZero = nFirst = nSecond = 0 ;
253
254 for ( i = 0 ; i < 5 ; i++) {
255 SlicesZero[i] = 0 ;
256 SlicesFirst[i] = 0 ;
257 SlicesSecond[i] = 0 ;
258 }
259
260}
261
262
263Float_t MTrigger::Fill( Int_t iPix, Float_t time ) {
264 //
265 // fills the information about one single Phe in the Trigger class
266 //
267 // parameter is the number of the pixel and the time-difference to the
268 // first particle
269 //
270 //
271
272 Int_t i, ichan ;
273
274 Float_t NoiseAmp = 0 ; // Amplitude of the PMT signal (results from noise)
275
276 //
277 // first we have to check if the pixel iPix is used or not until now
278 // if this is the first use, reset all signal for that pixels
279 //
280 if ( iPix >= CAMERA_PIXELS ) {
281 //
282 // the PixelID is greater than the CAMERA
283 //
284 cout << " WARNING: MTrigger::Fill() : iPix greater than CAMERA_PIXELS"
285 << endl ;
286 NoiseAmp = 0. ;
287 }
288 else if ( iPix >=TRIGGER_PIXELS ) {
289 //
290 // the pixel is inside the Camera, but outside of the TRIGGER-FIELD
291 //
292 // we just scramble the amplitude of the PMT-signal for the FADC
293 //
294 // scramble the Amplitude of this single photo electron signal
295 //
296 NoiseAmp = (histPmt->GetRandom()/histMean) ;
297 }
298 else {
299 //
300 // the photoelectron is contributing to the trigger
301 //
302 if ( used[iPix] == FALSE ) {
303 used [iPix] = TRUE ;
304 // baseline[iPix] = 0. ;
305
306 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
307 a_sig[iPix][i] = 0. ;
308 d_sig[iPix][i] = 0. ;
309 }
310 }
311
312 //
313 // then select the time slice to use (ican)
314 //
315
316
317 if ( time < 0. ) {
318 cout << " WARNING!! " << time << " below ZERO!! Very strange!!"
319 << endl ;
320 }
321 else if ( time < TOTAL_TRIGGER_TIME ) {
322 nphot[iPix]++ ;
323 //
324 ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
325
326 //
327 // scramble the Amplitude of this single photo electron signal
328 //
329 NoiseAmp = (histPmt->GetRandom()/histMean) ;
330
331 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
332
333 if ( (ichan+i) < TRIGGER_TIME_SLICES ) {
334 a_sig[iPix][ichan+i] += NoiseAmp * sing_resp[i] ;
335
336 }
337 }
338 }
339 else {
340 cout << " WARNING!! " << time << " out of TriggerTimeRange "
341 << TOTAL_TRIGGER_TIME << endl ;
342 }
343 }
344
345 return NoiseAmp ;
346
347}
348
349
350Float_t MTrigger::FillNSB( Int_t iPix, Float_t time ) {
351 //
352 // fills the information about one single Phe in the Trigger class
353 //
354 // parameter is the number of the pixel and the time-difference to the
355 // first particle
356 //
357 //
358
359 Int_t i, ichan ;
360
361 Float_t NoiseAmp = 0 ; // Amplitude of the PMT signal (results from noise)
362
363 //
364 // first we have to check if the pixel iPix is used or not until now
365 // if this is the first use, reset all signal for that pixels
366 //
367 if ( iPix >= CAMERA_PIXELS ) {
368 cout << " WARNING: MTrigger::Fill() : iPix greater than CAMERA_PIXELS"
369 << endl ;
370 }
371 else if ( iPix >= TRIGGER_PIXELS ) {
372 //
373 // scramble the Amplitude of this single photo electron signal
374 //
375 NoiseAmp = (histPmt->GetRandom()/histMean) ;
376 }
377
378 else {
379 if ( used[iPix] == FALSE ) {
380 used [iPix] = TRUE ;
381 // baseline[iPix] = 0. ;
382
383 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
384 a_sig[iPix][i] = 0. ;
385 d_sig[iPix][i] = 0. ;
386 }
387 }
388
389 //
390 // then select the time slice to use (ican)
391 //
392
393 if ( time < 0. ) {
394 cout << " WARNING!! " << time << " below ZERO!! Very strange!!"
395 << endl ;
396 }
397 else if ( time < TOTAL_TRIGGER_TIME ) {
398 //
399 // FillNSB doesn't add a photon to nphot[iPix] as the method Fill do!!
400 //
401
402 ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
403
404 //
405 // scramble the Amplitude of this single photo electron signal
406 //
407 NoiseAmp = (histPmt->GetRandom()/histMean) ;
408
409 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
410
411 if ( (ichan+i) < TRIGGER_TIME_SLICES ) {
412 a_sig[iPix][ichan+i] += NoiseAmp * sing_resp[i] ;
413 }
414 }
415 }
416 else {
417 cout << " WARNING!! " << time << " out of TriggerTimeRange "
418 << TOTAL_TRIGGER_TIME << endl ;
419 }
420 }
421
422 return NoiseAmp ;
423
424}
425
426void MTrigger::ElecNoise() {
427
428 Float_t rausch ;
429
430 rausch = RESPONSE_AMPLITUDE * 0.3 ;
431
432 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
433 if ( used [i] == TRUE ) {
434 //cout << "Pixel " << i << " used" ;
435
436 for ( Int_t ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
437
438 a_sig [i][ii] += GenElec->Gaus(0., rausch ) ;
439
440 }
441 }
442 }
443
444}
445
446
447Int_t MTrigger::Diskriminate() {
448
449 cout << " MTrigger::Diskriminate()" << flush ;
450
451 Int_t iM = 0 ;
452 Int_t i, ii ;
453
454 Int_t jmax = (Int_t) (gate_leng * SLICES_PER_NSEC ) ;
455
456
457 //
458 // first of all determine the integral of all signals to get
459 // the baseline shift.
460 //
461
462
463 for ( i=0 ; i < TRIGGER_PIXELS ; i++ ) {
464 if ( used[i] == TRUE ) {
465 baseline[i] = 0. ;
466
467 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
468 baseline[i] += a_sig[i][ii] ;
469 }
470
471 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
472
473 //cout << "Pixel " << i
474 // << " baseline " << baseline[i]
475 // <<endl ;
476
477 }
478 }
479
480 //
481 // take only that pixel which are used
482 //
483
484 for ( i=0 ; i < TRIGGER_PIXELS; i++ ) {
485 if ( used [i] == TRUE ) {
486 //cout << "Pixel " << i << " used" ;
487
488 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
489
490 //
491 // first check if the signal is crossing the CHANNEL_THRESHOLD
492 // form low to big signals
493 //
494
495 if ( a_sig[i][ii-1] < chan_thres &&
496 a_sig[i][ii] >= chan_thres ) {
497 {
498 if ( dknt[i] == FALSE ) {
499 dknt [i] = TRUE ;
500 iM++ ;
501 }
502 // cout << " disk " << ii ;
503 //
504 // put the standard diskriminator signal in
505 // the diskriminated signal
506 //
507 for ( Int_t j=0 ; j < jmax ; j++ ) {
508
509 if ( ii+j < TRIGGER_TIME_SLICES ) {
510 d_sig [i][ii+j] = 1. ;
511 sum_d_sig [ii+j] += 1. ;
512 }
513 }
514 ii = ii + jmax ;
515 }
516 }
517 }
518 // cout << endl ;
519 }
520 }
521
522 //cout << "** MTrigger::Diskriminate() " << iM << endl ;
523
524
525 //
526 // determine the number of zero level triggers
527 //
528 // zero level trigger = the sum of all diskriminated signals
529 // is above the TRIGGER_MULTI value.
530 // only for this events it is neccessay to look for next neighbours!!!
531 //
532
533 if ( iM > TRIGGER_MULTI ) {
534 Int_t iReturn = 0 ;
535
536 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
537 if ( sum_d_sig[ii] > TRIGGER_MULTI ) {
538 iReturn++ ;
539
540 SlicesZero[nZero++] = ii ;
541
542 //
543 // if a trigger occurs we read out the next 50 nsec
544 //
545 // -> don't study the next 50/0.25 = 200 slices
546 //
547 ii = ii + 200 ;
548 }
549 }
550
551 return ( iReturn ) ;
552 }
553 else {
554 return ( 0 ) ;
555 }
556
557 return ( 0 ) ;
558
559}
560
561Int_t MTrigger::FirstLevel() {
562
563 Int_t iReturn = 0 ;
564
565 Bool_t Muster[TRIGGER_PIXELS] ;
566 Int_t iMulti = 0 ;
567
568 // cout << "#### MTrigger::FirstLevel()" << endl ;
569 // cout << nZero << " " << SlicesZero[0] << endl ;
570
571 if ( nZero > 1 ) {
572 cout << " INFORMATION: more than one Zero Level TRIGGER " << endl ;
573 }
574
575 //
576 // loop over all ZeroLevel Trigger
577 //
578 // it is only neccessary to look after a ZeroLevel Trigger for
579 // a FirstLevel (NextNeighbour) trigger.
580 //
581
582 for (Int_t iloop = 0; iloop < nZero ; iloop++ ) {
583
584 //
585 // Then run over all slices
586 // start at the ZeroLevelTrigger slices
587 //
588
589 for ( Int_t iSli = SlicesZero[iloop];
590 iSli < SlicesZero[iloop]+ 200; iSli++ ) {
591
592 //
593 // then look in all pixel if the diskriminated signal is 1
594 //
595 iMulti = 0 ;
596
597 for ( Int_t iPix = 0 ; iPix < TRIGGER_PIXELS; iPix++ ) {
598 Muster[iPix] = kFALSE ;
599
600 if ( used [iPix] == TRUE ) {
601 //
602 // now check the diskriminated signal
603 //
604 if ( d_sig [iPix][iSli] > 0. ) {
605
606 iMulti++ ;
607 Muster[iPix] = kTRUE ;
608 }
609 }
610 } // end of loop over the pixels
611
612 //
613 // here we have to look for next neighbours
614 //
615
616 if ( PassNextNeighbour ( Muster ) ) {
617 //
618 // A NN-Trigger is detected at time Slice
619 //
620 SlicesFirst[nFirst++] = iSli ;
621 iReturn++ ;
622 break ;
623 }
624 } // end of loop over the slices
625
626 } // end of loop over zerolevelTriggers
627
628 //
629 // return the Number of FirstLevel Triggers
630 //
631 return iReturn ;
632}
633
634
635Bool_t MTrigger::PassNextNeighbour ( Bool_t m[] ) {
636 //
637 // This method is looking for next neighbour triggers using a
638 // NNlookup table. This table is builded by the default constructor
639 //
640
641 Int_t iNN ;
642
643 //
644 // loop over all trigger pixels
645 //
646 for ( Int_t i=0; i<TRIGGER_PIXELS; i++) {
647 //
648 // check if this pixel has a diskrminator signal
649 // (this is inside m[] )
650 //
651
652 if ( m[i] ) {
653 iNN = 1 ;
654 // cout << "/ " << i ;
655
656 //
657 // look in the next neighbours from the lookuptable
658 //
659 for ( Int_t kk=0; kk<6; kk++ ) {
660 //
661 // if the nextneighbour is outside the triggerarea do nothing
662 //
663 if (NN[i][kk] >= TRIGGER_PIXELS ) {
664
665 }
666 // the nextneighbout is inside the TRIGGER_PIXELS
667 else {
668 //
669 // look if the boolean of nn pixels is true
670 //
671
672 if ( m[ NN[i][kk] ] ) {
673 iNN++ ;
674 }
675 }
676 }
677
678 // cout << " NN " << iNN ;
679
680 if ( iNN >=4 ) {
681 return ( kTRUE ) ;
682 }
683 }
684 }
685 return ( kFALSE ) ;
686}
687
688Float_t MTrigger::GetFirstLevelTime(Int_t il ) {
689 return ( (Float_t)SlicesFirst[il]/ SLICES_PER_NSEC ) ;
690}
691
692
693
694void MTrigger::ShowSignal (MMcEvt *McEvt) {
695 //
696 // This method is used to book the histogramm to show the signal in
697 // a special gui frame (class MGTriggerSignal). After the look onto the
698 // signals for a better understanding of the things we will expect
699 // the gui frame and all histogramms will be destroyed.
700 //
701
702 //
703 // first of all create a list of the histograms to show
704 //
705 // take only that one with a entry
706
707 TH1F *hist ;
708 TH1F *dhist ;
709 Char_t dumm[10];
710 Char_t name[256];
711
712 TObjArray *AList ;
713 AList = new TObjArray(10) ;
714
715 TObjArray *DList ;
716 DList = new TObjArray(10) ;
717
718 // the list of analog signal histograms
719 // at the beginning we initalise 10 elements
720 // but this array expand automaticly if neccessay
721
722 Int_t ic = 0 ;
723 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
724 if ( used [i] == TRUE ) {
725
726 sprintf (dumm, "A_%d", i ) ;
727 sprintf (name, "analog %d", i ) ;
728
729 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
730 //
731 // fill the histogram
732 //
733
734 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
735 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
736 }
737 hist->SetMaximum(8.);
738 hist->SetStats(kFALSE);
739
740 AList->Add(hist) ;
741
742 sprintf (dumm, "D_%d", i ) ;
743 sprintf (name, "digital %d", i ) ;
744
745 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
746 if ( dknt[i] == TRUE ) {
747 //
748 // fill the histogram of digital signal
749 //
750 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
751 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
752 dhist->SetStats(kFALSE);
753 }
754 }
755 dhist->SetMaximum(1.5);
756
757 DList->Add(dhist);
758
759 ic++ ;
760
761 }
762 }
763
764 //
765 // create the Gui Tool
766 //
767 //
768
769 new MGTriggerSignal(McEvt,
770 AList,
771 DList,
772 gClient->GetRoot(),
773 gClient->GetRoot(),
774 400, 400 ) ;
775
776 //
777 // delete the List of histogramms
778 //
779
780 AList->Delete() ;
781 DList->Delete() ;
782
783 delete AList ;
784 delete DList ;
785}
786
Note: See TracBrowser for help on using the repository browser.