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

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