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

Last change on this file since 372 was 372, checked in by harald, 25 years ago
Introduction of the baseline shift behaviour!!
File size: 17.2 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 for ( ii = 0 ; ii < TRIGGER_TIME_SLICES ; ii++ ) {
479 a_sig[i][ii] = a_sig[i][ii] - baseline[i] ;
480 }
481 }
482 }
483
484 //
485 // take only that pixel which are used
486 //
487
488 for ( i=0 ; i < TRIGGER_PIXELS; i++ ) {
489 if ( used [i] == TRUE ) {
490 //cout << "Pixel " << i << " used" ;
491
492 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
493
494 //
495 // first check if the signal is crossing the CHANNEL_THRESHOLD
496 // form low to big signals
497 //
498
499 if ( a_sig[i][ii-1] < chan_thres &&
500 a_sig[i][ii] >= chan_thres ) {
501 {
502 if ( dknt[i] == FALSE ) {
503 dknt [i] = TRUE ;
504 iM++ ;
505 }
506 // cout << " disk " << ii ;
507 //
508 // put the standard diskriminator signal in
509 // the diskriminated signal
510 //
511 for ( Int_t j=0 ; j < jmax ; j++ ) {
512
513 if ( ii+j < TRIGGER_TIME_SLICES ) {
514 d_sig [i][ii+j] = 1. ;
515 sum_d_sig [ii+j] += 1. ;
516 }
517 }
518 ii = ii + jmax ;
519 }
520 }
521 }
522 // cout << endl ;
523 }
524 }
525
526 //cout << "** MTrigger::Diskriminate() " << iM << endl ;
527
528
529 //
530 // determine the number of zero level triggers
531 //
532 // zero level trigger = the sum of all diskriminated signals
533 // is above the TRIGGER_MULTI value.
534 // only for this events it is neccessay to look for next neighbours!!!
535 //
536
537 if ( iM > TRIGGER_MULTI ) {
538 Int_t iReturn = 0 ;
539
540 for ( ii=1 ; ii<TRIGGER_TIME_SLICES; ii++ ) {
541 if ( sum_d_sig[ii] > TRIGGER_MULTI ) {
542 iReturn++ ;
543
544 SlicesZero[nZero++] = ii ;
545
546 //
547 // if a trigger occurs we read out the next 50 nsec
548 //
549 // -> don't study the next 50/0.25 = 200 slices
550 //
551 ii = ii + 200 ;
552 }
553 }
554
555 return ( iReturn ) ;
556 }
557 else {
558 return ( 0 ) ;
559 }
560
561 return ( 0 ) ;
562
563}
564
565Int_t MTrigger::FirstLevel() {
566
567 Int_t iReturn = 0 ;
568
569 Bool_t Muster[TRIGGER_PIXELS] ;
570 Int_t iMulti = 0 ;
571
572 // cout << "#### MTrigger::FirstLevel()" << endl ;
573 // cout << nZero << " " << SlicesZero[0] << endl ;
574
575 if ( nZero > 1 ) {
576 cout << " INFORMATION: more than one Zero Level TRIGGER " << endl ;
577 }
578
579 //
580 // loop over all ZeroLevel Trigger
581 //
582 // it is only neccessary to look after a ZeroLevel Trigger for
583 // a FirstLevel (NextNeighbour) trigger.
584 //
585
586 for (Int_t iloop = 0; iloop < nZero ; iloop++ ) {
587
588 //
589 // Then run over all slices
590 // start at the ZeroLevelTrigger slices
591 //
592
593 for ( Int_t iSli = SlicesZero[iloop];
594 iSli < SlicesZero[iloop]+ 200; iSli++ ) {
595
596 //
597 // then look in all pixel if the diskriminated signal is 1
598 //
599 iMulti = 0 ;
600
601 for ( Int_t iPix = 0 ; iPix < TRIGGER_PIXELS; iPix++ ) {
602 Muster[iPix] = kFALSE ;
603
604 if ( used [iPix] == TRUE ) {
605 //
606 // now check the diskriminated signal
607 //
608 if ( d_sig [iPix][iSli] > 0. ) {
609
610 iMulti++ ;
611 Muster[iPix] = kTRUE ;
612 }
613 }
614 } // end of loop over the pixels
615
616 //
617 // here we have to look for next neighbours
618 //
619
620 if ( PassNextNeighbour ( Muster ) ) {
621 //
622 // A NN-Trigger is detected at time Slice
623 //
624 SlicesFirst[nFirst++] = iSli ;
625 iReturn++ ;
626 break ;
627 }
628 } // end of loop over the slices
629
630 } // end of loop over zerolevelTriggers
631
632 //
633 // return the Number of FirstLevel Triggers
634 //
635 return iReturn ;
636}
637
638
639Bool_t MTrigger::PassNextNeighbour ( Bool_t m[] ) {
640 //
641 // This method is looking for next neighbour triggers using a
642 // NNlookup table. This table is builded by the default constructor
643 //
644
645 Int_t iNN ;
646
647 //
648 // loop over all trigger pixels
649 //
650 for ( Int_t i=0; i<TRIGGER_PIXELS; i++) {
651 //
652 // check if this pixel has a diskrminator signal
653 // (this is inside m[] )
654 //
655
656 if ( m[i] ) {
657 iNN = 1 ;
658 // cout << "/ " << i ;
659
660 //
661 // look in the next neighbours from the lookuptable
662 //
663 for ( Int_t kk=0; kk<6; kk++ ) {
664 //
665 // if the nextneighbour is outside the triggerarea do nothing
666 //
667 if (NN[i][kk] >= TRIGGER_PIXELS ) {
668
669 }
670 // the nextneighbout is inside the TRIGGER_PIXELS
671 else {
672 //
673 // look if the boolean of nn pixels is true
674 //
675
676 if ( m[ NN[i][kk] ] ) {
677 iNN++ ;
678 }
679 }
680 }
681
682 // cout << " NN " << iNN ;
683
684 if ( iNN >=4 ) {
685 return ( kTRUE ) ;
686 }
687 }
688 }
689 return ( kFALSE ) ;
690}
691
692Float_t MTrigger::GetFirstLevelTime(Int_t il ) {
693 return ( (Float_t)SlicesFirst[il]/ SLICES_PER_NSEC ) ;
694}
695
696
697
698void MTrigger::ShowSignal (MMcEvt *McEvt) {
699 //
700 // This method is used to book the histogramm to show the signal in
701 // a special gui frame (class MGTriggerSignal). After the look onto the
702 // signals for a better understanding of the things we will expect
703 // the gui frame and all histogramms will be destroyed.
704 //
705
706 //
707 // first of all create a list of the histograms to show
708 //
709 // take only that one with a entry
710
711 TH1F *hist ;
712 TH1F *dhist ;
713 Char_t dumm[10];
714 Char_t name[256];
715
716 TObjArray *AList ;
717 AList = new TObjArray(10) ;
718
719 TObjArray *DList ;
720 DList = new TObjArray(10) ;
721
722 // the list of analog signal histograms
723 // at the beginning we initalise 10 elements
724 // but this array expand automaticly if neccessay
725
726 Int_t ic = 0 ;
727 for ( Int_t i=0 ; i < TRIGGER_PIXELS; i++ ) {
728 if ( used [i] == TRUE ) {
729
730 sprintf (dumm, "A_%d", i ) ;
731 sprintf (name, "analog %d", i ) ;
732
733 hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
734 //
735 // fill the histogram
736 //
737
738 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
739 hist->SetBinContent (ibin, a_sig[i][ibin-1]) ;
740 }
741 hist->SetMaximum(8.);
742 hist->SetMinimum(-8.);
743 hist->SetStats(kFALSE);
744
745 AList->Add(hist) ;
746
747 sprintf (dumm, "D_%d", i ) ;
748 sprintf (name, "digital %d", i ) ;
749
750 dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME);
751 if ( dknt[i] == TRUE ) {
752 //
753 // fill the histogram of digital signal
754 //
755 for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) {
756 dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ;
757 dhist->SetStats(kFALSE);
758 }
759 }
760 dhist->SetMaximum(1.5);
761
762 DList->Add(dhist);
763
764 ic++ ;
765
766 }
767 }
768
769 //
770 // create the Gui Tool
771 //
772 //
773
774 new MGTriggerSignal(McEvt,
775 AList,
776 DList,
777 gClient->GetRoot(),
778 gClient->GetRoot(),
779 400, 400 ) ;
780
781 //
782 // delete the List of histogramms
783 //
784
785 AList->Delete() ;
786 DList->Delete() ;
787
788 delete AList ;
789 delete DList ;
790}
791
Note: See TracBrowser for help on using the repository browser.