- Timestamp:
- 02/08/00 12:50:36 (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Simulation/Detector/include-MTrigger/MTrigger.cxx
r307 r351 6 6 #include "MTrigger.hxx" 7 7 8 #include "TROOT.h" 9 #include "TFile.h" 10 #include "TH1.h" 11 #include "TObjArray.h" 12 #include "MGTriggerSignal.hxx" 13 14 15 MTrigger::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, &l_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 226 MTrigger::~MTrigger() { 227 228 delete histPmt ; 229 } 230 231 void 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 263 Float_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 350 Float_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 426 void 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 447 Int_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 561 Int_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 635 Bool_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 688 Float_t MTrigger::GetFirstLevelTime(Int_t il ) { 689 return ( (Float_t)SlicesFirst[il]/ SLICES_PER_NSEC ) ; 690 } 691 692 693 694 void 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 TracChangeset
for help on using the changeset viewer.