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

Last change on this file since 362 was 356, checked in by harald, 25 years ago
small changes due to screen output of some warnings!
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 (" << iPix
285 <<")greater than CAMERA_PIXELS"
286 << endl ;
287 NoiseAmp = 0. ;
288 }
289 else if ( iPix >=TRIGGER_PIXELS ) {
290 //
291 // the pixel is inside the Camera, but outside of the TRIGGER-FIELD
292 //
293 // we just scramble the amplitude of the PMT-signal for the FADC
294 //
295 // scramble the Amplitude of this single photo electron signal
296 //
297 NoiseAmp = (histPmt->GetRandom()/histMean) ;
298 }
299 else {
300 //
301 // the photoelectron is contributing to the trigger
302 //
303 if ( used[iPix] == FALSE ) {
304 used [iPix] = TRUE ;
305 // baseline[iPix] = 0. ;
306
307 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
308 a_sig[iPix][i] = 0. ;
309 d_sig[iPix][i] = 0. ;
310 }
311 }
312
313 //
314 // then select the time slice to use (ican)
315 //
316
317
318 if ( time < 0. ) {
319 cout << " WARNING!! " << time << " below ZERO!! Very strange!!"
320 << endl ;
321 }
322 else if ( time < TOTAL_TRIGGER_TIME ) {
323 nphot[iPix]++ ;
324 //
325 ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
326
327 //
328 // scramble the Amplitude of this single photo electron signal
329 //
330 NoiseAmp = (histPmt->GetRandom()/histMean) ;
331
332 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
333
334 if ( (ichan+i) < TRIGGER_TIME_SLICES ) {
335 a_sig[iPix][ichan+i] += NoiseAmp * sing_resp[i] ;
336
337 }
338 }
339 }
340 else {
341 cout << " WARNING!! " << time << " out of TriggerTimeRange "
342 << TOTAL_TRIGGER_TIME << endl ;
343 }
344 }
345
346 return NoiseAmp ;
347
348}
349
350
351Float_t MTrigger::FillNSB( Int_t iPix, Float_t time ) {
352 //
353 // fills the information about one single Phe in the Trigger class
354 //
355 // parameter is the number of the pixel and the time-difference to the
356 // first particle
357 //
358 //
359
360 Int_t i, ichan ;
361
362 Float_t NoiseAmp = 0 ; // Amplitude of the PMT signal (results from noise)
363
364 //
365 // first we have to check if the pixel iPix is used or not until now
366 // if this is the first use, reset all signal for that pixels
367 //
368 if ( iPix >= CAMERA_PIXELS ) {
369 cout << " WARNING: MTrigger::Fill() : iPix greater than CAMERA_PIXELS"
370 << endl ;
371 }
372 else if ( iPix >= TRIGGER_PIXELS ) {
373 //
374 // scramble the Amplitude of this single photo electron signal
375 //
376 NoiseAmp = (histPmt->GetRandom()/histMean) ;
377 }
378
379 else {
380 if ( used[iPix] == FALSE ) {
381 used [iPix] = TRUE ;
382 // baseline[iPix] = 0. ;
383
384 for (i=0; i < TRIGGER_TIME_SLICES; i++ ) {
385 a_sig[iPix][i] = 0. ;
386 d_sig[iPix][i] = 0. ;
387 }
388 }
389
390 //
391 // then select the time slice to use (ican)
392 //
393
394 if ( time < 0. ) {
395 cout << " WARNING!! " << time << " below ZERO!! Very strange!!"
396 << endl ;
397 }
398 else if ( time < TOTAL_TRIGGER_TIME ) {
399 //
400 // FillNSB doesn't add a photon to nphot[iPix] as the method Fill do!!
401 //
402
403 ichan = (Int_t) ( time * ((Float_t) SLICES_PER_NSEC) ) ;
404
405 //
406 // scramble the Amplitude of this single photo electron signal
407 //
408 NoiseAmp = (histPmt->GetRandom()/histMean) ;
409
410 for ( i = 0 ; i<RESPONSE_SLICES; i++ ) {
411
412 if ( (ichan+i) < TRIGGER_TIME_SLICES ) {
413 a_sig[iPix][ichan+i] += NoiseAmp * sing_resp[i] ;
414 }
415 }
416 }
417 else {
418 cout << " WARNING!! " << time << " out of TriggerTimeRange "
419 << TOTAL_TRIGGER_TIME << endl ;
420 }
421 }
422
423 return NoiseAmp ;
424
425}
426
427void MTrigger::ElecNoise() {
428
429 Float_t rausch ;
430
431 rausch = RESPONSE_AMPLITUDE * 0.3 ;
432
433 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
434 if ( used [i] == TRUE ) {
435 //cout << "Pixel " << i << " used" ;
436
437 for ( Int_t ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
438
439 a_sig [i][ii] += GenElec->Gaus(0., rausch ) ;
440
441 }
442 }
443 }
444
445}
446
447
448Int_t MTrigger::Diskriminate() {
449
450 // cout << " MTrigger::Diskriminate()" << flush ;
451
452 Int_t iM = 0 ;
453 Int_t i, ii ;
454
455 Int_t jmax = (Int_t) (gate_leng * SLICES_PER_NSEC ) ;
456
457
458 //
459 // first of all determine the integral of all signals to get
460 // the baseline shift.
461 //
462
463
464 for ( i=0 ; i < TRIGGER_PIXELS ; i++ ) {
465 if ( used[i] == TRUE ) {
466 baseline[i] = 0. ;
467
468 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
469 baseline[i] += a_sig[i][ii] ;
470 }
471
472 baseline[i] = baseline[i] / ( (Float_t ) TRIGGER_TIME_SLICES) ;
473
474 //cout << "Pixel " << i
475 // << " baseline " << baseline[i]
476 // <<endl ;
477
478 }
479 }
480
481 //
482 // take only that pixel which are used
483 //
484
485 for ( i=0 ; i < TRIGGER_PIXELS; i++ ) {
486 if ( used [i] == TRUE ) {
487 //cout << "Pixel " << i << " used" ;
488
489 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
490
491 //
492 // first check if the signal is crossing the CHANNEL_THRESHOLD
493 // form low to big signals
494 //
495
496 if ( a_sig[i][ii-1] < chan_thres &&
497 a_sig[i][ii] >= chan_thres ) {
498 {
499 if ( dknt[i] == FALSE ) {
500 dknt [i] = TRUE ;
501 iM++ ;
502 }
503 // cout << " disk " << ii ;
504 //
505 // put the standard diskriminator signal in
506 // the diskriminated signal
507 //
508 for ( Int_t j=0 ; j < jmax ; j++ ) {
509
510 if ( ii+j < TRIGGER_TIME_SLICES ) {
511 d_sig [i][ii+j] = 1. ;
512 sum_d_sig [ii+j] += 1. ;
513 }
514 }
515 ii = ii + jmax ;
516 }
517 }
518 }
519 // cout << endl ;
520 }
521 }
522
523 //cout << "** MTrigger::Diskriminate() " << iM << endl ;
524
525
526 //
527 // determine the number of zero level triggers
528 //
529 // zero level trigger = the sum of all diskriminated signals
530 // is above the TRIGGER_MULTI value.
531 // only for this events it is neccessay to look for next neighbours!!!
532 //
533
534 if ( iM > TRIGGER_MULTI ) {
535 Int_t iReturn = 0 ;
536
537 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
538 if ( sum_d_sig[ii] > TRIGGER_MULTI ) {
539 iReturn++ ;
540
541 SlicesZero[nZero++] = ii ;
542
543 //
544 // if a trigger occurs we read out the next 50 nsec
545 //
546 // -> don't study the next 50/0.25 = 200 slices
547 //
548 ii = ii + 200 ;
549 }
550 }
551
552 return ( iReturn ) ;
553 }
554 else {
555 return ( 0 ) ;
556 }
557
558 return ( 0 ) ;
559
560}
561
562Int_t MTrigger::FirstLevel() {
563
564 Int_t iReturn = 0 ;
565
566 Bool_t Muster[TRIGGER_PIXELS] ;
567 Int_t iMulti = 0 ;
568
569 // cout << "#### MTrigger::FirstLevel()" << endl ;
570 // cout << nZero << " " << SlicesZero[0] << endl ;
571
572 if ( nZero > 1 ) {
573 cout << " INFORMATION: more than one Zero Level TRIGGER " << endl ;
574 }
575
576 //
577 // loop over all ZeroLevel Trigger
578 //
579 // it is only neccessary to look after a ZeroLevel Trigger for
580 // a FirstLevel (NextNeighbour) trigger.
581 //
582
583 for (Int_t iloop = 0; iloop < nZero ; iloop++ ) {
584
585 //
586 // Then run over all slices
587 // start at the ZeroLevelTrigger slices
588 //
589
590 for ( Int_t iSli = SlicesZero[iloop];
591 iSli < SlicesZero[iloop]+ 200; iSli++ ) {
592
593 //
594 // then look in all pixel if the diskriminated signal is 1
595 //
596 iMulti = 0 ;
597
598 for ( Int_t iPix = 0 ; iPix < TRIGGER_PIXELS; iPix++ ) {
599 Muster[iPix] = kFALSE ;
600
601 if ( used [iPix] == TRUE ) {
602 //
603 // now check the diskriminated signal
604 //
605 if ( d_sig [iPix][iSli] > 0. ) {
606
607 iMulti++ ;
608 Muster[iPix] = kTRUE ;
609 }
610 }
611 } // end of loop over the pixels
612
613 //
614 // here we have to look for next neighbours
615 //
616
617 if ( PassNextNeighbour ( Muster ) ) {
618 //
619 // A NN-Trigger is detected at time Slice
620 //
621 SlicesFirst[nFirst++] = iSli ;
622 iReturn++ ;
623 break ;
624 }
625 } // end of loop over the slices
626
627 } // end of loop over zerolevelTriggers
628
629 //
630 // return the Number of FirstLevel Triggers
631 //
632 return iReturn ;
633}
634
635
636Bool_t MTrigger::PassNextNeighbour ( Bool_t m[] ) {
637 //
638 // This method is looking for next neighbour triggers using a
639 // NNlookup table. This table is builded by the default constructor
640 //
641
642 Int_t iNN ;
643
644 //
645 // loop over all trigger pixels
646 //
647 for ( Int_t i=0; i<TRIGGER_PIXELS; i++) {
648 //
649 // check if this pixel has a diskrminator signal
650 // (this is inside m[] )
651 //
652
653 if ( m[i] ) {
654 iNN = 1 ;
655 // cout << "/ " << i ;
656
657 //
658 // look in the next neighbours from the lookuptable
659 //
660 for ( Int_t kk=0; kk<6; kk++ ) {
661 //
662 // if the nextneighbour is outside the triggerarea do nothing
663 //
664 if (NN[i][kk] >= TRIGGER_PIXELS ) {
665
666 }
667 // the nextneighbout is inside the TRIGGER_PIXELS
668 else {
669 //
670 // look if the boolean of nn pixels is true
671 //
672
673 if ( m[ NN[i][kk] ] ) {
674 iNN++ ;
675 }
676 }
677 }
678
679 // cout << " NN " << iNN ;
680
681 if ( iNN >=4 ) {
682 return ( kTRUE ) ;
683 }
684 }
685 }
686 return ( kFALSE ) ;
687}
688
689Float_t MTrigger::GetFirstLevelTime(Int_t il ) {
690 return ( (Float_t)SlicesFirst[il]/ SLICES_PER_NSEC ) ;
691}
692
693
694
695void MTrigger::ShowSignal (MMcEvt *McEvt) {
696 //
697 // This method is used to book the histogramm to show the signal in
698 // a special gui frame (class MGTriggerSignal). After the look onto the
699 // signals for a better understanding of the things we will expect
700 // the gui frame and all histogramms will be destroyed.
701 //
702
703 //
704 // first of all create a list of the histograms to show
705 //
706 // take only that one with a entry
707
708 TH1F *hist ;
709 TH1F *dhist ;
710 Char_t dumm[10];
711 Char_t name[256];
712
713 TObjArray *AList ;
714 AList = new TObjArray(10) ;
715
716 TObjArray *DList ;
717 DList = new TObjArray(10) ;
718
719 // the list of analog signal histograms
720 // at the beginning we initalise 10 elements
721 // but this array expand automaticly if neccessay
722
723 Int_t ic = 0 ;
724 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
725 if ( used [i] == TRUE ) {
726
727 sprintf (dumm, "A_%d", i ) ;
728 sprintf (name, "analog %d", i ) ;
729
730 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
731 //
732 // fill the histogram
733 //
734
735 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
736 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
737 }
738 hist->SetMaximum(8.);
739 hist->SetStats(kFALSE);
740
741 AList->Add(hist) ;
742
743 sprintf (dumm, "D_%d", i ) ;
744 sprintf (name, "digital %d", i ) ;
745
746 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
747 if ( dknt[i] == TRUE ) {
748 //
749 // fill the histogram of digital signal
750 //
751 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
752 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
753 dhist->SetStats(kFALSE);
754 }
755 }
756 dhist->SetMaximum(1.5);
757
758 DList->Add(dhist);
759
760 ic++ ;
761
762 }
763 }
764
765 //
766 // create the Gui Tool
767 //
768 //
769
770 new MGTriggerSignal(McEvt,
771 AList,
772 DList,
773 gClient->GetRoot(),
774 gClient->GetRoot(),
775 400, 400 ) ;
776
777 //
778 // delete the List of histogramms
779 //
780
781 AList->Delete() ;
782 DList->Delete() ;
783
784 delete AList ;
785 delete DList ;
786}
787
Note: See TracBrowser for help on using the repository browser.