source: trunk/MagicSoft/Simulation/Detector/Camera/camera.cxx@ 5258

Last change on this file since 5258 was 5247, checked in by moralejo, 21 years ago
Lots of changes intended to make it possible to select the FADC sampling frequency from the input card, through the command fadc_GHz. The most important ones are the following: - Removed FADC_SLICES de Mars/mmc/Mdefine.h Already defined in MFadcDefine.h! - Replaced fixed numbers in array dimensions of starresponse.cxx - Added in MFadc.cxx and MFadc.hxx (Float_t) casts to initializations of single phe response array - IMPORTANT: Fixed MFadc::GetResponse -> The returned single phe response had only RESPONSE_SLICES (which is actually for the trigger branch), whereas it should have RESPONSE_SLICES_MFADC. Fixed the same confusion in other two points of the code (filling of the FADC for the signal), in Fill() and FillOuter(). - RESPONSE_SLICES_MFADC is now eliminated, since this quantity is now decided by MFadc depending on other parameters. - Fixed problem in starresponse.cxx due to which the histograms fadcresp and fadcbase in the root output were actually identical. - Changed starresponse.cxx such that above 1 phe/ns/pixel the precision of the database is forced to be 0.1, and below 1, to 0.01 phe/ns/pixel - In Camera/creadparam.cxx: Now unkown tokens cause the program to stop, instead of being simply skipped as it was until now. - Fixed error in MStarLight::StoreHisto. TH1::SetBinContent uses bin numbers from 1 to nbins (in old code 0 to nbins-1 was assumed). - In MLons.cxx: use memcpy to copy pieces of the database into the FADC and trigger branches, to (hopefully) speed up execution. For this I had to add 2 getter functions in MStarLight.hxx - Everywhere: changed the shape parameter for trigger and FADC response to be an Int. Changed version of NSB database from 1002 to 1003. - In MTrigger.cxx, changed all initializations of SlicesFirst and SlicesSecond to 0 (instead of -50 as it was before). This controls the time of trigger. If no trigger happened (like when making pedestal files) the time was negative and the array index used to retrieve the noise from the database was negative, resulting in "discontinuities" in the noise (half-photoelectrons for instance). - In MStarLight changed fBinsTrig and fBinsFadc from Float_t to Int_t - Replace WIDTH_FADC_TIMESLICE by FADC_SLICES_PER_NSEC (which is the inverse of the former) - Replaced SLICES_PER_NSEC by TRIG_SLICES_PER_NSEC - TRIGBINS eliminated. It depends on other two values TRIGBINS = TIMERANGE*TRIG_SLICES_PER_NSEC - FADCBINS eliminated. It depends on other two values FADCBINS = TIMERANGE*FADC_SLICES_PER_NSEC - MTriggerDefine.h Changed RESPONSE_SLICES to RESPONSE_SLICES_TRIG - Added to the MLons constructor an argument regarding the FADC sampling frequency - MFadc: now the number of response slices for the FADC simulation is decided by the program according to the other parameters. - MStarLight: Added arguments (fadc_slices_per_ns, response_slices_fadc) to constructor. - creadparam.cxx, camera.cxx Changed default value of digital_noise to 0.
File size: 136.0 KB
Line 
1////!/////////////////////////////////////////////////////////////////////
2//
3// camera
4//
5// @file camera.cxx
6// @title Camera simulation
7// @subtitle Code for the simulation of the camera phase
8// @desc Code for the simulation of the camera of CT1 and MAGIC
9// @author J C Gonzalez
10// @email gonzalez@mppmu.mpg.de
11// @date Thu May 7 16:24:22 1998
12//
13//----------------------------------------------------------------------
14//
15// Created: Thu May 7 16:24:22 1998
16// Author: Jose Carlos Gonzalez
17// Purpose: Program for reflector simulation
18// Notes: See files README for details
19//
20//----------------------------------------------------------------------
21//
22// $RCSfile: camera.cxx,v $
23// $Revision: 1.72 $
24// $Author: moralejo $
25// $Date: 2004-10-12 13:39:34 $
26//
27////////////////////////////////////////////////////////////////////////
28// @tableofcontents @coverpage
29
30//=-----------------------------------------------------------
31//!@section Source code of |camera.cxx|.
32
33/*!@"
34
35 In this section we show the (commented) code of the program for the
36 read-out of the output files generated by the simulator of the
37 reflector, |reflector 0.3|.
38
39 @"*/
40
41//=-----------------------------------------------------------
42//!@subsection Includes and Global variables definition.
43
44//!@{
45
46// includes for ROOT
47// BEWARE: the order matters!
48
49#include "TROOT.h"
50
51#include "TRandom.h"
52#include "TApplication.h"
53
54#include "TFile.h"
55#include "TTree.h"
56#include "TBranch.h"
57#include "TCanvas.h"
58
59#include "TArrayC.h"
60#include "TObjArray.h"
61
62#include "MTrigger.hxx"
63#include "MFadc.hxx"
64#include "MLons.hxx"
65
66#include "MRawRunHeader.h"
67#include "MRawEvtData.h"
68#include "MRawEvtHeader.h"
69#include "MRawCrateArray.h"
70#include "MRawCrateData.h"
71#include "MMcEvt.hxx"
72#include "MMcTrig.hxx"
73#include "MMcRunHeader.hxx"
74#include "MMcConfigRunHeader.h"
75#include "MMcCorsikaRunHeader.h"
76#include "MMcTrigHeader.hxx"
77#include "MMcFadcHeader.hxx"
78#include "MGeomCamMagic.h"
79#include "MGeomCamMagic919.h"
80#include "MGeomCamMagicHG.h"
81#include "MGeomCamECO1000.h"
82#include "MGeomCamECO1000HG.h"
83#include "MGeomCamCT1.h"
84#include "MGeomCamCT1Daniel.h"
85#include "MGeomPix.h"
86#include "MGeomCorsikaCT.h"
87
88/*!@"
89
90 All the defines are located in the file |camera.h|.
91
92 @"*/
93
94#include "camera.h"
95
96//!@}
97
98/*!@"
99
100 The following set of flags are used in time of compilation. They do
101 not affect directly the behaviour of the program at run-time
102 (though, of course, if you disconnected the option for
103 implementation of the Trigger logic, you will not be able to use any
104 trigger at all. The 'default' values mean default in the sense of
105 what you got from the server when you obtained this program.
106
107 @"*/
108
109//!@{
110
111// flag for debugging (default: OFF )
112#define __DEBUG__
113#undef __DEBUG__
114
115
116//!@}
117
118//=-----------------------------------------------------------
119//!@subsection Definition of global variables.
120
121/*!@"
122
123 Now we define some global variables with data about the telescope,
124 such as "focal distance", number of pixels/mirrors,
125 "size of the camera", and so on.
126
127 @"*/
128
129/*!@"
130
131 Depending on the telescope we are using (CT1 or MAGIC), the
132 information stored in the definition file is different.
133 The variable |ct_Type| has the value 0 when we use
134 CT1, and 1 when we use MAGIC.
135
136 @"*/
137
138/*!@"
139
140 And this is the information about the whole telescope.
141
142 @"*/
143
144//!@{
145
146// parameters of the CT (from the CT definition file)
147
148//@: Number of pixels
149static int ct_NPixels;
150
151//@: Number of CT
152static int ct_Number;
153
154//@: list of showers to be skipped
155static int *Skip;
156
157//@: number of showers to be skipped
158static int nSkip=0;
159
160//@: flag: TRUE: data come from STDIN; FALSE: from file
161static int Data_From_STDIN = FALSE;
162
163//@: flag: TRUE: write all images to output; FALSE: only triggered showers
164static int Write_All_Images = FALSE;
165
166static int Write_McEvt = TRUE;
167static int Write_McTrig = TRUE;
168static int Write_McFADC = TRUE;
169static int Write_RawEvt = FALSE;
170
171//@: flag: TRUE: selection on the energy
172static int Select_Energy = TRUE;
173
174//@: Lower edge of the selected energy range (in GeV)
175static float Select_Energy_le = 0.0;
176
177//@: Upper edge of the selected energy range (in GeV)
178static float Select_Energy_ue = 100000.0;
179
180//@: flag: TRUE: show all fadc singnal in the screen; FALSE: don't
181static int FADC_Scan = FALSE;
182
183//@: flag: TRUE: show all trigger signal in the screen; FALSE: don't
184static int Trigger_Scan = FALSE;
185
186//@: flag: TRUE: loop trigger analysis over several thresholds, multiplicities and topologies; FALSE: a single trigger configuration
187static int Trigger_Loop = FALSE;
188
189//@: flag: TRUE: Different threshold for each pixel ; FALSE: same threshold for all pixels
190static int Individual_Thres_Pixel = FALSE;
191
192//@: Properties of the trigger
193static float Trigger_gate_length = 6.0;
194static float Trigger_response_ampl = 1.0;
195static float Trigger_response_fwhm = 2.0;
196static float Trigger_overlaping_time= 0.25;
197static float Trigger_noise= 0.3;
198
199//@: Properties of the FADC
200static Int_t FADC_shape = 0;
201static float FADC_response_integ = MFADC_RESPONSE_INTEGRAL;
202static float FADC_response_fwhm = MFADC_RESPONSE_FWHM;
203static Int_t FADC_shape_out = 0;
204static float FADC_resp_integ_out = MFADC_RESPONSE_INTEGRAL;
205static float FADC_resp_fwhm_out = MFADC_RESPONSE_FWHM;
206static float FADC_slices_per_ns = FADC_SLICES_PER_NSEC;
207static Int_t FADC_slices_written = FADC_SLICES;
208static float FADC_noise_inner = 2.0;
209static float FADC_noise_outer = 2.0;
210static float DIGITAL_noise = 0.0;
211static float FADC_high2low = HIGH2LOWGAIN;
212
213//@: Trigger conditions for a single trigger mode
214static float **qThreshold;
215static int Trigger_multiplicity[MAX_NUMBER_OF_CTS];
216static int Trigger_topology[MAX_NUMBER_OF_CTS];
217
218//@: Upper and lower edges of the trigger loop
219static float Trigger_loop_lthres = 2.0;
220static float Trigger_loop_uthres = 10.0;
221static float Trigger_loop_sthres = 1.0;
222static int Trigger_loop_lmult = 2;
223static int Trigger_loop_umult = 10;
224static int Trigger_loop_ltop = 0;
225static int Trigger_loop_utop = 2;
226
227//@: Direction of each shower
228static float Zenith = 0.0;
229static float Azimutal = 90.0;
230
231//@: Miss Pointing Simulation
232static int missPointing = 0;
233static float missP_x = 0.0;
234static float missP_y = 0.0;
235
236//@: Point Spread Function Added
237static float Spot_x=0.0;
238static float Spot_y=0.0;
239static float Spotsigma=0.0;
240
241
242//!@}
243
244/*!@"
245
246 The following double-pointer is a 2-dimensional table with information
247 about each pixel. The routine read_pixels will generate
248 the information for filling it using igen_pixel_coordinates().
249
250 @"*/
251
252//!@{
253// Pointer to a tables/Arrays with information about the pixels
254// and data stored on them with information about the pixels
255
256
257//@: contents of the pixels (ph.e.)
258static float *fnpix;
259
260
261//!@}
262
263/*!@"
264
265 The following double-pointer is a 2-dimensional table with the
266 Quantum Efficiency @$QE@$ of each pixel in the camera, as a function
267 of the wavelength @$\lambda@$. The routine |read_pixels()| will read
268 also this information from the file |qe.dat|.
269
270 @"*/
271
272//!@{
273// Pointer to a table with QE, number of datapoints, and wavelengths
274
275//@: table of QE
276static float ****QE;
277
278//@: number of datapoints for the QE curve
279static int pointsQE[MAX_NUMBER_OF_CTS];
280
281//@: table of QE
282static float *QElambda;
283
284//@: table of lightguide = WC; WC_outer for outer pixels.
285static float **WC;
286static float **WC_outer;
287
288//@: number of datapoints for the WC curve
289static int pointsWC;
290
291//!@}
292
293/*!@"
294
295 The following double-pointer is a 2-dimensional table with information
296 about each mirror in the dish. The routine |read_ct_file()| will read
297 this information from the CT definition file.
298
299 @"*/
300
301/*!@"
302
303 We define a table into where random numbers will be stored.
304 The routines used for random number generation are provided by
305 |RANLIB| (taken from NETLIB, |www.netlib.org|), and by
306 the routine |double drand48(void)| (prototype defined in
307 |stdlib.h|) through the macro |RandomNumber| defined in
308 |camera.h|.
309
310 @"*/
311
312
313//!@}
314
315extern char FileName[];
316// switch on starfield rotation
317static int Starfield_rotate = TRUE;
318
319//=-----------------------------------------------------------
320// @subsection Main program.
321
322//!@{
323
324//++++++++++++++++++++++++++++++++++++++++
325// MAIN PROGRAM
326//----------------------------------------
327
328int main(int argc, char **argv)
329{
330
331 //!@' @#### Definition of variables.
332 //@'
333
334 char **inname_CT; //@< array of names for each CT input file
335 char starfieldname[256]; //@< starfield input file name
336 char qe_filename[256]; //@< qe input file name
337
338 char datname[256]; //@< data (ASCII) output file name
339
340 char rootname[256] ; //@< ROOT file name
341 char rootname_loop[256] ; //@< ROOT file name
342
343 char parname[256]; //@< parameters file name
344
345 char nsbpathname[256]; //@< directory with the dataabse for th NSB
346 char nsbpath_outer[256]; //@< directory with the dataabse for outer pixels
347
348 char flag[SIZE_OF_FLAGS + 1]; //@< flags in the .rfl file
349 char flag_new[SIZE_OF_FLAGS + 1]; //@< New flag for the run header in the .rfl file
350 char **GeometryName; //@< Name of MGeomCam for each CT
351 int GeometryCamera[MAX_NUMBER_OF_CTS]; //@< Identification of MGeomCam for each CT
352 int TriggerPixels[MAX_NUMBER_OF_CTS]; //@< Number of pixels in the trigger region for each CT
353
354 int reflector_file_version=0; //@< vrsion of he reflector file
355
356 FILE *inputfile[MAX_NUMBER_OF_CTS]; //@< stream for the input file
357
358 ofstream datafile; //@< stream for the data file
359
360 MCRunHeader mcrunh; //@< Run Header class (MC)
361 MCEventHeader mcevth[MAX_NUMBER_OF_CTS]; //@< Event Header class (MC)
362 MCEventHeader_2 mcevth_2[MAX_NUMBER_OF_CTS]; //@< Event Header class (MC) for reflector > 0.6
363 MCCphoton cphoton; //@< Cherenkov Photon class (MC)
364
365 int inumphe; //@< number of photoelectrons in an event from showers
366 int inumphe_CT[MAX_NUMBER_OF_CTS]; //@< number of photoelectrons in an event from showers
367 float inumphensb[MAX_NUMBER_OF_CTS]; //@< number of photoelectrons in an event from nsb
368
369 float arrtmin_ns; //@ arrival time of the first photoelectron
370 float arrtmax_ns; //@ arrival time of the last photoelectron
371
372 float thetaCT[MAX_NUMBER_OF_CTS], phiCT[MAX_NUMBER_OF_CTS]; //@< theta and phi of telescopes
373
374 //@: Coordinates of telescopes in Corsika's coordinate system
375 float CTx[MAX_NUMBER_OF_CTS];
376 float CTy[MAX_NUMBER_OF_CTS];
377 float CTz[MAX_NUMBER_OF_CTS];
378
379 float mirror_frac[MAX_NUMBER_OF_CTS];
380
381 float thetashw, phishw; //@< parameters of a given shower
382 float coreX, coreY; //@< core position
383 float impactD[MAX_NUMBER_OF_CTS]; //@< impact parameter
384 float l1, m1, n1; //@< auxiliary variables
385 float factorqe_NSB[MAX_NUMBER_OF_CTS]; //@< factor on the NSB depending of QE
386
387 int nshow=0; //@< partial number of shower in a given run
388 int ntshow=0; //@< total number of showers
389 int ncph[MAX_NUMBER_OF_CTS]; //@< partial number of photons in a given run
390 int ntcph[MAX_NUMBER_OF_CTS]; //@< total number of photons
391
392 int ibr, j, k; //@< simple counters
393
394 int addElecNoise; //@< Will we add ElecNoise?
395
396 float riseDiskThres;
397 float secureDiskThres;
398
399 int simulateNSB; //@< Will we simulate NSB?
400 int nphe2NSB; //@< From how many phe will we simulate NSB?
401 float meanNSB; //@< diffuse NSB mean value (phe per ns per central pixel)
402 float **diffnsb_phepns;
403 //@< diffuse NSB values for each pixel derived from meanNSB
404
405 float **nsbrate_phepns; //@< non-diffuse nsb
406 //@< photoelectron rates
407 float **nsb_phepns;
408 //@< NSB values for each pixel
409
410 float **nsb_phepns_rotated;
411 //@< NSB values for each pixel after rotation
412
413 Float_t nsb_trigresp[TRIGGER_TIME_SLICES]; //@< array to write the trigger
414 //@< response from the database
415 Float_t *nsb_fadcresp; //@< array to write the fadc
416 //@< response from the database
417 Byte_t trigger_map[((Int_t)(CAMERA_PIXELS/8))+1]; //@< Pixels on when the
418 //@< camera triggers
419 Float_t fadc_elecnoise[CAMERA_PIXELS]; //@< Electronic noise for each pixel
420 Float_t fadc_diginoise[CAMERA_PIXELS]; //@< Digital noise for each pixel
421 Float_t fadc_pedestals[CAMERA_PIXELS]; //@< array for fadc pedestals values
422 Float_t fadc_sigma[CAMERA_PIXELS]; //@< array for fadc pedestals sigma
423 Float_t fadc_sigma_low[CAMERA_PIXELS]; //@< array for fadc pedestals sigma
424
425 float ext[iNUMWAVEBANDS] = { //@< average atmospheric extinction in each waveband
426 EXTWAVEBAND1,
427 EXTWAVEBAND2,
428 EXTWAVEBAND3,
429 EXTWAVEBAND4,
430 EXTWAVEBAND5
431 };
432 float zenfactor=1.0; // correction factor calculated from the extinction
433
434 int nstoredevents = 0;
435 int flagstoring = 0;
436
437 int ntrigger[MAX_NUMBER_OF_CTS]; //@< number of triggers in the whole file
438 int btrigger = 0; //@< trigger flag
439 int ithrescount; //@< counter for loop over threshold trigger
440 float fthrescount; //@< value for loop over threshold trigger
441 int imulticount; //@< counter for loop over multiplicity trigger
442 int itopocount; //@< counter for loop over topology trigger
443 int isorttopo[3]; //@< sorting the topologies
444 int icontrigger; //@< number of trigger conditions to be analised
445
446 float fpixelthres[CAMERA_PIXELS]; //@< Threshold values
447
448 TArrayC *fadcValues; //@< the analog Fadc High gain signal for pixels
449 TArrayC *fadcValuesLow; //@< the analog Fadc Low gain signal for pixels
450
451 int still_in_loop = FALSE;
452
453 //@< Variables to fill the McRunHeader
454 Int_t sfRaH = 5;
455 Int_t sfRaM = 34;
456 Int_t sfRaS = 32;
457 Int_t sfDeD = 22;
458 Int_t sfDeM = 00;
459 Int_t sfDeS = 52;
460 Float_t shthetamax = 0.0;
461 Float_t shthetamin = 0.0;
462 Float_t shphimax = 0.0;
463 Float_t shphimin = 0.0;
464 Float_t telestheta = 0.0;
465 Float_t telesphi = 0.0;
466 UInt_t corsika = 5200 ;
467 Float_t maxpimpact = 0.0;
468
469 // Star Field Rotation variables
470 Float_t zenith = 0.0;
471 Float_t azimutal = 90.0;
472 Float_t rho , C3 , C2 , C1;
473
474 //!@' @#### Definition of variables for |getopt()|.
475 //@'
476
477 int ch, errflg = 0; //@< used by getopt
478
479 //!@' @#### Initialisation of some variables
480 //@'
481
482 inname_CT = new char *[MAX_NUMBER_OF_CTS];
483 GeometryName = new char *[MAX_NUMBER_OF_CTS];
484 diffnsb_phepns = new float *[MAX_NUMBER_OF_CTS];
485 nsb_phepns = new float *[MAX_NUMBER_OF_CTS];
486 nsb_phepns_rotated = new float *[MAX_NUMBER_OF_CTS];
487
488 for(int i=0;i<MAX_NUMBER_OF_CTS;i++)
489 {
490 inname_CT[i] = new char[256];
491 GeometryName[i] = new char[50];
492 diffnsb_phepns[i] = new float[iMAXNUMPIX];
493 nsb_phepns[i] = new float[iMAXNUMPIX];
494 nsb_phepns_rotated[i] = new float[iMAXNUMPIX];
495 CTx[i] = 0.; CTy[i] = 0.; CTz[i] = 0.;
496 }
497
498 nsbrate_phepns = new float *[iMAXNUMPIX];
499 for(int i=0;i<iMAXNUMPIX;i++)
500 nsbrate_phepns[i] = new float[iNUMWAVEBANDS];
501
502 qThreshold = new float *[MAX_NUMBER_OF_CTS];
503 for(int i=0;i<MAX_NUMBER_OF_CTS;i++)
504 qThreshold[i] = new float [CAMERA_PIXELS];
505
506 for(int i=0;i<iMAXNUMPIX;i++){
507 for(int ict=0;ict<MAX_NUMBER_OF_CTS;ict++){
508 nsb_phepns[ict][i]=0;
509 nsb_phepns_rotated[ict][i]=0;
510 }
511 for(j=0;j<iNUMWAVEBANDS;j++)
512 nsbrate_phepns[i][j]=0.0; //@< Starlight rates initialised at 0.0
513 }
514 for(int i=0;i<MAX_NUMBER_OF_CTS;i++)
515 ntcph[i]=0;
516 /*!@'
517
518 @#### Beginning of the program.
519
520 We start with the main program. First we (could) make some
521 presentation, and follows the reading of the parameters file (now
522 from the |stdin|), the reading of the CT parameters file, and the
523 creation of the output file, where the processed data will be
524 stored.
525
526 */
527
528 //++
529 // START
530 //--
531
532 // make unbuffered output
533
534 // cout.setf ( ios::stdio );
535
536 // parse command line options (see reflector.h)
537
538 parname[0] = '\0';
539
540 optarg = NULL;
541 while ( !errflg && ((ch = getopt(argc, argv, COMMAND_LINE_OPTIONS)) != -1) )
542 switch (ch) {
543 case 'f':
544 strcpy(parname, optarg);
545 break;
546 case 'h':
547 usage();
548 break;
549 default :
550 errflg++;
551 }
552
553 // show help if error
554
555 if ( errflg>0 )
556 usage();
557
558 // make some sort of presentation
559
560 present();
561
562 // read parameters file
563
564 if ( strlen(parname) < 1 )
565 readparam(NULL);
566 else
567 readparam(parname);
568
569 // read data from file or from STDIN?
570
571 Data_From_STDIN = get_data_from_stdin();
572
573 // get number of telescopes and camera geometries
574
575 ct_Number=get_ct_number();
576 if (ct_Number > MAX_NUMBER_OF_CTS)
577 {
578 error( SIGNATURE, "Number of telescopes is larger than maximum allowed (%i). Stoping camera program ...", MAX_NUMBER_OF_CTS);
579 exit(1);
580 }
581
582 for(int ict=0;ict<ct_Number;ict++){
583 ntrigger[ict]=0;
584 GeometryCamera[ict]=get_ct_geometry(ict);
585
586 //
587 // Get telescope coordinates (if supplied) from input card (units cm).
588 //
589 CTx[ict] = get_telescope_location_cm(ict,0);
590 CTy[ict] = get_telescope_location_cm(ict,1);
591 CTz[ict] = get_telescope_location_cm(ict,2);
592
593 //
594 // Get fraction of operative mirror:
595 //
596 mirror_frac[ict] = get_mirror_fraction(ict);
597 }
598
599 // structure holding the camera definition
600
601 TObjArray camgeom;
602
603 for (int i=0; i<ct_Number;i++){
604 switch(GeometryCamera[i]){
605 case 1: camgeom[i]=new MGeomCamMagic;
606 strcpy(GeometryName[i],"MGeomCamMagic");
607 TriggerPixels[i]=TRIGGER_PIXELS_1;
608 break;
609 case 2: camgeom[i]=new MGeomCamMagic919;
610 strcpy(GeometryName[i],"MGeomCamMagic919");
611 TriggerPixels[i]=TRIGGER_PIXELS_2;
612 break;
613 case 3: camgeom[i]=new MGeomCamMagicHG;
614 strcpy(GeometryName[i],"MGeomCamMagicHG");
615 TriggerPixels[i]=TRIGGER_PIXELS_3;
616 break;
617 case 5: camgeom[i]=new MGeomCamECO1000;
618 strcpy(GeometryName[i],"MGeomCamECO1000");
619 TriggerPixels[i]=TRIGGER_PIXELS_5;
620 break;
621 case 6: camgeom[i]=new MGeomCamECO1000HG;
622 strcpy(GeometryName[i],"MGeomCamECO1000HG");
623 TriggerPixels[i]=TRIGGER_PIXELS_6;
624 break;
625 case 8: camgeom[i]=new MGeomCamCT1;
626 strcpy(GeometryName[i],"MGeomCamCT1");
627 TriggerPixels[i]=TRIGGER_PIXELS_8;
628 break;
629 case 9: camgeom[i]=new MGeomCamCT1Daniel;
630 strcpy(GeometryName[i],"MGeomCamCT1Daniel");
631 TriggerPixels[i]=TRIGGER_PIXELS_9;
632 break;
633 default:
634 error( SIGNATURE, "Camera geometry %i is not defined. Stoping camera program ...", GeometryCamera[i]);
635 exit(1);
636 break;
637 }
638 }
639
640 ct_NPixels=0;
641
642 for(int ict=0;ict<ct_Number;ict++)
643 ct_NPixels=(((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels()>(UInt_t)ct_NPixels)?
644 (Int_t)((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels():
645 ct_NPixels;
646
647 // read WC and QE files
648
649 // FIX ME !
650 // Currently the PMT N of any camera with same average QE has the same QE.
651
652 QE = new float *** [ct_Number];
653 for(int ict=0;ict<ct_Number;ict++){
654 strcpy( qe_filename, get_qe_filename(ict));
655 read_QE(qe_filename,ict);
656 }
657
658 read_WC();
659
660 // write all images, even those without trigger?
661
662 Write_All_Images = get_write_all_events();
663
664 Write_McEvt = get_write_McEvt() ;
665 Write_McTrig = get_write_McTrig() ;
666 Write_McFADC = get_write_McFadc() ;
667 Write_RawEvt = get_write_RawEvt() ;
668
669 FADC_Scan = get_FADC_Scan();
670 Trigger_Scan = get_Trigger_Scan();
671
672 Individual_Thres_Pixel = get_indi_thres_pixel();
673
674 get_secure_threhold(&riseDiskThres,&secureDiskThres);
675
676 get_FADC_properties
677 (&FADC_shape, &FADC_response_integ, &FADC_response_fwhm,
678 &FADC_shape_out, &FADC_resp_integ_out, &FADC_resp_fwhm_out,
679 &FADC_slices_per_ns, &FADC_slices_written);
680
681 // Allocate memory for the NSB contribution to the FADC signal:
682 nsb_fadcresp = new Float_t[(Int_t)(FADC_slices_per_ns*TOTAL_TRIGGER_TIME)];
683
684 FADC_high2low=get_High_to_Low();
685
686 // FIXME --- trigger properties may depend on the Camera geometry
687
688 get_Trigger_properties( &Trigger_gate_length, &Trigger_overlaping_time, &Trigger_response_ampl, &Trigger_response_fwhm);
689
690 Trigger_Loop = get_Trigger_Loop(&Trigger_loop_lthres, &Trigger_loop_uthres, &Trigger_loop_sthres, &Trigger_loop_lmult, &Trigger_loop_umult, &Trigger_loop_ltop, &Trigger_loop_utop);
691
692 icontrigger =((int)((Trigger_loop_uthres-Trigger_loop_lthres)
693 /Trigger_loop_sthres)+1)*
694 (Trigger_loop_umult-Trigger_loop_lmult+1)*
695 (Trigger_loop_utop-Trigger_loop_ltop+1);
696
697 // Trigger loop operation is not implemented for Multi telescopes
698
699 if ( Trigger_Loop && ct_Number > 1 ){
700 cout<<"ERROR : camera::main : Trigger loop option is not";
701 cout<<" implemented for Multi Telescopes option. "<<icontrigger<<
702 " "<<ct_Number<<endl;
703 exit(1);
704 }
705
706 if (!Trigger_Loop){
707 get_Trigger_Single (qThreshold,
708 &Trigger_multiplicity[0],
709 &Trigger_topology[0]);
710 icontrigger=1;
711 }
712 else
713 get_threshold(qThreshold[0]);
714
715 // get filenames
716
717 for(int ict=0;ict<ct_Number;ict++)
718 {
719 strcpy( inname_CT[ict], get_input_filename(ict) );
720 if (strlen(inname_CT[ict]) == 0)
721 {
722 printf("\nError: missing input file name for CT id = %d. Exiting.\n\n", ict);
723 exit(1);
724 }
725 }
726
727 strcpy( starfieldname, get_starfield_filename() );
728 strcpy( datname, get_data_filename() );
729 strcpy( rootname, get_root_filename() );
730 strcpy( rootname_loop, get_loop_filename() );
731 strcpy( nsbpathname, get_nsb_directory() );
732 strcpy( nsbpath_outer, get_nsb_directory_outer() );
733
734 // get different parameters of the simulation
735
736 addElecNoise = add_elec_noise(&FADC_noise_inner, &FADC_noise_outer, &DIGITAL_noise, &Trigger_noise);
737 simulateNSB = get_nsb( &meanNSB, &nphe2NSB );
738 missPointing = get_misspointing(&missP_x,&missP_y);
739 Spotsigma = get_sigma_xy_cm_spot(&Spot_x,&Spot_y);
740
741
742 // get selections on the parameters
743
744 Select_Energy = get_select_energy( &Select_Energy_le, &Select_Energy_ue);
745
746 //Parameters for starfield rotation
747
748 Starfield_rotate = get_starfield_rotate();
749
750 // log filenames information
751 for(Int_t ict=0;ict<ct_Number;ict++){
752
753 log(SIGNATURE,"\t%s : %i\n\t%20s:\t%s\n",
754 "------- TELESCOPE ",ict+1,
755 "Geometry ", GeometryName[ict]);
756 strcpy( qe_filename, get_qe_filename(ict));
757
758 printf("Telescope coordinates (cm): %.1f %.1f %.1f\n", CTx[ict], CTy[ict], CTz[ict]);
759
760 // Look to factor for NSB respect to emi_coat PMTs
761 if(strstr(qe_filename,"qe-emi-coat.RFL.dat") != 0)
762 factorqe_NSB[ict]=EMICOAT_NSB;
763 else if(strstr(qe_filename,"qe-emi.RFL.dat") != 0)
764 factorqe_NSB[ict]=EMI_NSB;
765 else if(strstr(qe_filename, "qe-intevac_hpd.RFL.dat") != 0)
766 factorqe_NSB[ict]=HPD_NSB;
767 else{
768 log(SIGNATURE,"WARNING : the factor for the diffuse NSB for this QE file (%s) is not known. The number of phe(ns stated in the inputcard will be used.\n",qe_filename);
769 factorqe_NSB[ict]=1.0;
770 }
771 log(SIGNATURE,
772 "%s:\n\t%20s:\t%s\n\t%20s:\t%s\n\t%20s\n\t%20s:\t%s\n\t%20s:\t%s\n\t%20s:\t%s\n\t%20s:\t%s\n\t%20s:\t%s\n",
773 "Filenames",
774 "In", inname_CT[ict],
775 "Stars", starfieldname,
776 "NSB database","(inner pixels)", nsbpathname,
777 "(outer pixels)", nsbpath_outer,
778 "QE", qe_filename,
779 "Data", datname,
780 "ROOT", rootname
781 );
782
783 // log parameters information
784
785 log(SIGNATURE,
786 "%s:\n\t%20s: %f: %s\n\t%20s: %f\n\t%20s: %f\n",
787 "Parameters",
788 "NSB (phes/ ns 0.1*0.1 deg^2 239 m^2)", meanNSB*factorqe_NSB[ict], ONoff(simulateNSB),
789 "Pedestals = ", get_FADC_pedestal(),
790 "High to Low gain = ", FADC_high2low
791 );
792
793 // log Trigger information
794
795 if (Trigger_Loop) {
796 log(SIGNATURE,
797 "%s:\n\t%20s: from %5.2f to %5.2f by %5.2f step\n\t%20s: %i - %i\n\t%20s: %i - %i\n\t%20s\n",
798 "Trigger Loop mode",
799 "Threshold",Trigger_loop_lthres,Trigger_loop_uthres,Trigger_loop_sthres,
800 "Multiplicity",Trigger_loop_lmult,Trigger_loop_umult,
801 "Topology",Trigger_loop_ltop,Trigger_loop_utop,
802 rootname_loop);
803 }
804 else if (Individual_Thres_Pixel == FALSE){
805 log(SIGNATURE,
806 "%s:\n\t%20s: %f\n\t%20s: %i\n\t%20s: %i\n",
807 "Single Trigger mode",
808 "Threshold",qThreshold[ict][0],
809 "Multiplicity",Trigger_multiplicity[ict],
810 "Topology",Trigger_topology[ict]);
811 }
812 else{
813 log(SIGNATURE,
814 "%s:\n\t%20s: %s\n\t%20s: %i\n\t%20s: %i\n",
815 "Single Trigger mode",
816 "Threshold","Different for each pixel",
817 "Multiplicity",Trigger_multiplicity[ict],
818 "Topology",Trigger_topology[ict]);
819 }
820 log(SIGNATURE,"\t%s\n",
821 "END TELESCOPE --------");
822 }
823 // log flags information
824
825 log(SIGNATURE,
826 "%s:\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s %3.2f, %s %3.2f (%s), %3.2f (%s) + %3.2f (%s) %s\n",
827 "Flags",
828 "Data_From_STDIN", ONoff(Data_From_STDIN),
829 "Write_All_Events", ONoff(Write_All_Images),
830 "Rotate Starfield", ONoff(Starfield_rotate),
831 "Electronic Noise", "trigger (rel. noise): ", Trigger_noise,
832 "FADC (ADC counts): ", FADC_noise_inner, "inner pixels",
833 FADC_noise_outer, "outer pixels",
834 DIGITAL_noise, "added digital noise at FADC", ONoff(addElecNoise)
835 );
836
837 // log flags information
838
839 log(SIGNATURE,
840 "%s:\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n",
841 "Root output",
842 "Write_McEvt", ONoff(Write_McEvt),
843 "Write_McTrig", ONoff(Write_McTrig),
844 "Write_McFADC", ONoff(Write_McFADC),
845 "Write_RawEvt", ONoff(Write_RawEvt));
846
847 // log selections
848
849 log(SIGNATURE,
850 "%s:\n\t%20s: %s (%f:%f)\n",
851 "Selections:",
852 "Energy", ONoff(Select_Energy), Select_Energy_le, Select_Energy_ue);
853
854 // Definition and initialization of array to save trigger statistics
855
856 int ***ntriggerloop;
857
858 ntriggerloop= new int ** [(int)((Trigger_loop_uthres-Trigger_loop_lthres)
859 /Trigger_loop_sthres)+1];
860 for (ithrescount=0, fthrescount=Trigger_loop_lthres;fthrescount<=Trigger_loop_uthres;fthrescount+=Trigger_loop_sthres, ithrescount++){
861 ntriggerloop[ithrescount]= new int * [Trigger_loop_umult-Trigger_loop_lmult+1];
862 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
863 ntriggerloop[ithrescount][imulticount]= new int [Trigger_loop_utop-Trigger_loop_ltop+1];
864 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
865 ntriggerloop[ithrescount][imulticount][itopocount]=0;
866 }
867 }
868 }
869
870 // We should be careful that topologies are sort from
871 // the less to the more restrictive one.
872
873 if (Trigger_loop_utop==Trigger_loop_ltop)
874 for(int is=0; is<3;is++)
875 isorttopo[is]=is;
876 else {
877 isorttopo[0]=1;
878 isorttopo[1]=0;
879 isorttopo[2]=2;
880 }
881
882 // get list of showers to evt. skip
883
884 nSkip = get_nskip_showers();
885
886 if (nSkip > 0) {
887 Skip = new int[ nSkip ];
888 get_skip_showers( Skip );
889
890 log(SIGNATURE, "There are some showers to skip:\n");
891 for (int i=0; i<nSkip; ++i)
892 log(SIGNATURE, "\tshower # %d\n", Skip[i]);
893 }
894
895
896 // read parameters from the ct.def file
897
898 //read_ct_file();
899
900 Int_t Lev0, Lev1;
901 Int_t Lev0MT[MAX_NUMBER_OF_CTS], Lev1MT[MAX_NUMBER_OF_CTS];
902
903 fadcValues = new TArrayC(FADC_slices_written);
904 fadcValuesLow = new TArrayC(FADC_slices_written);
905
906 // number of pixels for parameters
907
908 // Switched off writing TObject
909
910 MArray::Class()->IgnoreTObjectStreamer();
911 MParContainer::Class()->IgnoreTObjectStreamer();
912
913 // initialise ROOT
914
915 TROOT simple("simple", "MAGIC Telescope Monte Carlo");
916
917 // initialise instance of Trigger and FADC classes
918
919 MTrigger **Trigger_CT;
920 Trigger_CT = new MTrigger *[ct_Number];
921
922 for (int i=0; i<ct_Number;i++){
923 Trigger_CT[i] = new MTrigger(TriggerPixels[i],
924 ((MGeomCam*)(camgeom.UncheckedAt(i))),
925 Trigger_gate_length,
926 Trigger_overlaping_time,
927 Trigger_response_ampl,
928 Trigger_response_fwhm, i); //@< A instance of the Class MTrigger
929 Trigger_CT[i]->SetSeed(UInt_t(i+get_seeds(0)));
930 }
931
932 for (int ict=0; ict<ct_Number;ict++){
933 // Generate database for trigger electronic noise
934 if (addElecNoise)
935 Trigger_CT[ict]->SetElecNoise(Trigger_noise) ;
936
937 // Set Right Discriminator threshold, taking into account trigger pixels
938 Trigger_CT[ict]->CheckThreshold(&qThreshold[ict][0],GeometryCamera[ict]);
939 }
940 // Set flag in pixel 0 (not used for trigger) that indicates if secure pixel
941 // is active: secureDiskThres*10000+riseDiskThres
942
943 for (int ict=0; ict<ct_Number;ict++){
944 if(riseDiskThres>0.0)
945 qThreshold[ict][0]=((UInt_t)secureDiskThres*100)*100+riseDiskThres;
946 else
947 qThreshold[ict][0]=0.0;
948 }
949 // Initialise McTrig information class if we want to save trigger informtion
950
951 MMcTrig **McTrig = NULL;
952 MMcTrigHeader **HeaderTrig = NULL;
953 MMcFadcHeader **HeaderFadc = NULL;
954
955 int numberBranches;
956
957 if (!Trigger_Loop)
958 numberBranches=ct_Number;
959 else
960 numberBranches=icontrigger;
961
962 if (Write_McTrig){
963
964 McTrig = new MMcTrig * [numberBranches];
965
966 for (int i=0;i<numberBranches;i++) {
967 McTrig[i] = new MMcTrig();
968 }
969
970 HeaderTrig = new MMcTrigHeader * [numberBranches];
971
972 for (int i=0;i<numberBranches;i++) {
973 HeaderTrig[i] = new MMcTrigHeader();
974 }
975 }
976
977 if (Write_McFADC){
978
979 HeaderFadc = new MMcFadcHeader * [numberBranches];
980
981 for (int i=0;i<numberBranches;i++) {
982 HeaderFadc[i] = new MMcFadcHeader();
983 }
984 }
985
986 MFadc **Fadc_CT;
987 Fadc_CT = new MFadc *[ct_Number];
988
989 for (int i=0; i<ct_Number;i++)
990 Fadc_CT[i] =
991 new MFadc(((MGeomCam*)(camgeom.UncheckedAt(i)))->GetNumPixels(),
992 FADC_shape,
993 FADC_response_integ,FADC_response_fwhm,
994 FADC_shape_out,
995 FADC_resp_integ_out,FADC_resp_fwhm_out,
996 get_trig_delay(),
997 FADC_slices_per_ns,
998 FADC_slices_written); //@< A instance of the Class MFadc
999
1000
1001 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1002 //
1003 // Set the FADC pedestals for that run
1004 // Some modifications
1005 // mut be done to simulate a more realistic distribution of the pedestals.
1006 // This simualtion is done int the SetPedestals methode inside the
1007 // class MFadc
1008 // Currentlly a input_pedestal array is declared with the pedestals.
1009 // Thy can also be set randomly following a flat distribution.
1010 //
1011 /////////////////////////////////////////////////////////////////////
1012
1013 Float_t input_pedestals[ct_NPixels];
1014
1015 for(int i=0;i<ct_NPixels;i++)
1016 input_pedestals[i]=get_FADC_pedestal();
1017 for (int ict=0; ict<ct_Number;ict++){
1018
1019 Fadc_CT[ict]->SetPedestals(input_pedestals);
1020 Fadc_CT[ict]->SetHigh2LowGain(FADC_high2low);
1021
1022 // Generate database for the Fadc electronic noise
1023
1024 if (!addElecNoise)
1025 continue;
1026
1027 MGeomCam *camg = (MGeomCam*)(camgeom.UncheckedAt(ict));
1028 UInt_t n_inner_pixels; // Number of inner(small) pixels
1029 for (n_inner_pixels = 0; n_inner_pixels < camg->GetNumPixels();
1030 n_inner_pixels ++)
1031 {
1032 if (camg->GetPixRatio(n_inner_pixels) < 1.)
1033 break;
1034 }
1035 Fadc_CT[ict]->SetElecNoise(FADC_noise_inner, FADC_noise_outer,
1036 n_inner_pixels);
1037 Fadc_CT[ict]->SetDigitalNoise(DIGITAL_noise);
1038 }
1039
1040 // Prepare the raw data output
1041
1042 // Header Tree
1043 MGeomCam **camdummy = new MGeomCam * [ct_Number];
1044 for (int ict=0; ict<ct_Number;ict++){
1045 camdummy[ict]= ((MGeomCam*)(camgeom.UncheckedAt(ict)));
1046 }
1047 MRawRunHeader *RunHeader= new MRawRunHeader();
1048 MMcRunHeader *McRunHeader = new MMcRunHeader();
1049 MMcCorsikaRunHeader *McCorsikaRunHeader = new MMcCorsikaRunHeader("","",ct_Number);
1050
1051
1052 for (int i = 0; i < ct_Number; i++)
1053 McCorsikaRunHeader->FillCT(CTx[i], CTy[i], CTz[i], -1., -1., -1., -1., i);
1054
1055
1056 MMcConfigRunHeader **McConfigRunHeader = NULL;
1057 McConfigRunHeader = new MMcConfigRunHeader * [numberBranches];
1058 for (int i=0;i<numberBranches;i++) {
1059 McConfigRunHeader[i] = new MMcConfigRunHeader();
1060 }
1061
1062 // Header branch
1063
1064 MRawEvtHeader **EvtHeader = NULL;
1065
1066 if (Write_RawEvt) {
1067 EvtHeader = new MRawEvtHeader * [numberBranches];
1068
1069 for (int i=0;i<numberBranches;i++) {
1070 EvtHeader[i] = new MRawEvtHeader();
1071 }
1072
1073 }
1074
1075 // Data branch
1076
1077 MRawEvtData **EvtData = NULL; // Data branch
1078
1079 if (Write_RawEvt) {
1080 EvtData = new MRawEvtData * [numberBranches];
1081
1082 for (int i=0;i<numberBranches;i++) {
1083 EvtData[i] = new MRawEvtData();
1084 EvtData[i]->InitRead(RunHeader); // We need the RunHeader to read
1085 // number of pixels
1086 }
1087 }
1088
1089 MMcEvt **McEvt = NULL;
1090
1091 if (Write_McEvt) {
1092 if (ct_Number>1){
1093 McEvt = new MMcEvt *[numberBranches];
1094 for (int i=0;i<numberBranches;i++)
1095 McEvt[i]=new MMcEvt();
1096 }
1097 else {
1098 McEvt = new MMcEvt *[1];
1099 McEvt[0]=new MMcEvt();
1100 }
1101 }
1102 //
1103 // initalize a temporal ROOT file
1104 //
1105
1106 TFile outfile_temp ( rootname , "RECREATE" );
1107
1108 // create a Tree for the Header Event
1109 TTree HeaderTree("RunHeaders","Headers of Run");
1110
1111 // define branches of Header Tree
1112
1113 char help[4];
1114
1115 HeaderTree.Branch("MRawRunHeader.","MRawRunHeader",
1116 &RunHeader);
1117
1118 HeaderTree.Branch("MMcRunHeader.","MMcRunHeader",
1119 &McRunHeader);
1120
1121 HeaderTree.Branch("MMcCorsikaRunHeader.","MMcCorsikaRunHeader",
1122 &McCorsikaRunHeader);
1123
1124 if(!Trigger_Loop && Write_McTrig && ct_Number==1){
1125
1126 HeaderTree.Branch("MMcTrigHeader.","MMcTrigHeader",
1127 &HeaderTrig[0]);
1128 }
1129
1130 if (ct_Number==1){
1131 // HeaderTree.Branch("MGeomCam.", "MGeomCam", &camdummy[0]);
1132 HeaderTree.Branch("MGeomCam.", GeometryName[0], &camdummy[0]);
1133 HeaderTree.Branch("MMcConfigRunHeader.","MMcConfigRunHeader",
1134 &McConfigRunHeader[0]);
1135 }
1136 else{
1137 char branchname[256];
1138 for (int ict=0; ict<ct_Number;ict++){
1139 sprintf(help,"%i",ict+1);
1140 strcpy (branchname, "MGeomCam;");
1141 strcat (branchname, & help[0]);
1142 strcat (branchname, ".");
1143 HeaderTree.Branch(branchname, GeometryName[ict],
1144 &camdummy[ict]);
1145 }
1146 for(int i=0;i<numberBranches;i++){
1147 sprintf(help,"%i",i+1);
1148 strcpy (branchname, "MMcConfigRunHeader;");
1149 strcat (branchname, & help[0]);
1150 strcat (branchname, ".");
1151 HeaderTree.Branch(branchname,"MMcConfigRunHeader",
1152 &McConfigRunHeader[i]);
1153 }
1154
1155 }
1156
1157 if ((Trigger_Loop || ct_Number>1) && Write_McTrig){
1158 ibr=0;
1159 for(char branchname[256];ibr<numberBranches;ibr++){
1160
1161 sprintf(help,"%i",ibr+1);
1162 strcpy (branchname, "MMcTrigHeader;");
1163 strcat (branchname, & help[0]);
1164 strcat (branchname, ".");
1165 HeaderTree.Branch(branchname,"MMcTrigHeader",
1166 &HeaderTrig[ibr]);
1167 }
1168 }
1169
1170 if(!Trigger_Loop && Write_McFADC && ct_Number==1){
1171
1172 HeaderTree.Branch("MMcFadcHeader.","MMcFadcHeader",
1173 &HeaderFadc[0]);
1174 }
1175 if ((Trigger_Loop || ct_Number>1) && Write_McFADC){
1176 ibr=0;
1177 for(char branchname[256];ibr<numberBranches;ibr++){
1178
1179 sprintf(help,"%i",ibr+1);
1180 strcpy (branchname, "MMcFadcHeader;");
1181 strcat (branchname, & help[0]);
1182 strcat (branchname, ".");
1183
1184 HeaderTree.Branch(branchname,"MMcFadcHeader",
1185 &HeaderFadc[ibr]);
1186 }
1187 }
1188
1189 // Fill branches for MRawRunHeader
1190
1191 RunHeader->SetMagicNumber(MRawRunHeader::kMagicNumber);
1192 RunHeader->SetFormatVersion(4);
1193 RunHeader->SetSoftVersion((UShort_t) (VERSION*10));
1194 RunHeader->SetRunType(256);
1195 RunHeader->SetRunNumber(0);
1196 RunHeader->SetNumSamples(FADC_slices_written, FADC_slices_written);
1197 RunHeader->SetNumCrates(1);
1198 RunHeader->SetNumPixInCrate(ct_NPixels);
1199
1200 // Fill branches for MMcTrigHeader
1201
1202 if(!Trigger_Loop && Write_McTrig && ct_Number==1){
1203
1204 HeaderTrig[0]->SetTopology((Short_t) Trigger_topology[0]);
1205 HeaderTrig[0]->SetMultiplicity((Short_t) Trigger_multiplicity[0]);
1206 HeaderTrig[0]->SetThreshold(qThreshold[0]);
1207 HeaderTrig[0]->SetAmplitud(Trigger_response_ampl);
1208 HeaderTrig[0]->SetFwhm(Trigger_response_fwhm);
1209 HeaderTrig[0]->SetOverlap(Trigger_overlaping_time);
1210 HeaderTrig[0]->SetGate(Trigger_gate_length);
1211 HeaderTrig[0]->SetElecNoise(Trigger_noise);
1212 }
1213 if(!Trigger_Loop && Write_McTrig && ct_Number>1){
1214 for(int i=0;i<ct_Number;i++){
1215 HeaderTrig[i]->SetTopology((Short_t) Trigger_topology[i]);
1216 HeaderTrig[i]->SetMultiplicity((Short_t) Trigger_multiplicity[i]);
1217 HeaderTrig[i]->SetThreshold(qThreshold[i]);
1218 HeaderTrig[i]->SetAmplitud(Trigger_response_ampl);
1219 HeaderTrig[i]->SetFwhm(Trigger_response_fwhm);
1220 HeaderTrig[i]->SetOverlap(Trigger_overlaping_time);
1221 HeaderTrig[i]->SetGate(Trigger_gate_length);
1222 HeaderTrig[i]->SetElecNoise(Trigger_noise);
1223 }
1224 }
1225 if(Trigger_Loop && Write_McTrig){
1226
1227 int iconcount;
1228 for (iconcount=0,ithrescount=0,fthrescount=Trigger_loop_lthres;fthrescount<=Trigger_loop_uthres;ithrescount++,fthrescount+=Trigger_loop_sthres){
1229 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
1230 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
1231 HeaderTrig[iconcount]->SetTopology((Short_t) isorttopo[itopocount+Trigger_loop_ltop]);
1232 HeaderTrig[iconcount]->SetMultiplicity((Short_t) imulticount+Trigger_loop_lmult);
1233 for(int i=0;i<ct_NPixels;i++){
1234 fpixelthres[i]=
1235 ((Float_t)(fthrescount)>=qThreshold[0][i])?
1236 (Float_t)(fthrescount):qThreshold[0][i];
1237 }
1238 HeaderTrig[iconcount]->SetThreshold( fpixelthres);
1239 HeaderTrig[iconcount]->SetAmplitud(Trigger_response_ampl);
1240 HeaderTrig[iconcount]->SetFwhm(Trigger_response_fwhm);
1241 HeaderTrig[iconcount]->SetOverlap(Trigger_overlaping_time);
1242 HeaderTrig[iconcount]->SetGate(Trigger_gate_length);
1243 HeaderTrig[iconcount]->SetElecNoise(Trigger_noise);
1244 iconcount++;
1245 }
1246 }
1247 }
1248 }
1249
1250 // Fill branches for MMcFadcHeader
1251 Fadc_CT[0]->GetPedestals(&fadc_pedestals[0]);
1252
1253 if(!Trigger_Loop && Write_McFADC && ct_Number==1){
1254
1255 for(int k = 0; k < ct_NPixels; k++){
1256 if ( ((MGeomCam*)(camgeom.UncheckedAt(0)))->GetPixRatio(k) < 1.)
1257 fadc_elecnoise[k]=FADC_noise_outer; // outer pixels
1258 else
1259 fadc_elecnoise[k]=FADC_noise_inner; // inner pixels
1260
1261 fadc_diginoise[k]=DIGITAL_noise;
1262 }
1263
1264 HeaderFadc[0]->SetShape((Float_t)FADC_shape);
1265 HeaderFadc[0]->SetShapeOuter((Float_t)FADC_shape_out);
1266 HeaderFadc[0]->SetAmplitud(FADC_response_integ,
1267 FADC_resp_integ_out);
1268 HeaderFadc[0]->SetFwhm(FADC_response_fwhm,FADC_resp_fwhm_out);
1269 HeaderFadc[0]->SetLow2High(FADC_high2low);
1270 HeaderFadc[0]->SetPedestal(&fadc_pedestals[0],
1271 ((MGeomCam*)(camgeom.UncheckedAt(0)))->GetNumPixels());
1272 HeaderFadc[0]->SetElecNoise(&fadc_elecnoise[0], &fadc_diginoise[0],
1273 ((MGeomCam*)(camgeom.UncheckedAt(0)))->GetNumPixels());
1274 }
1275
1276 if(!Trigger_Loop && Write_McFADC && ct_Number>1){
1277 for(int i=0;i<ct_Number;i++){
1278
1279 for(int k = 0; k < ct_NPixels; k++){
1280 if ( ((MGeomCam*)(camgeom.UncheckedAt(i)))->GetPixRatio(k) < 1.)
1281 fadc_elecnoise[k]=FADC_noise_outer; // outer pixels
1282 else
1283 fadc_elecnoise[k]=FADC_noise_inner; // inner pixels
1284
1285 fadc_diginoise[k]=DIGITAL_noise;
1286 }
1287
1288 Fadc_CT[i]->GetPedestals(&fadc_pedestals[0]);
1289 HeaderFadc[i]->SetShape((Float_t)FADC_shape);
1290 HeaderFadc[i]->SetShapeOuter((Float_t)FADC_shape_out);
1291 HeaderFadc[i]->SetAmplitud(FADC_response_integ,
1292 FADC_resp_integ_out);
1293 HeaderFadc[i]->SetFwhm(FADC_response_fwhm,FADC_resp_fwhm_out);
1294 HeaderFadc[i]->SetLow2High(FADC_high2low);
1295 HeaderFadc[i]->SetPedestal(&fadc_pedestals[0],((MGeomCam*)(camgeom.UncheckedAt(i)))->GetNumPixels());
1296 HeaderFadc[i]->SetElecNoise(&fadc_elecnoise[0], &fadc_diginoise[0],
1297 ((MGeomCam*)(camgeom.UncheckedAt(i)))->GetNumPixels());
1298 }
1299 }
1300
1301 if(Trigger_Loop && Write_McFADC){
1302
1303 for(int k = 0; k < ct_NPixels; k++){
1304 if ( ((MGeomCam*)(camgeom.UncheckedAt(0)))->GetPixRatio(k) < 1.)
1305 fadc_elecnoise[k]=FADC_noise_outer; // outer
1306 else
1307 fadc_elecnoise[k]=FADC_noise_inner; // inner
1308
1309 fadc_diginoise[k]=DIGITAL_noise;
1310 }
1311
1312 int iconcount;
1313 for (iconcount=0,ithrescount=0,fthrescount=Trigger_loop_lthres;fthrescount<=Trigger_loop_uthres;ithrescount++, fthrescount+=Trigger_loop_sthres){
1314 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
1315 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
1316 Fadc_CT[0]->GetPedestals(&fadc_pedestals[0]);
1317 HeaderFadc[iconcount]->SetShape((Float_t)FADC_shape);
1318 HeaderFadc[iconcount]->SetShapeOuter((Float_t)FADC_shape_out);
1319 HeaderFadc[iconcount]->SetAmplitud(FADC_response_integ,
1320 FADC_resp_integ_out);
1321 HeaderFadc[iconcount]->SetFwhm(FADC_response_fwhm,
1322 FADC_resp_fwhm_out);
1323 HeaderFadc[iconcount]->SetLow2High(FADC_high2low);
1324 HeaderFadc[iconcount]->SetPedestal(&fadc_pedestals[0], ct_NPixels);
1325 HeaderFadc[iconcount]->SetElecNoise(&fadc_elecnoise[0],
1326 &fadc_diginoise[0],ct_NPixels);
1327 iconcount++;
1328 }
1329 }
1330 }
1331 }
1332
1333 // UnSet flag in pixel 0 (not used for trigger) that indicates if secure pixel
1334 // is active once it has been stored
1335
1336 for (int ict=0; ict<ct_Number;ict++){
1337 qThreshold[ict][0]=999999.99;
1338 }
1339
1340 // create a Tree for the Event data stream
1341 TTree EvtTree("Events","Normal Triggered Events");
1342
1343 if (Write_McEvt && ct_Number==1){
1344
1345 EvtTree.Branch("MMcEvt.","MMcEvt",
1346 &McEvt[0]);
1347 }
1348
1349 if (Write_McEvt && ct_Number!=1){
1350 ibr=0;
1351 for(char branchname[256];ibr<numberBranches;ibr++){
1352
1353 sprintf(help,"%i",ibr+1);
1354 strcpy (branchname, "MMcEvt;");
1355 strcat (branchname, & help[0]);
1356 strcat (branchname, ".");
1357 EvtTree.Branch(branchname,"MMcEvt",
1358 &McEvt[ibr]);
1359 }
1360 }
1361
1362 if(!Trigger_Loop && ct_Number==1){
1363
1364 if (Write_RawEvt){
1365 EvtTree.Branch("MRawEvtHeader.","MRawEvtHeader",
1366 &EvtHeader[0]);
1367 EvtTree.Branch("MRawEvtData.","MRawEvtData",
1368 &EvtData[0]);
1369 }
1370 if (Write_McTrig){
1371 EvtTree.Branch("MMcTrig.","MMcTrig",
1372 &McTrig[0]);
1373 }
1374 }
1375 else{
1376
1377 if (Write_McTrig){
1378 ibr=0;
1379 for(char branchname[256];ibr<numberBranches;ibr++){
1380
1381 sprintf(help,"%i",ibr+1);
1382 strcpy (branchname, "MMcTrig;");
1383 strcat (branchname, & help[0]);
1384 strcat (branchname, ".");
1385 EvtTree.Branch(branchname,"MMcTrig",
1386 &McTrig[ibr]);
1387 }
1388 }
1389 }
1390
1391 if ((Trigger_Loop || ct_Number>1) && Write_RawEvt){
1392 ibr=0;
1393 for(char branchname[256];ibr<numberBranches;ibr++){
1394
1395 sprintf(help,"%i",ibr+1);
1396 strcpy (branchname, "MRawEvtHeader;");
1397 strcat (branchname, & help[0]);
1398 strcat (branchname, ".");
1399 EvtTree.Branch(branchname,"MRawEvtHeader",
1400 &EvtHeader[ibr]);
1401 }
1402 ibr=0;
1403 for(char branchname[256];ibr<numberBranches;ibr++){
1404
1405 sprintf(help,"%i",ibr+1);
1406 strcpy (branchname, "MRawEvtData;");
1407 strcat (branchname, & help[0]);
1408 strcat (branchname, ".");
1409 EvtTree.Branch(branchname,"MRawEvtData",
1410 &EvtData[ibr]);
1411 }
1412 }
1413
1414
1415 TApplication theAppTrigger("App", &argc, argv);
1416
1417 if(FADC_Scan){
1418 if (gROOT->IsBatch()) {
1419 fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]);
1420 // return 1;
1421 }
1422 }
1423 if(FADC_Scan){
1424 //TApplication theAppFadc("App", &argc, argv);
1425
1426 if (gROOT->IsBatch()) {
1427 fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]);
1428 // return 1;
1429 }
1430 }
1431
1432 // prepare the NSB simulation
1433
1434 // Instance of the Mlons class
1435
1436 MLons lons(0, Trigger_response_ampl, Trigger_response_fwhm,
1437 FADC_shape, FADC_response_integ, FADC_response_fwhm,
1438 FADC_slices_per_ns);
1439
1440 lons.SetSeed(Int_t(get_seeds(1)%get_seeds(0))+1);
1441
1442 lons.SetPath(nsbpathname);
1443
1444 // Instance of the Mlons class
1445 MLons lons_outer(0, Trigger_response_ampl, Trigger_response_fwhm,
1446 FADC_shape_out,FADC_resp_integ_out,FADC_resp_fwhm_out,
1447 FADC_slices_per_ns);
1448
1449 lons_outer.SetSeed(Int_t(get_seeds(1)%get_seeds(0))+2);
1450
1451 lons_outer.SetPath(nsbpath_outer);
1452
1453 if( simulateNSB){
1454
1455 //
1456 // Calculate the non-diffuse NSB photoelectron rates
1457 //
1458
1459 //
1460 // FIXME! --- star NSB different for each camera?
1461 // Then we will have to use mirror_frac[ict]
1462 //
1463 log(SIGNATURE,"Produce NSB rates from Star Field...\n");
1464
1465 k = produce_nsbrates( starfieldname,
1466 ((MGeomCam*)(camgeom.UncheckedAt(0))),
1467 nsbrate_phepns,
1468 0,
1469 mirror_frac[0]);
1470
1471 //
1472 // Call to "produce_nsbrates" above accounts ONLY for
1473 // non-diffuse NSB (i.e. from stars). NOTE: produce_nsbrates already
1474 // accounts for the possibly different light collection efficiencies
1475 // of inner and outer pixels, through a call (see function) to
1476 // "produce_phes". The output array nsbrate_phepns contains only the
1477 // rates due to individual stars in the FOV, and not diffuse NSB light!
1478 //
1479
1480 if (k != 0){
1481 cout << "Error when reading starfield... \nExiting.\n";
1482 exit(1);
1483 }
1484
1485 // calculate diffuse rate correcting for the pixel size and telescope
1486
1487 float factorNSB_ct;
1488 for(int ict=0;ict<ct_Number;ict++){
1489
1490 // First we set the factor due to the mirror size with respect to the normal
1491 // MAGIC mirror geometry.
1492
1493 switch(GeometryCamera[ict]){
1494 case 1:
1495 case 2:
1496 case 3:
1497 case 4:
1498 factorNSB_ct=1.0;
1499 break;
1500 case 5:
1501 case 6:
1502 case 7:
1503 factorNSB_ct=1000.0/239.0;
1504 break;
1505 case 8:
1506 case 9:
1507 default:
1508 factorNSB_ct=1.0;
1509 break;
1510 }
1511
1512 factorNSB_ct = factorNSB_ct /
1513 ((*((MGeomCam*)(camgeom.UncheckedAt(ict)))).GetCameraDist()*1000*
1514 (*((MGeomCam*)(camgeom.UncheckedAt(ict)))).GetCameraDist()*1000*
1515 PIXEL_SIZE*PIXEL_SIZE); // [mm^-2]
1516
1517 for(UInt_t ui=0;
1518 ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels(); ui++){
1519 const Float_t size=
1520 (*((MGeomCam*)(camgeom.UncheckedAt(ict))))[ui].GetD();
1521 // Returns distance [mm] between two paralel sides of pixel
1522
1523
1524 Float_t diffusensb = meanNSB*mirror_frac[ict];
1525
1526 //
1527 // If pixel is outer pixel:
1528 //
1529 if ( ((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetPixRatio(ui) < 1. )
1530 diffusensb *= WC_outer[1][90] / WC[1][90];
1531 //
1532 // FIXME! Correction above is for (possibly) different light collection efficiencies of
1533 // inner and outer pixels. For the moment we assume the angular dependence of the light
1534 // collection is the same and hence use simply the ratio of efficiencies for light impinging
1535 // perpendicular to the camera plane (index 90 stands for 90 degrees)
1536 //
1537
1538 diffnsb_phepns[ict][ui] = (Int_t(diffusensb*factorNSB_ct*100*size*size+0.5))/(100.0)*factorqe_NSB[ict];
1539 }
1540 }
1541
1542 // calculate nsb rate including diffuse and starlight
1543 // we also include the extinction effect
1544 for(int ict=0;ict<ct_Number;ict++){
1545 for(j=0;j<iNUMWAVEBANDS;j++){
1546 // calculate the effect of the atmospheric extinction (for stars!)
1547
1548 zenfactor = pow(10., -0.4 * ext[j] );
1549
1550 for(UInt_t ui=0; ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();ui++){
1551 nsb_phepns[ict][ui]+=diffnsb_phepns[ict][ui]/iNUMWAVEBANDS + zenfactor *nsbrate_phepns[ui][j];
1552 nsb_phepns_rotated[ict][ui]=nsb_phepns[ict][ui];
1553 }
1554 }
1555 }
1556 }
1557
1558
1559 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1560 //
1561 // Now 500 empty events with the condition in which the camera is run
1562 // are simulated. In this way one gets an estimation of the
1563 // fluctuations of the pedestal of each FADC channel.
1564 // This computation is done assuming any noise that affects
1565 // the FADC but there is no rotation of the Star Field (otherwise it
1566 // should be done for each event). So it is valid if no starfield
1567 // rotation is used.
1568 //
1569 // Changed 20/03/2004, AM: now we no longer calculate the individual
1570 // FADC slice RMS. Due to correlations in the noise of neighboring
1571 // slides, it follows that RMS(sum_n_slices) != sqrt(n)*RMS(single_slice)
1572 //
1573 // In the analysis in Mars, however, the RMS of the fluctuations of the
1574 // signal (resulting from the integration of n slices) is estimated as
1575 // sqrt(n) * MMcFadcHeader.fPedesSigmaHigh, where the latter value,
1576 // stored in the camera output, is calculated in the next lines of code.
1577 // We have then made the following, as is being done also in real data:
1578 // calculate the RMS of the distribution of the sum of 14 slices, then
1579 // the stored value is
1580 // MMcFadcHeader.fPedesSigmaHigh = RMS(sum_14_slices)/sqrt(14), and the
1581 // same for the low gain. It can be seen that the RMS of the sum of n
1582 // slices, with n not too low (n>=6 or so), is more or less:
1583 // RMS(sum_n_slices) ~ sqrt(n) * RMS(sum_14_slices)/sqrt(14)
1584 //
1585 // The reason to sum 14 slices (and not 15) comes from the fact that in
1586 // real data there is a FADC clock noise affecting differently odd and
1587 // even FADC slices, so always an even number of them is added up so that
1588 // this cancels out. So we do the calculation in the same way as in real
1589 // data.
1590 //
1591 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1592
1593 Int_t empty_events = 500;
1594 Int_t n_slices = 14;
1595
1596 for(int ict=0;ict<ct_Number;ict++){
1597 for(UInt_t ui=0;
1598 ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
1599 ui++){
1600 fadc_sigma[ui]=0.0;
1601 fadc_sigma_low[ui]=0.0;
1602 }
1603 for(int ie=0; ie < empty_events; ie++){
1604 Fadc_CT[ict]->Reset() ;
1605 if (addElecNoise){
1606 Fadc_CT[ict]->ElecNoise() ;
1607 }
1608 if(simulateNSB)
1609 {
1610 for(UInt_t ui=0;
1611 ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
1612 ui++)
1613 {
1614 if(nsb_phepns[ict][ui]>0.0)
1615 {
1616 if((*((MGeomCam*)(camgeom.UncheckedAt(ict))))[ui].GetD() >
1617 (*((MGeomCam*)(camgeom.UncheckedAt(ict))))[0].GetD())
1618 {
1619
1620 k = lons_outer.GetResponse(nsb_phepns[ict][ui],0.01,
1621 & nsb_trigresp[0],
1622 & nsb_fadcresp[0]);
1623 }
1624 else
1625 {
1626 k=lons.GetResponse(nsb_phepns[ict][ui],0.01,
1627 & nsb_trigresp[0],& nsb_fadcresp[0]);
1628 }
1629
1630 if(k==0)
1631 {
1632 cout << "Exiting.\n";
1633 exit(1);
1634 }
1635 Fadc_CT[ict]->AddSignal(ui,nsb_fadcresp);
1636 }
1637 }
1638 }
1639 Fadc_CT[ict]->Pedestals();
1640
1641 for(UInt_t ui=0;
1642 ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
1643 ui++)
1644 {
1645 //
1646 // We add up n_slices FADC slices (pedestal subtracted), then
1647 // calculate the sigma_n-1 of this sum for the number of generated
1648 // noise events (=empty_events).
1649 //
1650 Float_t sumslices = Fadc_CT[ict]->AddNoiseInSlices(ui,1,n_slices);
1651 fadc_sigma[ui] += sumslices*sumslices;
1652
1653 // Now the low gain:
1654 sumslices = Fadc_CT[ict]->AddNoiseInSlices(ui,0,n_slices);
1655 fadc_sigma_low[ui]+= sumslices*sumslices;
1656 }
1657 }
1658
1659 for(UInt_t ui=0;
1660 ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
1661 ui++)
1662 {
1663 Float_t s_high = fadc_sigma[ui] / (Float_t)(empty_events-1) /
1664 (Float_t)(n_slices);
1665 fadc_sigma[ui] = sqrt(s_high);
1666
1667 Float_t s_low = fadc_sigma_low[ui] / (Float_t)(empty_events-1) /
1668 (Float_t)(n_slices);
1669 fadc_sigma_low[ui] = sqrt(s_low);
1670 }
1671
1672 HeaderFadc[ict]->SetPedestalSigma(&fadc_sigma_low[0],&fadc_sigma[0],
1673 ((MGeomCam*)(camgeom.UncheckedAt(ict)))
1674 ->GetNumPixels());
1675 }
1676
1677 //
1678 // Read the reflector file with the Cherenkov data
1679 //
1680
1681 // select input file
1682
1683 if ( Data_From_STDIN ) {
1684
1685 inputfile[0] = stdin;
1686
1687 }
1688 else{
1689 for(int ict=0;ict<ct_Number;ict++){
1690
1691 log( SIGNATURE, "Opening input \"rfl\" file %s\n", inname_CT[ict] );
1692 inputfile[ict] = fopen( inname_CT[ict], "r" );
1693
1694 if ( inputfile[ict] == NULL )
1695 error( SIGNATURE, "Cannot open input file: %s\n", inname_CT[ict] );
1696 }
1697
1698 }
1699
1700 // get signature, and check it
1701
1702 for(int ict=0;ict<ct_Number;ict++){
1703 if((reflector_file_version=check_reflector_file( inputfile[ict] ))==FALSE){
1704 exit(1);
1705 }
1706 }
1707
1708 // open data file
1709
1710 log( SIGNATURE, "Opening data \"dat\" file %s\n", datname );
1711 datafile.open( datname );
1712
1713 if ( datafile.bad() )
1714 error( SIGNATURE, "Cannot open data file: %s\n", datname );
1715
1716 // initializes flag
1717
1718 strcpy( flag, " \0" );
1719 strcpy( flag_new, " \0" );
1720
1721 // allocate space for PMTs numbers of pixels
1722
1723 fnpix = new float [ct_NPixels];
1724
1725
1726 //!@' @#### Main loop.
1727 //@'
1728
1729 // get flag
1730
1731 for(int ict=0;ict<ct_Number;ict++)
1732 fread( flag, SIZE_OF_FLAGS, 1, inputfile[ict] );
1733
1734
1735 // loop over the file
1736
1737 still_in_loop = TRUE;
1738
1739 // FIXME --- check if not eof for all input reflector files
1740
1741 while (
1742 ((! Data_From_STDIN) && ( !feof(inputfile[0]) ))
1743 ||
1744 (Data_From_STDIN && still_in_loop)
1745 ) {
1746
1747 // reading .rfl files
1748 if(!isA( flag, FLAG_START_OF_RUN )){
1749
1750 // We break the main loop
1751 cout<<"Warning: Expected start of run flag, but found:"<<flag<<endl;
1752 cout<<" We break the main loop"<<endl;
1753 break;
1754 }
1755 else { // found start of run
1756
1757 for(int ict=0;ict<ct_Number;ict++) {
1758
1759 fread( flag_new, 4, 1, inputfile[ict] );
1760
1761 if(!isA( flag_new, FLAG_START_OF_HEADER)){
1762
1763 // We break the main loop
1764 cout<<"Warning: Expected start of run header flag, but found:"<<flag_new<<endl;
1765 cout<<" We break the main loop"<<endl;
1766 break;
1767 }
1768
1769 // fread((char*)&mcrunh,(SIZE_OF_MCRUNHEADER)*sizeof(float), 1, inputfile[ict] );
1770 // AM, changed reading method, 02/2004:
1771
1772 mcrunh.read(inputfile[ict]);
1773
1774 }
1775
1776 nshow=0;
1777
1778 for(int ict=0;ict<ct_Number;ict++){
1779 fread( flag, SIZE_OF_FLAGS, 1, inputfile[ict] );
1780 }
1781 while( isA( flag, FLAG_START_OF_EVENT )){ // while there is a next event
1782 for(int ict=0;ict<ct_Number;ict++) {
1783 fread( flag_new, 4, 1, inputfile[ict] );
1784 if(!isA( flag_new, FLAG_EVENT_HEADER)){
1785
1786 // We break while events loop
1787 cout<<"Warning: Expected start of event header flag, but found:"<<flag_new<<" "<<ict<<endl;
1788 cout<<" We break the while events loop"<<endl;
1789 break;
1790 }
1791 }
1792
1793
1794 //
1795 // Clear Trigger and Fadc
1796 //
1797 for(int ict=0;ict<ct_Number;ict++) {
1798 Trigger_CT[ict]->Reset() ;
1799 Trigger_CT[ict]->ClearFirst();
1800 Trigger_CT[ict]->ClearZero();
1801 Fadc_CT[ict]->Reset() ;
1802 }
1803
1804 ++nshow;
1805 if((nshow+ntshow+1)%100 == 1)
1806 log(SIGNATURE, "Event %d(+%d)\n", nshow, ntshow);
1807
1808 // get MCEventHeader
1809 if (reflector_file_version<6){
1810 for(int ict=0;ict<ct_Number;ict++)
1811 {
1812 mcevth[ict].read(inputfile[ict]);
1813 }
1814
1815 }
1816 else{
1817 for(int ict=0;ict<ct_Number;ict++)
1818 {
1819 mcevth_2[ict].read(inputfile[ict]);
1820 }
1821 }
1822
1823 //
1824 // AM March 2004 simplified impact parameter calculation,
1825 // and allowed for correct estimate also for telescopes not
1826 // placed at Corsika's origin of coordinates (0.,0.).
1827 // FIXME: telescope coordinates still set by the user in the
1828 // input card, since they are not available in the reflector
1829 // file!
1830 //
1831 // Calculate impact parameter as distance between telescope
1832 // location and shower axis. In the previous implementation,
1833 // the definition was the distance between telescope axis and
1834 // shower axis, but this has less physical meaning in general.
1835 // Light yield depends above all on distance to shower axis!
1836 // Of course for shower axis paralel to telescope the old and
1837 // the new definitions of impact parameter agree.
1838 //
1839
1840
1841 // read the direction of the incoming shower
1842 // It is done only for one telescope since it is suposed
1843 // to be the same shower for all of them
1844 if (reflector_file_version<6){
1845 thetashw = mcevth[0].get_theta();
1846 phishw = mcevth[0].get_phi();
1847 }
1848 else{
1849 thetashw = mcevth_2[0].get_theta();
1850 phishw = mcevth_2[0].get_phi();
1851 }
1852 Zenith=thetashw; Azimutal=phishw;
1853
1854 // calculate vector for shower
1855
1856 l1 = sin(thetashw)*cos(phishw);
1857 m1 = sin(thetashw)*sin(phishw);
1858 n1 = cos(thetashw);
1859
1860 //
1861 // Note, A.M.:
1862 // Attention! "core vector from mcevth*.get_core
1863 // is the vector from the core to the telescope!
1864 //
1865 Float_t core2ct_x;
1866 Float_t core2ct_y;
1867
1868 if (reflector_file_version<6)
1869 mcevth[0].get_core(&core2ct_x, &core2ct_y);
1870 else
1871 mcevth_2[0].get_core(&core2ct_x, &core2ct_y);
1872
1873 //
1874 // Then true core position in Corsika's system is:
1875 //
1876
1877 coreX = CTx[0] - core2ct_x;
1878 coreY = CTy[0] - core2ct_y;
1879
1880 //
1881 // FIXME: This may not work fine for CTs at z != 0 !!
1882 //
1883 for(int ict=0;ict<ct_Number;ict++)
1884 impactD[ict] = dist_r_P( CTx[ict], CTy[ict], CTz[ict],
1885 l1, m1, n1, coreX, coreY, 0. );
1886
1887
1888 // energy cut
1889
1890 if ( Select_Energy ) {
1891 if (reflector_file_version<6)
1892 if (( mcevth[0].get_energy() < Select_Energy_le ) ||
1893 ( mcevth[0].get_energy() > Select_Energy_ue )) {
1894 log(SIGNATURE, "select_energy: shower rejected.\n");
1895 continue;
1896 }
1897 else
1898 if (( mcevth_2[0].get_energy() < Select_Energy_le ) ||
1899 ( mcevth_2[0].get_energy() > Select_Energy_ue )) {
1900 log(SIGNATURE, "select_energy: shower rejected.\n");
1901 continue;
1902 }
1903 }
1904
1905 inumphe=0;
1906
1907 for(int ict=0;ict<ct_Number;ict++){
1908
1909 // Read first and last time and put inumphe_CT[0] to 0
1910
1911 if (reflector_file_version<6)
1912 mcevth[ict].get_times(&arrtmin_ns,&arrtmax_ns);
1913 else
1914 mcevth_2[ict].get_times(&arrtmin_ns,&arrtmax_ns);
1915
1916 inumphe_CT[ict]=0;
1917
1918 // read the photons and produce the photoelectrons
1919
1920 k = produce_phes( inputfile[ict],
1921 ((MGeomCam*)(camgeom.UncheckedAt(ict))),
1922 WAVEBANDBOUND1,
1923 WAVEBANDBOUND6,
1924 Trigger_CT[ict], // will be changed by the function!
1925 Fadc_CT[ict], // will be changed by the function!
1926 &inumphe_CT[ict], // important for later: the size of photoe[]
1927 fnpix, // will be changed by the function!
1928 &ncph[ict], // will be changed by the function!
1929 &arrtmin_ns, // will be changed by the function!
1930 &arrtmax_ns, // will be changed by the function!
1931 ict,
1932 mirror_frac[ict]);
1933
1934 inumphe=(inumphe<inumphe_CT[ict])?inumphe_CT[ict]:inumphe;
1935
1936 if( k != 0 ){ // non-zero return value means error
1937 cout << "Exiting.\n";
1938 exit(1);
1939 }
1940 }
1941
1942 // NSB simulation
1943
1944 if(simulateNSB && nphe2NSB<=inumphe)
1945 {
1946
1947 if(Starfield_rotate){
1948
1949 // Introduction rho angle
1950
1951 zenith = thetashw;
1952 azimutal = phishw;
1953 C1 = 0.48 * sin(zenith) - 0.87 * cos(zenith) * cos(azimutal);
1954 C3 = (0.87 * cos(zenith) - 0.48 * sin(zenith) * cos(azimutal));
1955 C2 = sqrt( sin(zenith) * sin(zenith) * sin(azimutal) * sin(azimutal) +
1956 C3 * C3 );
1957 rho = acos( C1/C2 );
1958
1959 if ( sin(azimutal) < 0)
1960 rho = 2 * 3.14159 - rho;
1961 else
1962 rho = rho;
1963
1964 rho = rho*180/3.14159;
1965
1966 // Rotation of the NSB
1967 // FIXME --- We should rotate for all cameras. Is it always the same rho?
1968 for(int ict=0;ict<ct_Number;ict++)
1969 k = size_rotated(&nsb_phepns_rotated[ict][0],
1970 nsb_phepns[ict],
1971 rho);
1972 }
1973
1974 // Fill trigger and fadc response in the trigger class from the database
1975 for(int ict=0;ict<ct_Number;ict++)
1976 {
1977 for(UInt_t ui=0;
1978 ui<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
1979 ui++)
1980 {
1981 if(nsb_phepns_rotated[ict][ui]>0.0)
1982 {
1983 if((*((MGeomCam*)(camgeom.UncheckedAt(ict))))[ui].GetD() >
1984 (*((MGeomCam*)(camgeom.UncheckedAt(ict))))[0].GetD())
1985 {
1986 k=lons_outer.GetResponse(nsb_phepns_rotated[ict][ui],0.01,
1987 & nsb_trigresp[0],
1988 & nsb_fadcresp[0]);
1989 }
1990 else
1991 {
1992 k=lons.GetResponse(nsb_phepns_rotated[ict][ui],0.01,
1993 & nsb_trigresp[0],& nsb_fadcresp[0]);
1994 }
1995 if(k==0)
1996 {
1997 cout << "Exiting.\n";
1998 exit(1);
1999 }
2000 Trigger_CT[ict]->AddNSB(ui,nsb_trigresp);
2001 Fadc_CT[ict]->AddSignal(ui,nsb_fadcresp);
2002 }
2003 }
2004 }
2005
2006 }// end if(simulateNSB && nphe2NSB<=inumphe_CT[0]) ...
2007
2008
2009 for(int ict=0;ict<ct_Number;ict++)
2010 {
2011 inumphensb[ict]=0;
2012
2013 for (UInt_t ui=0;
2014 ui < ((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
2015 ui++)
2016 inumphensb[ict]+=nsb_phepns[ict][ui]*TOTAL_TRIGGER_TIME;
2017
2018 ntcph[ict]+=ncph[ict];
2019 if ((nshow+ntshow+1)%100 == 1){
2020 log(SIGNATURE, "End of this event: %d cphs(+%d). . .\n",
2021 ncph[ict], ntcph[ict]);
2022
2023 cout << "Total number of phes in CT "<<ict<<": "
2024 << inumphe_CT[ict]<<" (+ ";
2025 cout<<inumphensb[ict]<<" mean expected number from NSB)"<<endl;
2026 }
2027 }
2028
2029 // skip it ?
2030
2031 int i;
2032 for (i=0; i<nSkip; ++i ) {
2033 if (Skip[i] == (nshow+ntshow)) {
2034 i = -1;
2035 break;
2036 }
2037 }
2038
2039 // if after the previous loop, the exit value of i is -1
2040 // then the shower number is in the list of showers to be
2041 // skipped
2042
2043 if (i == -1) {
2044 log(SIGNATURE, "\t\tskipped!\n");
2045 continue;
2046 }
2047
2048 //++++++++++++++++++++++++++++++++++++++++++++++++++
2049 // at this point we have a camera full of
2050 // ph.e.s
2051 // we should first apply the trigger condition,
2052 // and if there's trigger, then clean the image,
2053 // calculate the islands statistics and the
2054 // other parameters of the image (Hillas' parameters
2055 // and so on).
2056 //--------------------------------------------------
2057
2058 // TRIGGER HERE
2059
2060 // We should simulate the AC coupling behaviour:
2061 // For the FADC it is only done for the NSB while producing
2062 // the StarResponse database.
2063 // For the trigger is done in the Trigger.Diskriminate(), which
2064 // is called later (it should be separated to speed up the program)
2065 //
2066
2067 // now the noise of the electronic
2068 // (preamps, optical transmission,..) is introduced.
2069 // This is done inside the class MTrigger by the method ElecNoise.
2070 //
2071
2072 for(int ict=0;ict<ct_Number;ict++)
2073 {
2074 if (addElecNoise && nphe2NSB<=inumphe)
2075 {
2076 Trigger_CT[ict]->ElecNoise(Trigger_noise) ;
2077 Fadc_CT[ict]->ElecNoise() ;
2078 }
2079 }
2080
2081 // now a shift in the fadc signal due to the pedestals is
2082 // introduced
2083 // This is done inside the class MFadc by the method Pedestals
2084
2085 for(int ict=0;ict<ct_Number;ict++)
2086 Fadc_CT[ict]->Pedestals();
2087
2088
2089 // We study several trigger conditons
2090 if(Trigger_Loop)
2091 {
2092 // Set to zero the flag to know if some conditon has triggered
2093 btrigger=0;
2094 flagstoring = 0;
2095
2096 // Loop over trigger threshold
2097 int iconcount;
2098 for (iconcount=0, ithrescount=0, fthrescount=Trigger_loop_lthres;
2099 fthrescount <= Trigger_loop_uthres;
2100 ithrescount++, fthrescount += Trigger_loop_sthres)
2101 {
2102 for (int i=0;i<ct_NPixels;i++)
2103 {
2104 fpixelthres[i] =
2105 ((Float_t)(fthrescount)>=qThreshold[0][i])?
2106 (Float_t)(fthrescount):qThreshold[0][i];
2107
2108 // Rise the discrimnator threshold to avoid huge rates
2109
2110 if(riseDiskThres>0.0 && simulateNSB && nphe2NSB<=inumphe)
2111 for(int ii=0;ii<ct_NPixels;ii++)
2112 if( nsb_phepns_rotated[0][ii]>riseDiskThres)
2113 fpixelthres[ii]=secureDiskThres;
2114 }
2115 Trigger_CT[0]->SetThreshold(fpixelthres);
2116
2117 Trigger_CT[0]->Diskriminate();
2118
2119 //
2120 // look if in all the signals in the trigger signal branch
2121 // is a possible Trigger. Therefore we habe to diskriminate all
2122 // the simulated analog signals (Method Diskriminate in class
2123 // MTrigger). We look simultanously for the moments at which
2124 // there are more than TRIGGER_MULTI pixels above the
2125 // CHANNEL_THRESHOLD.
2126 //
2127
2128 // Set trigger flags to zero
2129 Lev0=0;
2130 Lev1=0;
2131
2132 // loop over multiplicity of trigger configuration
2133 for (imulticount = Trigger_loop_lmult;
2134 imulticount <= Trigger_loop_umult;
2135 imulticount++)
2136 {
2137 Trigger_CT[0]->SetMultiplicity(imulticount);
2138 Trigger_CT[0]->ClearZero();
2139
2140 Lev0=(Short_t) Trigger_CT[0]->ZeroLevel();
2141 if (Lev0>0 || Write_All_Images || btrigger)
2142 {
2143
2144 // loop over topologies
2145 for(itopocount=Trigger_loop_ltop;
2146 itopocount<=Trigger_loop_utop;
2147 itopocount++)
2148 {
2149 Lev1=0;
2150
2151 if(itopocount==0 && imulticount>7)
2152 continue;
2153
2154 //COBB if(itopocount==2 && imulticount<3) continue;
2155 // It only makes to look for a different topology
2156 // if there are 3 or more N pixels.
2157 if(imulticount<3)
2158 Trigger_CT[0]->SetTopology(1);
2159 else
2160 {
2161 // We should be careful that topologies are sort from
2162 // the less to the more restrictive one.
2163 Trigger_CT[0]->SetTopology(isorttopo[itopocount]);
2164 }
2165 Trigger_CT[0]->ClearFirst();
2166
2167 //
2168 // Start the First Level Trigger simulation
2169 //
2170 if(Lev0!=0)
2171 Lev1=Trigger_CT[0]->FirstLevel();
2172 if(Lev1>0) {
2173 btrigger= 1;
2174 ntriggerloop[ithrescount]
2175 [imulticount-Trigger_loop_lmult]
2176 [itopocount-Trigger_loop_ltop]++;
2177 }
2178
2179 Lev0=1;
2180 Int_t NumImages = Lev1;
2181 if(Lev1==0 && (Write_All_Images || btrigger))
2182 {
2183 btrigger= 1;
2184 NumImages=1;
2185 Lev0=0;
2186 }
2187
2188 for (Int_t ii=0;ii<NumImages;ii++)
2189 {
2190 if (Write_McTrig)
2191 {
2192 McTrig[iconcount]->SetFirstLevel ((ii+1)*Lev0);
2193 McTrig[iconcount]->
2194 SetTime(Trigger_CT[0]->GetFirstLevelTime(ii),ii+1);
2195 Trigger_CT[0]->GetMapDiskriminator(trigger_map);
2196 McTrig[iconcount]->SetMapPixels(trigger_map,ii);
2197 }
2198 //
2199 // fill inside the class fadc the member output
2200 //
2201
2202 Fadc_CT[0]->TriggeredFadc(Trigger_CT[0]->
2203 GetFirstLevelTime(ii));
2204
2205 if( Write_RawEvt )
2206 {
2207 //
2208 // Fill the header of this event
2209 //
2210
2211 EvtHeader[iconcount]->
2212 FillHeader( (UInt_t) (ntshow + nshow),0);
2213
2214 // fill pixel information
2215 if (Lev1 || Write_All_Images){
2216 if (addElecNoise) Fadc_CT[0]->DigitalNoise();
2217 for(UInt_t i=0;
2218 i<((MGeomCam*)(camgeom.UncheckedAt(0)))
2219 ->GetNumPixels();i++){
2220 //
2221 // AM 15 01 2004: commented out "continue"
2222 // statement, so that also pixels with no
2223 // C-photons will be written to the output
2224 // in case the camera is run with no noise.
2225 // if(!Fadc_CT[0]->IsPixelUsed(i)) continue;
2226
2227 for (j=0;j<FADC_slices_written;j++){
2228 fadcValues->AddAt(Fadc_CT[0]->
2229 GetFadcSignal(i,j),j);
2230 fadcValuesLow->AddAt(Fadc_CT[0]->
2231 GetFadcLowGainSignal(i,j),j);
2232 }
2233 EvtData[iconcount]->AddPixel(i,fadcValues,0);
2234 EvtData[iconcount]->AddPixel(i,fadcValuesLow,kTRUE);
2235 }
2236 }
2237 }
2238 }
2239 //
2240 // Increase counter of analised trigger conditions
2241 //
2242 iconcount++;
2243 }
2244 }
2245 else{
2246 break;
2247 }
2248 }
2249 if (!btrigger) break;
2250 }
2251 if (btrigger){
2252
2253 //
2254 // fill the MMcEvt with all information
2255 //
2256
2257 if(!flagstoring)
2258 nstoredevents++;
2259 flagstoring = 1;
2260
2261 if (Write_McEvt) {
2262 Float_t ftime, ltime;
2263 if (reflector_file_version<6){
2264 mcevth[0].get_times(&ftime, &ltime);
2265 McEvt[0]->Fill( 0,
2266 (UShort_t) mcevth[0].get_primary() ,
2267 mcevth[0].get_energy(),
2268 -1.0,
2269 -1.0,
2270 -1.0,
2271 mcevth[0].get_theta(),
2272 mcevth[0].get_phi(),
2273 mcevth[0].get_core(),
2274 coreX,
2275 coreY,
2276 impactD[0],
2277 phiCT[0],
2278 thetaCT[0],
2279 ftime,
2280 ltime,
2281 0,
2282 0,
2283 0,
2284 0,
2285 0,
2286 0,
2287 0,
2288 (UInt_t)mcevth[0].get_CORSIKA(),
2289 (UInt_t)mcevth[0].get_AtmAbs(),
2290 (UInt_t)(mcevth[0].get_MirrAbs()+
2291 mcevth[0].get_OutOfMirr()+
2292 mcevth[0].get_BlackSpot()),
2293 (UInt_t) ncph[0],
2294 (UInt_t) inumphe_CT[0],
2295 (UInt_t) inumphensb[0]+inumphe_CT[0],
2296 -1.0,
2297 -1.0,
2298 -1.0);
2299 }
2300 else{
2301 Float_t Nmax, t0, tmax, a, b, c, chi2;
2302 mcevth_2[0].get_times(&ftime, &ltime);
2303 chi2=mcevth_2[0].get_NKGfit(&Nmax, &t0, &tmax, &a, &b, &c);
2304 McEvt[0]->Fill((UInt_t) mcevth_2[0].get_evt_number(),
2305 (UShort_t) mcevth_2[0].get_primary() ,
2306 mcevth_2[0].get_energy(),
2307 mcevth_2[0].get_thick0(),
2308 mcevth_2[0].get_first_target(),
2309 mcevth_2[0].get_z_first_int(),
2310 mcevth_2[0].get_theta(),
2311 mcevth_2[0].get_phi(),
2312 mcevth_2[0].get_core(),
2313 coreX,
2314 coreY,
2315 impactD[0],
2316 mcevth_2[0].get_phi_CT(),
2317 mcevth_2[0].get_theta_CT(),
2318 ftime,
2319 ltime,
2320 Nmax,
2321 t0,
2322 tmax,
2323 a,
2324 b,
2325 c,
2326 chi2,
2327 (UInt_t)mcevth_2[0].get_CORSIKA(),
2328 (UInt_t)mcevth_2[0].get_AtmAbs(),
2329 (UInt_t)(mcevth_2[0].get_MirrAbs()+
2330 mcevth_2[0].get_OutOfMirr()+
2331 mcevth_2[0].get_BlackSpot()),
2332 (UInt_t) ncph[0],
2333 (UInt_t) inumphe_CT[0],
2334 (UInt_t) inumphensb[0]+inumphe_CT[0],
2335 mcevth_2[0].get_ElecFraction(),
2336 mcevth_2[0].get_MuonFraction(),
2337 mcevth_2[0].get_OtherFraction());
2338 }
2339 }
2340 // Fill the Tree with the current leaves of each branch
2341 i=EvtTree.Fill() ;
2342
2343 // Clear the branches
2344 if(Write_McTrig){
2345 for(int i=0;i<numberBranches;i++){
2346 McTrig[i]->Clear() ;
2347 }
2348 }
2349 if( Write_RawEvt ){
2350 for(int i=0;i<numberBranches;i++){
2351 EvtHeader[i]->Clear() ;
2352 EvtData[i]->ResetPixels (0, 0);
2353 }
2354 }
2355 if (Write_McEvt)
2356 McEvt[0]->Clear() ;
2357 }
2358 }
2359
2360 // We study a single trigger condition
2361 else {
2362
2363 // Set to zero the flag to know if some conditon has triggered
2364 btrigger=0;
2365 flagstoring = 0;
2366
2367 for(int ict = 0; ict < ct_Number; ict++)
2368 {
2369
2370 // Setting trigger conditions
2371 Trigger_CT[ict]->SetMultiplicity(Trigger_multiplicity[ict]);
2372 Trigger_CT[ict]->SetTopology(Trigger_topology[ict]);
2373 for (int i=0;i<ct_NPixels;i++)
2374 fpixelthres[i]=qThreshold[ict][i];
2375
2376 // Rise the discrimnator threshold to avoid huge rates
2377 if(riseDiskThres>0.0 && simulateNSB && nphe2NSB<=inumphe)
2378 for(int ii=0;ii<ct_NPixels;ii++)
2379 {
2380 if( nsb_phepns_rotated[ict][ii]>riseDiskThres)
2381 fpixelthres[ii]=secureDiskThres;
2382 }
2383
2384 Trigger_CT[ict]->SetThreshold(fpixelthres);
2385
2386 Trigger_CT[ict]->Diskriminate() ;
2387
2388 //
2389 // Look if in all the signals in the trigger signal branch
2390 // is a possible Trigger. Therefore we have to discriminate all
2391 // the simulated analog signals (Method Diskriminate in class
2392 // MTrigger). We look simultaneously for the moments at which
2393 // there are more than TRIGGER_MULTI pixels above the
2394 // CHANNEL_THRESHOLD.
2395 //
2396
2397 Lev0MT[ict] = (Short_t) Trigger_CT[ict]->ZeroLevel() ;
2398
2399 Lev1MT[ict] = 0 ;
2400
2401 //
2402 // Start the First Level Trigger simulation
2403 //
2404
2405 if ( Lev0MT[ict] > 0 || Write_All_Images)
2406 Lev1MT[ict]= Trigger_CT[ict]->FirstLevel();
2407
2408 if (Lev1MT[ict]>0)
2409 ++ntrigger[ict];
2410
2411 }
2412
2413 Int_t NumImages = 0;
2414 Int_t CT_triggered=0;
2415 for(int ict=0;ict<ct_Number;ict++)
2416 {
2417 if(NumImages==0 && Lev1MT[ict]>0)
2418 CT_triggered=ict;
2419 NumImages = (NumImages>=Lev1MT[ict]) ? NumImages : 1;
2420 Lev0MT[ict]=1;
2421
2422 if (Lev1MT[ict]==0 && Write_All_Images)
2423 {
2424 NumImages=1;
2425 Lev0MT[ict]=0;
2426 }
2427 }
2428
2429 for(int ict=0;ict<ct_Number;ict++){
2430 for(Int_t ii=0;ii<NumImages;ii++){
2431
2432 btrigger=1;
2433
2434 // Loop over different level one triggers
2435
2436 //
2437 // fill inside class fadc the member output
2438 //
2439 if(Lev1MT[ict]>0)
2440 Fadc_CT[ict]->
2441 TriggeredFadc(Trigger_CT[ict]->GetFirstLevelTime(ii));
2442 else
2443 Fadc_CT[ict]->
2444 TriggeredFadc(Trigger_CT[CT_triggered]->GetFirstLevelTime(ii));
2445
2446 if(!flagstoring)
2447 nstoredevents++;
2448 flagstoring = 1;
2449
2450 if (Write_McTrig){
2451 McTrig[ict]->SetFirstLevel (Lev1MT[ict]);
2452 McTrig[ict]
2453 ->SetTime(Trigger_CT[ict]->GetFirstLevelTime(ii),ii+1);
2454 Trigger_CT[ict]->GetMapDiskriminator(trigger_map);
2455 McTrig[ict]->SetMapPixels(trigger_map,ii);
2456 }
2457
2458 // Fill Evt information
2459
2460 if (Write_RawEvt){
2461
2462 //
2463 // Fill the header of this event
2464 //
2465
2466 EvtHeader[ict]
2467 ->FillHeader ( (UInt_t) (ntshow + nshow) , 20 ) ;
2468
2469 // fill pixel information
2470
2471 if (Lev1MT[ict] || Write_All_Images){
2472 if (addElecNoise) Fadc_CT[ict]->DigitalNoise();
2473 for(UInt_t i=0;
2474 i<((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();
2475 i++){
2476//
2477// AM 15 01 2004 Commented out "continue" statement, so that also pixels
2478// containing no C-photons will be written to the output in case of running
2479// camera with no noise added to the signal.
2480// if(!Fadc_CT[ict]->IsPixelUsed(i)) continue;
2481//
2482 for (j = 0; j < FADC_slices_written; j++)
2483 {
2484 fadcValues->AddAt(Fadc_CT[ict]->GetFadcSignal(i,j),j);
2485 fadcValuesLow->AddAt(Fadc_CT[ict]->GetFadcLowGainSignal(i,j),j);
2486 }
2487 EvtData[ict]->AddPixel(i,fadcValues,0);
2488 EvtData[ict]->AddPixel(i,fadcValuesLow,kTRUE);
2489 }
2490 }
2491 }
2492 }
2493 //
2494 // if a first level trigger occurred, then
2495 // 1. do some other stuff (not implemented)
2496 // 2. start the gui tool
2497
2498 if(FADC_Scan){
2499 if ( Lev0MT[ict] > 0 ) {
2500 Fadc_CT[ict]->ShowSignal( McEvt[ict], (Float_t) 60. ) ;
2501 }
2502 }
2503
2504 if(Trigger_Scan){
2505 if ( Lev0MT[ict] > 0 ) {
2506 Trigger_CT[ict]->ShowSignal(McEvt[ict]) ;
2507 }
2508 }
2509
2510 } // end CT loop
2511
2512 // If there is trigger in some telecope or we store all showers
2513 if(btrigger){
2514 if (Write_McEvt){
2515 //
2516 // fill the MMcEvt with all information
2517 //
2518
2519
2520 for (int ict=0;ict<ct_Number;ict++){
2521 Float_t ftime, ltime;
2522 if (reflector_file_version<6){
2523 mcevth[ict].get_times(&ftime, &ltime);
2524 McEvt[ict]->Fill( 0,
2525 (UShort_t) mcevth[0].get_primary() ,
2526 mcevth[ict].get_energy(),
2527 -1.0,
2528 -1.0,
2529 -1.0,
2530 mcevth[ict].get_theta(),
2531 mcevth[ict].get_phi(),
2532 mcevth[ict].get_core(),
2533 coreX,
2534 coreY,
2535 impactD[ict],
2536 phiCT[ict],
2537 thetaCT[ict],
2538 ftime,
2539 ltime,
2540 0,
2541 0,
2542 0,
2543 0,
2544 0,
2545 0,
2546 0,
2547 (UInt_t)mcevth[ict].get_CORSIKA(),
2548 (UInt_t)mcevth[ict].get_AtmAbs(),
2549 (UInt_t)(mcevth[ict].get_MirrAbs()+mcevth[0].get_OutOfMirr()+mcevth[0].get_BlackSpot()),
2550 (UInt_t) ncph[ict],
2551 (UInt_t) inumphe_CT[ict],
2552 (UInt_t) inumphensb[ict]+inumphe_CT[ict],
2553 -1.0,
2554 -1.0,
2555 -1.0);
2556 }
2557 else{
2558 Float_t Nmax, t0, tmax, a, b, c, chi2;
2559 mcevth_2[ict].get_times(&ftime, &ltime);
2560 chi2=mcevth_2[ict].get_NKGfit(&Nmax, &t0, &tmax, &a, &b, &c);
2561 McEvt[ict]->Fill( (UInt_t) mcevth_2[ict].get_evt_number(),
2562 (UShort_t) mcevth_2[ict].get_primary() ,
2563 mcevth_2[ict].get_energy(),
2564 mcevth_2[ict].get_thick0(),
2565 mcevth_2[ict].get_first_target(),
2566 mcevth_2[ict].get_z_first_int(),
2567 mcevth_2[ict].get_theta(),
2568 mcevth_2[ict].get_phi(),
2569 mcevth_2[ict].get_core(),
2570 coreX,
2571 coreY,
2572 impactD[ict],
2573 mcevth_2[ict].get_phi_CT(),
2574 mcevth_2[ict].get_theta_CT(),
2575 ftime,
2576 ltime,
2577 Nmax,
2578 t0,
2579 tmax,
2580 a,
2581 b,
2582 c,
2583 chi2,
2584 (UInt_t)mcevth_2[ict].get_CORSIKA(),
2585 (UInt_t)mcevth_2[ict].get_AtmAbs(),
2586 (UInt_t) (mcevth_2[ict].get_MirrAbs()+mcevth_2[ict].get_OutOfMirr()+mcevth_2[ict].get_BlackSpot()),
2587 (UInt_t) ncph[ict],
2588 (UInt_t) inumphe_CT[ict],
2589 (UInt_t) inumphensb[ict]+inumphe_CT[ict],
2590 mcevth_2[ict].get_ElecFraction(),
2591 mcevth_2[ict].get_MuonFraction(),
2592 mcevth_2[ict].get_OtherFraction());
2593 }
2594 }
2595 }
2596 // We don not count photons out of the camera.
2597
2598
2599 //
2600 // write it out to the file outfile
2601 //
2602
2603 EvtTree.Fill() ;
2604 }
2605
2606 // clear all
2607 for(int ict=0;ict<ct_Number;ict++){
2608 if (Write_RawEvt) EvtHeader[ict]->Clear() ;
2609 if (Write_RawEvt) EvtData[ict]->ResetPixels(0,0);
2610 if (Write_McTrig) McTrig[ict]->Clear() ;
2611 if (Write_McEvt) McEvt[ict]->Clear() ;
2612 }
2613 }
2614
2615#ifdef __DEBUG__
2616 printf("\n");
2617
2618 for ( ici=0; ici<PIX_ARRAY_SIDE; ++ici ) {
2619
2620 for ( icj=0; icj<PIX_ARRAY_SIDE; ++icj ) {
2621
2622 if ( (int)pixels[ici][icj][PIXNUM] > -1 ) {
2623
2624 if ( fnpix[(int)pixels[ici][icj][PIXNUM]] > 0. ) {
2625
2626 printf ("@@ %4d %4d %10f %10f %4f (%4d %4d)\n", nshow,
2627 (int)pixels[ici][icj][PIXNUM],
2628 pixels[ici][icj][PIXX],
2629 pixels[ici][icj][PIXY],
2630 fnpix[(int)pixels[ici][icj][PIXNUM]], ici, icj);
2631
2632 }
2633 }
2634 }
2635 }
2636
2637 for (int i=0;
2638 i<((MGeomCam*)(camgeom.UncheckedAt(0)))->GetNumPixels(); ++i) {
2639 printf("%d (%d): ", i, npixneig[i]);
2640 for (j=0; j<npixneig[i]; ++i)
2641 printf(" %d", pixneig[i][j]);
2642 printf("\n");
2643 }
2644
2645#endif // __DEBUG__
2646
2647
2648 // We search the maximum impact parameter fo the simualted showers
2649 maxpimpact=maxpimpact<impactD[0]?impactD[0]:maxpimpact;
2650
2651 // look for the next event
2652
2653 for(int ict=0;ict<ct_Number;ict++)
2654 fread( flag, SIZE_OF_FLAGS, 1, inputfile[ict] );
2655
2656 } // end while there is a next event
2657
2658 if( !isA( flag, FLAG_END_OF_RUN )){
2659 error( SIGNATURE, "Expected end of run flag, but found: %s\n", flag );
2660 break;
2661 }
2662 else { // found end of run
2663 ntshow += nshow;
2664 log(SIGNATURE, "End of this run with %d events . . .\n", nshow);
2665
2666 //fread( flag, SIZE_OF_FLAGS, 1, inputfile );
2667 for(int ict=0;ict<ct_Number;ict++)
2668 fread( flag, SIZE_OF_FLAGS, 1, inputfile[ict] );
2669
2670 if( isA( flag, FLAG_END_OF_FILE ) ){ // end of file
2671 log(SIGNATURE, "End of file . . .\n");
2672 still_in_loop = FALSE;
2673 log(SIGNATURE, "Reading ASCII files at the end of the reflector file. . .\n");
2674 for(int ict=0;ict<ct_Number;ict++){
2675 read_ascii(inputfile[ict], McConfigRunHeader[ict]);
2676 McConfigRunHeader[ict]->SetMissPointingX(missP_x);
2677 McConfigRunHeader[ict]->SetMissPointingY(missP_y);
2678 if ( Spotsigma > 0.)
2679 {
2680 Float_t ref_spotsigma = McConfigRunHeader[ict]->GetPointSpread();
2681 Float_t newsigma = sqrt(ref_spotsigma * ref_spotsigma +
2682 Spot_x* Spot_x);
2683 McConfigRunHeader[ict]->SetPointSpreadX(newsigma);
2684 newsigma = sqrt(ref_spotsigma * ref_spotsigma + Spot_y* Spot_y);
2685 McConfigRunHeader[ict]->SetPointSpreadY(newsigma);
2686 }
2687 }
2688 if ((! Data_From_STDIN) && ( !feof(inputfile[0]) )){
2689
2690 // we have concatenated input files.
2691 // get signature of the next part and check it.
2692
2693 if((reflector_file_version=check_reflector_file( inputfile[0] ))==FALSE){
2694 log(SIGNATURE, "Next file is not recognised as a reflector file.\n");
2695 log(SIGNATURE, "Stopping ...\n");
2696 break;
2697 }
2698
2699 }
2700
2701 for(int ict=0;ict<ct_Number;ict++)
2702 fread( flag, SIZE_OF_FLAGS, 1, inputfile[ict] );
2703
2704 } // end if found end of file
2705 } // end if found end of run
2706
2707 } // end if else found start of run
2708 } // end big while loop
2709
2710 //<@ Finally we should fill th McRunHeader
2711
2712 Float_t heights[10];
2713 time_t ltime;
2714 Float_t ftime;
2715 Float_t rnum;
2716 Float_t viewcone[2]={0,0};
2717
2718 get_starfield_center(&sfRaH,&sfRaM,&sfRaS,&sfDeD,&sfDeM,&sfDeS);
2719 if (reflector_file_version<6){
2720 telestheta=-10.0;
2721 telesphi=-10.0;
2722 mcevth[0].get_theta_range(&shthetamin, &shthetamax);
2723 mcevth[0].get_phi_range(&shphimin,&shphimax);
2724 mcevth[0].get_theta_range(&shthetamin, &shthetamax);
2725 mcevth[0].get_phi_range(&shphimin,&shphimax);
2726 corsika=UInt_t(mcevth[0].get_VersionPGM()*1000);
2727 for (int i=0; i< 10;i++)
2728 heights[i]=mcevth[0].get_HeightLev (i);
2729 rnum=mcevth[0].get_RunNumber();
2730 }
2731 else{
2732 telestheta=mcevth_2[0].get_theta_CT();
2733 telesphi=mcevth_2[0].get_phi_CT();
2734 mcevth_2[0].get_theta_range(&shthetamin, &shthetamax);
2735 mcevth_2[0].get_phi_range(&shphimin,&shphimax);
2736 corsika=UInt_t(mcevth_2[0].get_VersionPGM()*1000);
2737 for (int i=0; i< 10;i++)
2738 heights[i]=mcevth_2[0].get_HeightLev (i);
2739 rnum=mcevth_2[0].get_RunNumber();
2740 mcevth_2[0].get_viewcone(&viewcone[0],&viewcone[1]);
2741 }
2742
2743 if(!Trigger_Loop) icontrigger=0;
2744 time (&ltime);
2745 ftime = ((Float_t)ltime)/1000;
2746
2747 if (reflector_file_version<6)
2748 McRunHeader->Fill(rnum,
2749 (UInt_t) 0,
2750 mcevth[0].get_DateRun(),
2751 ftime,
2752 icontrigger,
2753 !Write_All_Images,
2754 Write_McEvt,
2755 Write_McTrig,
2756 Write_McFADC,
2757 Write_RawEvt,
2758 addElecNoise,
2759 ct_NPixels,
2760 (UInt_t)ntshow,
2761 (UInt_t)nstoredevents,
2762 0,
2763 sfRaH,
2764 sfRaM,
2765 sfRaS,
2766 sfDeD,
2767 sfDeM,
2768 sfDeS,
2769 meanNSB,
2770 telestheta,
2771 telesphi,
2772 shthetamax,
2773 shthetamin,
2774 shphimax,
2775 shphimin,
2776 maxpimpact,
2777 mcevth[0].get_CWaveLower(),
2778 mcevth[0].get_CWaveUpper(),
2779 mcevth[0].get_slope(),
2780 1,
2781 heights,
2782 corsika,
2783 (UInt_t)(reflector_file_version*100),
2784 (UInt_t)(VERSION*100),
2785 0);
2786 else
2787 McRunHeader->Fill(rnum,
2788 (UInt_t) 0,
2789 mcevth_2[0].get_DateRun(),
2790 ftime,
2791 icontrigger,
2792 !Write_All_Images,
2793 Write_McEvt,
2794 Write_McTrig,
2795 Write_McFADC,
2796 Write_RawEvt,
2797 addElecNoise,
2798 ct_NPixels,
2799 (UInt_t)ntshow,
2800 (UInt_t)nstoredevents,
2801 0,
2802 sfRaH,
2803 sfRaM,
2804 sfRaS,
2805 sfDeD,
2806 sfDeM,
2807 sfDeS,
2808 meanNSB,
2809 telestheta,
2810 telesphi,
2811 shthetamax,
2812 shthetamin,
2813 shphimax,
2814 shphimin,
2815 maxpimpact,
2816 mcevth_2[0].get_CWaveLower(),
2817 mcevth_2[0].get_CWaveUpper(),
2818 mcevth_2[0].get_slope(),
2819 1,
2820 heights,
2821 corsika,
2822 (UInt_t)(reflector_file_version*100),
2823 (UInt_t)(VERSION*100),
2824 0);
2825 // Fill some missing values for MRawRunHeader
2826
2827 RunHeader->SetRunNumber((UInt_t)rnum);
2828 RunHeader->SetNumEvents(nstoredevents);
2829
2830 // Fill MMcCorsikaRunHeader
2831
2832 Float_t constantC[50];
2833 mcrunh.get_constantC(&constantC[0]);
2834 Float_t constantCKA[40];
2835 mcrunh.get_constantCKA(&constantCKA[0]);
2836 Float_t constantCETA[5];
2837 mcrunh.get_constantCETA(&constantCETA[0]);
2838 Float_t constantCSTRBA[11];
2839 mcrunh.get_constantCSTRBA(&constantCSTRBA[0]);
2840 Float_t constantAATM[5];
2841 mcrunh.get_constantAATM(&constantAATM[0]);
2842 Float_t constantBATM[5];
2843 mcrunh.get_constantBATM(&constantBATM[0]);
2844 Float_t constantCATM[5];
2845 mcrunh.get_constantCATM(&constantCATM[0]);
2846 Float_t constantNFL[4];
2847 mcrunh.get_constantNFL(&constantNFL[0]);
2848
2849 if(reflector_file_version>5)
2850 McCorsikaRunHeader->Fill(rnum,
2851 mcrunh.get_date(),
2852 corsika,
2853 1,
2854 heights,
2855 mcevth_2[0].get_slope(),
2856 mcrunh.get_ELow(),
2857 mcrunh.get_EUpp(),
2858 mcrunh.get_EGS4(),
2859 mcrunh.get_NKG(),
2860 mcrunh.get_Ecutoffh(),
2861 mcrunh.get_Ecutoffm(),
2862 mcrunh.get_Ecutoffe(),
2863 mcrunh.get_Ecutoffg(),
2864 constantC,
2865 constantCKA,
2866 constantCETA,
2867 constantCSTRBA,
2868 constantAATM,
2869 constantBATM,
2870 constantCATM,
2871 constantNFL,
2872 viewcone,
2873 mcrunh.get_wobble(),
2874 mcrunh.get_atmophere()
2875 );
2876
2877 // Store qe for each PMT in output file
2878 TArrayF qe_pmt;
2879 TArrayF wav_pmt;
2880
2881 for(int ict=0;ict<ct_Number;ict++){
2882 McConfigRunHeader[ict]->InitSizePMTs(ct_NPixels);
2883 for(int i=0; i<(Int_t)((MGeomCam*)(camgeom.UncheckedAt(ict)))->GetNumPixels();i++){
2884 McConfigRunHeader[ict]->AddPMT(i);
2885 MGeomPMT &pmt = McConfigRunHeader[ict]->GetPMT(i);
2886 qe_pmt.Set(pointsQE[ict],QE[ict][i][1]);
2887 wav_pmt.Set(pointsQE[ict],QElambda);
2888 pmt.SetArraySize(pointsQE[ict]);
2889 pmt.SetPMTContent(i,wav_pmt,qe_pmt);
2890 }
2891
2892 // Store Light Collection factors in the output file
2893 TArrayF theta_lc;
2894 TArrayF factor_lc;
2895 TArrayF factor_lc_outer;
2896
2897 theta_lc.Set(pointsWC,WC[0]);
2898 factor_lc.Set(pointsWC,WC[1]);
2899 factor_lc_outer.Set(pointsWC,WC_outer[1]);
2900
2901 McConfigRunHeader[ict]->SetLightCollection(theta_lc, factor_lc,
2902 factor_lc_outer);
2903
2904 }
2905
2906 // Fill the Header Tree with the current leaves of each branch
2907 HeaderTree.Fill() ;
2908
2909 //++
2910 // put the Event to the root file
2911 //--
2912
2913 outfile_temp.Write() ;
2914 outfile_temp.Close() ;
2915
2916 // close input file
2917
2918 if (Trigger_Loop){
2919 log( SIGNATURE, "%d event(s), with a total of %d C.photons\n",
2920 ntshow, ntcph[0] );
2921 datafile<<ntshow<<" event(s), with a total of "<<ntcph[0]<<" C.photons"<<endl;
2922 log( SIGNATURE, "Trigger Mode. \n");
2923 log( SIGNATURE, "Fraction of triggers: \n");
2924 datafile<<"Fraction of triggers: "<<endl;
2925 for (ithrescount=0, fthrescount=Trigger_loop_lthres;fthrescount<=Trigger_loop_uthres;ithrescount++, fthrescount+=Trigger_loop_sthres){
2926 for (imulticount=Trigger_loop_lmult;imulticount<=Trigger_loop_umult;imulticount++){
2927 for(itopocount=Trigger_loop_ltop;itopocount<=Trigger_loop_utop;itopocount++){
2928 log( SIGNATURE, "Thres %5.1f, Multi %d, Topo %d: %5.1f%% (%d out of %d)\n",
2929 fthrescount,imulticount,isorttopo[itopocount],((float)ntriggerloop[ithrescount][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop] / ((float)ntshow) * 100.0), ntriggerloop[ithrescount][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop], ntshow);
2930 datafile<<"Thres "<<fthrescount<<", Multi "<<imulticount<<", Topo"<<isorttopo[itopocount]<<": ";
2931 datafile<<((float)ntriggerloop[ithrescount][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop] / ((float)ntshow) * 100.0)<<"% ("<<ntriggerloop[ithrescount][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop]<<" out of "<<ntshow<<")"<<endl;
2932 }
2933 }
2934 }
2935 }
2936 else{
2937 for(int ict=0;ict<ct_Number;ict++){
2938 log( SIGNATURE,
2939 "%d event(s), with a total of %d C.photons in CT %i (%s)\n",
2940 ntshow, ntcph[ict],ict,GeometryName[ict] );
2941 datafile<<ntshow<<" event(s), with a total of "<<ntcph[ict]
2942 <<" C.photons in CT "<<ict<<" ("<<GeometryName[ict]<<")"<<endl;
2943 log( SIGNATURE, "Fraction of triggers: %5.1f%% (%d out of %d)\n",
2944 ((float)ntrigger[ict]) / ((float)ntshow) * 100.0, ntrigger[ict], ntshow);
2945 datafile<<"Fraction of triggers: "<<((float)ntrigger[ict]) / ((float)ntshow) * 100.0<<" ("<<ntrigger[ict]<<" out of "<<ntshow<<" )"<<endl;
2946 }
2947 }
2948
2949 // close files
2950
2951 log( SIGNATURE, "Closing files\n" );
2952
2953 if( ! Data_From_STDIN ){
2954 for(int ict=0;ict<ct_Number;ict++)
2955 fclose( inputfile[ict] );
2956 }
2957 datafile.close();
2958
2959 // program finished
2960
2961 log( SIGNATURE, "Done.\n");
2962
2963 return( 0 );
2964}
2965//!@}
2966
2967// @T \newpage
2968
2969//!@subsection Functions definition.
2970
2971//!-----------------------------------------------------------
2972// @name present
2973//
2974// @desc Make some presentation
2975//
2976// @date Sat Jun 27 05:58:56 MET DST 1998
2977//------------------------------------------------------------
2978// @function
2979
2980//!@{
2981void
2982present(void)
2983{
2984 cout << "##################################################\n"
2985 << SIGNATURE << '\n' << '\n'
2986 << "Processor of the reflector output\n"
2987 << "J C Gonzalez, Jun 1998\n"
2988 << "##################################################\n\n"
2989 << flush ;
2990}
2991//!@}
2992
2993
2994//!-----------------------------------------------------------
2995// @name usage
2996//
2997// @desc show help
2998//
2999// @date Tue Dec 15 16:23:30 MET 1998
3000//------------------------------------------------------------
3001// @function
3002
3003//!@{
3004void
3005usage(void)
3006{
3007 present();
3008 cout << "\nusage ::\n\n"
3009 << "\t camera "
3010 << " [ -@ paramfile ] "
3011 << " [ -h ] "
3012 << "\n\n or \n\n"
3013 << "\t camera < paramfile"
3014 << "\n\n";
3015 exit(0);
3016}
3017//!@}
3018
3019
3020//!-----------------------------------------------------------
3021// @name log
3022//
3023// @desc function to send log information
3024//
3025// @var funct Name of the caller function
3026// @var fmt Format to be used (message)
3027// @var ... Other information to be shown
3028//
3029// @date Sat Jun 27 05:58:56 MET DST 1998
3030//------------------------------------------------------------
3031// @function
3032
3033//!@{
3034void
3035log(const char *funct, char *fmt, ...)
3036{
3037 va_list args;
3038
3039 // Display the name of the function that called error
3040 printf("[%s]: ", funct);
3041
3042 // Display the remainder of the message
3043 va_start(args, fmt);
3044 vprintf(fmt, args);
3045 va_end(args);
3046}
3047//!@}
3048
3049
3050//!-----------------------------------------------------------
3051// @name error
3052//
3053// @desc function to send an error message, and abort the program
3054//
3055// @var funct Name of the caller function
3056// @var fmt Format to be used (message)
3057// @var ... Other information to be shown
3058//
3059// @date Sat Jun 27 05:58:56 MET DST 1998
3060//------------------------------------------------------------
3061// @function
3062
3063//!@{
3064void
3065error(const char *funct, char *fmt, ...)
3066{
3067 va_list args;
3068
3069 // Display the name of the function that called error
3070 fprintf(stdout, "ERROR in %s: ", funct);
3071
3072 // Display the remainder of the message
3073 va_start(args, fmt);
3074 vfprintf(stdout, fmt, args);
3075 va_end(args);
3076
3077 perror(funct);
3078
3079 exit(1);
3080}
3081//!@}
3082
3083
3084//!-----------------------------------------------------------
3085// @name isA
3086//
3087// @desc returns TRUE(FALSE), if the flag is(is not) the given
3088//
3089// @var s1 String to be searched
3090// @var flag Flag to compare with string s1
3091// @return TRUE: both strings match; FALSE: oth.
3092//
3093// @date Wed Jul 8 15:25:39 MET DST 1998
3094//------------------------------------------------------------
3095// @function
3096
3097//!@{
3098int
3099isA( char * s1, const char * flag ) {
3100 return ( (strncmp((char *)s1, flag, SIZE_OF_FLAGS)==0) ? 1 : 0 );
3101}
3102//!@}
3103
3104
3105//!-----------------------------------------------------------
3106// @name read_QE
3107//
3108// @desc read QE data
3109//
3110// @date thu 5 17:59:57 CEST 2002
3111//------------------------------------------------------------
3112// @function
3113
3114//!@{
3115void
3116read_QE(char fname[256], int ict){
3117 ifstream qefile;
3118 char line[LINE_MAX_LENGTH];
3119 int i, j, icount;
3120 float qe;
3121
3122 //------------------------------------------------------------
3123 // second, pixels' QE
3124
3125 // try to open the file
3126
3127 log("read_QE", "Opening the file \"%s\" . . .\n", fname);
3128
3129 qefile.open( fname );
3130
3131 // if it is wrong or does not exist, exit
3132
3133 if ( qefile.bad() )
3134 error( "read_QE", "Cannot open \"%s\". Exiting.\n", fname );
3135
3136 // read file
3137
3138 log("read_QE", "Reading data . . .\n");
3139
3140 i=-1;
3141 icount = 0;
3142
3143 while ( ! qefile.eof() ) {
3144
3145 // get line from the file
3146
3147 qefile.getline(line, LINE_MAX_LENGTH);
3148
3149 // skip if comment
3150
3151 if ( *line == '#' )
3152 continue;
3153
3154 // if it is the first valid value, it is the number of QE data points
3155
3156 if ( i < 0 ) {
3157
3158 // get the number of datapoints
3159
3160 sscanf(line, "%d", &pointsQE[ict]);
3161
3162 // allocate memory for the table of QEs
3163
3164 QE[ict] = new float ** [ct_NPixels];
3165
3166 for ( i=0; i<ct_NPixels; ++i ) {
3167 QE[ict][i] = new float * [2];
3168 QE[ict][i][0] = new float[pointsQE[ict]];
3169 QE[ict][i][1] = new float[pointsQE[ict]];
3170 }
3171
3172 QElambda = new float [pointsQE[ict]];
3173
3174 for ( i=0; i<pointsQE[ict]; ++i ) {
3175 qefile.getline(line, LINE_MAX_LENGTH);
3176 sscanf(line, "%f", &QElambda[i]);
3177 }
3178
3179 i=0;
3180
3181 continue;
3182 }
3183
3184 // get the values (num-pixel, num-datapoint, QE-value)
3185
3186 if( sscanf(line, "%d %d %f", &i, &j, &qe) != 3 )
3187 break;
3188
3189 if ( (i < ct_NPixels) && (i > -1) &&
3190 ((j-1) < pointsQE[ict]) && ((j-1) > -1) ) {
3191 QE[ict][i][0][j-1] = QElambda[j-1];
3192 QE[ict][i][1][j-1] = qe;
3193 }
3194
3195 if ( i > ct_NPixels) break;
3196
3197 icount++;
3198
3199 }
3200
3201 if(icount/pointsQE[ict] < ct_NPixels){
3202 error( "read_QE", "The quantum efficiency file is faulty\n (found only %d pixels instead of %d).\n",
3203 icount/pointsQE[ict], ct_NPixels );
3204 }
3205
3206 // close file
3207
3208 qefile.close();
3209
3210 // test QE
3211
3212 for(icount=0; icount< ct_NPixels; icount++){
3213 for(i=0; i<pointsQE[ict]; i++){
3214 if( QE[ict][icount][0][i] < 100. || QE[ict][icount][0][i] > 1000. ||
3215 QE[ict][icount][1][i] < 0. || QE[ict][icount][1][i] > 100.){
3216 error( "read_QE", "The quantum efficiency file is faulty\n pixel %d, point %d is % f, %f\n",
3217 icount, i, QE[ict][icount][0][i], QE[ict][icount][1][i] );
3218 }
3219 }
3220 }
3221
3222 // end
3223
3224 log("read_QE", "Done.\n");
3225}
3226//!@}
3227
3228//!-----------------------------------------------------------
3229// @name read_WC
3230//
3231// @desc read WC data
3232//
3233// @date thu 5 17:59:57 CEST 2002
3234//------------------------------------------------------------
3235// @function
3236
3237//!@{
3238void
3239read_WC(void){
3240 ifstream wcfile;
3241 char line[LINE_MAX_LENGTH];
3242 int i;
3243
3244 //------------------------------------------------------------
3245 // Read Light Collection data
3246
3247 // try to open the file
3248
3249 log("read_WC", "Opening the file \"%s\" . . .\n", WC_FILE);
3250
3251 wcfile.open( WC_FILE );
3252
3253 // if it is wrong or does not exist, exit
3254
3255 if ( wcfile.bad() )
3256 error( "read_WC", "Cannot open \"%s\". Exiting.\n", WC_FILE );
3257
3258 // read file
3259
3260 log("read_WC", "Reading data . . .\n");
3261
3262 // get line from the file
3263
3264 do
3265 wcfile.getline(line, LINE_MAX_LENGTH);
3266 while (line[0] == '#');
3267
3268 // get the number of datapoints
3269
3270 sscanf(line, "%d", &pointsWC);
3271
3272 // allocate memory for the table of QEs
3273
3274 WC = new float * [2];
3275 WC[0] = new float[pointsWC];
3276 WC[1] = new float[pointsWC];
3277
3278 for ( i=0; i<pointsWC; ++i ) {
3279 wcfile.getline(line, LINE_MAX_LENGTH);
3280 sscanf(line, "%f %f", &WC[0][i], &WC[1][i]);
3281 }
3282
3283 //
3284 // Now read info for outer pixels
3285 //
3286 WC_outer = new float * [2];
3287 WC_outer[0] = new float[pointsWC];
3288 WC_outer[1] = new float[pointsWC];
3289
3290 do
3291 wcfile.getline(line, LINE_MAX_LENGTH);
3292 while (line[0] == '#');
3293
3294 if (wcfile.eof())
3295 {
3296 log("read_WC", "ERROR. Missing data for outer pixels in file \"%s\"...\n",WC_FILE);
3297 log("read_WC", "EXITING camera\n");
3298 exit(-1);
3299 }
3300
3301 sscanf(line, "%f %f", &WC_outer[0][0], &WC_outer[1][0]);
3302 for ( i=1; i<pointsWC; ++i ) {
3303 wcfile.getline(line, LINE_MAX_LENGTH);
3304 sscanf(line, "%f %f", &WC_outer[0][i], &WC_outer[1][i]);
3305 }
3306
3307 // close file
3308
3309 wcfile.close();
3310
3311 // read
3312
3313 log("read_WC", "Done.\n");
3314}
3315//!@}
3316
3317
3318//!-----------------------------------------------------------
3319// @name read_ascii
3320//
3321// @desc read ascii configuration files used by the reflector
3322//
3323// @date tue dec 10 17:14:10 CET 2002
3324//------------------------------------------------------------
3325// @function
3326
3327//!@{
3328void
3329read_ascii(FILE *sp, MMcConfigRunHeader *config)
3330{
3331 Float_t radius = -1.0;
3332 Float_t focal = -1.0;
3333 Float_t point = -1.0;
3334 Float_t spot = -1.0;
3335 Float_t camwidth = -1.0;
3336
3337 Int_t imir;
3338 Float_t f,sx,sy,x,y,z,thetan,phin,xn,yn,zn;
3339 Float_t dx,dy;
3340 Int_t nummir, numref;
3341 Float_t wav,ref;
3342
3343 Char_t token[40];
3344 Char_t line[511];
3345 Char_t flag;
3346
3347 while(1){
3348 if((flag=fgetc(sp))==EOF)
3349 break;
3350 if (flag == '\n') // skip empty lines
3351 continue;
3352
3353 fgets(&line[1],500,sp);
3354 line[0]=flag;
3355
3356 if ( strstr(line, "# reflectivity file") == line ) {
3357 while (strstr(line, "# number of datapoints") != line)
3358 fgets(line,500,sp);
3359
3360 fgets(line,500,sp);
3361 sscanf(line,"%i",&numref);
3362
3363 TArrayF wavarray(numref);
3364 TArrayF refarray(numref);
3365
3366 while (strstr(line, "# datapoints") != line)
3367 fgets(line,500,sp);
3368
3369 for(int i=0; i<numref;i++){
3370 fgets(line,500,sp);
3371 if (line[0] == '#')
3372 {
3373 i--;
3374 continue;
3375 }
3376 sscanf(line,"%f %f",&wav,&ref);
3377 wavarray[i]=wav;
3378 refarray[i]=ref;
3379 }
3380 for (int j=0; j<nummir;j++){
3381
3382 MGeomMirror &mirror = config->GetMirror(j);
3383 mirror.SetArraySize(numref);
3384 mirror.SetReflectivity(wavarray, refarray);
3385 }
3386 continue;
3387 }
3388 if (line[0]== '#')
3389 continue;
3390 if (strstr(line, "type") == line)
3391 continue;
3392 if (strstr(line, "focal_distance") == line){
3393 sscanf(line,"%s %f",token,&focal);
3394 continue;
3395 }
3396 if (strstr(line, "point_spread") == line){
3397 sscanf(line,"%s %f",token,&point);
3398 continue;
3399 }
3400 if (strstr(line, "black_spot") == line){
3401 sscanf(line,"%s %f",token,&spot);
3402 continue;
3403 }
3404 if (strstr(line, "camera_width") == line){
3405 sscanf(line,"%s %f",token,&camwidth);
3406 continue;
3407 }
3408 //
3409 // Skip obsolete magic.def entries:
3410 //
3411 if (strstr(line, "n_pixels") == line)
3412 continue;
3413 if (strstr(line, "pixel_width") == line)
3414 continue;
3415 if (strstr(line, "n_centralpixels") == line)
3416 continue;
3417 if (strstr(line, "n_gappixels") == line)
3418 continue;
3419
3420 if (strstr(line, "n_mirrors") == line){
3421 sscanf(line,"%s %i",token,&nummir);
3422 config->InitSizeMirror(nummir);
3423 continue;
3424 }
3425 if (strstr(line, "r_mirror") == line){
3426 sscanf(line,"%s %f",token,&radius);
3427 continue;
3428 }
3429 if (strstr(line, "define_mirrors") == line){
3430 for(int i=0;i<nummir;i++){
3431 fgets(line,500,sp);
3432 sscanf(line,"%i %f %f %f %f %f %f %f %f %f %f %f",
3433 &imir,&f,&sx,&sy,&x,&y,&z,&thetan,&phin,&xn,&yn,&zn);
3434 config->AddMirror(i);
3435 MGeomMirror &mirror = config->GetMirror(i);
3436 mirror.SetMirrorContent(imir,f,sx,sy,x,y,z,thetan,phin,xn,yn,zn);
3437 }
3438 fgets(line,500,sp);
3439
3440 while ( ! strstr(line, "axis deviation"))
3441 fgets(line,500,sp);
3442
3443 for(int i=0;i<nummir;i++){
3444 fgets(line,500,sp);
3445 if (line[0] == '#')
3446 {
3447 i--;
3448 continue;
3449 }
3450 sscanf(line,"%f %f",&dx,&dy);
3451 MGeomMirror &mirror = config->GetMirror(i);
3452 mirror.SetMirrorDeviations(dx,dy);
3453 }
3454 continue;
3455 }
3456 }
3457 config->SetMagicDef(radius, focal, point, spot, camwidth);
3458}
3459
3460
3461//!-----------------------------------------------------------
3462// @name igen_pixel_coordinates
3463//
3464// @desc generate the pixel center coordinates
3465//
3466// @var *pcam structure camera containing all the
3467// camera information
3468// @return total number of pixels
3469//
3470// DP
3471//
3472// @date Thu Oct 14 10:41:03 CEST 1999
3473//------------------------------------------------------------
3474// @function
3475
3476//!@{
3477/******** igen_pixel_coordinates() *********************************/
3478
3479int igen_pixel_coordinates(struct camera *pcam) {
3480 /* generate pixel coordinates, return value is number of pixels */
3481
3482 int i, itot_inside_ring, iN, in, ipixno, iring_no, ipix_in_ring, isegment;
3483 float fsegment_fract;
3484 double dtsize;
3485 double dhsize;
3486 double dpsize;
3487 double dxfirst_pix;
3488 double dyfirst_pix;
3489 double ddxseg1, ddxseg2, ddxseg3, ddxseg4, ddxseg5;
3490 double ddyseg1, ddyseg2, ddyseg3, ddyseg4, ddyseg5;
3491
3492
3493 double dstartx, dstarty; /* for the gap pixels and outer pixels */
3494 int j, nrow;
3495
3496 dpsize = pcam->dpixdiameter_cm;
3497 dtsize = dpsize * sqrt(3.) / 2.;
3498 dhsize = dpsize / 2.;
3499
3500 /* Loop over central pixels to generate co-ordinates */
3501
3502 for(ipixno=1; ipixno <= pcam->inumcentralpixels; ipixno++){
3503
3504 /* Initialise variables. The central pixel = ipixno 1 in ring iring_no 0 */
3505
3506 pcam->dpixsizefactor[ipixno-1] = 1.;
3507
3508 in = 0;
3509
3510 i = 0;
3511 itot_inside_ring = 0;
3512 iring_no = 0;
3513
3514 /* Calculate the number of pixels out to and including the ring containing pixel number */
3515 /* ipixno e.g. for pixel number 17 in ring number 2 itot_inside_ring = 19 */
3516
3517 while (itot_inside_ring == 0){
3518
3519 iN = 3*(i*(i+1)) + 1;
3520
3521 if (ipixno <= iN){
3522 iring_no = i;
3523 itot_inside_ring = iN;
3524 }
3525
3526 i++;
3527 }
3528
3529
3530 /* Find the number of pixels which make up ring number iring_no e.g. ipix_in_ring = 6 for ring 1 */
3531
3532 ipix_in_ring = 0;
3533 for (i = 0; i < iring_no; ++i){
3534
3535 ipix_in_ring = ipix_in_ring + 6;
3536 }
3537
3538 /* The camera is viewed as 6 radial segments ("pie slices"). Knowing the number of pixels in its */
3539 /* ring calculate which segment the pixel ipixno is in. Then find how far across this segment it is */
3540 /* as a fraction of the number of pixels in this sixth of the ring (ask SMB). */
3541
3542 isegment = 0;
3543 fsegment_fract = 0.;
3544 if (iring_no > 0) {
3545
3546 isegment = (int)((ipixno - itot_inside_ring + ipix_in_ring - 0.5) / iring_no + 1); /* integer division ! numbering starts at 1 */
3547
3548 fsegment_fract = (ipixno - (itot_inside_ring - ipix_in_ring)) - ((isegment-1)*iring_no) - 1 ;
3549
3550 }
3551
3552 /* the first pixel in each ring lies on the positive x axis at a distance dxfirst_pix = iring_no * the */
3553 /* pixel width (flat to flat) dpsize. */
3554
3555 dxfirst_pix = dpsize*iring_no;
3556 dyfirst_pix = 0.;
3557
3558 /* the vector between the first and last pixels in a segment n is (ddxsegn, ddysegn) */
3559
3560 ddxseg1 = - dhsize*iring_no;
3561 ddyseg1 = dtsize*iring_no;
3562 ddxseg2 = -dpsize*iring_no;
3563 ddyseg2 = 0.;
3564 ddxseg3 = ddxseg1;
3565 ddyseg3 = -ddyseg1;
3566 ddxseg4 = -ddxseg1;
3567 ddyseg4 = -ddyseg1;
3568 ddxseg5 = -ddxseg2;
3569 ddyseg5 = 0.;
3570
3571 /* to find the position of pixel ipixno take the position of the first pixel in the ring and move */
3572 /* anti-clockwise around the ring by adding the segment to segment vectors. */
3573
3574 switch (isegment) {
3575
3576 case 0:
3577
3578 pcam->dxc[ipixno-1] = 0.;
3579 pcam->dyc[ipixno-1] = 0.;
3580
3581 case 1:
3582 pcam->dxc[ipixno-1] = dxfirst_pix - dhsize*fsegment_fract;
3583 pcam->dyc[ipixno-1] = dyfirst_pix + dtsize*fsegment_fract;
3584
3585 break;
3586
3587 case 2:
3588
3589 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 - dpsize*fsegment_fract;
3590 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + 0.;
3591
3592 break;
3593
3594 case 3:
3595
3596 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 - dhsize*fsegment_fract;
3597 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 - dtsize*fsegment_fract;
3598
3599 break;
3600
3601 case 4:
3602
3603 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + dhsize*fsegment_fract;
3604 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 - dtsize*fsegment_fract;
3605
3606 break;
3607
3608 case 5:
3609
3610 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + ddxseg4 + dpsize*fsegment_fract;
3611 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 + ddyseg4 + 0.;
3612
3613 break;
3614
3615 case 6:
3616
3617 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + ddxseg4 + ddxseg5 + dhsize*fsegment_fract;
3618 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 + ddyseg4 + ddyseg5 + dtsize*fsegment_fract;
3619
3620 break;
3621
3622 default:
3623
3624 fprintf(stderr, "ERROR: problem in coordinate generation for pixel %d\n", ipixno);
3625 return(0);
3626
3627 } /* end switch */
3628
3629 } /* end for */
3630
3631 dstartx = pcam->dxc[pcam->inumcentralpixels - 1] + dhsize;
3632 dstarty = pcam->dyc[pcam->inumcentralpixels - 1] + dtsize;
3633
3634 if(pcam->inumgappixels > 0){ /* generate the positions of the gap pixels */
3635
3636 j = pcam->inumcentralpixels;
3637
3638 for(i=0; i<pcam->inumgappixels; i=i+6){
3639 pcam->dxc[j + i ] = dstartx + 2. * (i/6 + 1) * dpsize;
3640 pcam->dyc[j + i ] = dstarty;
3641 pcam->dpixsizefactor[j + i] = 1.;
3642 pcam->dxc[j + i + 1] = pcam->dxc[j + i ] / 2.;
3643 pcam->dyc[j + i + 1] = sqrt(3.) * pcam->dxc[j + i + 1];
3644 pcam->dpixsizefactor[j + i + 1] = 1.;
3645 pcam->dxc[j + i + 2] = - pcam->dxc[j + i + 1];
3646 pcam->dyc[j + i + 2] = pcam->dyc[j + i + 1];
3647 pcam->dpixsizefactor[j + i+ 2] = 1.;
3648 pcam->dxc[j + i + 3] = - pcam->dxc[j + i];
3649 pcam->dyc[j + i + 3] = dstarty;
3650 pcam->dpixsizefactor[j + i+ 3] = 1.;
3651 pcam->dxc[j + i + 4] = pcam->dxc[j + i + 2];
3652 pcam->dyc[j + i + 4] = - pcam->dyc[j + i + 2];
3653 pcam->dpixsizefactor[j + i+ 4] = 1.;
3654 pcam->dxc[j + i + 5] = pcam->dxc[j + i + 1];
3655 pcam->dyc[j + i + 5] = - pcam->dyc[j + i + 1];
3656 pcam->dpixsizefactor[j + i + 5] = 1.;
3657 } /* end for */
3658 } /* end if */
3659
3660 /* generate positions of the outer pixels */
3661
3662 if( pcam->inumbigpixels > 0 ){
3663
3664 j = pcam->inumcentralpixels + pcam->inumgappixels;
3665
3666 for(i=0; i<pcam->inumbigpixels; i++){
3667 pcam->dpixsizefactor[j + i] = 2.;
3668 }
3669
3670 in = 0;
3671
3672 nrow = (int) ceil(dstartx / 2. / dpsize);
3673
3674 while(in < pcam->inumbigpixels){
3675
3676 pcam->dxc[j + in] = dstartx + dpsize;
3677 pcam->dyc[j + in] = dstarty + 2 * dpsize / sqrt(3.);
3678 pcam->dxc[j + in + nrow] = dstartx / 2. - dpsize / 2.;
3679 pcam->dyc[j + in + nrow] = sqrt(3.)/2. * dstartx + 2.5 * dpsize/sqrt(3.);
3680 pcam->dxc[j + in + 3 * nrow - 1] = - pcam->dxc[j + in];
3681 pcam->dyc[j + in + 3 * nrow - 1] = pcam->dyc[j + in];
3682 pcam->dxc[j + in + 3 * nrow] = - pcam->dxc[j + in];
3683 pcam->dyc[j + in + 3 * nrow] = - pcam->dyc[j + in];
3684 pcam->dxc[j + in + 5 * nrow - 1] = pcam->dxc[j + in + nrow];
3685 pcam->dyc[j + in + 5 * nrow - 1] = - pcam->dyc[j + in + nrow];
3686 pcam->dxc[j + in + 6 * nrow - 1] = pcam->dxc[j + in];
3687 pcam->dyc[j + in + 6 * nrow - 1] = - pcam->dyc[j + in];
3688 for(i=1; i<nrow; i++){
3689 pcam->dxc[j + in + i] = pcam->dxc[j + in] - i * dpsize;
3690 pcam->dyc[j + in + i] = pcam->dyc[j + in] + i * dpsize * sqrt(3.);
3691 pcam->dxc[j + in + i + nrow] = pcam->dxc[j + in + nrow] - i * 2 * dpsize;
3692 pcam->dyc[j + in + i + nrow] = pcam->dyc[j + in + nrow];
3693 pcam->dxc[j + in + 3 * nrow - 1 - i] = - pcam->dxc[j + in + i];
3694 pcam->dyc[j + in + 3 * nrow - 1- i] = pcam->dyc[j + in + i];
3695 pcam->dxc[j + in + i + 3 * nrow] = - pcam->dxc[j + in + i];
3696 pcam->dyc[j + in + i + 3 * nrow] = - pcam->dyc[j + in + i];
3697 pcam->dxc[j + in + 5 * nrow - 1 - i] = pcam->dxc[j + in + i + nrow];
3698 pcam->dyc[j + in + 5 * nrow - 1 - i] = - pcam->dyc[j + in + i + nrow];
3699 pcam->dxc[j + in + 6 * nrow - 1 - i] = pcam->dxc[j + in + i];
3700 pcam->dyc[j + in + 6 * nrow - 1 - i] = - pcam->dyc[j + in + i];
3701 }
3702 in = in + 6 * nrow;
3703 dstartx = dstartx + 2. * dpsize;
3704 nrow = nrow + 1;
3705 } /* end while */
3706
3707 } /* end if */
3708
3709 return(pcam->inumpixels);
3710
3711}
3712//!@}
3713
3714//!-----------------------------------------------------------
3715// @name bpoint_is_in_pix
3716//
3717// @desc check if a point (x,y) in camera coordinates is inside a given pixel
3718//
3719// @var *pcam structure camera containing all the
3720// camera information
3721// @var dx, dy point coordinates in centimeters
3722// @var ipixnum pixel number (starting at 0)
3723// @return TRUE if the point is inside the pixel, FALSE otherwise
3724//
3725// DP
3726//
3727// @date Thu Oct 14 16:59:04 CEST 1999
3728//------------------------------------------------------------
3729// @function
3730
3731//!@{
3732
3733/******** bpoint_is_in_pix() ***************************************/
3734
3735#define sqrt13 0.577350269 // = 1./sqrt(3.)
3736#define sqrt3 1.732050807 // = sqrt(3.)
3737
3738int bpoint_is_in_pix(double dx, double dy, MGeomCam *pgeomcam)
3739{
3740 /* return TRUE if point (dx, dy) is in pixel number ipixnum, else return FALSE (use camera coordinate system) */
3741 /* the pixel is assumed to be a "closed set" */
3742
3743 /*
3744 a = length of one of the edges of one pixel,
3745 b = half the width of one pixel
3746 */
3747
3748 const int numN = pgeomcam->GetNumPixels();
3749
3750 for (int i=0; i<numN; i++)
3751 {
3752 MGeomPix &pixel = (*pgeomcam)[i];
3753 const double b = pixel.GetD()/2;
3754 const double a = pixel.GetD()/sqrt3;
3755
3756 const double xx = dx - pixel.GetX();
3757 const double yy = dy - pixel.GetY();
3758
3759 if(((-b <= xx) && (xx <= 0.) && ((-sqrt13 * xx - a) <= yy) && (yy <= ( sqrt13 * xx + a))) ||
3760 ((0. < xx) && (xx <= b ) && (( sqrt13 * xx - a) <= yy) && (yy <= (-sqrt13 * xx + a))) ){
3761
3762 return i; // inside i
3763 }
3764
3765 // return -1; // outside
3766 }
3767
3768 return -1; // outside
3769}
3770
3771//!@}
3772
3773//------------------------------------------------------------
3774// @name dist_r_P
3775//
3776// @desc distance straight line r - point P
3777//
3778// @date Sat Jun 27 05:58:56 MET DST 1998
3779// @function @code
3780//------------------------------------------------------------
3781// dist_r_P
3782//
3783// distance straight line r (x+t*l, y+t*m, z+t*n) to point P(a,b,c)
3784//
3785// We assume that vector (l, m, n) is normalized l^2+m^2+n^2 = 1
3786//------------------------------------------------------------
3787
3788float
3789dist_r_P(float a, float b, float c,
3790 float l, float m, float n,
3791 float x, float y, float z)
3792{
3793 return (
3794 sqrt((SQR((a-x)*m-(b-y)*l) +
3795 SQR((b-y)*n-(c-z)*m) +
3796 SQR((c-z)*l-(a-x)*n)))
3797 );
3798}
3799
3800//------------------------------------------------------------
3801// @name check_reflector_file
3802//
3803// @desc check if a given reflector file has the right signature
3804// @desc return TRUE or FALSE
3805//
3806// @date Mon Feb 14 16:44:21 CET 2000
3807// @function @code
3808//------------------------------------------------------------
3809
3810int check_reflector_file(FILE *infile){
3811
3812 char sign[20]; // auxiliary variable
3813
3814 strcpy(sign, REFL_SIGNATURE_B);
3815
3816 fread( (char *)sign, strlen(REFL_SIGNATURE_B), 1, infile);
3817 if (strcmp(sign, REFL_SIGNATURE_A) == 0){
3818 fread( (char *)sign, 1, 1, infile);
3819 return 4;
3820 }
3821 else if (strcmp(sign, REFL_SIGNATURE_B) == 0){
3822 fread( (char *)sign, 1, 1, infile);
3823 return 5;
3824 }
3825 else if (strcmp(sign, REFL_SIGNATURE_C) == 0){
3826 // An empty bin has been removed and therefore we do not need to rezd it.
3827 return 6;
3828 }
3829 else {
3830 cout << "ERROR: Signature of .rfl file is not correct\n";
3831 cout << '"' << sign << '"' << '\n';
3832 cout << "should be: " << REFL_SIGNATURE_A <<" or "<< REFL_SIGNATURE_B <<" or " << REFL_SIGNATURE_C <<" or "<< '\n';
3833 return(FALSE);
3834 }
3835
3836
3837}
3838
3839//------------------------------------------------------------
3840// @name lin_interpol
3841//
3842// @desc interpolate linearly between two points returning the
3843// @desc y-value of the result
3844//
3845// @date Thu Feb 17 11:31:32 CET 2000
3846// @function @code
3847//------------------------------------------------------------
3848
3849float lin_interpol( float x1, float y1, float x2, float y2, float x){
3850
3851 if( (x2 - x1)<=0. ){ // avoid division by zero, return average
3852 cout << "Warning: lin_interpol was asked to interpolate between two points with x1>=x2.\n";
3853 return((y1+y2)/2.);
3854 }
3855 else{ // note: the check whether x1 < x < x2 is omitted for speed reasons
3856 return((float) (y1 + (y2-y1)/(x2-x1)*(x-x1)) );
3857 }
3858}
3859
3860//------------------------------------------------------------
3861// @name size_rotated
3862//
3863// @desc It rotates the NSB
3864//
3865// @date Tue Jan 7 17:09:25 CET 2003
3866// @function @code
3867//------------------------------------------------------------
3868
3869int size_rotated(
3870 float *rotated,
3871 float *nsb,
3872 float rho)
3873{
3874 int r=0;
3875 float size_rotated;
3876 float Num_Pixels;
3877 float PixNum=0;
3878 float rho_pixel;
3879 int j=0;
3880 int k=0;
3881
3882 for(int i=1; i<iMAXNUMPIX;i++){
3883// Substituir per Int_t radius[iMAXNUMPIX]={0,1,1,1,1,1,1,2,2,2,2, ...}
3884 Num_Pixels=0;
3885 for (int ii=1; ii<17;ii++){
3886 if (Num_Pixels >= i){
3887 r=ii-1;
3888 break;
3889 }
3890
3891
3892
3893 if (ii<12){
3894 Num_Pixels+=ii*6;
3895 PixNum=6*ii;
3896 // size_rotated = (360/PixNum);
3897 //rho_pixel = rho/size_rotated;
3898 }
3899
3900
3901 else
3902 {
3903 Num_Pixels+=(ii-6)*6;
3904 PixNum=(ii-6)*6;
3905 // size_rotated = (360/PixNum);
3906 // rho_pixel = rho/size_rotated;
3907 }
3908 }
3909
3910
3911
3912 size_rotated = (360/PixNum);
3913 rho_pixel = rho/size_rotated;
3914
3915 //Buscar j i k que no canvin de r!!!
3916
3917 j=i-int(rho_pixel);
3918
3919 //cout<<"j inicial "<<j<<endl;
3920 int MINPIXinner[13]= {0,1,7,19,37,61,91,127,169,217,271,331,397};
3921 int MINPIXouter[5]={397,433,475,523,578};
3922
3923 if( r<12 ){
3924 if (j < MINPIXinner[r])
3925 {
3926 j = i+6 * r - int(rho_pixel);
3927 }
3928
3929 k=j-1;
3930 if (k < MINPIXinner[r])
3931 {
3932 k = MINPIXinner[r+1]-1;
3933 }
3934 }
3935 if( r > 11 && r < 16){
3936 if (j < MINPIXouter[r-12])
3937 {
3938 j = i + (r - 6) * 6 - int(rho_pixel);
3939
3940 }
3941
3942 k=j-1;
3943 if ( k < MINPIXouter[r-12])
3944 {
3945 k = MINPIXouter[r-11] - 1;
3946 }
3947 }
3948 rotated[i]= (1 - ((rho_pixel)-floor(rho_pixel))) * nsb[j] + (rho_pixel-floor(rho_pixel)) * nsb[k];
3949 }
3950 return (int(rho_pixel));
3951
3952}
3953
3954
3955//------------------------------------------------------------
3956// @name produce_phes
3957//
3958// @desc read the photons of an event, pixelize them and simulate QE
3959// @desc return various statistics and the array of Photoelectrons
3960//
3961// @date Mon Feb 14 16:44:21 CET 2000
3962// @function @code
3963//------------------------------------------------------------
3964
3965int produce_phes( FILE *sp, // the input file
3966 class MGeomCam *camgeom, // the camera layout
3967 float minwl_nm, // the minimum accepted wavelength
3968 float maxwl_nm, // the maximum accepted wavelength
3969 class MTrigger *trigger, // the generated phes
3970 class MFadc *fadc,
3971 int *itotnphe, // total number of produced photoelectrons
3972 float *nphe, // number of photoelectrons in each pixel
3973 int *incph, // total number of cph within camera
3974 float *tmin_ns, // minimum arrival time of all phes
3975 float *tmax_ns, // maximum arrival time of all phes
3976 int ict, // Telescope that is being analised to get the right QE.
3977 float mirror_fraction // Fraction of total mirror really present
3978 ){
3979
3980 static uint i;
3981 static int k, ipixnum;
3982 static float cx, cy, wl, qe;
3983 static float cw;
3984 static MCCphoton photon;
3985 static float **qept;
3986 static char flag[SIZE_OF_FLAGS + 1];
3987 static float radius_mm;
3988
3989 Float_t t;
3990
3991 // reset variables
3992
3993 for ( i=0; i<camgeom->GetNumPixels(); ++i )
3994 nphe[i] = 0.0;
3995
3996
3997 *itotnphe = 0;
3998 *incph = 0;
3999
4000 radius_mm = camgeom->GetMaxRadius();
4001
4002 TRandom random;
4003 random.SetSeed((Int_t)(get_seeds(0)*get_seeds(1)));
4004
4005 float C1, C2, C3, rho;
4006
4007
4008 //- - - - - - - - - - - - - - - - - - - - - - - - -
4009 // read photons and "map" them into the pixels
4010 //--------------------------------------------------
4011
4012 // initialize CPhoton
4013
4014 photon.fill(0., 0., 0., 0., 0., 0., 0., 0.);
4015
4016 // read the photons data
4017
4018 // loop over the photons
4019
4020 while (1) {
4021
4022 photon.read(sp);
4023 photon.get_flag(flag);
4024
4025 if (isA( flag, FLAG_END_OF_EVENT ))
4026 {
4027 fseek (sp, SIZE_OF_FLAGS-photon.mysize(), SEEK_CUR);
4028 break;
4029 }
4030
4031 // Check if photon is inside trigger time range
4032
4033 t = photon.get_t() ;
4034
4035 if (t-*tmin_ns>TOTAL_TRIGGER_TIME) {
4036 continue;
4037 }
4038
4039 //
4040 // Account for possibly missing mirrors, or lower reflectivity...
4041 // mirror_fraction is the fraction of the total mirror really
4042 // working.
4043 //
4044 if (mirror_fraction < 1.)
4045 if (RandomNumber > mirror_fraction)
4046 continue;
4047
4048 //
4049 // Pixelization
4050 //
4051
4052 cx = photon.get_x();
4053 cy = photon.get_y();
4054
4055 if (Spotsigma > 0.)
4056 {
4057 cx += random.Gaus(0.,Spot_x);
4058 cy += random.Gaus(0.,Spot_y);
4059 }
4060 if (missPointing > 0.)
4061 {
4062 // We should take intot acount the rotation of the FoV
4063 C1 = 0.48 * sin(Zenith) - 0.87 * cos(Zenith) * cos(Azimutal);
4064 C3 = (0.87 * cos(Zenith) - 0.48 * sin(Zenith) * cos(Azimutal));
4065 C2 = sqrt( sin(Zenith) * sin(Zenith) * sin(Azimutal) * sin(Azimutal) + C3 * C3 );
4066 rho = acos( C1/C2 );
4067 rho=(sin(Azimutal)<0 ? (2 * 3.14159 - rho) : rho);
4068
4069 rho = rho*180/3.14159;
4070
4071 cx += (missP_x*cos(rho)-missP_y*sin(rho))/(10*camgeom->GetConvMm2Deg());
4072 cy += (missP_x*sin(rho)+missP_y*cos(rho))/(10*camgeom->GetConvMm2Deg());
4073 }
4074
4075
4076 // get wavelength
4077
4078 wl = photon.get_wl();
4079
4080 // cout << "wl " << wl << " radius " << sqrt(cx*cx + cy*cy) << "\n";
4081
4082 // check if photon has valid wavelength and is inside outermost camera radius
4083
4084 if( (wl > maxwl_nm) || (wl < minwl_nm) || (sqrt(cx*cx + cy*cy)*10 > radius_mm ) ){
4085 continue;
4086
4087 }
4088
4089 ipixnum = bpoint_is_in_pix(cx*10, cy*10, camgeom);
4090
4091 // -1 = the photon is in none of the pixels
4092 // 0 = the phton is in the central pixel, which is not used for trigger
4093 if (ipixnum==-1 || ipixnum==0) {
4094 continue;
4095 }
4096
4097 // AM changed meaning of incph: before it was all photons read from
4098 // reflector file, now only those within a valid pixel:
4099 //
4100 // increase number of photons
4101 (*incph)++;
4102
4103 //+++
4104 // QE simulation
4105 //---
4106
4107 // set pointer to the QE table of the relevant pixel
4108
4109 qept = (float **)QE[ict][ipixnum];
4110
4111 // check if wl is inside table; outside the table, QE is assumed to be zero
4112
4113 if((wl < qept[0][0]) || (wl > qept[0][pointsQE[ict]-1])){
4114 continue;
4115
4116 }
4117
4118 // find data point in the QE table (-> k)
4119
4120 k = 1; // start at 1 because the condition was already tested for 0
4121 while (k < pointsQE[ict]-1 && qept[0][k] < wl){
4122 k++;
4123 }
4124
4125 // calculate the qe value between 0. and 1.
4126
4127 qe = lin_interpol(qept[0][k-1], qept[1][k-1], qept[0][k], qept[1][k], wl) / 100.0;
4128
4129 //
4130 // Apply incient angular correction due to Light Guides, plexiglas,
4131 // 1st dynode collection efficiency, double crossings... etc.
4132 // This information is contained in the file Data/LightCollection.dat
4133 //
4134 cw=photon.get_phi()*180./3.14159265;
4135
4136 // find data point in the WC table (-> k)
4137
4138 if ( camgeom->GetPixRatio(ipixnum) < 1.) // => Pixel is outer pixel
4139 {
4140 k = 0;
4141 while (k < pointsWC-1 && WC_outer[0][k] < cw)
4142 k++;
4143 // correct the qe with WC data.
4144 qe = qe*lin_interpol(WC_outer[0][k-1], WC_outer[1][k-1],
4145 WC_outer[0][k], WC_outer[1][k], cw);
4146 }
4147
4148 else // => Pixel is inner pixel
4149 {
4150 k = 0;
4151 while (k < pointsWC-1 && WC[0][k] < cw)
4152 k++;
4153 // correct the qe with WC data.
4154 qe = qe*lin_interpol(WC[0][k-1], WC[1][k-1], WC[0][k], WC[1][k], cw);
4155 }
4156
4157
4158 // if random > quantum efficiency, reject it
4159
4160 if ( (RandomNumber) > qe ) {
4161 continue;
4162 }
4163
4164 //+++
4165 // The photon has produced a photo electron
4166 //---
4167
4168 // cout << " accepted\n";
4169
4170 // increment the number of photoelectrons in the relevant pixel
4171
4172 nphe[ipixnum] += 1.0;
4173
4174
4175 // store the new photoelectron
4176
4177 fadc->Fill(ipixnum,(t-*tmin_ns) ,
4178 trigger->FillShow(ipixnum,t-*tmin_ns),
4179 !((*camgeom)[ipixnum].GetD()>(*camgeom)[0].GetD()));
4180
4181 *itotnphe += 1;
4182 }
4183
4184 return(0);
4185
4186}
4187
4188
4189//------------------------------------------------------------
4190// @name produce_nsbrates
4191//
4192// @desc read the starfield file, call produce_phes on it in,
4193// @desc different wavebands, calculate the nsbrates
4194//
4195// @date Mon Feb 14 16:44:21 CET 2000
4196// @function @code
4197//------------------------------------------------------------
4198
4199int produce_nsbrates( char *iname, // the starfield input file name
4200 MGeomCam *camgeom, // camera layout
4201 float **rate_phepns,
4202 // the product of this function:
4203 // the NSB rates in phe/ns for each pixel
4204 int ict,
4205 float mirror_fraction)
4206{
4207 uint i, j; // counters
4208 int k, ii; // counters
4209
4210 static float wl_nm[iNUMWAVEBANDS + 1] = { WAVEBANDBOUND1,
4211 WAVEBANDBOUND2,
4212 WAVEBANDBOUND3,
4213 WAVEBANDBOUND4,
4214 WAVEBANDBOUND5,
4215 WAVEBANDBOUND6 };
4216
4217 FILE *infile; // the input file
4218 fpos_t fileposition; // marker on the input file
4219 static char cflag[SIZE_OF_FLAGS + 1]; // auxiliary variable
4220 static MCEventHeader evth; // the event header
4221 static MCEventHeader evth_2; // the event header
4222 static float nphe[iMAXNUMPIX]; // the number of photoelectrons in each pixel
4223 int reflector_file_version;
4224 int itnphe; // total number of produced photoelectrons
4225 int itotnphe; // total number of produced photoelectrons after averaging
4226 int incph; // total number of cph read
4227 float tmin_ns; // minimum arrival time of all phes
4228 float tmax_ns; // maximum arrival time of all phes
4229 float integtime_ns; // integration time from the starfield generator
4230 char flag_new[4];
4231
4232
4233 if (strlen(iname) == 0)
4234 {
4235 log( SIGNATURE, "No starfield input file has been provided.\n");
4236 return (0);
4237 }
4238 else // check if the starfield input file exists and open it
4239 {
4240 log(SIGNATURE, "Opening starfield input \"rfl\" file %s\n", iname );
4241 infile = fopen( iname, "r" );
4242
4243 if ( infile == NULL )
4244 {
4245 log( SIGNATURE, "ERROR! Cannot open starfield input file: %s\n", iname );
4246 exit(-1);
4247 }
4248 }
4249
4250
4251 // get signature, and check it
4252
4253 if((reflector_file_version=check_reflector_file( infile ))==FALSE){
4254 exit(1);
4255 }
4256
4257 // Instance of MTrigger and MFadc; needed here only as dummies for
4258 // a call to produce_phes (see below).
4259 // 15/09/2004, A. Moralejo, changed "trigger" and "flashadc" to
4260 // pointers, the former static allocation caused memory problems and
4261 // segmentation fault in some systems.
4262
4263 MTrigger* trigger = new MTrigger(camgeom->GetNumPixels(),camgeom,
4264 Trigger_gate_length,
4265 Trigger_overlaping_time,
4266 Trigger_response_ampl,
4267 Trigger_response_fwhm);
4268
4269 MFadc* flashadc = new MFadc(camgeom->GetNumPixels(),
4270 FADC_shape,
4271 FADC_response_integ,FADC_response_fwhm,
4272 FADC_shape_out,
4273 FADC_resp_integ_out,FADC_resp_fwhm_out,
4274 get_trig_delay(),
4275 FADC_slices_per_ns,
4276 FADC_slices_written);
4277
4278 // initialize flag
4279 strcpy( cflag, " \0" );
4280
4281 // get flag
4282
4283 fread( cflag, SIZE_OF_FLAGS, 1, infile );
4284
4285 if ( ! feof(infile)){
4286
4287 // reading .rfl file
4288
4289 if(!isA( cflag, FLAG_START_OF_RUN )){
4290 error( SIGNATURE, "Expected start of run flag, but found: %s\n", cflag );
4291 }
4292 else { // found start of run
4293
4294 if (reflector_file_version > 5){
4295
4296 fread( flag_new, 4, 1, infile );
4297
4298 if(!isA( flag_new, FLAG_START_OF_HEADER)){
4299
4300 // We break the main loop
4301 cout<<"Warning: Expected start of run header flag, but found:"<<flag_new<<endl;
4302 cout<<" We assume no Star Light"<<endl;
4303 return(0);
4304 }
4305
4306 Float_t flag_temp[SIZE_OF_MCRUNHEADER];
4307
4308 fread( flag_temp, (SIZE_OF_MCRUNHEADER)*sizeof(float), 1, infile );
4309
4310 }
4311
4312 fread( cflag, SIZE_OF_FLAGS, 1, infile );
4313
4314 if( isA( cflag, FLAG_START_OF_EVENT )){ // there is a event
4315 fread( flag_new, 4, 1, infile );
4316
4317 if(!isA( flag_new, FLAG_EVENT_HEADER)){
4318
4319 // We break while events loop
4320 cout<<"Warning: Expected start of event header flag, but found:"<<flag_new<<endl;
4321 cout<<" We assume no light from Stars"<<endl;
4322 return(0);
4323 }
4324
4325 // get MCEventHeader
4326
4327 if (reflector_file_version<6)
4328 // fread( (char*)&evth, evth.mysize(), 1, infile );
4329 evth.read(infile);
4330 else
4331 // fread( (char*)&evth_2, evth_2.mysize(), 1, infile );
4332 evth_2.read(infile);
4333
4334 if (reflector_file_version<6)
4335 integtime_ns = evth.get_energy();
4336 else
4337 integtime_ns = evth_2.get_energy();
4338
4339 // memorize where we are in the file
4340
4341 if (fgetpos( infile, &fileposition ) != 0){
4342 error( SIGNATURE, "Cannot position in file ...\n");
4343 }
4344
4345 // loop over the wavebands
4346
4347 for(i=0; i<iNUMWAVEBANDS; i++){
4348
4349 // initialize the rate array
4350
4351 for(j = 0; j<camgeom->GetNumPixels(); j++){ // loop over pixels
4352 rate_phepns[j][i] = 0.;
4353 }
4354
4355 itotnphe = 0;
4356
4357 // read the photons and produce the photoelectrons
4358 // - in order to average over the QE simulation, call the
4359 // production function iNUMNSBPRODCALLS times
4360
4361 for(ii=0; ii<iNUMNSBPRODCALLS; ii++){
4362
4363 // position the file pointer to the beginning of the photons
4364
4365 fsetpos( infile, &fileposition);
4366
4367 // produce photoelectrons
4368
4369 k = produce_phes( infile,
4370 camgeom,
4371 wl_nm[i],
4372 wl_nm[i+1],
4373 trigger, // this is a dummy here
4374 flashadc, // this is a dummy here
4375 &itnphe,
4376 nphe, // we want this!
4377 &incph,
4378 &tmin_ns,
4379 &tmax_ns,
4380 0,
4381 mirror_fraction); // photons from starfield
4382
4383 if( k != 0 ){ // non-zero returnvalue means error
4384 cout << "Exiting.\n";
4385 exit(1);
4386 }
4387
4388 for(j = 0; j<camgeom->GetNumPixels(); j++){ // loop over pixels
4389 rate_phepns[j][i] += nphe[j]/integtime_ns/(float)iNUMNSBPRODCALLS;
4390 }
4391
4392 itotnphe += itnphe;
4393
4394 } // end for(ii=0 ...
4395
4396 fprintf(stdout, "Starfield, %6f - %6f nm: %d photoelectrons for %6f ns integration time\n",
4397 wl_nm[i], wl_nm[i+1], itotnphe/iNUMNSBPRODCALLS, integtime_ns);
4398
4399 } // end for(i=0 ...
4400
4401 }
4402 else{
4403 cout << "Starfield file contains no event.\nExiting.\n";
4404 exit(1);
4405 } // end if( isA ... event
4406 } // end if ( isA ... run
4407 }
4408 else{
4409 cout << "Starfield file contains no run.\nExiting.\n";
4410 exit(1);
4411 }
4412
4413 fclose( infile );
4414
4415 return(0);
4416}
4417
4418
4419// @endcode
4420
4421
4422//=------------------------------------------------------------
4423//!@subsection Log of this file.
4424
4425//!@{
4426//
4427// $Log: not supported by cvs2svn $
4428// Revision 1.71 2004/09/17 09:20:52 moralejo
4429//
4430// Updated some calls to current version of Mars:
4431//
4432// - EvtData[i]->InitRead(RunHeader) instead of EvtData[i]->Init(RunHeader);
4433// - MRawRunHeader::kMagicNumber instead of just kMagicNumber
4434// - EvtData[i]->ResetPixels (0, 0) instead of EvtData[i]->DeletePixels();
4435//
4436// Revision 1.70 2004/09/16 15:23:12 moralejo
4437//
4438// Changed "flashadc" and "trigger" in procedure produce_nsbrates from
4439// objects to pointers (followed by dynamical allocation). This is only
4440// to avoid memory problems (-> segmentation fault) in some systems.
4441// Introduced missing initialization to 0 of *itotnphe in produce_phes.
4442// Now the number of phes produced by stars shown on the screen make sense.
4443//
4444//
4445// Revision 1.69 2004/03/30
4446// Changed calculation of MMcFadcHeader.fPedesSigmaHigh and
4447// MMcFadcHeader.fPedesSigmaLow to do as in real data (see comments in
4448// code). Changed meaning of MMcFadcHeader.fAmplFadc and fAmplFadcOuter,
4449// from amplitude to integral of single photoelectron pulse in FADC
4450// counts. Added possibility to choose a realistic pulse shaped (as
4451// measured using pulpo). Changed file Data/lightguides.dat by
4452// Data/LightCollection.dat, intended to contain the information on
4453// light collection efficiency regarding Winston cones, plexiglas, double
4454// PMT crossing and colection efficiency of 1st dynode of PMT. Now the
4455// information for inner and outer pixels can be different, since in the
4456// LightCollection.dat file they are set independently.
4457//
4458// Revision 1.68 2004/02/06 17:39:24 blanch
4459// Compiling with root 3.05 and updating MARS files.
4460//
4461// Revision 1.67 2004/01/30 09:51:18 blanch
4462// [Changes mainly done by A. Moralejo]
4463//
4464// Several minnor changes have been done. For instance, some name of the
4465// variables have been modified to a more self-explained name and
4466// modifications while reading the asciis files at the end of the reflector file
4467// has been introduced.
4468//
4469// The possibilty to enlarge the point spread function has been introduced
4470// in order to be able to simualte the current data.
4471//
4472// All pixels are always written.
4473//
4474// Revision 1.65 2003/10/26 19:43:00 blanch
4475// - The screen output information has been improved to prevent some
4476// non-desired running conditions just looking at the output screen.
4477// - One MMcEvt for each Telscope is stored in the output file.
4478// - 500 empty events are simualted to get a more precise estimation of the
4479// pedestal Sigma for each pixel.
4480//
4481// Revision 1.64 2003/10/21 07:42:50 blanch
4482// A factor 2.35 to transform the fwhm into the sigma of gaussian was missing
4483// in the storing of FADC single hpe pulse determination.
4484//
4485// Revision 1.63 2003/10/17 19:38:31 blanch
4486// Now the camera program will stop if a undefined Geometry is required.
4487// The NSB is internally scaled for any camera geometry and qe.
4488// The seeds in the input card are used to initilize the random numbers.
4489// The Amplitud stored in the MMcFadcHeader is the amplitud of the sphe reponse.
4490// The Pedestal rms is simulated in an artificial empty event.
4491//
4492// Revision 1.62 2003/09/26 11:25:07 blanch
4493// Modification to be able to read MGeomCam branch for any Geometry.
4494//
4495// Revision 1.61 2003/09/25 17:09:20 blanch
4496// Bug on the number of phe from diffuse NSB fixed.
4497//
4498// Revision 1.60 2003/09/23 16:50:55 blanch
4499// WE do not read ct_file anymore since all Telescope information is
4500// in the reflector or in MGeomCam.
4501//
4502// Revision 1.58 2003/09/15 09:59:53 blanch
4503// The concept of the camera prgoram has not changed but this version has
4504// quite a lot of changes to allow several Camera geometries as well as
4505// multitelescope.
4506//
4507// It is suposed to be the first working code for camera 0.7.
4508//
4509// Revision 1.57 2003/07/17 18:02:46 blanch
4510// Several new features introduced as well as fixed bugs
4511//
4512// - 1/100 events printed out
4513// - Low gain implemented
4514// - Different response for outer and inner pixels
4515// - Some warnings removed
4516// - pedestal and qe file from inpuit card
4517// - Faster electronic simulation
4518//
4519// Revision 1.55 2003/02/12 12:22:10 blanch
4520// *** empty log message ***
4521//
4522// Revision 1.54 2003/02/12 11:55:01 blanch
4523// *** empty log message ***
4524//
4525// Revision 1.53 2003/01/23 18:35:21 blanch
4526// *** empty log message ***
4527//
4528// Revision 1.52 2003/01/20 17:19:20 blanch
4529// It fills the MMcCorsikaRun.
4530//
4531// Revision 1.51 2003/01/14 13:40:17 blanch
4532// MRawRunHeader::fNumEvents has been filled with the number of events in
4533// this file.
4534// Problems in fImpact computation have been solved.
4535// Option to set a dc value to rise the discriminator threshold has been added.
4536//
4537// Revision 1.50 2003/01/07 16:33:31 blanch
4538// Star Field Rotation has been implemented by Raul Orduna. Now there is a
4539// rotation for each shower. It is done by a non enter pixel rotation assuming
4540// a circular symetry of the camera. It is not exact but it is accurate enough and
4541// much faster.
4542//
4543// Revision 1.49 2002/12/13 10:04:07 blanch
4544// *** empty log message ***
4545//
4546// Revision 1.48 2002/12/12 17:40:50 blanch
4547// *** empty log message ***
4548//
4549// Revision 1.47 2002/12/10 17:19:31 blanch
4550// *** empty log message ***
4551//
4552// Revision 1.46 2002/11/08 17:51:00 blanch
4553// *** empty log message ***
4554//
4555// Revision 1.45 2002/10/29 17:15:27 blanch
4556// Reading several reflector versions.
4557//
4558// Revision 1.44 2002/10/18 16:53:03 blanch
4559// Modification to read several reflector files.
4560//
4561// Revision 1.43 2002/09/13 10:53:39 blanch
4562// Minor change to remove some undisired comments.
4563//
4564// Revision 1.42 2002/09/09 16:00:49 blanch
4565// Statement has been included to avoid writting to disk MParContainer and MArray.
4566// It has also been added the effect of the WC, the actual values must be added,
4567// once they are measured.
4568//
4569// Revision 1.41 2002/09/04 09:57:42 blanch
4570// Modifications done to use MGeomCam from MARS.
4571//
4572// Revision 1.40 2002/07/16 16:15:22 blanch
4573// A first implementation of the Star field rotation has been done.
4574//
4575// Revision 1.39 2002/04/27 10:48:39 blanch
4576// Some unused varibles have been removed.
4577//
4578// Revision 1.38 2002/03/18 18:44:29 blanch
4579// Small modificatin to set the electronic Noise in the MMcTrigHeader class.
4580//
4581// Revision 1.37 2002/03/18 16:42:20 blanch
4582// The data member fProductionSite of the MMcRunHeader has been set to 0,
4583// which means that the prodution site is unknown.
4584//
4585// Revision 1.35 2002/03/15 15:15:52 blanch
4586// Several modifications to simulate the actual trigger zone.
4587//
4588// Revision 1.34 2002/03/13 18:13:56 blanch
4589// Some changes to fill correctly the new format of MMcRunHeader.
4590//
4591// Revision 1.33 2002/03/04 17:21:48 blanch
4592// Small and not important changes.
4593//
4594// Revision 1.32 2002/02/28 15:04:52 blanch
4595// A small back has been solved. Before, while not using the option
4596// writte_all_images, not all triggered showers were stored. Now it is solved.
4597// For that it is important that the less restrictive trigger option is
4598// checked first.
4599// A new facility has been introduced and now one can choose the step size in
4600// trigger loop mode for the discriminator threshold.
4601// The close-compact topology for less than 3 pixels does not make sense. Before
4602// the program was ignoring that, now it switch to simple neighbour condition.
4603//
4604// Revision 1.31 2002/01/18 17:41:02 blanch
4605// The option of adding noise to all pixels or to not adding the noise
4606// has been added.
4607// We removed the pixels larger than 577. When there were more than one
4608// trigger in one shower, the pixel number was increasing. Now it is
4609// flagged by the variable MMcTrig::fFirstLvlTrig.
4610//
4611// Revision 1.30 2001/11/27 09:49:54 blanch
4612// Fixing bug which was treating wrongly the extension of star photons.
4613//
4614// Revision 1.29 2001/11/14 17:38:23 blanch
4615// Sveral changes have been done:
4616// - bpoint_in_in_pixel has been dodified to speed up the program
4617// - Some minor changes have been done to remove warnings
4618// - buffer size and split version of the Branches have been removed
4619// - Some modifications were needed to adat the program to the new
4620// MRawEvtData::DeletePixels
4621//
4622// Revision 1.28 2001/10/26 16:31:45 blanch
4623// Removing several warnings.
4624//
4625// Revision 1.27 2001/09/05 10:04:33 blanch
4626// *** empty log message ***
4627//
4628// Revision 1.26 2001/07/19 09:29:53 blanch
4629// Different threshold for each pixel can be used.
4630//
4631// Revision 1.25 2001/05/08 08:07:54 blanch
4632// New numbering for branches from different trigger conditions has been
4633// implemented. Now, they are calles: ClassName;1., ClasNema;2., ...
4634// The MontaCarlo Headers (MMcTrigHeader and MMcFadcHeader) have been move to
4635// the RunHeaders tree. Also the MRawRunHeader is thera with some of its
4636// information already filled.
4637//
4638// Revision 1.24 2001/04/06 16:48:09 magicsol
4639// New camera version able to read the new format of the reflector output:
4640// reflector 0.4
4641//
4642// Revision 1.23 2001/03/28 16:13:41 blanch
4643// While feeling the MMcFadeHeader branch the boolean conditoin was wrong. It has
4644// been solved.
4645//
4646// Revision 1.22 2001/03/20 18:52:43 blanch
4647// *** empty log message ***
4648//
4649// Revision 1.21 2001/03/19 19:53:03 blanch
4650// Some print outs have been removed.
4651//
4652// Revision 1.20 2001/03/19 19:30:06 magicsol
4653// Minor changes have been done to improve the FADC pedestals treatment.
4654//
4655// Revision 1.19 2001/03/05 11:14:41 magicsol
4656// I changed the position of readinf a parameter. It is a minnor change.
4657//
4658// Revision 1.18 2001/03/05 10:36:52 blanch
4659// A branch with information about the FADC simulation (MMcFadcHeader) is writen
4660// in the McHeaders tree of the aoutput root file.
4661// The NSB contribution is only applied if the the number of phe form the shower
4662// are above a given number.
4663//
4664// Revision 1.17 2001/02/23 11:05:57 magicsol
4665// Small changes due to slightly different output format and the introduction of
4666// pedesals for teh FADC.
4667//
4668// Revision 1.16 2001/01/18 18:44:40 magicsol
4669// *** empty log message ***
4670//
4671// Revision 1.15 2001/01/17 09:32:27 harald
4672// The changes are neccessary to have the same name for trees in MC and in
4673// data. So now there should be no differences in MC data and real data from
4674// FADC system.
4675//
4676// Revision 1.14 2001/01/15 12:33:34 magicsol
4677// Some modifications have been done to use the new (Dec'2000) Raw data format.
4678// There are also some minnors modifications to adapt the improvements in the
4679// MTrigger class (overlaping time and trigger cells).
4680//
4681// Revision 1.13 2000/10/25 08:14:23 magicsol
4682// The routine that produce poisson random numbers to decide how many phe
4683// form NSB are emmited in each pixel has been replaced. Now a ROOT routine
4684// is used.
4685//
4686// Revision 1.10 2000/07/04 14:10:20 MagicSol
4687// Some changes have been done in the root output file. The RawEvt tree is only
4688// stored in the single trigger mode.
4689// The trigger input parameters are also given by the general input card.
4690// The diffuse NSB and the star NSB have been decoupled. Now the contribution of
4691// each one can be studied seperately.
4692//
4693// Revision 1.9 2000/06/13 13:25:24 blanch
4694// The multiple arrays have been replaced, since they do not work
4695// in alpha machines. Now we are using pointers and the command new
4696// to allocate memory.
4697//
4698// Revision 1.8 2000/05/11 13:57:27 blanch
4699// The option to loop over several trigger configurations has been included.
4700// Some non-sense with triggertime range has been solved.
4701// Montecarlo information and ADC counts are saved in a root file.
4702// There was a problem with the maximum number of phe that the program could analyse. Now there is not limit.
4703//
4704// Revision 1.7 2000/03/24 18:10:46 blanch
4705// A first FADC simulation and a trigger simulation are already implemented.
4706// The calculation of the Hillas Parameters have been removed, since it was decided that it should be in the analysis software.
4707// A loop over trigger threshold and some corretcions in the time range where it looks for a trigger will be implemented as soon as possible.
4708//
4709// Revision 1.6 2000/03/20 18:35:11 blanch
4710// The trigger is already implemented but it does not save the trigger information in any file as it is implemented in timecam. In the next days there will be a version which also creates the files with the trigger information. It is going to be a mixing of the current camera and timecam programs.
4711//
4712// Revision 1.5 2000/02/18 17:40:35 petry
4713// This version includes drastic changes compared to camera.cxx 1.4.
4714// It is not yet finished and not immediately useful because the
4715// trigger simulation is not yet re-implemented. I had to take it
4716// out together with some other stuff in order to tidy the whole
4717// program up. This is not meant as an insult to anyone. I needed
4718// to do this in order to be able to work on it.
4719//
4720// This version has been put in the repository in order to be
4721// able to share the further development with others.
4722//
4723// If you need something working, wait or take an earlier one.
4724// See file README.
4725//
4726// Revision 1.4 2000/01/25 08:36:23 petry
4727// The pixelization in previous versions was buggy.
4728// This is the first version with a correct pixelization.
4729//
4730// Revision 1.3 2000/01/20 18:22:17 petry
4731// Found little bug which makes camera crash if it finds a photon
4732// of invalid wavelength. This bug is now fixed and the range
4733// of valid wavelengths extended to 290 - 800 nm.
4734// This is in preparation for the NSB simulation to come.
4735// Dirk
4736//
4737// Revision 1.2 1999/11/19 08:40:42 harald
4738// Now it is possible to compile the camera programm under osf1.
4739//
4740// Revision 1.1.1.1 1999/11/05 11:59:31 harald
4741// This the starting point for CVS controlled further developments of the
4742// camera program. The program was originally written by Jose Carlos.
4743// But here you can find a "rootified" version to the program. This means
4744// that there is no hbook stuff in it now. Also the output of the
4745// program changed to the MagicRawDataFormat.
4746//
4747// The "rootification" was done by Dirk Petry and Harald Kornmayer.
4748//
4749// Revision 1.3 1999/10/22 15:01:28 petry
4750// version sent to H.K. and N.M. on Fri Oct 22 1999
4751//
4752// Revision 1.2 1999/10/22 09:44:23 petry
4753// first synthesized version which compiles and runs without crashing;
4754//
4755// Revision 1.1.1.1 1999/10/21 16:35:10 petry
4756// first synthesised version
4757//
4758// Revision 1.13 1999/03/15 14:59:05 gonzalez
4759// camera-1_1
4760//
4761// Revision 1.12 1999/03/02 09:56:10 gonzalez
4762// *** empty log message ***
4763//
4764//
4765//!@}
4766
4767//=EOF
Note: See TracBrowser for help on using the repository browser.