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

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