Changeset 365 for trunk/MagicSoft/Simulation/Detector/Camera/camera.cxx
- Timestamp:
- 02/18/00 17:40:35 (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Simulation/Detector/Camera/camera.cxx
r344 r365 21 21 // 22 22 // $RCSfile: camera.cxx,v $ 23 // $Revision: 1. 4$23 // $Revision: 1.5 $ 24 24 // $Author: petry $ 25 // $Date: 2000-0 1-25 08:36:23$25 // $Date: 2000-02-18 17:40:35 $ 26 26 // 27 27 //////////////////////////////////////////////////////////////////////// … … 54 54 55 55 #include "MDiag.h" 56 57 #include "MTrigger.hxx"58 56 59 57 #include "MRawEvt.h" … … 86 84 #undef __DEBUG__ 87 85 88 // flag for NNT in CT1 camera (default: ON )89 #undef __CT1_NO_NEIGHBOURS__90 #define __CT1_NO_NEIGHBOURS__91 92 // flag for calculation of NSB (default: ON )93 #undef __NSB__94 #define __NSB__95 96 // flag for calculation of QE for pixels (default: ON )97 #undef __QE__98 #define __QE__99 100 101 // flag for implementation of DETAIL_TRIGGER (default: ON )102 //103 // This is the new implementation of Trigger studies104 // It relies on a better simulation of the time stucture105 // of the PhotoMultiplier. For more details see the106 // documentation of the --> class MTrigger <--107 #define __DETAIL_TRIGGER__108 #undef __DETAIL_TRIGGER__109 110 // flag for implementation of TRIGGER (default: ON )111 #undef __TRIGGER__112 #define __TRIGGER__113 114 // flag for implementation of Tail-Cut (default: ON )115 #undef __TAILCUT__116 #define __TAILCUT__117 118 // flag for calculation of islands stat. (default: ON )119 #define __ISLANDS__120 #undef __ISLANDS__121 122 // flag for calculation of image parameters (default: ON )123 #undef __MOMENTS__124 #define __MOMENTS__125 126 // flag for ROOT (default: ON )127 #undef __ROOT__128 #define __ROOT__129 130 86 //!@} 131 87 … … 259 215 // and data stored on them with information about the pixels 260 216 261 //@: table for IJ sys.262 static float pixels[PIX_ARRAY_SIDE][PIX_ARRAY_SIDE][4];263 217 264 218 //@: coordinates x,y for each pixel … … 276 230 //@: contents of the pixels (ph.e.) after cleanning 277 231 static float *fnpixclean; 278 279 //@: contents of the sum of all ph.e. in one timeslice of 1 ns280 static float *fnslicesum ;281 232 282 233 … … 364 315 @"*/ 365 316 366 //!@{367 // table of random numbers368 369 // (unused)370 //static double RandomNumbers[500];371 //!@}372 373 /*!@"374 375 The following is a variable to count the number of Cphotons376 in the different steps of the simulation.377 The definition is as follows:378 @[379 \mbox{CountCphotons}[ \mbox{FILTER} ] \equiv380 \mbox{\it Number of photons after the filter} \mbox{FILTER}381 @]382 The filters are defined and can be found in the file |camera.h|.383 384 @"*/385 386 //!@{387 // vector to count photons at any given step of the simulation388 389 static int CountCphotons[10];390 //!@}391 392 317 /*!@" 393 318 … … 430 355 431 356 char inname[256]; //@< input file name 432 char outname[256]; //@< output file name357 char starfieldname[256]; //@< starfield input file name 433 358 char datname[256]; //@< data (ASCII) output file name 434 359 char diagname[256]; //@< diagnistic output file (ROOT format) … … 437 362 char parname[256]; //@< parameters file name 438 363 439 char sign[20]; //@< initialize sign440 441 364 char flag[SIZE_OF_FLAGS + 1]; //@< flags in the .rfl file 442 365 443 ifstream inputfile; //@< stream for the input file 444 ofstream outputfile; //@< stream for the output file 366 FILE *inputfile; //@< stream for the input file 445 367 ofstream datafile; //@< stream for the data file 446 368 447 369 MCEventHeader mcevth; //@< Event Header class (MC) 448 MCCphoton cphoton; //@< Cherenkov Photon class (MC) 370 371 Photoelectron *photoe = NULL; //@< array of the photoelectrons of one event 372 int inumphe; //@< number of photoelectrons in an event 373 374 float arrtmin_ns; //@ arrival time of the first photoelectron 375 float arrtmax_ns; //@ arrival time of the last photoelectron 449 376 450 377 float thetaCT, phiCT; //@< parameters of a given shower … … 458 385 int nshow=0; //@< partial number of shower in a given run 459 386 int ntshow=0; //@< total number of showers 460 int ncph=0; //@< partial number of shower in a given run 461 int ntcph=0; //@< total number of showers 462 463 int i, ii, j, k; //@< simple counters 464 465 float t_ini; //@< time of the first Cphoton read in 466 float t; //@< time for a single photon 467 int t_chan ; //@< the bin (channel) in time of a single photon 468 469 int startchan ; //@< the first bin with entries in the time slices 470 471 float cx, cy, ci, cj; //@< coordinates in the XY and IJ systems 472 int ici, icj, iici, iicj; //@< coordinates in the IJ (integers) 473 474 int nPMT; //@< number of pixel 475 476 float wl, last_wl; //@< wavelength of the photon 477 float qe; //@< quantum efficiency 478 float **qeptr; 387 int ncph=0; //@< partial number of photons in a given run 388 int ntcph=0; //@< total number of photons 389 390 int i, j, k; //@< simple counters 479 391 480 392 int simulateNSB; //@< Will we simulate NSB? 481 float meanNSB; //@< NSB mean value (per pixel) 393 float meanNSB; //@< diffuse NSB mean value (phe per ns per central pixel) 394 float diffnsb_phepns[iMAXNUMPIX]; //@< diffuse NSB values for each pixel derived 395 //@< from meanNSB 396 float nsbrate_phepns[iMAXNUMPIX][iNUMWAVEBANDS]; //@< non-diffuse nsb 397 //@< photoelectron rates 398 float ext[iNUMWAVEBANDS] = { //@< average atmospheric extinction in each waveband 399 EXTWAVEBAND1, 400 EXTWAVEBAND2, 401 EXTWAVEBAND3, 402 EXTWAVEBAND4, 403 EXTWAVEBAND5 404 }; 405 float baseline_mv[iMAXNUMPIX]; //@< The baseline (mV) caused by the NSB; to be subtracted 406 //@< in order to simulate the preamps' AC coupling 407 482 408 float qThreshold; //@< Threshold value 483 409 float qTailCut; //@< Tail Cut value … … 488 414 float fCorrection; //@< Factor to apply to pixel values (def. 1.) 489 415 490 float q0; //@< trigger threshold ( intermediate variable )491 float maxcharge; //@< maximum charge in pixels492 int noverq0, novq0; //@< number of pixels above threshold493 int ngrpq0, mxgrp; //@< number of pixels in a group494 495 416 int trigger; //@< trigger flag 496 417 int itrigger; //@< index of pixel fired 497 418 int ntrigger = 0; //@< number of triggers in the whole file 498 unsigned char triggerBits; //@< byte for trigger condition check (MAGIC)499 int bit; //@< intermediate variable500 419 501 420 float plateScale_cm2deg; //@< plate scale (deg/cm) … … 506 425 int still_in_loop = FALSE; 507 426 508 char Signature[20];509 510 427 float *image_data; 511 428 int nvar, hidt; … … 513 430 struct camera cam; // structure holding the camera definition 514 431 515 #ifdef __DETAIL_TRIGGER__516 517 MTrigger Trigger ; //@< A instance of the Class MTrigger518 519 #endif // __DETAIL_TRIGGER__520 432 521 433 //!@' @#### Definition of variables for |getopt()|. … … 592 504 593 505 strcpy( inname, get_input_filename() ); 594 strcpy( outname, get_output_filename() );506 strcpy( starfieldname, get_starfield_filename() ); 595 507 strcpy( datname, get_data_filename() ); 596 508 strcpy( diagname, get_diag_filename() ); … … 615 527 "Filenames", 616 528 "In", inname, 617 "Out", outname, 529 "Stars", starfieldname, 530 "CT", ct_filename, 618 531 "Data", datname, 619 532 "Diag", diagname, 620 "ROOT", rootname ,621 "CT", ct_filename);533 "ROOT", rootname 534 ); 622 535 623 536 … … 669 582 read_ct_file(); 670 583 671 // read pixels data584 // read camera setup 672 585 673 586 read_pixels(&cam); 674 587 588 // allocate memory for the photoelectrons 589 590 photoe = new Photoelectron[iMAXNUMPHE]; 591 675 592 // initialise ROOT 676 593 … … 682 599 683 600 hfile = new TFile( diagname,"RECREATE", "MAGIC Telescope MC diagnostic data"); 684 685 601 686 602 // Create the ROOT Tree for the diagnostic data … … 698 614 tree->Branch("event", "MDiagEventobject", &event, bsize, split); 699 615 700 #ifdef __ROOT__ 616 // Prepare the raw data output 701 617 702 618 MRawEvt *Evt = new MRawEvt() ; … … 706 622 // 707 623 708 TFile outfile ( rootname , "RECREATE" ) ; 709 710 // 624 TFile outfile ( rootname , "RECREATE" ); 625 711 626 // create a Tree for the Event data stream 712 //713 627 714 628 TTree EvtTree("EvtTree","Events of Run"); … … 722 636 &McEvt, bsize, split); 723 637 724 725 float flli = 0. ;726 unsigned short ulli = 0 ;727 728 #endif // __ROOT__729 638 730 639 // for safety and for dimensioning image_data: count the elements in the … … 787 696 anaPixels = (anaPixels == -1) ? ct_NPixels : anaPixels; 788 697 789 // open input file if we DO read data from a file 790 791 if (! Data_From_STDIN) { 792 log( SIGNATURE, "Openning input \"rfl\" file %s\n", inname ); 793 inputfile.open( inname ); 794 if ( inputfile.bad() ) 698 // prepare the NSB simulation 699 700 if( simulateNSB ){ 701 702 // 703 // Calculate the non-diffuse NSB photoelectron rates 704 // 705 706 k = produce_nsbrates( starfieldname, 707 &cam, 708 photoe, // only a dummy here 709 nsbrate_phepns ); 710 if (k != 0){ 711 cout << "Error when reading starfield... \nExiting.\n"; 712 exit(1); 713 } 714 715 // for(i=0; i<cam.inumpixels; i++){ 716 // cout << i; 717 // for(j=0; j<iNUMWAVEBANDS; j++){ 718 // cout << " " << j << " " << nsbrate_phepns[i][j]; 719 // } 720 // cout << "\n"; 721 // } 722 723 // calculate diffuse rate correcting for the pixel size 724 725 for(i=0; i<cam.inumpixels; i++){ 726 diffnsb_phepns[i] = meanNSB * 727 cam.dpixsizefactor[i] * cam.dpixsizefactor[i]; 728 } 729 730 } 731 732 // 733 // Read the reflector file with the Cherenkov data 734 // 735 736 // select input file 737 738 if ( Data_From_STDIN ) { 739 740 inputfile = stdin; 741 742 } 743 else{ 744 745 log( SIGNATURE, "Opening input \"rfl\" file %s\n", inname ); 746 inputfile = fopen( inname, "r" ); 747 if ( inputfile == NULL ) 795 748 error( SIGNATURE, "Cannot open input file: %s\n", inname ); 749 796 750 } 797 751 798 752 // get signature, and check it 799 // NOTE: this part repeats further down in the code; 800 // if you change something here you probably want to change it 801 // there as well 802 803 strcpy(Signature, REFL_SIGNATURE); 804 805 strcpy(sign, Signature); 806 807 if ( Data_From_STDIN ) 808 cin.read( (char *)sign, strlen(Signature)); 809 else 810 inputfile.read( (char *)sign, strlen(Signature)); 811 812 if (strcmp(sign, Signature) != 0) { 813 cerr << "ERROR: Signature of .rfl file is not correct\n"; 814 cerr << '"' << sign << '"' << '\n'; 815 cerr << "should be: " << Signature << '\n'; 753 754 if(check_reflector_file( inputfile )==FALSE){ 816 755 exit(1); 817 756 } 818 757 819 if ( Data_From_STDIN )820 cin.read( (char *)sign, 1);821 else822 inputfile.read( (char *)sign, 1);823 824 // open output file825 826 log( SIGNATURE, "Openning output \"phe\" file %s\n", outname );827 outputfile.open( outname );828 829 if ( outputfile.bad() )830 error( SIGNATURE, "Cannot open output file: %s\n", outname );831 832 758 // open data file 833 759 834 log( SIGNATURE, "Open ning data \"dat\" file %s\n", datname );760 log( SIGNATURE, "Opening data \"dat\" file %s\n", datname ); 835 761 datafile.open( datname ); 836 762 837 if ( outputfile.bad() ) 838 error( SIGNATURE, "Cannot open output file: %s\n", outname ); 839 840 // write signature 841 842 outputfile.write( SIGNATURE, sizeof(SIGNATURE) ); 843 763 if ( datafile.bad() ) 764 error( SIGNATURE, "Cannot open data file: %s\n", datname ); 765 844 766 // initializes flag 845 767 … … 851 773 fnpixclean = new float [ ct_NPixels ]; 852 774 853 #ifdef __ROOT__854 855 fnslicesum = new float [ (2 * SLICES) ] ;856 857 float slices [CAMERA_PIXELS][ (2 * SLICES) ] ;858 float slices2 [CAMERA_PIXELS][ SLICES ] ;859 860 float trans [ SLICES ] ;861 #endif // __ROOT__862 863 864 775 moments_ptr = moments( anaPixels, NULL, NULL, 0.0, 1 ); 776 777 // initialize baseline 778 779 for(i=0; i<cam.inumpixels; i++){ 780 baseline_mv[i] = 0.; 781 } 865 782 866 783 //!@' @#### Main loop. 867 784 //@' 868 785 869 //begin my version870 871 786 // get flag 872 787 873 if ( Data_From_STDIN ) 874 cin.read( flag, SIZE_OF_FLAGS ); 875 else 876 inputfile.read ( flag, SIZE_OF_FLAGS ); 788 fread( flag, SIZE_OF_FLAGS, 1, inputfile ); 877 789 878 790 // loop over the file … … 881 793 882 794 while ( 883 ((! Data_From_STDIN) && ( ! inputfile.eof()))795 ((! Data_From_STDIN) && ( !feof(inputfile) )) 884 796 || 885 797 (Data_From_STDIN && still_in_loop) … … 891 803 } 892 804 else { // found start of run 805 893 806 nshow=0; 894 // read next flag 895 896 if ( Data_From_STDIN ) 897 cin.read( flag, SIZE_OF_FLAGS ); 898 else 899 inputfile.read ( flag, SIZE_OF_FLAGS ); 807 808 fread( flag, SIZE_OF_FLAGS, 1, inputfile ); 900 809 901 810 while( isA( flag, FLAG_START_OF_EVENT )){ // while there is a next event 902 /*!@'903 904 For the case |FLAG\_START\_OF\_EVENT|,905 we read each Cherenkov photon, and follow these steps:906 907 @enumerate908 909 @- Transform XY-coordinates to IJ-coordinates.910 911 @- With this, we obtain the pixel where the photon hits.912 913 @- Use the wavelength $\lambda$ and the table of QE, and914 calculate the estimated (third order interpolated) quantum915 efficiency for that photon. The photon can be rejected.916 917 @- If accepted, then add to the pixel.918 919 @endenumerate920 921 In principle, we should stop here, and use another program to922 'smear' the image, to add the Night Sky Background, and to923 simulate the trigger logic, but we will make this program924 quick and dirty, and include all here.925 926 If we are reading PHE files, we jump to the point where the927 pixelization process already has finished.928 929 */930 811 931 812 ++nshow; … … 934 815 // get MCEventHeader 935 816 936 if ( Data_From_STDIN ) 937 cin.read( (char*)&mcevth, mcevth.mysize() ); 938 else 939 mcevth.read( inputfile ); 817 fread( (char*)&mcevth, mcevth.mysize(), 1, inputfile ); 940 818 941 819 // calculate core distance and impact parameter … … 1023 901 } 1024 902 1025 // clear camera 1026 1027 for ( i=0; i<ct_NPixels; ++i ){ 1028 1029 fnpix[i] = 0.0; 1030 #ifdef __ROOT__ 1031 for ( ii=0; ii<(2 * SLICES); ii++ ) { 1032 slices [i][ii] = 0 ; 1033 } 1034 #endif // __ROOT__ 903 // read the photons and produce the photoelectrons 904 905 k = produce_phes( inputfile, 906 &cam, 907 WAVEBANDBOUND1, 908 WAVEBANDBOUND6, 909 photoe, // will be changed by the function! 910 &inumphe, // important for later: the size of photoe[] 911 fnpix, // will be changed by the function! 912 &ncph, // will be changed by the function! 913 &arrtmin_ns, // will be changed by the function! 914 &arrtmax_ns // will be changed by the function! 915 ); 916 917 if( k != 0 ){ // non-zero returnvalue means error 918 cout << "Exiting.\n"; 919 exit(1); 1035 920 } 1036 1037 ntcph +=ncph; 1038 ncph = 0; 1039 1040 #ifdef __DETAIL_TRIGGER__ 1041 // 1042 // clear Trigger 1043 // 1044 1045 Trigger.Reset() ; 1046 #endif // __DETAIL_TRIGGER__ 1047 1048 //- - - - - - - - - - - - - - - - - - - - - - - - - 1049 // read photons and "map" them into the pixels 1050 //-------------------------------------------------- 1051 1052 // initialize CPhoton 1053 1054 cphoton.fill(0., 0., 0., 0., 0., 0., 0., 0.); 1055 1056 // read the photons data 1057 1058 if ( Data_From_STDIN ) 1059 cin.read( flag, SIZE_OF_FLAGS ); 1060 else 1061 inputfile.read ( flag, SIZE_OF_FLAGS ); 1062 1063 // loop over the photons 1064 1065 t_ini = -99999; 1066 1067 while ( !isA( flag, FLAG_END_OF_EVENT ) ) { 1068 1069 memcpy( (char*)&cphoton, flag, SIZE_OF_FLAGS ); 1070 1071 if ( Data_From_STDIN ) 1072 cin.read( ((char*)&cphoton)+SIZE_OF_FLAGS, cphoton.mysize()-SIZE_OF_FLAGS ); 1073 else 1074 inputfile.read( ((char*)&cphoton)+SIZE_OF_FLAGS, cphoton.mysize()-SIZE_OF_FLAGS ); 1075 1076 // increase number of photons 1077 1078 ncph++; 1079 1080 t = cphoton.get_t() ; 1081 1082 if(t_ini == -99999){ // this is the first photon we read from this event 1083 t_ini = t; // memorize time 1084 } 1085 1086 // The photons don't come in chronological order! 1087 // Put the first photon at the center of the array by adding the constant SLICES 1088 1089 t_chan = (int) ((t - t_ini )/ WIDTH_TIMESLICE ) + SLICES ; 1090 1091 if (t_chan > (2 * SLICES)){ 1092 log(SIGNATURE, "warning, channel number (%d) exceded limit (%d).\n Setting it to %d .\n", 1093 t_chan, (2 * SLICES), (2 * SLICES)); 1094 t_chan = (2 * SLICES); 1095 } 1096 else if(t_chan < 0){ 1097 log(SIGNATURE, "warning, channel number (%d) below limit (%d).\n Setting it to %d .\n", 1098 t_chan, 0, 0); 1099 t_chan = 0; 1100 } 1101 1102 // Pixelization 1103 1104 cx = cphoton.get_x(); 1105 cy = cphoton.get_y(); 1106 1107 // get wavelength 1108 1109 last_wl = wl; 1110 wl = cphoton.get_wl(); 1111 1112 // check if photon has valid wavelength and is inside outermost camera radius 1113 1114 if( (wl > 800.0) || (wl < 290.0) || 1115 (sqrt(cx*cx + cy*cy) > (cam.dxc[ct_NPixels-1]+1.5*ct_PixelWidth)) ){ 1116 1117 // read next CPhoton 1118 if ( Data_From_STDIN ) 1119 cin.read( flag, SIZE_OF_FLAGS ); 1120 else 1121 inputfile.read ( flag, SIZE_OF_FLAGS ); 1122 1123 // go to beginning of loop, the photon is lost 1124 continue; 1125 1126 } 1127 1128 // cout << "@#1 " << nshow << ' ' << cx << ' ' << cy << endl; 1129 1130 nPMT = -1; 1131 1132 for(i=0; i<ct_NPixels; i++){ 1133 if( bpoint_is_in_pix( cx, cy, i, &cam) ){ 1134 nPMT = i; 1135 break; 1136 } 1137 } 1138 1139 if(nPMT==-1){// the photon is in none of the pixels 1140 1141 // read next CPhoton 1142 if ( Data_From_STDIN ) 1143 cin.read( flag, SIZE_OF_FLAGS ); 1144 else 1145 inputfile.read ( flag, SIZE_OF_FLAGS ); 1146 1147 // go to beginning of loop, the photon is lost 1148 continue; 1149 } 1150 1151 1152 1153 #ifdef __QE__ 1154 1155 //!@' @#### QE simulation. 1156 //@' 1157 1158 //+++ 1159 // QE simulation 1160 //--- 1161 1162 // find data point to be used in Lagrange interpolation (-> k) 1163 1164 qeptr = (float **)QE[nPMT]; 1165 1166 FindLagrange(qeptr,k,wl); 1167 1168 // if random > quantum efficiency, reject it 1169 1170 qe = Lagrange(qeptr,k,wl) / 100.0; 1171 1172 // fprintf(stdout, "%f\n", qe); 1173 1174 if ( RandomNumber > qe ) { 1175 1176 // read next CPhoton 1177 if ( Data_From_STDIN ) 1178 cin.read( flag, SIZE_OF_FLAGS ); 1179 else 1180 inputfile.read ( flag, SIZE_OF_FLAGS ); 1181 1182 // go to beginning of loop 1183 continue; 1184 1185 } 1186 1187 #endif // __QE__ 1188 1189 //+++ 1190 // Cphoton is accepted 1191 //--- 1192 1193 // increase the number of Cphs. in the PMT, i.e., 1194 // increase in one unit the counter of the photons 1195 // stored in the pixel nPMT 1196 1197 fnpix[nPMT] += 1.0; 1198 1199 #ifdef __ROOT__ 1200 fnslicesum[t_chan] += 1.0 ; 1201 slices[nPMT][t_chan] += 1.0 ; 1202 #endif // __ROOT__ 1203 1204 #ifdef __DETAIL_TRIGGER__ 1205 // 1206 // fill the Trigger class with this phe 1207 // 1208 // 1209 1210 Trigger.Fill( nPMT, ( t - t_ini ) ) ; 1211 #endif // __DETAIL_TRIGGER__ 1212 1213 // read next CPhoton 1214 1215 if ( Data_From_STDIN ) 1216 cin.read( flag, SIZE_OF_FLAGS ); 1217 else 1218 inputfile.read ( flag, SIZE_OF_FLAGS ); 1219 1220 } // end while, i.e. found end of event 1221 921 1222 922 log(SIGNATURE, "End of this event: %d cphs(+%d). . .\n", 1223 923 ncph, ntcph); 1224 1225 // show number of photons 1226 1227 //cout << ncph << " photons read . . . " << endl << flush; 1228 924 925 ntcph += ncph; 926 1229 927 // skip it ? 1230 928 … … 1245 943 } 1246 944 1247 /*!@' 1248 1249 After reading all the Cherenkov photons for a given event, 1250 we have in the table of number of photons for each pixel 1251 only the 'raw' amount of Cherenkov photons @$n_p@$. Now, we 1252 should take this number as the mean value of the 1253 distribution of photons in that pixel @$p@$, following a 1254 Poisson distribution. 1255 1256 @[ n_p \equiv \mu_p @] 1257 1258 and with this number the amount of light coming from the 1259 shower is calculated @$\hat{n}_p@$. 1260 1261 Then, we calculate the amount of Night Sky Background we 1262 must introduce in that pixel @$p@$. We calculate this using 1263 again a Poisson distribution with mean @$\mu_\mathrm{NSB}@$ 1264 (defined in the |camera.h| file). The value of 1265 @$\mu_\mathrm{NSB}@$ is obtained from measurements. With this 1266 value, the amount of photons @$\hat{n}_\mathrm{NSB}@$ coming 1267 from the Night Sky Background is calculated. 1268 1269 Finally, the amount of photons for that pixels is: 1270 @[ \hat{n}_p^\mathrm{final} = \hat{n}_p + \hat{n}_\mathrm{NSB} @] 1271 1272 */ 1273 1274 // after reading all the photons, our camera is filled 945 // energy cut 1275 946 1276 947 if ( Select_Energy ) { … … 1281 952 } 1282 953 } 1283 1284 #ifdef __NSB__ 1285 1286 //!@' @#### NSB (Night Sky Background) simulation. 1287 //@' 1288 1289 //+++ 954 1290 955 // NSB simulation 1291 //--- 1292 1293 // add NSB "noise" 1294 // TO DO: make meanNSB an array and read the contents from a file! 1295 1296 if ( simulateNSB ) 1297 for ( i=0; i<ct_NPixels; ++i ) 1298 fnpix[i] += (float)ignpoi( meanNSB ); 1299 1300 #endif // __NSB__ 1301 1302 // if we should apply any kind of correction, do it here. 1303 1304 for ( i=0; i<ct_NPixels; ++i ) 1305 fnpix[i] *= fCorrection; 1306 1307 #ifdef __DETAIL_TRIGGER__ 1308 // Trigger.Print() ; 1309 cout << Trigger.Diskriminate() << endl << endl ; 1310 #endif // __DETAIL_TRIGGER__ 1311 1312 #ifdef __ROOT__ 1313 1314 // 1315 // Fill the header of this event 1316 // 1317 1318 Evt->FillHeader ( (UShort_t) (ntshow + nshow) , 20 ) ; 1319 1320 // now put out the data of interest 1321 // 1322 // 1. -> look for the first slice with signal 1323 // 1324 1325 for ( i=0; i<(2 * SLICES); i++ ) 1326 if ( fnslicesum[i] > 0. ) 1327 break ; 1328 1329 startchan = i ; 1330 1331 // 1332 // copy the slices out of the big array 1333 // 1334 // put the first slice with signal to slice 4 1335 // 1336 1337 for (i=0; i<ct_NPixels; i++ ) 1338 for ( ii=(startchan-3); ii < (startchan+12); ii++ ) 1339 slices2 [i][ii-startchan+3] = slices [i][ii] ; 1340 1341 1342 // 1343 // if a pixes has a signal put it to the MRawEvt 1344 // 1345 1346 for (i=0; i<ct_NPixels; i++ ) { 1347 if ( fnpix[i] > 0 ) { 1348 1349 for ( ii=0; ii < 15; ii++ ) { 1350 trans [ii] = slices2[i][ii] ; 1351 } 1352 1353 Evt->FillPixel ( (UShort_t) i , trans ) ; 1354 956 957 if(simulateNSB){ 958 959 k = produce_nsb_phes( &arrtmin_ns, // will be changed by the function! 960 &arrtmax_ns, // will be changed by the function! 961 thetaCT, 962 &cam, 963 nsbrate_phepns, 964 diffnsb_phepns, 965 ext, 966 fnpix, // will be changed by the function! 967 photoe, // will be changed by the function! 968 &inumphe, // important for later: the size of photoe[] 969 baseline_mv // will be generated by the function 970 ); 971 972 if( k != 0 ){ // non-zero returnvalue means error 973 cout << "Exiting.\n"; 974 exit(1); 1355 975 } 1356 } 1357 1358 // 1359 // 1360 // 1361 1362 McEvt->Fill( (UShort_t) mcevth.get_primary() , 1363 mcevth.get_energy(), 1364 mcevth.get_theta(), 1365 mcevth.get_phi(), 1366 mcevth.get_core(), 1367 mcevth.get_coreX(), 1368 mcevth.get_coreY(), 1369 flli, 1370 ulli, ulli, ulli, ulli, ulli ) ; 1371 1372 // 1373 // write it out to the file outfile 1374 // 1375 1376 EvtTree.Fill() ; 1377 1378 // clear all 1379 1380 Evt->Clear() ; 1381 McEvt->Clear() ; 1382 1383 #endif // __ROOT__ 1384 1385 //++++++++++++++++++++++++++++++++++++++++++++++++++ 1386 // at this point we have a camera full of 1387 // ph.e.s 1388 // we should first apply the trigger condition, 1389 // and if there's trigger, then clean the image, 1390 // calculate the islands statistics and the 1391 // other parameters of the image (Hillas' parameters 1392 // and so on). 1393 //-------------------------------------------------- 1394 1395 #ifdef __TRIGGER__ 1396 1397 /*!@' 1398 1399 @#### Trigger logic simulation. 1400 1401 In the following block we look at the pixel contents, looking 1402 for pixels fulfilling the trigger condition. This condition, 1403 in this current version of the program, is the following: 1404 1405 @itemize 1406 1407 @- |CT1|: Two neighbour pixels with charge above the threshold 1408 @$q_0@$. For the old CT1 data, however, the trigger condition 1409 was 'any two pixels with charge above the threshold @$q_0@$'. 1410 1411 @- |MAGIC|: A 'closed-packet' of four neighbour pixels, each 1412 of them with charge above the threshold @$q_0@$. 1413 1414 @enditemize 1415 1416 In the following figure you can find a sort of description 1417 about the meanning of 'closed-packet'. 1418 1419 @F 1420 1421 \begin{figure}[htbp] 1422 \begin{center} 1423 \includegraphics{closepck.eps} 1424 \caption{Meanning of the expression ``{\it close-packet}''} 1425 \label{fig:closepacket} 1426 \end{center} 1427 \end{figure} 1428 1429 @F 1430 1431 */ 1432 1433 //++ 1434 // TRIGGER Condition 1435 //-- 1436 1437 //@ If the input parameter "threshold" is 0 we find the maximum 1438 //@ trigger threshold this event can pass 1439 1440 for(k=0; ( qThreshold == 0 ? (k <= iMAX_THRESHOLD_PHE) : (k == 1) ); k++){ 1441 1442 // is there trigger? 1443 1444 noverq0 = 0; 1445 q0 = ( qThreshold == 0. ? (float) k : qThreshold ); 1446 trigger = FALSE; 1447 mxgrp = 0; 1448 maxcharge = 0.0; 1449 1450 // Warning! NOT all the camera is able to give trigger 1451 // only up to 'degTrigger' degrees 1452 1453 for ( i=0 ; (i<ct_NCentralPixels) && (trigger==FALSE) ; ++i ) { 1454 1455 // calculate absolute maximum 1456 1457 maxcharge = MAX(fnpix[i],maxcharge); 1458 1459 // is this pixel above threshold ? 1460 1461 if ( fnpix[i] <= q0 ) 1462 continue; 1463 1464 // it is: increment the number of pixels above threshold 1465 1466 ++noverq0; 1467 1468 // if the trigger already fired, just count the pixels 1469 // above threshold 1470 1471 if ( trigger == TRUE ) 1472 continue; 1473 1474 // is this pixel inside the trigger zone in the camera ? 1475 1476 if ( (sqrt(SQR(pixary[i][0]) + 1477 SQR(pixary[i][1]))*plateScale_cm2deg) > degTriggerZone) 1478 continue; 1479 1480 // 'ngrpq0' is the number of neighbours of pixel i with q > q0 1481 1482 ngrpq0 = 0; 1483 1484 // look at each pixel in the neighborhood, and count 1485 // those above threshold q0 1486 1487 for ( j=0 ; j<npixneig[i] && pixneig[i][j]>-1 ; ++j ) 1488 if ( fnpix[pixneig[i][j]] > q0 ) 1489 ++ngrpq0; 1490 1491 // check whether we have trigger 1492 1493 if ( ct_Type == 0 ) { 1494 1495 //++ >>>>> CT1 <<<<< 1496 1497 #ifdef __CT1_NO_NEIGHBOURS__ 1498 1499 if ( noverq0 > 1 ) 1500 trigger = TRUE; 1501 1502 #else 1503 1504 if ( ngrpq0 > 0 ) 1505 trigger = TRUE; 1506 1507 #endif 1508 1509 //-- >>>>> CT1 <<<<< 1510 1511 } else { 1512 1513 //++ >>>>> MAGIC <<<<< 1514 1515 // (at least 4 packed with at least q0 phes) 1516 1517 // there are 3 cases 1518 // 1. zero, one or two neighbours have enough charge: no trigger 1519 // 2. five or six neighbours with enough charge: trigger? sure!! 1520 // 3. three or four neighbours with q > q0 : we must look 1521 // for 'closeness'. 1522 1523 switch ( ngrpq0 ) { 1524 1525 case 0: 1526 case 1: 1527 case 2: 1528 1529 trigger = FALSE; 1530 break; 1531 1532 case 3: 1533 case 4: 1534 1535 // if reaches this line, it means three or four neighbours 1536 // around the central pixel 1537 1538 triggerBits = 1; 1539 1540 for ( j=0 ; j<npixneig[i] && pixneig[i][j]>-1; ++j ) { 1541 1542 if ( fnpix[pixneig[i][j]] > q0 ) { 1543 1544 if ( pixary[pixneig[i][j]][0] > pixary[i][0] ) { 1545 1546 if ( nint(pixary[pixneig[i][j]][1]*10.0) > 1547 nint(pixary[i][1]*10.0) ) 1548 bit = 2; 1549 else if ( nint(pixary[pixneig[i][j]][1]*10.0) < 1550 nint(pixary[i][1]*10.0) ) 1551 bit = 6; 1552 else 1553 bit = 1; 1554 1555 } else { 1556 1557 if ( nint(pixary[pixneig[i][j]][1]*10.0) > 1558 nint(pixary[i][1]*10.0) ) 1559 bit = 3; 1560 else if ( nint(pixary[pixneig[i][j]][1]*10.0) < 1561 nint(pixary[i][1]*10.0) ) 1562 bit = 5; 1563 else 1564 bit = 4; 1565 1566 } 1567 1568 triggerBits |= (1<<bit); 1569 1570 } 1571 1572 } 1573 1574 if ( ngrpq0 == 3 ) { // 4-fold trigger 1575 1576 switch ( triggerBits ) { 1577 1578 case 0x0f: // 0 000111 1 1579 case 0x1d: // 0 001110 1 1580 case 0x39: // 0 011100 1 1581 case 0x71: // 0 111000 1 1582 case 0x63: // 0 110001 1 1583 case 0x47: // 0 100011 1 1584 1585 trigger = TRUE; 1586 break; 1587 1588 default: 1589 1590 trigger = FALSE; 1591 1592 } 1593 1594 } else { // 4-fold trigger 1595 1596 switch ( triggerBits ) { 1597 1598 case 0x1f: // 0 001111 1 1599 case 0x3d: // 0 011110 1 1600 case 0x79: // 0 111100 1 1601 case 0x73: // 0 111001 1 1602 case 0x67: // 0 110011 1 1603 case 0x4f: // 0 100111 1 1604 1605 trigger = TRUE; 1606 break; 1607 1608 default: 1609 1610 trigger = FALSE; 1611 1612 } 1613 1614 } 1615 1616 mxgrp = MAX(ngrpq0,mxgrp); 1617 1618 break; 1619 1620 case 5: 1621 case 6: 1622 1623 trigger = TRUE; 1624 break; 1625 1626 default: 1627 1628 trigger = FALSE; 1629 error( SIGNATURE, "Number of neighbours > 6 !!! Exiting.\n\n"); 1630 break; 1631 1632 } // switch (ngrpq0) 1633 1634 } // ct_Type 1635 1636 } // for each pixel i 1637 1638 if ( trigger == FALSE ) { 1639 break; 1640 } // end if 1641 1642 } //end for each threshold 1643 maxtrigthr_phe = (float) k-1; // i.e. maxtrigthr_phe < 0. means that 1644 // the event doesn't even pass threshold 0. 1645 // maxtrigthr_phe >= 0 means, the event passes some threshold 1646 // or (in case the input parameter "threshold" was > 0), the event 1647 // passes the threshold given by the input parameter. 1648 if ( maxtrigthr_phe >= 0. ) { 1649 trigger = TRUE; 1650 } 1651 1652 1653 novq0 = noverq0; 976 977 }// end if(simulateNSB) ... 978 979 980 // cout << arrtmin_ns << " " << arrtmax_ns << "\n"; 981 // for(i=0; i<cam.inumpixels; i++){ 982 // cout << i << " " << baseline_mv[i] <<"\n"; 983 // } 984 985 986 cout << "Total number of phes: " << inumphe << "\n"; 987 988 // TRIGGER HERE 989 990 trigger = FALSE; 991 992 if( TRUE ) trigger = TRUE; // put your trigger function here 993 994 // for( i=0; i<inumphe; i++){ 995 // cout << "phe " << photoe[i].ipixnum << " " << photoe[i].iarrtime_ns << "\n"; 996 // } 1654 997 1655 998 if ( trigger == TRUE ) { … … 1660 1003 memcpy( fnpixclean, fnpix, sizeof(float) * ct_NPixels ); 1661 1004 1662 #ifdef __TAILCUT__1663 1664 //!@' @#### Tail-cut condition.1665 //@'1666 1667 //++1668 // tail-cut1669 //--1670 1671 // Tail-Cut = 0 : No Tail-Cut1672 // Tail-Cut > 0 : Make Tail-Cut1673 // Tail-Cut < 0 : Make Tail-Cut with t_0 = Sqrt[ maximum ]1674 1675 if (qTailCut > 0.0) {1676 1677 for ( i=0; i<ct_NPixels; ++i )1678 if ( fnpix[i] < qTailCut )1679 fnpixclean[i] = 0.0;1680 1681 } else if (qTailCut < 0.0) {1682 1683 maxcharge = sqrt(maxcharge);1684 for ( i=0; i<ct_NPixels; ++i )1685 if ( fnpix[i] < maxcharge )1686 fnpixclean[i] = 0.0;1687 1688 }1689 1690 #endif // __TAILCUT__1691 1005 1692 1006 #ifdef __ISLANDS__ … … 1705 1019 #endif // __ISLANDS__ 1706 1020 1707 #ifdef __MOMENTS__1708 1021 1709 1022 //!@' @#### Calculation of parameters of the image. … … 1797 1110 } 1798 1111 1799 1800 #endif // __MOMENTS__1801 1802 1803 1112 // revert the fnpixclean matrix into fnpix 1804 1113 // (now we do this, but maybe in a future we want to … … 1889 1198 1890 1199 } // trigger == FALSE 1891 1892 #endif // __TRIGGER__ 1893 1200 1894 1201 //!@' @#### Save data. 1895 1202 //@' … … 1904 1211 // save the image to the file 1905 1212 //-- 1906 1907 // write MCEventHeader to output file 1908 1909 outputfile.write( (char *)&mcevth, mcevth.mysize() ); 1910 1911 #ifdef __TRIGGER__ 1912 1913 // save the image 1914 1915 if ( (trigger == TRUE) || (Write_All_Images == TRUE) ) 1916 outputfile.write( (char *) fnpix, ct_NPixels * sizeof( float ) ); 1917 1918 #else 1919 1920 // save the image 1921 1922 outputfile.write( (char *) fnpix, ct_NPixels * sizeof( float ) ); 1923 1924 #endif // __TRIGGER__ 1925 1926 if ( Data_From_STDIN ) 1927 cin.read( flag, SIZE_OF_FLAGS ); 1928 else 1929 inputfile.read ( flag, SIZE_OF_FLAGS ); 1930 1213 1214 1215 1216 // look for the next event 1217 1218 fread( flag, SIZE_OF_FLAGS, 1, inputfile ); 1219 1931 1220 } // end while there is a next event 1932 1221 … … 1938 1227 log(SIGNATURE, "End of this run with %d events . . .\n", nshow); 1939 1228 1940 if ( Data_From_STDIN ) 1941 cin.read( flag, SIZE_OF_FLAGS ); 1942 else 1943 inputfile.read ( flag, SIZE_OF_FLAGS ); 1229 fread( flag, SIZE_OF_FLAGS, 1, inputfile ); 1944 1230 1945 1231 if( isA( flag, FLAG_END_OF_FILE ) ){ // end of file … … 1947 1233 still_in_loop = FALSE; 1948 1234 1949 if ((! Data_From_STDIN) && ( ! inputfile.eof())){1235 if ((! Data_From_STDIN) && ( !feof(inputfile) )){ 1950 1236 1951 1237 // we have concatenated input files. 1952 1238 // get signature of the next part and check it. 1953 // NOTE: this part repeats further up in the code; 1954 // if you change something here you probably want to change it 1955 // there as well 1956 1957 strcpy(Signature, REFL_SIGNATURE); 1958 1959 strcpy(sign, Signature); 1960 1961 inputfile.read( (char *)sign, strlen(Signature)); 1962 1963 if (strcmp(sign, Signature) != 0) { 1964 cerr << "ERROR: Signature of .rfl file is not correct\n"; 1965 cerr << '"' << sign << '"' << '\n'; 1966 cerr << "should be: " << Signature << '\n'; 1239 1240 if(check_reflector_file( inputfile )==FALSE){ 1967 1241 exit(1); 1968 1242 } 1969 1243 1970 if ( Data_From_STDIN )1971 cin.read( (char *)sign, 1);1972 else1973 inputfile.read( (char *)sign, 1);1974 1975 1244 } 1976 1245 1977 1246 } // end if found end of file 1978 1247 } // end if found end of run 1979 if ( Data_From_STDIN ) 1980 cin.read( flag, SIZE_OF_FLAGS ); 1981 else 1982 inputfile.read ( flag, SIZE_OF_FLAGS ); 1248 1249 fread( flag, SIZE_OF_FLAGS, 1, inputfile ); 1250 1983 1251 } // end if else found start of run 1984 1252 } // end big while loop 1985 1253 1986 //!@' @#### End of program.1987 //@'1988 1989 //end my version1990 1991 #ifdef __ROOT__1992 1254 //++ 1993 1255 // put the Event to the root file … … 1998 1260 outfile.Close() ; 1999 1261 2000 #endif // __ROOT__2001 1262 2002 1263 // close input file 2003 1264 2004 ntcph += ncph;2005 1265 log( SIGNATURE, "%d event(s), with a total of %d C.photons\n", 2006 1266 ntshow, ntcph ); … … 2012 1272 log( SIGNATURE, "Closing files\n" ); 2013 1273 2014 inputfile.close(); 2015 outputfile.close(); 1274 if( ! Data_From_STDIN ){ 1275 fclose( inputfile ); 1276 } 2016 1277 datafile.close(); 2017 1278 … … 2019 1280 2020 1281 hfile->Close(); 2021 2022 #ifdef __DETAIL_TRIGGER__2023 // Output of Trigger statistics2024 //2025 2026 Trigger.PrintStat() ;2027 #endif // __DETAIL_TRIGGER__2028 1282 2029 1283 // program finished … … 2138 1392 2139 1393 // Display the name of the function that called error 2140 fprintf(std err, "ERROR in %s: ", funct);1394 fprintf(stdout, "ERROR in %s: ", funct); 2141 1395 2142 1396 // Display the remainder of the message 2143 1397 va_start(args, fmt); 2144 vfprintf(std err, fmt, args);1398 vfprintf(stdout, fmt, args); 2145 1399 va_end(args); 2146 1400 … … 2425 1679 ifstream qefile; 2426 1680 char line[LINE_MAX_LENGTH]; 2427 int n, i, j, k;1681 int n, i, j, icount; 2428 1682 float qe; 2429 1683 … … 2438 1692 2439 1693 // initialize pixel numbers 2440 2441 for ( i=0; i<PIX_ARRAY_SIDE; ++i )2442 for ( j=0; j<PIX_ARRAY_SIDE; ++j )2443 pixels[i][j][PIXNUM] = -1;2444 1694 2445 1695 pixary = new float* [2*ct_NCentralPixels]; … … 2462 1712 igen_pixel_coordinates(pcam); 2463 1713 2464 // transfer coordinates to the working arrays for2465 // the central pixels2466 2467 for(k=0; k<ct_NCentralPixels; k++){2468 2469 i = (int) pcam->di[k];2470 j = (int) pcam->dj[k];2471 2472 pixels[i+PIX_ARRAY_HALF_SIDE][j+PIX_ARRAY_HALF_SIDE][PIXNUM] = k;2473 pixels[i+PIX_ARRAY_HALF_SIDE][j+PIX_ARRAY_HALF_SIDE][PIXX] = pcam->dxc[k];2474 pixels[i+PIX_ARRAY_HALF_SIDE][j+PIX_ARRAY_HALF_SIDE][PIXY] = pcam->dyc[k];2475 2476 pixary[k][0] = pcam->dxc[k];2477 pixary[k][1] = pcam->dyc[k];2478 }2479 1714 2480 1715 // calculate tables of neighbours … … 2519 1754 // try to open the file 2520 1755 2521 log("read_pixels", "Open ning the file \"%s\" . . .\n", QE_FILE);1756 log("read_pixels", "Opening the file \"%s\" . . .\n", QE_FILE); 2522 1757 2523 1758 qefile.open( QE_FILE ); … … 2533 1768 2534 1769 i=-1; 1770 icount = 0; 2535 1771 2536 1772 while ( ! qefile.eof() ) { … … 2577 1813 // get the values (num-pixel, num-datapoint, QE-value) 2578 1814 2579 sscanf(line, "%d %d %f", &i, &j, &qe); 1815 if( sscanf(line, "%d %d %f", &i, &j, &qe) != 3 ) 1816 break; 2580 1817 2581 1818 if ( ((i-1) < ct_NPixels) && ((i-1) > -1) && … … 2585 1822 } 2586 1823 1824 if ( i > ct_NPixels) break; 1825 1826 icount++; 1827 2587 1828 } 2588 1829 1830 if(icount/pointsQE < ct_NPixels){ 1831 error( "read_pixels", "The quantum efficiency file is faulty\n (found only %d pixels instead of %d).\n", 1832 icount/pointsQE, ct_NPixels ); 1833 } 1834 2589 1835 // close file 2590 1836 2591 1837 qefile.close(); 1838 1839 // test QE 1840 1841 for(icount=0; icount< ct_NPixels; icount++){ 1842 for(i=0; i<pointsQE; i++){ 1843 if( QE[icount][0][i] < 100. || QE[icount][0][i] > 1000. || 1844 QE[icount][1][i] < 0. || QE[icount][1][i] > 100.){ 1845 error( "read_pixels", "The quantum efficiency file is faulty\n pixel %d, point %d is % f, %f\n", 1846 icount, i, QE[icount][0][i], QE[icount][1][i] ); 1847 } 1848 } 1849 } 2592 1850 2593 1851 // end … … 2875 2133 } /* end if */ 2876 2134 2877 /* generate the ij coordinates */2878 2879 for(i=0; i<pcam->inumpixels; i++){2880 pcam->dj[i] = pcam->dyc[i]/SIN60/dpsize;2881 pcam->di[i] = pcam->dxc[i]/dpsize - pcam->dj[i]*COS60;2882 2883 // fprintf(stdout, "%d %f %f %f %f %f\n",2884 // i+1, pcam->di[i], pcam->dj[i], pcam->dxc[i], pcam->dyc[i],2885 // pcam->dpixsizefactor[i]);2886 2887 }2888 2889 2135 return(pcam->inumpixels); 2890 2136 … … 2968 2214 ); 2969 2215 } 2216 2217 //------------------------------------------------------------ 2218 // @name check_reflector_file 2219 // 2220 // @desc check if a given reflector file has the right signature 2221 // @desc return TRUE or FALSE 2222 // 2223 // @date Mon Feb 14 16:44:21 CET 2000 2224 // @function @code 2225 //------------------------------------------------------------ 2226 2227 int check_reflector_file(FILE *infile){ 2228 2229 char Signature[20]; // auxiliary variable 2230 char sign[20]; // auxiliary variable 2231 2232 strcpy(Signature, REFL_SIGNATURE); 2233 2234 strcpy(sign, Signature); 2235 2236 fread( (char *)sign, strlen(Signature), 1, infile); 2237 2238 if (strcmp(sign, Signature) != 0) { 2239 cout << "ERROR: Signature of .rfl file is not correct\n"; 2240 cout << '"' << sign << '"' << '\n'; 2241 cout << "should be: " << Signature << '\n'; 2242 return(FALSE); 2243 } 2244 2245 fread( (char *)sign, 1, 1, infile); 2246 2247 return(TRUE); 2248 2249 } 2250 2251 //------------------------------------------------------------ 2252 // @name lin_interpol 2253 // 2254 // @desc interpolate linearly between two points returning the 2255 // @desc y-value of the result 2256 // 2257 // @date Thu Feb 17 11:31:32 CET 2000 2258 // @function @code 2259 //------------------------------------------------------------ 2260 2261 float lin_interpol( float x1, float y1, float x2, float y2, float x){ 2262 2263 if( (x2 - x1)<=0. ){ // avoid division by zero, return average 2264 cout << "Warning: lin_interpol was asked to interpolate between two points with x1>=x2.\n"; 2265 return((y1+y2)/2.); 2266 } 2267 else{ // note: the check whether x1 < x < x2 is omitted for speed reasons 2268 return((float) (y1 + (y2-y1)/(x2-x1)*(x-x1)) ); 2269 } 2270 } 2271 2272 2273 //------------------------------------------------------------ 2274 // @name Photoelectron 2275 // 2276 // @desc constructor for class Photoelectron 2277 // 2278 // @date Mon Feb 15 16:44:21 CET 2000 2279 // @function @code 2280 //------------------------------------------------------------ 2281 2282 Photoelectron::Photoelectron(void){ 2283 iarrtime_ns = NOTIME; 2284 ipixnum = -1; 2285 } 2286 2287 //------------------------------------------------------------ 2288 // @name produce_phes 2289 // 2290 // @desc read the photons of an event, pixelize them and simulate QE 2291 // @desc return various statistics and the array of Photoelectrons 2292 // 2293 // @date Mon Feb 14 16:44:21 CET 2000 2294 // @function @code 2295 //------------------------------------------------------------ 2296 2297 int produce_phes( FILE *sp, // the input file 2298 struct camera *cam, // the camera layout 2299 float minwl_nm, // the minimum accepted wavelength 2300 float maxwl_nm, // the maximum accepted wavelength 2301 class Photoelectron phe[iMAXNUMPHE], // the generated phes 2302 int *itotnphe, // total number of produced photoelectrons 2303 float nphe[iMAXNUMPIX], // number of photoelectrons in each pixel 2304 int *incph, // total number of cph read 2305 float *tmin_ns, // minimum arrival time of all phes 2306 float *tmax_ns // maximum arrival time of all phes 2307 ){ 2308 2309 static int i, k, ipixnum; 2310 static float cx, cy, wl, qe, t; 2311 static MCCphoton photon; 2312 static float **qept; 2313 static char flag[SIZE_OF_FLAGS + 1]; 2314 static float radius; 2315 2316 // reset variables 2317 2318 for ( i=0; i<cam->inumpixels; ++i ){ 2319 2320 nphe[i] = 0.0; 2321 2322 } 2323 2324 *itotnphe = 0; 2325 *incph = 0; 2326 *tmin_ns = NOTIME; // very big 2327 *tmax_ns = -NOTIME; // very small 2328 2329 radius = cam->dxc[cam->inumpixels-1] 2330 + 1.5*cam->dpixdiameter_cm*cam->dpixsizefactor[cam->inumpixels-1]; 2331 2332 //- - - - - - - - - - - - - - - - - - - - - - - - - 2333 // read photons and "map" them into the pixels 2334 //-------------------------------------------------- 2335 2336 // initialize CPhoton 2337 2338 photon.fill(0., 0., 0., 0., 0., 0., 0., 0.); 2339 2340 // read the photons data 2341 2342 fread ( flag, SIZE_OF_FLAGS, 1, sp ); 2343 2344 // loop over the photons 2345 2346 while ( !isA( flag, FLAG_END_OF_EVENT ) ) { 2347 2348 memcpy( (char*)&photon, flag, SIZE_OF_FLAGS ); 2349 2350 fread( ((char*)&photon)+SIZE_OF_FLAGS, photon.mysize()-SIZE_OF_FLAGS, 1, sp ); 2351 2352 // increase number of photons 2353 2354 (*incph)++; 2355 2356 // 2357 // Pixelization 2358 // 2359 2360 cx = photon.get_x(); 2361 cy = photon.get_y(); 2362 2363 // get wavelength 2364 2365 wl = photon.get_wl(); 2366 2367 // cout << "wl " << wl << " radius " << sqrt(cx*cx + cy*cy) << "\n"; 2368 2369 // check if photon has valid wavelength and is inside outermost camera radius 2370 2371 if( (wl > maxwl_nm) || (wl < minwl_nm) || (sqrt(cx*cx + cy*cy) > radius ) ){ 2372 2373 // cout << " lost first check\n"; 2374 2375 // read next CPhoton 2376 2377 fread ( flag, SIZE_OF_FLAGS, 1, sp ); 2378 2379 // go to beginning of loop, the photon is lost 2380 continue; 2381 2382 } 2383 2384 ipixnum = -1; 2385 2386 for(i=0; i<cam->inumpixels; i++){ 2387 if( bpoint_is_in_pix( cx, cy, i, cam) ){ 2388 ipixnum = i; 2389 break; 2390 } 2391 } 2392 2393 if(ipixnum==-1){// the photon is in none of the pixels 2394 2395 // cout << " lost pixlization\n"; 2396 2397 // read next CPhoton 2398 2399 fread ( flag, SIZE_OF_FLAGS, 1, sp ); 2400 2401 // go to beginning of loop, the photon is lost 2402 continue; 2403 } 2404 2405 //+++ 2406 // QE simulation 2407 //--- 2408 2409 // set pointer to the QE table of the relevant pixel 2410 2411 qept = (float **)QE[ipixnum]; 2412 2413 // check if wl is inside table; outside the table, QE is assumed to be zero 2414 2415 if((wl < qept[0][0]) || (wl > qept[0][pointsQE-1])){ 2416 2417 // cout << " lost\n"; 2418 2419 // read next Photon 2420 2421 fread ( flag, SIZE_OF_FLAGS, 1, sp ); 2422 2423 // go to beginning of loop 2424 continue; 2425 2426 } 2427 2428 // find data point in the QE table (-> k) 2429 2430 k = 1; // start at 1 because the condition was already tested for 0 2431 while (k < pointsQE-1 && qept[0][k] < wl){ 2432 k++; 2433 } 2434 2435 // calculate the qe value between 0. and 1. 2436 2437 qe = lin_interpol(qept[0][k-1], qept[1][k-1], qept[0][k], qept[1][k], wl) / 100.0; 2438 2439 // if random > quantum efficiency, reject it 2440 2441 if ( RandomNumber > qe ) { 2442 2443 // cout << " lost\n"; 2444 2445 // read next Photon 2446 2447 fread ( flag, SIZE_OF_FLAGS, 1, sp ); 2448 2449 // go to beginning of loop 2450 continue; 2451 2452 } 2453 2454 //+++ 2455 // The photon has produced a photo electron 2456 //--- 2457 2458 // cout << " accepted\n"; 2459 2460 // increment the number of photoelectrons in the relevant pixel 2461 2462 nphe[ipixnum] += 1.0; 2463 2464 t = photon.get_t() ; 2465 2466 // cout << " t " << t; 2467 2468 // find minimum and maximum arrival time 2469 2470 if(t < *tmin_ns){ 2471 *tmin_ns = t; // memorize time 2472 } 2473 if(t > *tmax_ns){ 2474 *tmax_ns = t; // memorize time 2475 } 2476 2477 // store the new photoelectron 2478 2479 if(*itotnphe >= iMAXNUMPHE){ 2480 cout << "Error: Memory overflow. Event produces more than maximum\n"; 2481 cout << " allowed number of photoelectrons (" << iMAXNUMPHE << ").\n"; 2482 return(1); 2483 } 2484 2485 phe[*itotnphe].iarrtime_ns = (int)t; 2486 phe[*itotnphe].ipixnum = ipixnum; 2487 2488 *itotnphe += 1; 2489 2490 // read next Photon 2491 2492 fread( flag, SIZE_OF_FLAGS, 1, sp ); 2493 2494 } // end while, i.e. found end of event 2495 2496 return(0); 2497 2498 } 2499 2500 2501 //------------------------------------------------------------ 2502 // @name produce_nsbrates 2503 // 2504 // @desc read the starfield file, call produce_phes on it in, 2505 // @desc different wavebands, calculate the nsbrates 2506 // 2507 // @date Mon Feb 14 16:44:21 CET 2000 2508 // @function @code 2509 //------------------------------------------------------------ 2510 2511 int produce_nsbrates( char *iname, // the starfield input file name 2512 struct camera *cam, // camera layout 2513 class Photoelectron phe[iMAXNUMPHE], // array for photoelectrons 2514 float rate_phepns[iMAXNUMPIX][iNUMWAVEBANDS] // the product of this function: 2515 // the NSB rates in phe/ns for each pixel 2516 ){ 2517 2518 int i, j, k, ii; // counters 2519 2520 static float wl_nm[iNUMWAVEBANDS + 1] = { WAVEBANDBOUND1, 2521 WAVEBANDBOUND2, 2522 WAVEBANDBOUND3, 2523 WAVEBANDBOUND4, 2524 WAVEBANDBOUND5, 2525 WAVEBANDBOUND6 }; 2526 2527 FILE *infile; // the input file 2528 fpos_t fileposition; // marker on the input file 2529 static char cflag[SIZE_OF_FLAGS + 1]; // auxiliary variable 2530 static MCEventHeader evth; // the event header 2531 static float nphe[iMAXNUMPIX]; // the number of photoelectrons in each pixel 2532 int itnphe; // total number of produced photoelectrons 2533 int itotnphe; // total number of produced photoelectrons after averaging 2534 int incph; // total number of cph read 2535 float tmin_ns; // minimum arrival time of all phes 2536 float tmax_ns; // maximum arrival time of all phes 2537 float integtime_ns; // integration time from the starfield generator 2538 2539 // open input file 2540 2541 log(SIGNATURE, "Opening starfield input \"rfl\" file %s\n", iname ); 2542 2543 infile = fopen( iname, "r" ); 2544 if ( infile == NULL ) 2545 error( SIGNATURE, "Cannot open starfield input file: %s\n", iname ); 2546 2547 // get signature, and check it 2548 2549 if(check_reflector_file(infile)==FALSE){ 2550 exit(1); 2551 } 2552 2553 // initialize flag 2554 2555 strcpy( cflag, " \0" ); 2556 2557 // get flag 2558 2559 fread( cflag, SIZE_OF_FLAGS, 1, infile ); 2560 2561 if ( ! feof(infile)){ 2562 2563 // reading .rfl file 2564 2565 if(!isA( cflag, FLAG_START_OF_RUN )){ 2566 error( SIGNATURE, "Expected start of run flag, but found: %s\n", cflag ); 2567 } 2568 else { // found start of run 2569 2570 fread( cflag, SIZE_OF_FLAGS, 1, infile ); 2571 2572 if( isA( cflag, FLAG_START_OF_EVENT )){ // there is a event 2573 2574 // get MCEventHeader 2575 2576 fread( (char*)&evth, evth.mysize(), 1, infile ); 2577 2578 integtime_ns = evth.get_energy(); 2579 2580 // memorize where we are in the file 2581 2582 if (fgetpos( infile, &fileposition ) != 0){ 2583 error( SIGNATURE, "Cannot position in file ...\n"); 2584 } 2585 2586 // loop over the wavebands 2587 2588 for(i=0; i<iNUMWAVEBANDS; i++){ 2589 2590 // initialize the rate array 2591 2592 for(j = 0; j<cam->inumpixels; j++){ // loop over pixels 2593 rate_phepns[j][i] = 0.; 2594 } 2595 2596 itotnphe = 0; 2597 2598 // read the photons and produce the photoelectrons 2599 // - in order to average over the QE simulation, call the 2600 // production function iNUMNSBPRODCALLS times 2601 2602 for(ii=0; ii<iNUMNSBPRODCALLS; ii++){ 2603 2604 // position the file pointer to the beginning of the photons 2605 2606 fsetpos( infile, &fileposition); 2607 2608 // produce photoelectrons 2609 2610 k = produce_phes( infile, 2611 cam, 2612 wl_nm[i], 2613 wl_nm[i+1], 2614 phe, // this is a dummy here 2615 &itnphe, 2616 nphe, // we want this! 2617 &incph, 2618 &tmin_ns, 2619 &tmax_ns ); 2620 2621 if( k != 0 ){ // non-zero returnvalue means error 2622 cout << "Exiting.\n"; 2623 exit(1); 2624 } 2625 2626 for(j = 0; j<cam->inumpixels; j++){ // loop over pixels 2627 rate_phepns[j][i] += nphe[j]/integtime_ns/(float)iNUMNSBPRODCALLS; 2628 } 2629 2630 itotnphe += itnphe; 2631 2632 } // end for(ii=0 ... 2633 2634 fprintf(stdout, "Starfield, %6f - %6f nm: %d photoelectrons for %6f ns integration time\n", 2635 wl_nm[i], wl_nm[i+1], itotnphe/iNUMNSBPRODCALLS, integtime_ns); 2636 2637 } // end for(i=0 ... 2638 2639 } 2640 else{ 2641 cout << "Starfield file contains no event.\nExiting.\n"; 2642 exit(1); 2643 } // end if( isA ... event 2644 } // end if ( isA ... run 2645 } 2646 else{ 2647 cout << "Starfield file contains no run.\nExiting.\n"; 2648 exit(1); 2649 } 2650 2651 fclose( infile ); 2652 2653 return(0); 2654 2655 } 2656 2657 2658 //------------------------------------------------------------ 2659 // @name produce_nsb_phes 2660 // 2661 // @desc produce the photoelectrons from the nsbrates 2662 // 2663 // @date Thu Feb 17 17:10:40 CET 2000 2664 // @function @code 2665 //------------------------------------------------------------ 2666 2667 int produce_nsb_phes( float *atmin_ns, 2668 float *atmax_ns, 2669 float theta_rad, 2670 struct camera *cam, 2671 float nsbr_phepns[iMAXNUMPIX][iNUMWAVEBANDS], 2672 float difnsbr_phepns[iMAXNUMPIX], 2673 float extinction[iNUMWAVEBANDS], 2674 float fnpx[iMAXNUMPIX], 2675 Photoelectron photo[iMAXNUMPHE], 2676 int *inphe, 2677 float base_mv[iMAXNUMPIX]){ 2678 2679 float simtime_ns; // NSB simulation time 2680 int i, j, k, ii; 2681 float zenfactor; // correction factor calculated from the extinction 2682 int inumnsbphe; // number of photoelectrons caused by NSB 2683 2684 ii = *inphe; // avoid dereferencing 2685 2686 // check if the arrival times are set; if not generate them 2687 2688 if(*atmin_ns == NOTIME){ 2689 2690 *atmin_ns = 0.; 2691 *atmax_ns = simtime_ns = SLICES*WIDTH_TIMESLICE; 2692 2693 } 2694 else{ // extend the event time window by the given offsets 2695 2696 *atmin_ns = *atmin_ns - SIMTIMEOFFSET_NS; 2697 *atmax_ns = *atmax_ns + SIMTIMEOFFSET_NS; 2698 2699 simtime_ns = *atmax_ns - *atmin_ns; 2700 2701 // make sure the simulated time is long enough for the FADC simulation 2702 2703 if(simtime_ns< SLICES*WIDTH_TIMESLICE){ 2704 *atmax_ns = *atmin_ns + SLICES*WIDTH_TIMESLICE; 2705 simtime_ns = SLICES*WIDTH_TIMESLICE; 2706 } 2707 2708 } 2709 2710 // initialize baselines 2711 2712 for(i=0; i<cam->inumpixels; i++){ 2713 base_mv[i] = 0.; 2714 } 2715 2716 // calculate baselines and generate phes 2717 2718 for(i=0; i<iNUMWAVEBANDS; i++){ // loop over the wavebands 2719 2720 // calculate the effect of the atmospheric extinction 2721 2722 zenfactor = pow(10., -0.4 * extinction[i]/cos(theta_rad) ); 2723 2724 for(j=0; j<cam->inumpixels; j++){ // loop over the pixels 2725 2726 inumnsbphe = (int) ((zenfactor * nsbr_phepns[j][i] + difnsbr_phepns[j]/iNUMWAVEBANDS) 2727 * simtime_ns ); 2728 2729 base_mv[j] += inumnsbphe; 2730 2731 // randomize 2732 2733 inumnsbphe = ignpoi( inumnsbphe ); 2734 2735 // create the photoelectrons 2736 2737 for(k=0; k < inumnsbphe; k++){ 2738 2739 if(ii >= iMAXNUMPHE){ 2740 cout << "Error: Memory overflow. NSB simulation produces more than maximum\n"; 2741 cout << " allowed number of photoelectrons (" << iMAXNUMPHE << ").\n"; 2742 return(1); 2743 } 2744 2745 photo[ii].iarrtime_ns = (int)(RandomNumber * simtime_ns + *atmin_ns ); 2746 photo[ii].ipixnum = j; 2747 2748 // cout << "Created phe " << photo[ii].iarrtime_ns << " " 2749 // << photo[ii].ipixnum << "\n"; 2750 2751 ii++; // increment total number of photoelectons 2752 2753 fnpx[j] += 1.; // increment number of photoelectrons in this pixel 2754 2755 } 2756 2757 } // end for(j=0 ... 2758 } // end for(i=0 ... 2759 2760 // finish baseline calculation 2761 2762 for(i=0; i<cam->inumpixels; i++){ 2763 base_mv[i] *= RESPONSE_FWHM * RESPONSE_AMPLITUDE / simtime_ns; 2764 } 2765 2766 *inphe = ii; // update the pointer 2767 2768 return(0); 2769 } 2770 2771 2970 2772 // @endcode 2971 2773 … … 2977 2779 // 2978 2780 // $Log: not supported by cvs2svn $ 2781 // Revision 1.4 2000/01/25 08:36:23 petry 2782 // The pixelization in previous versions was buggy. 2783 // This is the first version with a correct pixelization. 2784 // 2979 2785 // Revision 1.3 2000/01/20 18:22:17 petry 2980 2786 // Found little bug which makes camera crash if it finds a photon … … 2996 2802 // The "rootification" was done by Dirk Petry and Harald Kornmayer. 2997 2803 // 2998 // In the following you can see the README file of that version:2999 //3000 // ==================================================3001 //3002 // Fri Oct 22 1999 D.P.3003 //3004 // The MAGIC Monte Carlo System3005 //3006 // Camera Simulation Programme3007 // ---------------------------3008 //3009 // 1) Description3010 //3011 // This version is the result of the fusion of H.K.'s3012 // root_camera which is described below (section 2)3013 // and another version by D.P. which had a few additional3014 // useful features.3015 //3016 // The version compiles under Linux with ROOT 2.22 installed3017 // (variable ROOTSYS has to be set).3018 //3019 // Compile as before simply using "make" in the root_camera3020 // directory.3021 //3022 // All features of H.K.'s root_camera were retained.3023 //3024 // Additional features of this version are:3025 //3026 // a) HBOOK is no longer used and all references are removed.3027 //3028 // b) Instead of HBOOK, the user is given now the possibility of3029 // having Diagnostic data in ROOT format as a complement3030 // to the ROOT Raw data.3031 //3032 // This data is written to the file which is determined by3033 // the new input parameter "diag_file" in the camera parameter3034 // file.3035 //3036 // All source code file belonging to this part have filenames3037 // starting with "MDiag".3038 //3039 // The user can read the output file using the following commands3040 // in an interactive ROOT session:3041 //3042 // root [0] .L MDiag.so3043 // root [1] new TFile("diag.root");3044 // root [2] new TTreeViewer("T");3045 //3046 // This brings up a viewer from which all variables of the3047 // TTree can be accessed and histogrammed. This example3048 // assumes that you have named the file "diag.root", that3049 // you are using ROOT version 2.22 or later and that you have3050 // the shared object library "MDiag.so" which is produced3051 // by the Makefile along with the executable "camera".3052 //3053 // ! The contents of the so-called diag file is not yet fixed.3054 // ! At the moment it is what J.C.G. used to put into the HBOOK3055 // ! ntuple. In future versions the moments calculation can be3056 // ! removed and the parameter list be modified correspondingly.3057 //3058 // c) Now concatenated reflector files can be read. This is useful3059 // if you have run the reflector with different parameters but3060 // you want to continue the analysis with all reflector data3061 // going into ONE ROOT outputfile.3062 //3063 // The previous camera version contained a bug which made reading3064 // of two or more concatenated reflector files impossible.3065 //3066 // d) The reflector output format was changed. It is now version3067 // 0.4 .3068 // The change solely consists in a shortening of the flag3069 // definition in the file3070 //3071 // include-MC/MCCphoton.hxx3072 //3073 // ! IF YOU WANT TO READ REFLECTOR FORMAT 0.3, you can easily3074 // ! do so by recompiling camera with the previous version of3075 // ! include-MC/MCCphoton.hxx.3076 //3077 // The change was necessary for saving space and better3078 // debugging. From now on, this format can be frozen.3079 //3080 // ! For producing reflector output in the new format, you3081 // ! of course have to recompile your reflector with the3082 // ! new include-MC/MCCphoton.hxx .3083 //3084 // e) A first version of the pixelization with the larger3085 // outer pixels is implemented. THIS IS NOT YET FULLY3086 // TESTED, but first rough tests show that it works3087 // at least to a good approximation.3088 //3089 // The present version implements the camera outline3090 // with 18 "gap-pixels" and 595 pixels in total as3091 // shown in3092 //3093 // http://sarastro.ifae.es/internal/home/hardware/camera/numbering.ps3094 //3095 // This change involved3096 //3097 // (i) The file pixels.dat is no longer needed. Instead3098 // the coordinates are generated by the program itself3099 // (takes maybe 1 second). In the file3100 //3101 // pixel-coords.txt3102 //3103 // in the same directory as this README, you find a list3104 // of the coordinates generated by this new routine. It3105 // has the format3106 //3107 // number i j x y size-factor3108 //3109 // where i and j are J.C.G.'s so called biaxis hexagonal3110 // coordinates (for internal use) and x and y are the3111 // coordinates of the pixel centers in the standard camera3112 // coordinate system in units of centimeters. The value3113 // of "size-factor" determines the linear size of the pixel3114 // relative to the central pixels.3115 //3116 // (ii) The magic.def file has two additional parameters3117 // which give the number of central pixels and the3118 // number of gap pixels3119 //3120 // (iii) In camera.h and camera.cxx several changes were3121 // necessary, among them the introduction of several3122 // new functions3123 //3124 // The newly suggested outline with asymmetric Winston cones3125 // will be implemented in a later version.3126 //3127 // f) phe files can no longer be read since this contradicts3128 // our philosophy that the analysis should be done with other3129 // programs like e.g. EVITA and not with "camera" itself.3130 // This possibility was removed.3131 //3132 // g) ROOT is no longer invoked with an interactive interface.3133 // In this way, camera can better be run as a batch program and3134 // it uses less memory.3135 //3136 // h) small changes concerning the variable "t_chan" were necessary in3137 // order to avoid segmentation faults: The variable is used as an3138 // index and it went sometimes outside the limits when camera3139 // was reading proton data. This is because the reflector files3140 // don't contain the photons in a chronological order and also3141 // the timespread can be considerably longer that the foreseen3142 // digitisation timespan. Please see the source code of camera.cxx3143 // round about line 1090.3144 //3145 // j) several unused variables were removed, a few warning messages3146 // occur when you compile camera.cxx but these can be ignored at3147 // the moment.3148 //3149 // In general the program is of course not finished. It still needs3150 // debugging, proper trigger simulation, simulation of the asymmetric3151 // version of the outer pixels, proper NSB simulation, adaption of3152 // the diag "ntuple" contents to our need and others small improvements.3153 //3154 // In the directory rfl-files there is now a file in reflector format 0.43155 // containing a single event produced by the starfiled adder. It has3156 // a duration of 30 ns and represents the region around the Crab Nebula.3157 // Using the enclosed input parameter file, camera should process this3158 // file without problems.3159 //3160 // 2) The README for the previous version of root_camera3161 //3162 // README for a preliminary version of the3163 // root_camera program.3164 //3165 // root_camera is based on the program "camera"of Jose Carlos3166 // Gonzalez. It was changed in the way that only the pixelisation3167 // and the distibution of the phe to the FADCs works in a3168 // first version.3169 //3170 // Using the #undef command most possibilities of the orignal3171 // program are switched of.3172 //3173 // The new parts are signed by3174 //3175 // - ROOT or __ROOT__3176 // nearly all important codelines for ROOT output are enclosed3177 // in structures like3178 // #ifdef __ROOT__3179 //3180 // code3181 //3182 // #endif __ROOT__3183 //3184 // In same case the new lines are signed by a comment with the word3185 // ROOT in it.3186 //3187 // For timing of the pulse some variable names are changed.3188 // (t0, t1, t --> t_ini, t_fin, t_1st, t_chan,...)3189 // Look also for this changes.3190 //3191 // For the new root-file is also a change in readparm-files3192 //3193 //3194 // - __DETAIL_TRIGGER__3195 //3196 // This is for the implementation of the current work on trigger3197 // studies. Because the class MTrigger is not well documented it3198 // isn´t a part of this tar file. Only a dummy File exists.3199 //3200 //3201 //3202 // With all files in the archive, the root_camera program should run.3203 //3204 // A reflector file is in the directory rfl-files3205 //3206 // ==================================================3207 //3208 // From now on, use CVS for development!!!!3209 //3210 //3211 //3212 2804 // Revision 1.3 1999/10/22 15:01:28 petry 3213 2805 // version sent to H.K. and N.M. on Fri Oct 22 1999
Note:
See TracChangeset
for help on using the changeset viewer.