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

Last change on this file since 723 was 723, checked in by magicsol, 24 years ago
New camera version able to read the new format of the reflector output: reflector 0.4
File size: 93.0 KB
Line 
1//!/////////////////////////////////////////////////////////////////////
2//
3// camera
4//
5// @file camera.cxx
6// @title Camera simulation
7// @subtitle Code for the simulation of the camera phase
8// @desc Code for the simulation of the camera of CT1 and MAGIC
9// @author J C Gonzalez
10// @email gonzalez@mppmu.mpg.de
11// @date Thu May 7 16:24:22 1998
12//
13//----------------------------------------------------------------------
14//
15// Created: Thu May 7 16:24:22 1998
16// Author: Jose Carlos Gonzalez
17// Purpose: Program for reflector simulation
18// Notes: See files README for details
19//
20//----------------------------------------------------------------------
21//
22// $RCSfile: camera.cxx,v $
23// $Revision: 1.24 $
24// $Author: magicsol $
25// $Date: 2001-04-06 16:48:09 $
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
61#include "MTrigger.hxx"
62#include "MFadc.hxx"
63#include "MLons.hxx"
64
65#include "MRawEvtData.h"
66#include "MRawEvtHeader.h"
67#include "MRawCrateData.h"
68#include "MMcEvt.hxx"
69#include "MMcTrig.hxx"
70#include "MMcTrigHeader.hxx"
71#include "MMcFadcHeader.hxx"
72
73/*!@"
74
75 All the defines are located in the file |camera.h|.
76
77 @"*/
78
79#include "camera.h"
80
81//!@}
82
83/*!@"
84
85 The following set of flags are used in time of compilation. They do
86 not affect directly the behaviour of the program at run-time
87 (though, of course, if you disconnected the option for
88 implementation of the Trigger logic, you will not be able to use any
89 trigger at all. The 'default' values mean default in the sense of
90 what you got from the server when you obtained this program.
91
92 @"*/
93
94//!@{
95
96// flag for debugging (default: OFF )
97#define __DEBUG__
98#undef __DEBUG__
99
100
101//!@}
102
103//=-----------------------------------------------------------
104//!@subsection Definition of global variables.
105
106/*!@"
107
108 Now we define some global variables with data about the telescope,
109 such as "focal distance", number of pixels/mirrors,
110 "size of the camera", and so on.
111
112 @"*/
113
114/*!@"
115
116 Depending on the telescope we are using (CT1 or MAGIC), the
117 information stored in the definition file is different.
118 The variable |ct_Type| has the value 0 when we use
119 CT1, and 1 when we use MAGIC.
120
121 @"*/
122
123//!@{
124static int ct_Type; //@< Type of telescope: 0:CT1, 1:MAGIC
125//!@}
126
127/*!@"
128
129 And this is the information about the whole telescope.
130
131 @"*/
132
133//!@{
134
135// parameters of the CT (from the CT definition file)
136
137////@: Focal distances [cm]
138//static float *ct_Focal;
139
140//@: Mean Focal distances [cm]
141static float ct_Focal_mean;
142
143//@: STDev. Focal distances [cm]
144static float ct_Focal_std;
145
146//@: Mean Point Spread function [cm]
147static float ct_PSpread_mean;
148
149//@: STDev. Point Spread function [cm]
150static float ct_PSpread_std;
151
152//@: STDev. Adjustmente deviation [cm]
153static float ct_Adjustment_std;
154
155//@: Radius of the Black Spot in mirror [cm]
156static float ct_BlackSpot_rad;
157
158//@: Radius of one mirror [cm]
159static float ct_RMirror;
160
161//@: Camera width [cm]
162static float ct_CameraWidth;
163
164//@: Pixel width [cm]
165static float ct_PixelWidth;
166
167//@: ct_PixelWidth_corner_2_corner = ct_PixelWidth / cos(60)
168static float ct_PixelWidth_corner_2_corner;
169
170//@: ct_PixelWidth_corner_2_corner / 2
171static float ct_PixelWidth_corner_2_corner_half;
172
173//@: Number of mirrors
174static int ct_NMirrors = 0;
175
176//@: Number of pixels
177static int ct_NPixels;
178
179//@: Number of pixels
180static int ct_NCentralPixels;
181
182//@: Number of pixels
183static int ct_NGapPixels;
184
185//@: ct_Apot = ct_PixelWidth / 2
186static float ct_Apot;
187
188//@: ct_2Apot = 2 * ct_Apot = ct_PixelWidth
189static float ct_2Apot;
190
191//@: name of the CT definition file to use
192static char ct_filename[256];
193
194//@: list of showers to be skipped
195static int *Skip;
196
197//@: number of showers to be skipped
198static int nSkip=0;
199
200//@: flag: TRUE: data come from STDIN; FALSE: from file
201static int Data_From_STDIN = FALSE;
202
203//@: flag: TRUE: write all images to output; FALSE: only triggered showers
204static int Write_All_Images = FALSE;
205
206//@: flag: TRUE: write all data to output; FALSE: only triggered showers
207static int Write_All_Data = FALSE;
208
209static int Write_McEvt = TRUE;
210static int Write_McTrig = TRUE;
211static int Write_McFADC = TRUE;
212static int Write_RawEvt = FALSE;
213
214//@: flag: TRUE: selection on the energy
215static int Select_Energy = TRUE;
216
217//@: Lower edge of the selected energy range (in GeV)
218static float Select_Energy_le = 0.0;
219
220//@: Upper edge of the selected energy range (in GeV)
221static float Select_Energy_ue = 100000.0;
222
223//@: flag: TRUE: show all fadc singnal in the screen; FALSE: don't
224static int FADC_Scan = FALSE;
225
226//@: flag: TRUE: show all trigger singnal in the screen; FALSE: don't
227static int Trigger_Scan = FALSE;
228
229//@: flag: TRUE: loop trigger analysis over several thresholds, multiplicities and topologies; FALSE: a single trigger configuration
230static int Trigger_Loop = FALSE;
231
232//@: Properties of the trigger
233static float Trigger_gate_length = 6.0;
234static float Trigger_response_ampl = 1.0;
235static float Trigger_response_fwhm = 2.0;
236static float Trigger_overlaping_time= 0.25;
237
238//@: Properties of the FADC
239static float FADC_response_ampl = MFADC_RESPONSE_AMPLITUDE;
240static float FADC_response_fwhm = MFADC_RESPONSE_FWHM;
241
242//@: Trigger conditions for a single trigger mode
243static float Trigger_threshold = 7.0;
244static int Trigger_multiplicity = 4;
245static int Trigger_topology = 2;
246
247//@: Upper and lower edges of the trigger loop
248static int Trigger_loop_lthres = 0;
249static int Trigger_loop_uthres = 10;
250static int Trigger_loop_lmult = 2;
251static int Trigger_loop_umult = 10;
252static int Trigger_loop_ltop = 0;
253static int Trigger_loop_utop = 2;
254
255//!@}
256
257/*!@"
258
259 The following double-pointer is a 2-dimensional table with information
260 about each pixel. The routine read_pixels will generate
261 the information for filling it using igen_pixel_coordinates().
262
263 @"*/
264
265//!@{
266// Pointer to a tables/Arrays with information about the pixels
267// and data stored on them with information about the pixels
268
269
270//@: coordinates x,y for each pixel
271static float **pixary;
272
273//@: indexes of pixels neighbours of a given one
274static int **pixneig;
275
276//@: number of neighbours a pixel have
277static int *npixneig;
278
279//@: contents of the pixels (ph.e.)
280static float *fnpix;
281
282
283//!@}
284
285/*!@"
286
287 The following double-pointer is a 2-dimensional table with the
288 Quantum Efficiency @$QE@$ of each pixel in the camera, as a function
289 of the wavelength @$\lambda@$. The routine |read_pixels()| will read
290 also this information from the file |qe.dat|.
291
292 @"*/
293
294//!@{
295// Pointer to a table with QE, number of datapoints, and wavelengths
296
297//@: table of QE
298static float ***QE;
299
300//@: number of datapoints for the QE curve
301static int pointsQE;
302
303//@: table of QE
304static float *QElambda;
305//!@}
306
307/*!@"
308
309 The following double-pointer is a 2-dimensional table with information
310 about each mirror in the dish. The routine |read_ct_file()| will read
311 this information from the CT definition file.
312
313 @"*/
314
315//!@{
316// Pointer to a table with the following info.:
317
318static float **ct_data;
319
320/*
321 * TYPE=0 (CT1)
322 * i s rho theta x y z thetan phin xn yn zn
323 *
324 * i : number of the mirror
325 * s : arc length [cm]
326 * rho : polar rho of the position of the center of the mirror [cm]
327 * theta : polar angle of the position of the center of the mirror [cm]
328 * x : x coordinate of the center of the mirror [cm]
329 * y : y coordinate of the center of the mirror [cm]
330 * z : z coordinate of the center of the mirror [cm]
331 * thetan : polar theta angle of the direction where the mirror points to
332 * phin : polar phi angle of the direction where the mirror points to
333 * xn : xn coordinate of the normal vector in the center (normalized)
334 * yn : yn coordinate of the normal vector in the center (normalized)
335 * zn : zn coordinate of the normal vector in the center (normalized)
336 *
337 * TYPE=1 (MAGIC)
338 * i f sx sy x y z thetan phin
339 *
340 * i : number of the mirror
341 * f : focal distance of that mirror
342 * sx : curvilinear coordinate of mirror's center in X[cm]
343 * sy : curvilinear coordinate of mirror's center in X[cm]
344 * x : x coordinate of the center of the mirror [cm]
345 * y : y coordinate of the center of the mirror [cm]
346 * z : z coordinate of the center of the mirror [cm]
347 * thetan : polar theta angle of the direction where the mirror points to
348 * phin : polar phi angle of the direction where the mirror points to
349 * xn : xn coordinate of the normal vector in the center (normalized)
350 * yn : yn coordinate of the normal vector in the center (normalized)
351 * zn : zn coordinate of the normal vector in the center (normalized)
352 */
353//!@}
354
355/*!@"
356
357 We define a table into where random numbers will be stored.
358 The routines used for random number generation are provided by
359 |RANLIB| (taken from NETLIB, |www.netlib.org|), and by
360 the routine |double drand48(void)| (prototype defined in
361 |stdlib.h|) through the macro |RandomNumber| defined in
362 |camera.h|.
363
364 @"*/
365
366
367//!@}
368
369extern char FileName[];
370
371
372//=-----------------------------------------------------------
373// @subsection Main program.
374
375//!@{
376
377//++++++++++++++++++++++++++++++++++++++++
378// MAIN PROGRAM
379//----------------------------------------
380
381int main(int argc, char **argv)
382{
383
384 //!@' @#### Definition of variables.
385 //@'
386
387 int ioscar=0;
388
389 char inname[256]; //@< input file name
390 char starfieldname[256]; //@< starfield input file name
391
392 char datname[256]; //@< data (ASCII) output file name
393
394 char rootname[256] ; //@< ROOT file name
395 char rootname_loop[256] ; //@< ROOT file name
396
397 char parname[256]; //@< parameters file name
398
399 char nsbpathname[256]; //@< directory with the dataabse for th NSB
400
401 char flag[SIZE_OF_FLAGS + 1]; //@< flags in the .rfl file
402
403 FILE *inputfile; //@< stream for the input file
404 ofstream datafile; //@< stream for the data file
405
406 MCEventHeader mcevth; //@< Event Header class (MC)
407 MCCphoton cphoton; //@< Cherenkov Photon class (MC)
408
409 int inumphe; //@< number of photoelectrons in an event from showers
410 float inumphensb; //@< number of photoelectrons in an event from nsb
411
412 float arrtmin_ns; //@ arrival time of the first photoelectron
413 float arrtmax_ns; //@ arrival time of the last photoelectron
414
415 float thetaCT, phiCT; //@< parameters of a given shower
416 float thetashw, phishw; //@< parameters of a given shower
417 float coreD, coreX, coreY; //@< core position
418 float impactD; //@< impact parameter
419 float l1, m1, n1; //@< auxiliary variables
420 float l2, m2, n2; //@< auxiliary variables
421 float num, den; //@< auxiliary variables
422
423 int nshow=0; //@< partial number of shower in a given run
424 int ntshow=0; //@< total number of showers
425 int ncph=0; //@< partial number of photons in a given run
426 int ntcph=0; //@< total number of photons
427
428 int i, j, k; //@< simple counters
429
430 int simulateNSB; //@< Will we simulate NSB?
431 int nphe2NSB; //@< From how many ohe will we simulate NSB?
432 float meanNSB; //@< diffuse NSB mean value (phe per ns per central pixel)
433 float diffnsb_phepns[iMAXNUMPIX]; //@< diffuse NSB values for each pixel
434 //@< derived from meanNSB
435 float nsbrate_phepns[iMAXNUMPIX][iNUMWAVEBANDS]; //@< non-diffuse nsb
436 //@< photoelectron rates
437 float nsb_phepns[iMAXNUMPIX]; //@< NSB values for each pixel
438
439 Float_t nsb_trigresp[TRIGGER_TIME_SLICES]; //@< array to write the trigger
440 //@< response from the database
441 Float_t nsb_fadcresp[(Int_t) SLICES_MFADC]; //@< array to write the fadc
442 //@< response from the database
443 Byte_t trigger_map[((Int_t)(TRIGGER_PIXELS/8))+1];//@< Pixels on when the
444 //@< camera triggers
445 Float_t fadc_elecnoise[CAMERA_PIXELS]; //@< Electronic niose for each pixel
446 Float_t fadc_pedestals[CAMERA_PIXELS]; //@< array for fadc pedestals values
447
448 float ext[iNUMWAVEBANDS] = { //@< average atmospheric extinction in each waveband
449 EXTWAVEBAND1,
450 EXTWAVEBAND2,
451 EXTWAVEBAND3,
452 EXTWAVEBAND4,
453 EXTWAVEBAND5
454 };
455
456 float qThreshold; //@< Threshold value
457 float qTailCut; //@< Tail Cut value
458 int nIslandsCut; //@< Islands Cut value
459 int countIslands; //@< Will we count the islands?
460 int anaPixels;
461
462 float fCorrection; //@< Factor to apply to pixel values (def. 1.)
463
464 int ntrigger = 0; //@< number of triggers in the whole file
465 int btrigger = 0; //@< trigger flag
466 int ithrescount; //@< counter for loop over threshold trigger
467 int imulticount; //@< counter for loop over multiplicity trigger
468 int itopocount; //@< counter for loop over topology trigger
469 int icontrigger; //@< number of trigger conditions to be analised
470 UShort_t numPix; //@< number of sets of fadc written counts
471
472 float fpixelthres[TRIGGER_PIXELS];
473
474 TArrayC *fadcValues; //@< the analog Fadc siganl for pixels
475
476 float plateScale_cm2deg; //@< plate scale (deg/cm)
477 float degTriggerZone; //@< trigger area in the camera (radius, in deg.)
478
479 int still_in_loop = FALSE;
480
481 struct camera cam; // structure holding the camera definition
482
483
484 //!@' @#### Definition of variables for |getopt()|.
485 //@'
486
487 int ch, errflg = 0; //@< used by getopt
488
489 //!@' @#### Initialisation of some variables
490 //@'
491
492 for(i=0;i<iMAXNUMPIX;i++)
493 for(j=0;j<iNUMWAVEBANDS;j++)
494 nsbrate_phepns[i][j]=0.0; //@< Starlight rates initialised at 0.0
495
496 /*!@'
497
498 @#### Beginning of the program.
499
500 We start with the main program. First we (could) make some
501 presentation, and follows the reading of the parameters file (now
502 from the |stdin|), the reading of the CT parameters file, and the
503 creation of the output file, where the processed data will be
504 stored.
505
506 */
507
508 //++
509 // START
510 //--
511
512 // make unbuffered output
513
514 cout.setf ( ios::stdio );
515
516 // parse command line options (see reflector.h)
517
518 parname[0] = '\0';
519
520 optarg = NULL;
521 while ( !errflg && ((ch = getopt(argc, argv, COMMAND_LINE_OPTIONS)) != -1) )
522 switch (ch) {
523 case 'f':
524 strcpy(parname, optarg);
525 break;
526 case 'h':
527 usage();
528 break;
529 default :
530 errflg++;
531 }
532
533 // show help if error
534
535 if ( errflg>0 )
536 usage();
537
538 // make some sort of presentation
539
540 present();
541
542 // read parameters file
543
544 if ( strlen(parname) < 1 )
545 readparam(NULL);
546 else
547 readparam(parname);
548
549 // read data from file or from STDIN?
550
551 Data_From_STDIN = get_data_from_stdin();
552
553 // write all images, even those without trigger?
554
555 Write_All_Images = get_write_all_images();
556
557 // write all data (i.e., ph.e.s in pixels)
558
559 Write_All_Data = get_write_all_data();
560
561 Write_McEvt = get_write_McEvt() ;
562 Write_McTrig = get_write_McTrig() ;
563 Write_McFADC = get_write_McFadc() ;
564 Write_RawEvt = get_write_RawEvt() ;
565
566 FADC_Scan = get_FADC_Scan();
567 Trigger_Scan = get_Trigger_Scan();
568
569 get_FADC_properties( &FADC_response_ampl, &FADC_response_fwhm);
570
571 get_Trigger_properties( &Trigger_gate_length, &Trigger_overlaping_time, &Trigger_response_ampl, &Trigger_response_fwhm);
572
573 Trigger_Loop = get_Trigger_Loop(&Trigger_loop_lthres, &Trigger_loop_uthres, &Trigger_loop_lmult, &Trigger_loop_umult, &Trigger_loop_ltop, &Trigger_loop_utop);
574
575 icontrigger =(Trigger_loop_uthres-Trigger_loop_lthres+1)*
576 (Trigger_loop_umult-Trigger_loop_lmult+1)*
577 (Trigger_loop_utop-Trigger_loop_ltop+1);
578
579 if (!Trigger_Loop){
580 get_Trigger_Single (&Trigger_threshold, &Trigger_multiplicity, &Trigger_topology);
581 icontrigger=1;
582 }
583
584 // get filenames
585
586 strcpy( inname, get_input_filename() );
587 strcpy( starfieldname, get_starfield_filename() );
588 strcpy( datname, get_data_filename() );
589 strcpy( rootname, get_root_filename() );
590 strcpy( rootname_loop, get_loop_filename() );
591 strcpy( ct_filename, get_ct_filename() );
592 strcpy( nsbpathname, get_nsb_directory() );
593
594 // get different parameters of the simulation
595
596 qThreshold = get_threshold();
597 qTailCut = get_tail_cut();
598 simulateNSB = get_nsb( &meanNSB, &nphe2NSB );
599 countIslands = get_islands_cut( &nIslandsCut );
600
601 // get selections on the parameters
602
603 Select_Energy = get_select_energy( &Select_Energy_le, &Select_Energy_ue);
604
605 // log filenames information
606
607 log(SIGNATURE,
608 "%s:\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\t%20s:\t%s\n",
609 "Filenames",
610 "In", inname,
611 "Stars", starfieldname,
612 "NSB database", nsbpathname,
613 "CT", ct_filename,
614 "Data", datname,
615 "ROOT", rootname
616 );
617
618 // log Trigger information
619
620 if (Trigger_Loop) {
621 log(SIGNATURE,
622 "%s:\n\t%20s: %i - %i\n\t%20s: %i - %i\n\t%20s: %i - %i\n\t%20s\n",
623 "Trigger Loop mode",
624 "Threshold",Trigger_loop_lthres,Trigger_loop_uthres,
625 "Multiplicity",Trigger_loop_lmult,Trigger_loop_umult,
626 "Topology",Trigger_loop_ltop,Trigger_loop_utop,
627 rootname_loop);
628 }
629 else{
630 log(SIGNATURE,
631 "%s:\n\t%20s: %f\n\t%20s: %i\n\t%20s: %i\n",
632 "Single Trigger mode",
633 "Threshold",Trigger_threshold,
634 "Multiplicity",Trigger_multiplicity,
635 "Topology",Trigger_topology);
636 }
637
638 // log flags information
639
640 log(SIGNATURE,
641 "%s:\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n",
642 "Flags",
643 "Data_From_STDIN", ONoff(Data_From_STDIN),
644 "Write_All_Images", ONoff(Write_All_Images),
645 "Write_All_Data", ONoff(Write_All_Data));
646
647 // log flags information
648
649 log(SIGNATURE,
650 "%s:\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n",
651 "Root output",
652 "Write_McEvt", ONoff(Write_McEvt),
653 "Write_McTrig", ONoff(Write_McTrig),
654 "Write_McFADC", ONoff(Write_McFADC),
655 "Write_RawEvt", ONoff(Write_RawEvt));
656
657 // log parameters information
658
659 log(SIGNATURE,
660 "%s:\n\t%20s: %f\n\t%20s: %f\n\t%20s: %f %s\n\t%20s: %f %s\n",
661 "Parameters",
662 "q0 (Threshold)", qThreshold,
663 "t0 (Tail-cut)", qTailCut,
664 "NSB (phes/pixel)", meanNSB, ONoff(simulateNSB),
665 "i0 (Islands-cut)", nIslandsCut, ONoff(countIslands));
666
667 // log selections
668
669 log(SIGNATURE,
670 "%s:\n\t%20s: %s (%f:%f)\n",
671 "Selections:",
672 "Energy", ONoff(Select_Energy), Select_Energy_le, Select_Energy_ue);
673
674 // Definition and initialization of array to save trigger statistics
675
676 int ***ntriggerloop;
677
678 ntriggerloop= new int ** [(int) (Trigger_loop_uthres+1-Trigger_loop_lthres)];
679 for (ithrescount=0;ithrescount<=Trigger_loop_uthres-Trigger_loop_lthres;ithrescount++){
680 ntriggerloop[ithrescount]= new int * [Trigger_loop_umult-Trigger_loop_lmult+1];
681 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
682 ntriggerloop[ithrescount][imulticount]= new int [Trigger_loop_utop-Trigger_loop_ltop+1];
683 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
684 ntriggerloop[ithrescount][imulticount][itopocount]=0;
685 }
686 }
687 }
688
689 // set all random numbers seeds
690
691 setall( get_seeds(0), get_seeds(1) );
692
693 // get list of showers to evt. skip
694
695 nSkip = get_nskip_showers();
696
697 if (nSkip > 0) {
698 Skip = new int[ nSkip ];
699 get_skip_showers( Skip );
700
701 log(SIGNATURE, "There are some showers to skip:\n");
702 for (i=0; i<nSkip; ++i)
703 log(SIGNATURE, "\tshower # %d\n", Skip[i]);
704 }
705
706
707 // read parameters from the ct.def file
708
709 read_ct_file();
710
711 // read camera setup
712
713 read_pixels(&cam);
714
715 Int_t Lev0, Lev1, Lev2 ;
716
717 fadcValues = new TArrayC(FADC_SLICES);
718
719 // number of pixels for parameters
720
721 anaPixels = get_ana_pixels();
722 anaPixels = (anaPixels == -1) ? ct_NPixels : anaPixels;
723
724 // initialise ROOT
725
726 TROOT simple("simple", "MAGIC Telescope Monte Carlo");
727
728 // initialise instance of Trigger and FADC classes
729
730 MTrigger Trigger(Trigger_gate_length, Trigger_overlaping_time,
731 Trigger_response_ampl, Trigger_response_fwhm); //@< A instance of the Class MTrigger
732
733 // Initialise McTrig information class if we want to save trigger informtion
734
735 MMcTrig **McTrig;
736 MMcTrigHeader **HeaderTrig;
737 MMcFadcHeader **HeaderFadc;
738
739 if (Write_McTrig){
740
741 McTrig = new MMcTrig * [icontrigger];
742
743 for (i=0;i<icontrigger;i++) {
744 McTrig[i] = new MMcTrig();
745 }
746
747 HeaderTrig = new MMcTrigHeader * [icontrigger];
748
749 for (i=0;i<icontrigger;i++) {
750 HeaderTrig[i] = new MMcTrigHeader();
751 }
752 }
753
754 if (Write_McFADC){
755
756 HeaderFadc = new MMcFadcHeader * [icontrigger];
757
758 for (i=0;i<icontrigger;i++) {
759 HeaderFadc[i] = new MMcFadcHeader();
760 }
761 }
762
763 MFadc fadc(FADC_response_ampl,FADC_response_fwhm) ; //@< A instance of the Class MFadc
764
765 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
766 //
767 // Set the FADC pedestals for that run
768 // Some modifications
769 // mut be done to simulate a more realistic distribution of the pedestals.
770 // This simualtion is done int the SetPedestals methode inside the
771 // class MFadc
772 // Currentlly a input_pedestal array is declared with the pedestals.
773 // Thy can also be set randomly following a flat distribution.
774 //
775 /////////////////////////////////////////////////////////////////////
776
777 Float_t input_pedestals[CAMERA_PIXELS];
778
779 for(i=0;i<CAMERA_PIXELS;i++)
780 input_pedestals[i]=10.5;
781
782 fadc.SetPedestals(input_pedestals);
783
784 // Prepare the raw data output
785
786 // Header branch
787
788 MRawEvtHeader **EvtHeader;
789
790 if (Write_RawEvt) {
791 EvtHeader = new MRawEvtHeader * [icontrigger];
792
793 for (i=0;i<icontrigger;i++) {
794 EvtHeader[i] = new MRawEvtHeader();
795 }
796 }
797
798 // Data branch
799
800 MRawEvtData **EvtData; // Data branch
801
802 if (Write_RawEvt) {
803 EvtData = new MRawEvtData * [icontrigger];
804
805 for (i=0;i<icontrigger;i++) {
806 EvtData[i] = new MRawEvtData();
807 }
808 }
809
810 MMcEvt *McEvt = new MMcEvt ();
811
812 //
813 // initalize a temporal ROOT file
814 //
815
816 TFile outfile_temp ( rootname , "RECREATE" );
817
818 Int_t bsize=128000; Int_t split=1;
819
820 // create a Tree for the Header Event
821 TTree HeaderTree("McHeaders","Monte Carlo Header of Run");
822
823 // define branches of Header Tree
824
825 char help[4];
826
827 if(!Trigger_Loop && Write_McTrig){
828
829 HeaderTree.Branch("MMcTrigHeader","MMcTrigHeader",
830 &HeaderTrig[0], bsize, split);
831 }
832 if (Trigger_Loop && Write_McTrig){
833 for(char branchname[20],i=0;i<icontrigger;i++){
834
835 sprintf(help,"%i",i+1);
836 strcpy (branchname, "MMcTrigHeader");
837 strcat (branchname, & help[0]);
838 strcat (branchname, ".");
839 HeaderTree.Branch(branchname,"MMcTrigHeader",
840 &HeaderTrig[i], bsize, split);
841 }
842 }
843
844 if(!Trigger_Loop && Write_McFADC){
845
846 HeaderTree.Branch("MMcFadcHeader","MMcFadcHeader",
847 &HeaderFadc[0], bsize, split);
848 }
849 if (Trigger_Loop && Write_McFADC){
850 for(char branchname[20],i=0;i<icontrigger;i++){
851
852 sprintf(help,"%i",i+1);
853 strcpy (branchname, "MMcFadcHeader");
854 strcat (branchname, & help[0]);
855 strcat (branchname, ".");
856 HeaderTree.Branch(branchname,"MMcFadcHeader",
857 &HeaderFadc[i], bsize, split);
858 }
859 }
860
861 // Fill branches for MMcTrigHeader
862
863 if(!Trigger_Loop && Write_McTrig){
864
865 HeaderTrig[0]->SetTopology((Short_t) Trigger_topology);
866 HeaderTrig[0]->SetMultiplicity((Short_t) Trigger_multiplicity);
867 for(i=0;i<TRIGGER_PIXELS;i++){
868 fpixelthres[i]=(Float_t)Trigger_threshold;
869 }
870 HeaderTrig[0]->SetThreshold( fpixelthres);
871 HeaderTrig[0]->SetAmplitud(Trigger_response_ampl);
872 HeaderTrig[0]->SetFwhm(Trigger_response_fwhm);
873 HeaderTrig[0]->SetOverlap(Trigger_overlaping_time);
874 HeaderTrig[0]->SetGate(Trigger_gate_length);
875 }
876 if(Trigger_Loop && Write_McTrig){
877
878 for (int iconcount=0,ithrescount=0;ithrescount<=Trigger_loop_uthres-Trigger_loop_lthres;ithrescount++){
879 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
880 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
881 HeaderTrig[iconcount]->SetTopology((Short_t) itopocount+Trigger_loop_ltop);
882 HeaderTrig[iconcount]->SetMultiplicity((Short_t) imulticount+Trigger_loop_lmult);
883 for(i=0;i<TRIGGER_PIXELS;i++){
884 fpixelthres[i]=(Float_t)(ithrescount+Trigger_loop_lthres);
885 }
886 HeaderTrig[iconcount]->SetThreshold( fpixelthres);
887 HeaderTrig[iconcount]->SetAmplitud(Trigger_response_ampl);
888 HeaderTrig[iconcount]->SetFwhm(Trigger_response_fwhm);
889 HeaderTrig[iconcount]->SetOverlap(Trigger_overlaping_time);
890 HeaderTrig[iconcount]->SetGate(Trigger_gate_length);
891 iconcount++;
892 }
893 }
894 }
895 }
896
897 // Fill branches for MMcFadcHeader
898
899 for(i=0;i<CAMERA_PIXELS;i++){
900 fadc_elecnoise[i]=2.0;
901 }
902 fadc.GetPedestals(&fadc_pedestals[0]);
903
904 if(!Trigger_Loop && Write_McFADC){
905
906 HeaderFadc[0]->SetShape(0.0);
907 HeaderFadc[0]->SetAmplitud(FADC_response_ampl);
908 HeaderFadc[0]->SetFwhm(FADC_response_fwhm);
909 HeaderFadc[0]->SetPedestal(&fadc_pedestals[0],anaPixels);
910 HeaderFadc[0]->SetElecNoise(&fadc_elecnoise[0],anaPixels);
911 }
912 if(Trigger_Loop && Write_McFADC){
913
914 for (int iconcount=0,ithrescount=0;ithrescount<=Trigger_loop_uthres-Trigger_loop_lthres;ithrescount++){
915 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
916 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
917 HeaderFadc[iconcount]->SetShape(0.0);
918 HeaderFadc[iconcount]->SetAmplitud(Trigger_response_ampl);
919 HeaderFadc[iconcount]->SetFwhm(Trigger_response_fwhm);
920 HeaderFadc[iconcount]->SetPedestal(&fadc_pedestals[0],anaPixels);
921 HeaderFadc[iconcount]->SetElecNoise(&fadc_elecnoise[0],anaPixels);
922 iconcount++;
923 }
924 }
925 }
926 }
927
928 // Fill the Header Tree with the current leaves of each branch
929 HeaderTree.Fill() ;
930
931
932 // create a Tree for the Event data stream
933 TTree EvtTree("Events","Normal Triggered Events");
934
935 if (Write_McEvt){
936
937 EvtTree.Branch("MMcEvt","MMcEvt",
938 &McEvt, bsize, split);
939 }
940
941 if(!Trigger_Loop){
942
943 if (Write_RawEvt){
944 EvtTree.Branch("MRawEvtHeader","MRawEvtHeader",
945 &EvtHeader[0], bsize, split);
946 EvtTree.Branch("MRawEvtData","MRawEvtData",
947 &EvtData[0], bsize, split);
948 }
949 if (Write_McTrig){
950 EvtTree.Branch("MMcTrig","MMcTrig",
951 &McTrig[0], bsize, split);
952 }
953 }
954 else{
955 if (Write_McTrig){
956 for(char branchname[10],i=0;i<icontrigger;i++){
957
958 sprintf(help,"%i",i+1);
959 strcpy (branchname, "MMcTrig");
960 strcat (branchname, & help[0]);
961 strcat (branchname, ".");
962 EvtTree.Branch(branchname,"MMcTrig",
963 &McTrig[i], bsize, split);
964 }
965 }
966 }
967
968 if (Trigger_Loop && Write_RawEvt){
969 for(char branchname[15],i=0;i<icontrigger;i++){
970
971 sprintf(help,"%i",i+1);
972 strcpy (branchname, "MRawEvtHeader");
973 strcat (branchname, & help[0]);
974 strcat (branchname, ".");
975 EvtTree.Branch(branchname,"MRawEvtHeader",
976 &EvtHeader[i], bsize, split);
977 }
978 for(char branchname[15],i=0;i<icontrigger;i++){
979
980 sprintf(help,"%i",i+1);
981 strcpy (branchname, "MRawEvtData");
982 strcat (branchname, & help[0]);
983 strcat (branchname, ".");
984 EvtTree.Branch(branchname,"MRawEvtData",
985 &EvtData[i], bsize, split);
986 }
987 }
988
989 unsigned short ulli = 0 ;
990
991 TApplication theAppTrigger("App", &argc, argv);
992
993 if (gROOT->IsBatch()) {
994 fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]);
995 // return 1;
996 }
997
998 if(FADC_Scan){
999 TApplication theAppFadc("App", &argc, argv);
1000
1001 if (gROOT->IsBatch()) {
1002 fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]);
1003 // return 1;
1004 }
1005 }
1006
1007 // set plate scale (deg/cm) and trigger area (deg)
1008
1009 plateScale_cm2deg = ( ct_Type == 0 ) ? (0.244/2.1) : 0.030952381;
1010
1011 if ( ! get_trigger_radius( &degTriggerZone ) )
1012 degTriggerZone = ( ct_Type == 0 ) ? (5.0) : (5.0);
1013
1014 if ( ! get_correction( &fCorrection ) )
1015 fCorrection = 1.0;
1016
1017 // prepare the NSB simulation
1018
1019 // Instance of the Mlons class
1020 MLons lons(Trigger_response_ampl, Trigger_response_fwhm,
1021 MFADC_RESPONSE_AMPLITUDE, MFADC_RESPONSE_FWHM);
1022
1023 lons.SetPath(nsbpathname);
1024
1025 if( simulateNSB ){
1026
1027 //
1028 // Calculate the non-diffuse NSB photoelectron rates
1029 //
1030
1031 k = produce_nsbrates( starfieldname,
1032 &cam,
1033 nsbrate_phepns );
1034
1035 if (k != 0){
1036 cout << "Error when reading starfield... \nExiting.\n";
1037 exit(1);
1038 }
1039
1040 // calculate diffuse rate correcting for the pixel size
1041
1042 for(i=0; i<cam.inumpixels; i++){
1043 diffnsb_phepns[i] = meanNSB *
1044 cam.dpixsizefactor[i] * cam.dpixsizefactor[i];
1045 }
1046
1047 // calculate nsb rate including diffuse and starlight
1048 for(i=0; i<cam.inumpixels;i++){
1049 nsb_phepns[i]= diffnsb_phepns[i];
1050 for(j=0;j<iNUMWAVEBANDS;j++)
1051 nsb_phepns[i]=nsb_phepns[i]+ nsbrate_phepns[i][j];
1052 }
1053 }
1054
1055 //
1056 // Read the reflector file with the Cherenkov data
1057 //
1058
1059 // select input file
1060
1061 if ( Data_From_STDIN ) {
1062
1063 inputfile = stdin;
1064
1065 }
1066 else{
1067
1068 log( SIGNATURE, "Opening input \"rfl\" file %s\n", inname );
1069 inputfile = fopen( inname, "r" );
1070 if ( inputfile == NULL )
1071 error( SIGNATURE, "Cannot open input file: %s\n", inname );
1072
1073 }
1074
1075 // get signature, and check it
1076
1077 if(check_reflector_file( inputfile )==FALSE){
1078 exit(1);
1079 }
1080
1081 // open data file
1082
1083 log( SIGNATURE, "Opening data \"dat\" file %s\n", datname );
1084 datafile.open( datname );
1085
1086 if ( datafile.bad() )
1087 error( SIGNATURE, "Cannot open data file: %s\n", datname );
1088
1089 // initializes flag
1090
1091 strcpy( flag, " \0" );
1092
1093 // allocate space for PMTs numbers of pixels
1094
1095 fnpix = new float [ ct_NPixels ];
1096
1097
1098 //!@' @#### Main loop.
1099 //@'
1100
1101 // get flag
1102
1103 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1104
1105 // loop over the file
1106
1107 still_in_loop = TRUE;
1108
1109 while (
1110 ((! Data_From_STDIN) && ( !feof(inputfile) ))
1111 ||
1112 (Data_From_STDIN && still_in_loop)
1113 ) {
1114
1115 // reading .rfl files
1116 if(!isA( flag, FLAG_START_OF_RUN )){
1117
1118 // We exit
1119 //error( SIGNATURE, "Expected start of run flag, but found: %s\n", flag );
1120 // We break the main loop
1121 cout<<"Warning: Expected start of run flag, but found:"<<flag<<endl;
1122 cout<<" We break the main loop"<<endl;
1123 break;
1124 }
1125 else { // found start of run
1126
1127 nshow=0;
1128
1129 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1130
1131 while( isA( flag, FLAG_START_OF_EVENT )){ // while there is a next event
1132 //
1133 // Clear Trigger and Fadc
1134 //
1135 Trigger.Reset() ;
1136 Trigger.ClearFirst();
1137 Trigger.ClearZero();
1138 fadc.Reset() ;
1139
1140 ++nshow;
1141 log(SIGNATURE, "Event %d(+%d)\n", nshow, ntshow);
1142
1143 // get MCEventHeader
1144 fread( (char*)&mcevth, mcevth.mysize(), 1, inputfile );
1145
1146 // calculate core distance and impact parameter
1147
1148 coreD = mcevth.get_core(&coreX, &coreY);
1149
1150 // calculate impact parameter (shortest distance betwee the original
1151 // trajectory of the primary (assumed shower-axis) and the
1152 // direction where the telescope points to
1153 //
1154 // we use the following equation, given that the shower core position
1155 // is (x1,y1,z1)=(x,y,0),the trajectory is given by (l1,m1,n1),
1156 // and the telescope position and orientation are (x2,y2,z2)=(0,0,0)
1157 // and (l2,m2,n2)
1158 //
1159 // | |
1160 // | x1-x2 y1-y2 z1-z2 |
1161 // | |
1162 // + | l1 m1 n1 |
1163 // - | |
1164 // | l2 m2 n2 |
1165 // | |
1166 // dist = ------------------------------------ ( > 0 )
1167 // [ |l1 m1|2 |m1 n1|2 |n1 l1|2 ]1/2
1168 // [ | | + | | + | | ]
1169 // [ |l2 m2| |m2 n2| |n2 l2| ]
1170 //
1171 // playing a little bit, we get this reduced for in our case:
1172 //
1173 //
1174 // dist = (- m2 n1 x + m1 n2 x + l2 n1 y - l1 n2 y - l2 m1 z + l1 m2 z) /
1175 // [(l2^2 (m1^2 + n1^2) + (m2 n1 - m1 n2)^2 -
1176 // 2 l1 l2 (m1 m2 + n1 n2) + l1^2 (m2^2 + n2^2) ] ^(1/2)
1177
1178 // read the direction of the incoming shower
1179
1180 thetashw = mcevth.get_theta();
1181 phishw = mcevth.get_phi();
1182
1183 // calculate vector for shower
1184
1185 l1 = sin(thetashw)*cos(phishw);
1186 m1 = sin(thetashw)*sin(phishw);
1187 n1 = cos(thetashw);
1188
1189 // read the deviation of the telescope with respect to the shower
1190
1191 mcevth.get_deviations ( &thetaCT, &phiCT );
1192
1193 if ( (thetaCT == 0.) && (phiCT == 0.) ) {
1194
1195 // CT was looking to the source (both lines are parallel)
1196 // therefore, we calculate the impact parameter as the distance
1197 // between the CT axis and the core position
1198
1199 impactD = dist_r_P( 0., 0., 0., l1, m1, n1, coreX, coreY, 0. );
1200
1201 } else {
1202
1203 // the shower comes off-axis
1204
1205 // obtain with this the final direction of the CT
1206
1207 thetaCT += thetashw;
1208 phiCT += phishw;
1209
1210 // calculate vector for telescope
1211
1212 l2 = sin(thetaCT)*cos(phiCT);
1213 m2 = sin(thetaCT)*sin(phiCT);
1214 n2 = cos(thetaCT);
1215
1216 num = (m1*n2*coreX - m2*n1*coreX + l2*n1*coreY - l1*n2*coreY);
1217 den = (SQR(l1*m2 - l2*m1) +
1218 SQR(m1*n2 - m2*n1) +
1219 SQR(n1*l2 - n2*l1));
1220 den = sqrt(den);
1221
1222 impactD = fabs(num)/den;
1223
1224 }
1225
1226 // energy cut
1227
1228 if ( Select_Energy ) {
1229 if (( mcevth.get_energy() < Select_Energy_le ) ||
1230 ( mcevth.get_energy() > Select_Energy_ue )) {
1231 log(SIGNATURE, "select_energy: shower rejected.\n");
1232 continue;
1233 }
1234 }
1235
1236 // Read first and last time and put inumphe to 0
1237
1238 mcevth.get_times(&arrtmin_ns,&arrtmax_ns);
1239 inumphe=0;
1240
1241 // read the photons and produce the photoelectrons
1242
1243 k = produce_phes( inputfile,
1244 &cam,
1245 WAVEBANDBOUND1,
1246 WAVEBANDBOUND6,
1247 &Trigger, // will be changed by the function!
1248 &fadc, // will be changed by the function!
1249 &inumphe, // important for later: the size of photoe[]
1250 fnpix, // will be changed by the function!
1251 &ncph, // will be changed by the function!
1252 &arrtmin_ns, // will be changed by the function!
1253 &arrtmax_ns // will be changed by the function!
1254 );
1255
1256 if( k != 0 ){ // non-zero returnvalue means error
1257 cout << "Exiting.\n";
1258 exit(1);
1259 }
1260
1261 // NSB simulation
1262
1263 if(simulateNSB && nphe2NSB<=inumphe){
1264
1265 // Fill trigger and fadc response in the trigger class from the database
1266 for(i=0;i<cam.inumpixels;i++)
1267 if(nsb_phepns[i]>0.0){
1268 k=lons.GetResponse(nsb_phepns[i],0.1,
1269 & nsb_trigresp[0],& nsb_fadcresp[0]);
1270 if(k==0){
1271 cout << "Exiting.\n";
1272 exit(1);
1273 }
1274 Trigger.AddNSB(i,nsb_trigresp);
1275 fadc.AddSignal(i,nsb_fadcresp);
1276 }
1277 }// end if(simulateNSB && nphe2NSB<=inumphe) ...
1278
1279 log(SIGNATURE, "End of this event: %d cphs(+%d). . .\n",
1280 ncph, ntcph);
1281
1282 ntcph += ncph;
1283
1284 // skip it ?
1285
1286 for ( i=0; i<nSkip; ++i ) {
1287 if (Skip[i] == (nshow+ntshow)) {
1288 i = -1;
1289 break;
1290 }
1291 }
1292
1293 // if after the previous loop, the exit value of i is -1
1294 // then the shower number is in the list of showers to be
1295 // skipped
1296
1297 if (i == -1) {
1298 log(SIGNATURE, "\t\tskipped!\n");
1299 continue;
1300 }
1301
1302 cout << "Total number of phes: " << inumphe<<" + ";
1303 inumphensb=0;
1304 for (i=0;i<cam.inumpixels;i++){
1305 inumphensb+=nsb_phepns[i]*TOTAL_TRIGGER_TIME;
1306 }
1307 cout<<inumphensb<<endl;
1308
1309 //++++++++++++++++++++++++++++++++++++++++++++++++++
1310 // at this point we have a camera full of
1311 // ph.e.s
1312 // we should first apply the trigger condition,
1313 // and if there's trigger, then clean the image,
1314 // calculate the islands statistics and the
1315 // other parameters of the image (Hillas' parameters
1316 // and so on).
1317 //--------------------------------------------------
1318
1319 // TRIGGER HERE
1320
1321 //
1322 // now the noise of the electronic
1323 // (preamps, optical transmission,..) is introduced.
1324 // This is done inside the class MTrigger by the method ElecNoise.
1325 //
1326 Trigger.ElecNoise() ;
1327
1328 fadc.ElecNoise() ;
1329
1330 // now a shift in the fadc signal due to the pedestlas is
1331 // intorduced
1332 // This is done inside the class MFadc by the method Pedestals
1333 fadc.Pedestals();
1334
1335 // We study several trigger conditons
1336 if(Trigger_Loop){
1337 // Loop over trigger threshold
1338 for (int iconcount=0,ithrescount=Trigger_loop_lthres;ithrescount<=Trigger_loop_uthres;ithrescount++){
1339 for (i=0;i<TRIGGER_PIXELS;i++)
1340 fpixelthres[i]=(float) ithrescount;
1341 Trigger.SetThreshold(fpixelthres);
1342
1343 Trigger.Diskriminate();
1344 //
1345 // look if in all the signals in the trigger signal branch
1346 // is a possible Trigger. Therefore we habe to diskriminate all
1347 // the simulated analog signals (Method Diskriminate in class
1348 // MTrigger). We look simultanously for the moments at which
1349 // there are more than TRIGGER_MULTI pixels above the
1350 // CHANNEL_THRESHOLD.
1351 //
1352
1353 // Set trigger flags to zero
1354 Lev1=Lev2=0;
1355 btrigger=0;
1356
1357 // loop over multiplicity of trigger configuration
1358 for (imulticount=Trigger_loop_lmult;imulticount<=Trigger_loop_umult;imulticount++){
1359 Trigger.SetMultiplicity(imulticount);
1360 Trigger.ClearZero();
1361
1362 Lev0=(Short_t) Trigger.ZeroLevel();
1363 if (Lev0>0 || Write_All_Images || btrigger){
1364
1365 // loop over topologies
1366 for(itopocount=Trigger_loop_ltop;itopocount<=Trigger_loop_utop;itopocount++){
1367 Lev1=Lev2=0;
1368
1369 if(itopocount==0 && imulticount>7) continue;
1370 if(itopocount==2 && imulticount<3) continue;
1371 Trigger.SetTopology(itopocount);
1372 Trigger.ClearFirst();
1373
1374 //
1375 // Start the First Level Trigger simulation
1376 //
1377 Lev1=Trigger.FirstLevel();
1378 if (Write_McTrig)
1379 McTrig[iconcount]->SetFirstLevel (Lev1);
1380 if(Lev1>0) {
1381 btrigger= 1;
1382 ntriggerloop[ithrescount-Trigger_loop_lthres][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop]++;
1383 }
1384
1385 if(Lev1==0 && (Write_All_Images || btrigger)){
1386 btrigger= 1;
1387 Lev1=1;
1388 }
1389 numPix=0;
1390 for (Int_t ii=0;ii<Lev1;ii++){
1391 if (Write_McTrig)
1392 McTrig[iconcount]->SetTime(Trigger.GetFirstLevelTime(ii),ii+1);
1393 if (Write_McTrig){
1394 Trigger.GetMapDiskriminator(trigger_map);
1395 McTrig[iconcount]->SetMapPixels(trigger_map,ii);
1396 }
1397 //
1398 // fill inside the class fadc the member output
1399 //
1400
1401 fadc.TriggeredFadc(Trigger.GetFirstLevelTime(ii));
1402
1403 if( Write_RawEvt ){
1404 //
1405 // Fill the header of this event
1406 //
1407
1408 EvtHeader[iconcount]->FillHeader ( (UInt_t) (ntshow + nshow),0);
1409 // fill pixel information
1410 for(i=0;i<ct_NPixels;i++){
1411 for (j=0;j<FADC_SLICES;j++){
1412 fadcValues->AddAt(fadc.GetFadcSignal(i,j),j);
1413 }
1414 EvtData[iconcount]->AddPixel(i+1000*ii,fadcValues,0);
1415 }
1416 }
1417 }
1418 //
1419 // Increase counter of analised trigger conditions
1420 //
1421 iconcount++;
1422 }
1423 }
1424 else{
1425 break;
1426 }
1427 }
1428 if (!btrigger) break;
1429 }
1430 if (btrigger){
1431
1432 //
1433 // fill the MMcEvt with all information
1434 //
1435
1436 if (Write_McEvt) {
1437 McEvt->Fill( (UShort_t) mcevth.get_primary() ,
1438 mcevth.get_energy(),
1439 mcevth.get_theta(),
1440 mcevth.get_phi(),
1441 mcevth.get_core(),
1442 mcevth.get_coreX(),
1443 mcevth.get_coreY(),
1444 impactD,
1445 (UInt_t)mcevth.get_CORSIKA(),
1446 (UInt_t)mcevth.get_AtmAbs(),
1447 (UInt_t)mcevth.get_MirrAbs()+mcevth.get_OutOfMirr()+mcevth.get_BlackSpot(),
1448 (UInt_t) ncph,
1449 (UInt_t) inumphe,
1450 (UInt_t) inumphensb+inumphe);
1451 }
1452 // Fill the Tree with the current leaves of each branch
1453 i=EvtTree.Fill() ;
1454
1455 // Clear the branches
1456 if(Write_McTrig){
1457 for(i=0;i<icontrigger;i++){
1458 McTrig[i]->Clear() ;
1459 }
1460 }
1461 if( Write_RawEvt ){
1462 for(i=0;i<icontrigger;i++){
1463 EvtHeader[i]->Clear() ;
1464 EvtData[i]->DeletePixels();
1465 }
1466 }
1467 if (Write_McEvt)
1468 McEvt->Clear() ;
1469 }
1470 }
1471 // We study a single trigger condition
1472 else {
1473
1474 // Setting trigger conditions
1475 Trigger.SetMultiplicity(Trigger_multiplicity);
1476 Trigger.SetTopology(Trigger_topology);
1477 for (i=0;i<TRIGGER_PIXELS;i++)
1478 fpixelthres[i]=Trigger_threshold;
1479 Trigger.SetThreshold(fpixelthres);
1480
1481 Trigger.Diskriminate() ;
1482
1483 //
1484 // look if in all the signals in the trigger signal branch
1485 // is a possible Trigger. Therefore we habe to diskriminate all
1486 // the simulated analog signals (Method Diskriminate in class
1487 // MTrigger). We look simultanously for the moments at which
1488 // there are more than TRIGGER_MULTI pixels above the
1489 // CHANNEL_THRESHOLD.
1490 //
1491
1492 Lev0 = (Short_t) Trigger.ZeroLevel() ;
1493
1494 Lev1 = Lev2 = 0 ;
1495
1496 //
1497 // Start the First Level Trigger simulation
1498 //
1499
1500 if ( Lev0 > 0 || Write_All_Images) {
1501 Lev1= Trigger.FirstLevel();
1502 if (Write_McTrig)
1503 McTrig[0]->SetFirstLevel (Lev1);
1504 }
1505 if (Lev1>0){
1506 ++ntrigger;
1507 }
1508 if (Lev1==0 && Write_All_Images){
1509 Lev1=1;
1510 }
1511
1512 numPix=0;
1513 for(Int_t ii=0;ii<Lev1;ii++){
1514 // Loop over different level one triggers
1515
1516 //
1517 // fill inside class fadc the member output
1518 //
1519 fadc.TriggeredFadc(Trigger.GetFirstLevelTime(ii));
1520
1521 if (Write_McTrig)
1522 McTrig[0]->SetTime(Trigger.GetFirstLevelTime(ii),ii+1);
1523
1524 if (Write_McTrig){
1525 Trigger.GetMapDiskriminator(trigger_map);
1526 McTrig[0]->SetMapPixels(trigger_map,ii);
1527 }
1528
1529 // Fill Evt information
1530
1531 if (Write_RawEvt){
1532
1533 //
1534 // Fill the header of this event
1535 //
1536
1537 EvtHeader[0]->FillHeader ( (UShort_t) (ntshow + nshow) , 20 ) ;
1538
1539 // fill pixel information
1540
1541 for(i=0;i<ct_NPixels;i++){
1542 for (j=0;j<FADC_SLICES;j++){
1543 fadcValues->AddAt(fadc.GetFadcSignal(i,j),j);
1544 }
1545 EvtData[0]->AddPixel(i+ii*1000,fadcValues,0);
1546 }
1547 }
1548 //
1549 // fill the MMcEvt with all information
1550 //
1551
1552 if (Write_McEvt){
1553 McEvt->Fill( (UShort_t) mcevth.get_primary() ,
1554 mcevth.get_energy(),
1555 mcevth.get_theta(),
1556 mcevth.get_phi(),
1557 mcevth.get_core(),
1558 mcevth.get_coreX(),
1559 mcevth.get_coreY(),
1560 impactD,
1561 (UInt_t)mcevth.get_CORSIKA(),
1562 (UInt_t)mcevth.get_AtmAbs(),
1563 (UInt_t)mcevth.get_MirrAbs()+mcevth.get_OutOfMirr()+mcevth.get_BlackSpot(),
1564 (UInt_t) ncph,
1565 (UInt_t) inumphe,
1566 (UInt_t) inumphensb+inumphe);
1567 }
1568 // We don not count photons out of the camera.
1569
1570
1571 //
1572 // write it out to the file outfile
1573 //
1574
1575 EvtTree.Fill() ;
1576
1577 //
1578 // if a first level trigger occurred, then
1579 // 1. do some other stuff (not implemented)
1580 // 2. start the gui tool
1581
1582 if(FADC_Scan){
1583 if ( Lev0 > 0 ) {
1584 fadc.ShowSignal( McEvt, (Float_t) 60. ) ;
1585 }
1586 }
1587
1588 if(Trigger_Scan){
1589 if ( Lev0 > 0 ) {
1590 Trigger.ShowSignal(McEvt) ;
1591 }
1592 }
1593
1594 // clear all
1595 if (Write_RawEvt) EvtHeader[0]->Clear() ;
1596 if (Write_RawEvt) EvtData[0]->DeletePixels();
1597 if (Write_McEvt) McEvt->Clear() ;
1598 }
1599 if (Write_McTrig) McTrig[0]->Clear() ;
1600 }
1601
1602#ifdef __DEBUG__
1603 printf("\n");
1604
1605 for ( ici=0; ici<PIX_ARRAY_SIDE; ++ici ) {
1606
1607 for ( icj=0; icj<PIX_ARRAY_SIDE; ++icj ) {
1608
1609 if ( (int)pixels[ici][icj][PIXNUM] > -1 ) {
1610
1611 if ( fnpix[(int)pixels[ici][icj][PIXNUM]] > 0. ) {
1612
1613 printf ("@@ %4d %4d %10f %10f %4f (%4d %4d)\n", nshow,
1614 (int)pixels[ici][icj][PIXNUM],
1615 pixels[ici][icj][PIXX],
1616 pixels[ici][icj][PIXY],
1617 fnpix[(int)pixels[ici][icj][PIXNUM]], ici, icj);
1618
1619 }
1620 }
1621 }
1622 }
1623
1624 for (i=0; i<ct_NPixels; ++i) {
1625 printf("%d (%d): ", i, npixneig[i]);
1626 for (j=0; j<npixneig[i]; ++i)
1627 printf(" %d", pixneig[i][j]);
1628 printf("\n");
1629 }
1630
1631#endif // __DEBUG__
1632
1633
1634 // look for the next event
1635
1636 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1637
1638 } // end while there is a next event
1639
1640 if( !isA( flag, FLAG_END_OF_RUN )){
1641 error( SIGNATURE, "Expected end of run flag, but found: %s\n", flag );
1642 }
1643 else { // found end of run
1644 ntshow += nshow;
1645 log(SIGNATURE, "End of this run with %d events . . .\n", nshow);
1646
1647 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1648
1649 if( isA( flag, FLAG_END_OF_FILE ) ){ // end of file
1650 log(SIGNATURE, "End of file . . .\n");
1651 still_in_loop = FALSE;
1652
1653 if ((! Data_From_STDIN) && ( !feof(inputfile) )){
1654
1655 // we have concatenated input files.
1656 // get signature of the next part and check it.
1657
1658 if(check_reflector_file( inputfile )==FALSE){
1659 exit(1);
1660 }
1661
1662 }
1663
1664 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1665
1666 } // end if found end of file
1667 } // end if found end of run
1668
1669 } // end if else found start of run
1670 } // end big while loop
1671
1672 //++
1673 // put the Event to the root file
1674 //--
1675
1676 outfile_temp.Write() ;
1677 outfile_temp.Close() ;
1678
1679
1680 // close input file
1681
1682 log( SIGNATURE, "%d event(s), with a total of %d C.photons\n",
1683 ntshow, ntcph );
1684 datafile<<ntshow<<" event(s), with a total of "<<ntcph<<" C.photons"<<endl;
1685 if (Trigger_Loop){
1686 log( SIGNATURE, "Trigger Mode. \n");
1687 log( SIGNATURE, "Fraction of triggers: \n");
1688 datafile<<"Fraction of triggers: "<<endl;
1689 for (ithrescount=Trigger_loop_lthres;ithrescount<=Trigger_loop_uthres;ithrescount++){
1690 for (imulticount=Trigger_loop_lmult;imulticount<=Trigger_loop_umult;imulticount++){
1691 for(itopocount=Trigger_loop_ltop;itopocount<=Trigger_loop_utop;itopocount++){
1692 log( SIGNATURE, "Thres %d, Multi %d, Topo %d: %5.1f%% (%d out of %d)\n",
1693 ithrescount,imulticount,itopocount,((float)ntriggerloop[ithrescount-Trigger_loop_lthres][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop] / ((float)ntshow) * 100.0), ntriggerloop[ithrescount-Trigger_loop_lthres][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop], ntshow);
1694 datafile<<"Thres "<<ithrescount<<", Multi "<<imulticount<<", Topo"<<itopocount<<": ";
1695 datafile<<((float)ntriggerloop[ithrescount-Trigger_loop_lthres][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop] / ((float)ntshow) * 100.0)<<"% ("<<ntriggerloop[ithrescount-Trigger_loop_lthres][imulticount-Trigger_loop_lmult][itopocount-Trigger_loop_ltop]<<" out of "<<ntshow<<")"<<endl;
1696 }
1697 }
1698 }
1699 }
1700 else{
1701 log( SIGNATURE, "Fraction of triggers: %5.1f%% (%d out of %d)\n",
1702 ((float)ntrigger) / ((float)ntshow) * 100.0, ntrigger, ntshow);
1703 datafile<<"Fraction of triggers: "<<((float)ntrigger) / ((float)ntshow) * 100.0<<" ("<<ntrigger<<" out of "<<ntshow<<" )"<<endl;
1704 }
1705
1706 // close files
1707
1708 log( SIGNATURE, "Closing files\n" );
1709
1710 if( ! Data_From_STDIN ){
1711 fclose( inputfile );
1712 }
1713 datafile.close();
1714
1715 // program finished
1716
1717 log( SIGNATURE, "Done.\n");
1718
1719 return( 0 );
1720}
1721//!@}
1722
1723// @T \newpage
1724
1725//!@subsection Functions definition.
1726
1727//!-----------------------------------------------------------
1728// @name present
1729//
1730// @desc Make some presentation
1731//
1732// @date Sat Jun 27 05:58:56 MET DST 1998
1733//------------------------------------------------------------
1734// @function
1735
1736//!@{
1737void
1738present(void)
1739{
1740 cout << "##################################################\n"
1741 << SIGNATURE << '\n' << '\n'
1742 << "Processor of the reflector output\n"
1743 << "J C Gonzalez, Jun 1998\n"
1744 << "##################################################\n\n"
1745 << flush ;
1746}
1747//!@}
1748
1749
1750//!-----------------------------------------------------------
1751// @name usage
1752//
1753// @desc show help
1754//
1755// @date Tue Dec 15 16:23:30 MET 1998
1756//------------------------------------------------------------
1757// @function
1758
1759//!@{
1760void
1761usage(void)
1762{
1763 present();
1764 cout << "\nusage ::\n\n"
1765 << "\t camera "
1766 << " [ -@ paramfile ] "
1767 << " [ -h ] "
1768 << "\n\n or \n\n"
1769 << "\t camera < paramfile"
1770 << "\n\n";
1771 exit(0);
1772}
1773//!@}
1774
1775
1776//!-----------------------------------------------------------
1777// @name log
1778//
1779// @desc function to send log information
1780//
1781// @var funct Name of the caller function
1782// @var fmt Format to be used (message)
1783// @var ... Other information to be shown
1784//
1785// @date Sat Jun 27 05:58:56 MET DST 1998
1786//------------------------------------------------------------
1787// @function
1788
1789//!@{
1790void
1791log(const char *funct, char *fmt, ...)
1792{
1793 va_list args;
1794
1795 // Display the name of the function that called error
1796 printf("[%s]: ", funct);
1797
1798 // Display the remainder of the message
1799 va_start(args, fmt);
1800 vprintf(fmt, args);
1801 va_end(args);
1802}
1803//!@}
1804
1805
1806//!-----------------------------------------------------------
1807// @name error
1808//
1809// @desc function to send an error message, and abort the program
1810//
1811// @var funct Name of the caller function
1812// @var fmt Format to be used (message)
1813// @var ... Other information to be shown
1814//
1815// @date Sat Jun 27 05:58:56 MET DST 1998
1816//------------------------------------------------------------
1817// @function
1818
1819//!@{
1820void
1821error(const char *funct, char *fmt, ...)
1822{
1823 va_list args;
1824
1825 // Display the name of the function that called error
1826 fprintf(stdout, "ERROR in %s: ", funct);
1827
1828 // Display the remainder of the message
1829 va_start(args, fmt);
1830 vfprintf(stdout, fmt, args);
1831 va_end(args);
1832
1833 perror(funct);
1834
1835 exit(1);
1836}
1837//!@}
1838
1839
1840//!-----------------------------------------------------------
1841// @name isA
1842//
1843// @desc returns TRUE(FALSE), if the flag is(is not) the given
1844//
1845// @var s1 String to be searched
1846// @var flag Flag to compare with string s1
1847// @return TRUE: both strings match; FALSE: oth.
1848//
1849// @date Wed Jul 8 15:25:39 MET DST 1998
1850//------------------------------------------------------------
1851// @function
1852
1853//!@{
1854int
1855isA( char * s1, const char * flag ) {
1856 return ( (strncmp((char *)s1, flag, SIZE_OF_FLAGS)==0) ? 1 : 0 );
1857}
1858//!@}
1859
1860
1861//!-----------------------------------------------------------
1862// @name read_ct_file
1863//
1864// @desc read CT definition file
1865//
1866// @date Sat Jun 27 05:58:56 MET DST 1998
1867//------------------------------------------------------------
1868// @function
1869
1870//!@{
1871void
1872read_ct_file(void)
1873{
1874 char line[LINE_MAX_LENGTH]; //@< line to get from the ctin
1875 char token[ITEM_MAX_LENGTH]; //@< a single token
1876 int i, j; //@< dummy counters
1877
1878 log( "read_ct_file", "start.\n" );
1879
1880 ifstream ctin ( ct_filename );
1881
1882 if ( ctin.bad() )
1883 error( "read_ct_file",
1884 "Cannot open CT def. file: %s\n", ct_filename );
1885
1886 // loop till the "end" directive is reached
1887
1888 while (!ctin.eof()) {
1889
1890 // get line from stdin
1891
1892 ctin.getline(line, LINE_MAX_LENGTH);
1893
1894 // look for each item at the beginning of the line
1895
1896 for (i=0; i<=define_mirrors; i++)
1897 if (strstr(line, CT_ITEM_NAMES[i]) == line)
1898 break;
1899
1900 // if it is not a valid line, just ignore it
1901
1902 if (i == define_mirrors+1)
1903 continue;
1904
1905 // case block for each directive
1906
1907 switch ( i ) {
1908
1909 case type: // <type of telescope> (0:CT1 ¦ 1:MAGIC)
1910
1911 // get focal distance
1912
1913 sscanf(line, "%s %d", token, &ct_Type);
1914
1915 log( "read_ct_file", "<Type of Telescope>: %s\n",
1916 ((ct_Type==0) ? "CT1" : "MAGIC") );
1917
1918 break;
1919
1920 case focal_distance: // <focal distance> [cm]
1921
1922 // get focal distance
1923
1924 sscanf(line, "%s %f", token, &ct_Focal_mean);
1925
1926 log( "read_ct_file", "<Focal distance>: %f cm\n", ct_Focal_mean );
1927
1928 break;
1929
1930 case focal_std: // s(focal distance) [cm]
1931
1932 // get focal distance
1933
1934 sscanf(line, "%s %f", token, &ct_Focal_std);
1935
1936 log( "read_ct_file", "s(Focal distance): %f cm\n", ct_Focal_std );
1937
1938 break;
1939
1940 case point_spread: // <point spread> [cm]
1941
1942 // get point spread
1943
1944 sscanf(line, "%s %f", token, &ct_PSpread_mean);
1945
1946 log( "read_ct_file", "<Point spread>: %f cm\n", ct_PSpread_mean );
1947
1948 break;
1949
1950 case point_std: // s(point spread) [cm]
1951
1952 // get point spread
1953
1954 sscanf(line, "%s %f", token, &ct_PSpread_std);
1955
1956 log( "read_ct_file", "s(Point spread): %f cm\n", ct_PSpread_std );
1957
1958 break;
1959
1960 case adjustment_dev: // s(adjustment_dev) [cm]
1961
1962 // get point spread
1963
1964 sscanf(line, "%s %f", token, &ct_Adjustment_std);
1965
1966 log( "read_ct_file", "s(Adjustment): %f cm\n", ct_Adjustment_std );
1967
1968 break;
1969
1970 case black_spot: // radius of the black spot in the center [cm]
1971
1972 // get black spot radius
1973
1974 sscanf(line, "%s %f", token, &ct_BlackSpot_rad);
1975
1976 log( "read_ct_file", "Radius of the black spots: %f cm\n",
1977 ct_BlackSpot_rad);
1978
1979 break;
1980
1981 case r_mirror: // radius of the mirrors [cm]
1982
1983 // get radius of mirror
1984
1985 sscanf(line, "%s %f", token, &ct_RMirror);
1986
1987 log( "read_ct_file", "Radii of the mirrors: %f cm\n", ct_RMirror );
1988
1989 break;
1990
1991 case n_mirrors: // number of mirrors
1992
1993 // get the name of the output_file from the line
1994
1995 sscanf(line, "%s %d", token, &ct_NMirrors);
1996
1997 log( "read_ct_file", "Number of mirrors: %d\n", ct_NMirrors );
1998
1999 break;
2000
2001 case camera_width: // camera width [cm]
2002
2003 // get the name of the ct_file from the line
2004
2005 sscanf(line, "%s %f", token, &ct_CameraWidth);
2006
2007 log( "read_ct_file", "Camera width: %f cm\n", ct_CameraWidth );
2008
2009 break;
2010
2011 case n_pixels: // number of pixels
2012
2013 // get the name of the output_file from the line
2014
2015 sscanf(line, "%s %d", token, &ct_NPixels);
2016
2017 log( "read_ct_file", "Number of pixels: %d\n", ct_NPixels );
2018
2019 break;
2020
2021 case n_centralpixels: // number of central pixels
2022
2023 // get the name of the output_file from the line
2024
2025 sscanf(line, "%s %d", token, &ct_NCentralPixels);
2026
2027 log( "read_ct_file", "Number of central pixels: %d\n", ct_NCentralPixels );
2028
2029 break;
2030
2031 case n_gappixels: // number of gap pixels
2032
2033 // get the name of the output_file from the line
2034
2035 sscanf(line, "%s %d", token, &ct_NGapPixels);
2036
2037 log( "read_ct_file", "Number of gap pixels: %d\n", ct_NGapPixels );
2038
2039 break;
2040
2041 case pixel_width: // pixel width [cm]
2042
2043 // get the name of the ct_file from the line
2044
2045 sscanf(line, "%s %f", token, &ct_PixelWidth);
2046
2047 ct_PixelWidth_corner_2_corner = ct_PixelWidth / cos(RAD(30.0));
2048 ct_PixelWidth_corner_2_corner_half =
2049 ct_PixelWidth_corner_2_corner * 0.50;
2050 ct_Apot = ct_PixelWidth / 2;
2051 ct_2Apot = ct_Apot * 2.0;
2052
2053 log( "read_ct_file", "Pixel width: %f cm\n", ct_PixelWidth );
2054
2055 break;
2056
2057 case define_mirrors: // read table with the parameters of the mirrors
2058
2059 log( "read_ct_file", "Table of mirrors data:\n" );
2060
2061 // check whether the number of mirrors was already set
2062
2063 if ( ct_NMirrors == 0 )
2064 error( "read_ct_file", "NMirrors was not set.\n" );
2065
2066 // allocate memory for paths list
2067
2068 log( "read_ct_file", "Allocating memory for ct_data\n" );
2069
2070 ct_data = new float*[ct_NMirrors];
2071
2072 for (i=0; i<ct_NMirrors; i++)
2073 ct_data[i] = new float[CT_NDATA];
2074
2075 // read data
2076
2077 log( "read_ct_file", "Reading mirrors data...\n" );
2078
2079 for (i=0; i<ct_NMirrors; i++)
2080 for (j=0; j<CT_NDATA; j++)
2081 ctin >> ct_data[i][j];
2082
2083 break;
2084
2085 } // switch ( i )
2086
2087 } // end while
2088
2089 // end
2090
2091 log( "read_ct_file", "done.\n" );
2092
2093 return;
2094}
2095//!@}
2096
2097
2098//!-----------------------------------------------------------
2099// @name read_pixels
2100//
2101// @desc read pixels data
2102//
2103// @date Fri Mar 12 16:33:34 MET 1999
2104//------------------------------------------------------------
2105// @function
2106
2107//!@{
2108void
2109read_pixels(struct camera *pcam)
2110{
2111 ifstream qefile;
2112 char line[LINE_MAX_LENGTH];
2113 int n, i, j, icount;
2114 float qe;
2115
2116 //------------------------------------------------------------
2117 // first, pixels' coordinates
2118
2119 pcam->inumpixels = ct_NPixels;
2120 pcam->inumcentralpixels = ct_NCentralPixels;
2121 pcam->inumgappixels = ct_NGapPixels;
2122 pcam->inumbigpixels = ct_NPixels - ct_NCentralPixels - ct_NGapPixels;
2123 pcam->dpixdiameter_cm = ct_PixelWidth;
2124
2125 // initialize pixel numbers
2126
2127 pixary = new float* [2*ct_NCentralPixels];
2128 for ( i=0; i<2*ct_NCentralPixels; ++i )
2129 pixary[i] = new float[2];
2130
2131 pixneig = new int* [ct_NCentralPixels];
2132 for ( i=0; i<ct_NCentralPixels; ++i ) {
2133 pixneig[i] = new int[6];
2134 for ( j=0; j<6; ++j )
2135 pixneig[i][j] = -1;
2136 }
2137
2138 npixneig = new int[ct_NCentralPixels];
2139 for ( i=0; i<ct_NCentralPixels; ++i )
2140 npixneig[i] = 0;
2141
2142 // generate all coordinates
2143
2144 igen_pixel_coordinates(pcam);
2145
2146
2147 // calculate tables of neighbours
2148
2149#ifdef __DEBUG__
2150 for ( n=0 ; n<ct_NPixels ; ++n ) {
2151 cout << "Para el pixel " << n << ": ";
2152 for ( i=n+1 ; (i<ct_NPixels)&&(npixneig[n]<6) ; ++i) {
2153 if ( pixels_are_neig(n,i) == TRUE ) {
2154 pixneig[n][npixneig[n]] = i;
2155 pixneig[i][npixneig[i]] = n;
2156 cout << i << ' ';
2157 ++npixneig[n];
2158 ++npixneig[i];
2159 }
2160 }
2161 cout << endl << flush;
2162 }
2163#else // ! __DEBUG__
2164 for ( n=0 ; n<ct_NCentralPixels ; ++n )
2165 for ( i=n+1 ; (i<ct_NCentralPixels)&&(npixneig[n]<6) ; ++i)
2166 if ( pixels_are_neig(n,i) == TRUE ) {
2167 pixneig[n][npixneig[n]] = i;
2168 pixneig[i][npixneig[i]] = n;
2169 ++npixneig[n];
2170 ++npixneig[i];
2171 }
2172#endif // ! __DEBUG__
2173
2174#ifdef __DEBUG__
2175 for ( n=0 ; n<ct_NPixels ; ++n ) {
2176 cout << n << ':';
2177 for ( j=0; j<npixneig[n]; ++j)
2178 cout << ' ' << pixneig[n][j];
2179 cout << endl << flush;
2180 }
2181#endif // __DEBUG__
2182
2183 //------------------------------------------------------------
2184 // second, pixels' QE
2185
2186 // try to open the file
2187
2188 log("read_pixels", "Opening the file \"%s\" . . .\n", QE_FILE);
2189
2190 qefile.open( QE_FILE );
2191
2192 // if it is wrong or does not exist, exit
2193
2194 if ( qefile.bad() )
2195 error( "read_pixels", "Cannot open \"%s\". Exiting.\n", QE_FILE );
2196
2197 // read file
2198
2199 log("read_pixels", "Reading data . . .\n");
2200
2201 i=-1;
2202 icount = 0;
2203
2204 while ( ! qefile.eof() ) {
2205
2206 // get line from the file
2207
2208 qefile.getline(line, LINE_MAX_LENGTH);
2209
2210 // skip if comment
2211
2212 if ( *line == '#' )
2213 continue;
2214
2215 // if it is the first valid value, it is the number of QE data points
2216
2217 if ( i < 0 ) {
2218
2219 // get the number of datapoints
2220
2221 sscanf(line, "%d", &pointsQE);
2222
2223 // allocate memory for the table of QEs
2224
2225 QE = new float ** [ct_NPixels];
2226
2227 for ( i=0; i<ct_NPixels; ++i ) {
2228 QE[i] = new float * [2];
2229 QE[i][0] = new float[pointsQE];
2230 QE[i][1] = new float[pointsQE];
2231 }
2232
2233 QElambda = new float [pointsQE];
2234
2235 for ( i=0; i<pointsQE; ++i ) {
2236 qefile.getline(line, LINE_MAX_LENGTH);
2237 sscanf(line, "%f", &QElambda[i]);
2238 }
2239
2240 i=0;
2241
2242 continue;
2243 }
2244
2245 // get the values (num-pixel, num-datapoint, QE-value)
2246
2247 if( sscanf(line, "%d %d %f", &i, &j, &qe) != 3 )
2248 break;
2249
2250 if ( ((i-1) < ct_NPixels) && ((i-1) > -1) &&
2251 ((j-1) < pointsQE) && ((j-1) > -1) ) {
2252 QE[i-1][0][j-1] = QElambda[j-1];
2253 QE[i-1][1][j-1] = qe;
2254 }
2255
2256 if ( i > ct_NPixels) break;
2257
2258 icount++;
2259
2260 }
2261
2262 if(icount/pointsQE < ct_NPixels){
2263 error( "read_pixels", "The quantum efficiency file is faulty\n (found only %d pixels instead of %d).\n",
2264 icount/pointsQE, ct_NPixels );
2265 }
2266
2267 // close file
2268
2269 qefile.close();
2270
2271 // test QE
2272
2273 for(icount=0; icount< ct_NPixels; icount++){
2274 for(i=0; i<pointsQE; i++){
2275 if( QE[icount][0][i] < 100. || QE[icount][0][i] > 1000. ||
2276 QE[icount][1][i] < 0. || QE[icount][1][i] > 100.){
2277 error( "read_pixels", "The quantum efficiency file is faulty\n pixel %d, point %d is % f, %f\n",
2278 icount, i, QE[icount][0][i], QE[icount][1][i] );
2279 }
2280 }
2281 }
2282
2283 // end
2284
2285 log("read_pixels", "Done.\n");
2286
2287}
2288//!@}
2289
2290
2291//!-----------------------------------------------------------
2292// @name pixels_are_neig
2293//
2294// @desc check whether two pixels are neighbours
2295//
2296// @var pix1 Number of the first pixel
2297// @var pix2 Number of the second pixel
2298// @return TRUE: both pixels are neighbours; FALSE: oth.
2299//
2300// @date Wed Sep 9 17:58:37 MET DST 1998
2301//------------------------------------------------------------
2302// @function
2303
2304//!@{
2305int
2306pixels_are_neig(int pix1, int pix2)
2307{
2308 if ( sqrt(SQR( pixary[pix1][0] - pixary[pix2][0] ) +
2309 SQR( pixary[pix1][1] - pixary[pix2][1] ) )
2310 > ct_PixelWidth_corner_2_corner )
2311 return ( FALSE );
2312 else
2313 return ( TRUE );
2314}
2315//!@}
2316
2317//!-----------------------------------------------------------
2318// @name igen_pixel_coordinates
2319//
2320// @desc generate the pixel center coordinates
2321//
2322// @var *pcam structure camera containing all the
2323// camera information
2324// @return total number of pixels
2325//
2326// DP
2327//
2328// @date Thu Oct 14 10:41:03 CEST 1999
2329//------------------------------------------------------------
2330// @function
2331
2332//!@{
2333/******** igen_pixel_coordinates() *********************************/
2334
2335int igen_pixel_coordinates(struct camera *pcam) {
2336 /* generate pixel coordinates, return value is number of pixels */
2337
2338 int i, itot_inside_ring, iN, in, ipixno, iring_no, ipix_in_ring, isegment;
2339 float fsegment_fract;
2340 double dtsize;
2341 double dhsize;
2342 double dpsize;
2343 double dxfirst_pix;
2344 double dyfirst_pix;
2345 double ddxseg1, ddxseg2, ddxseg3, ddxseg4, ddxseg5, ddxseg6;
2346 double ddyseg1, ddyseg2, ddyseg3, ddyseg4, ddyseg5, ddyseg6;
2347
2348
2349 double dstartx, dstarty; /* for the gap pixels and outer pixels */
2350 int j, nrow;
2351
2352 dpsize = pcam->dpixdiameter_cm;
2353 dtsize = dpsize * sqrt(3.) / 2.;
2354 dhsize = dpsize / 2.;
2355
2356 /* Loop over central pixels to generate co-ordinates */
2357
2358 for(ipixno=1; ipixno <= pcam->inumcentralpixels; ipixno++){
2359
2360 /* Initialise variables. The central pixel = ipixno 1 in ring iring_no 0 */
2361
2362 pcam->dpixsizefactor[ipixno-1] = 1.;
2363
2364 in = 0;
2365
2366 i = 0;
2367 itot_inside_ring = 0;
2368 iring_no = 0;
2369
2370 /* Calculate the number of pixels out to and including the ring containing pixel number */
2371 /* ipixno e.g. for pixel number 17 in ring number 2 itot_inside_ring = 19 */
2372
2373 while (itot_inside_ring == 0){
2374
2375 iN = 3*(i*(i+1)) + 1;
2376
2377 if (ipixno <= iN){
2378 iring_no = i;
2379 itot_inside_ring = iN;
2380 }
2381
2382 i++;
2383 }
2384
2385
2386 /* Find the number of pixels which make up ring number iring_no e.g. ipix_in_ring = 6 for ring 1 */
2387
2388 ipix_in_ring = 0;
2389 for (i = 0; i < iring_no; ++i){
2390
2391 ipix_in_ring = ipix_in_ring + 6;
2392 }
2393
2394 /* The camera is viewed as 6 radial segments ("pie slices"). Knowing the number of pixels in its */
2395 /* ring calculate which segment the pixel ipixno is in. Then find how far across this segment it is */
2396 /* as a fraction of the number of pixels in this sixth of the ring (ask SMB). */
2397
2398 isegment = 0;
2399 fsegment_fract = 0.;
2400 if (iring_no > 0) {
2401
2402 isegment = (int)((ipixno - itot_inside_ring + ipix_in_ring - 0.5) / iring_no + 1); /* integer division ! numbering starts at 1 */
2403
2404 fsegment_fract = (ipixno - (itot_inside_ring - ipix_in_ring)) - ((isegment-1)*iring_no) - 1 ;
2405
2406 }
2407
2408 /* the first pixel in each ring lies on the positive x axis at a distance dxfirst_pix = iring_no * the */
2409 /* pixel width (flat to flat) dpsize. */
2410
2411 dxfirst_pix = dpsize*iring_no;
2412 dyfirst_pix = 0.;
2413
2414 /* the vector between the first and last pixels in a segment n is (ddxsegn, ddysegn) */
2415
2416 ddxseg1 = - dhsize*iring_no;
2417 ddyseg1 = dtsize*iring_no;
2418 ddxseg2 = -dpsize*iring_no;
2419 ddyseg2 = 0.;
2420 ddxseg3 = ddxseg1;
2421 ddyseg3 = -ddyseg1;
2422 ddxseg4 = -ddxseg1;
2423 ddyseg4 = -ddyseg1;
2424 ddxseg5 = -ddxseg2;
2425 ddyseg5 = 0.;
2426 ddxseg6 = -ddxseg1;
2427 ddyseg6 = ddyseg1;
2428
2429 /* to find the position of pixel ipixno take the position of the first pixel in the ring and move */
2430 /* anti-clockwise around the ring by adding the segment to segment vectors. */
2431
2432 switch (isegment) {
2433
2434 case 0:
2435
2436 pcam->dxc[ipixno-1] = 0.;
2437 pcam->dyc[ipixno-1] = 0.;
2438
2439 case 1:
2440 pcam->dxc[ipixno-1] = dxfirst_pix - dhsize*fsegment_fract;
2441 pcam->dyc[ipixno-1] = dyfirst_pix + dtsize*fsegment_fract;
2442
2443 break;
2444
2445 case 2:
2446
2447 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 - dpsize*fsegment_fract;
2448 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + 0.;
2449
2450 break;
2451
2452 case 3:
2453
2454 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 - dhsize*fsegment_fract;
2455 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 - dtsize*fsegment_fract;
2456
2457 break;
2458
2459 case 4:
2460
2461 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + dhsize*fsegment_fract;
2462 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 - dtsize*fsegment_fract;
2463
2464 break;
2465
2466 case 5:
2467
2468 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + ddxseg4 + dpsize*fsegment_fract;
2469 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 + ddyseg4 + 0.;
2470
2471 break;
2472
2473 case 6:
2474
2475 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + ddxseg4 + ddxseg5 + dhsize*fsegment_fract;
2476 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 + ddyseg4 + ddyseg5 + dtsize*fsegment_fract;
2477
2478 break;
2479
2480 default:
2481
2482 fprintf(stderr, "ERROR: problem in coordinate generation for pixel %d\n", ipixno);
2483 return(0);
2484
2485 } /* end switch */
2486
2487 } /* end for */
2488
2489 dstartx = pcam->dxc[pcam->inumcentralpixels - 1] + dhsize;
2490 dstarty = pcam->dyc[pcam->inumcentralpixels - 1] + dtsize;
2491
2492 if(pcam->inumgappixels > 0){ /* generate the positions of the gap pixels */
2493
2494 j = pcam->inumcentralpixels;
2495
2496 for(i=0; i<pcam->inumgappixels; i=i+6){
2497 pcam->dxc[j + i ] = dstartx + 2. * (i/6 + 1) * dpsize;
2498 pcam->dyc[j + i ] = dstarty;
2499 pcam->dpixsizefactor[j + i] = 1.;
2500 pcam->dxc[j + i + 1] = pcam->dxc[j + i ] / 2.;
2501 pcam->dyc[j + i + 1] = sqrt(3.) * pcam->dxc[j + i + 1];
2502 pcam->dpixsizefactor[j + i + 1] = 1.;
2503 pcam->dxc[j + i + 2] = - pcam->dxc[j + i + 1];
2504 pcam->dyc[j + i + 2] = pcam->dyc[j + i + 1];
2505 pcam->dpixsizefactor[j + i+ 2] = 1.;
2506 pcam->dxc[j + i + 3] = - pcam->dxc[j + i];
2507 pcam->dyc[j + i + 3] = dstarty;
2508 pcam->dpixsizefactor[j + i+ 3] = 1.;
2509 pcam->dxc[j + i + 4] = pcam->dxc[j + i + 2];
2510 pcam->dyc[j + i + 4] = - pcam->dyc[j + i + 2];
2511 pcam->dpixsizefactor[j + i+ 4] = 1.;
2512 pcam->dxc[j + i + 5] = pcam->dxc[j + i + 1];
2513 pcam->dyc[j + i + 5] = - pcam->dyc[j + i + 1];
2514 pcam->dpixsizefactor[j + i + 5] = 1.;
2515 } /* end for */
2516 } /* end if */
2517
2518 /* generate positions of the outer pixels */
2519
2520 if( pcam->inumbigpixels > 0 ){
2521
2522 j = pcam->inumcentralpixels + pcam->inumgappixels;
2523
2524 for(i=0; i<pcam->inumbigpixels; i++){
2525 pcam->dpixsizefactor[j + i] = 2.;
2526 }
2527
2528 in = 0;
2529
2530 nrow = (int) ceil(dstartx / 2. / dpsize);
2531
2532 while(in < pcam->inumbigpixels){
2533
2534 pcam->dxc[j + in] = dstartx + dpsize;
2535 pcam->dyc[j + in] = dstarty + 2 * dpsize / sqrt(3.);
2536 pcam->dxc[j + in + nrow] = dstartx / 2. - dpsize / 2.;
2537 pcam->dyc[j + in + nrow] = sqrt(3.)/2. * dstartx + 2.5 * dpsize/sqrt(3.);
2538 pcam->dxc[j + in + 3 * nrow - 1] = - pcam->dxc[j + in];
2539 pcam->dyc[j + in + 3 * nrow - 1] = pcam->dyc[j + in];
2540 pcam->dxc[j + in + 3 * nrow] = - pcam->dxc[j + in];
2541 pcam->dyc[j + in + 3 * nrow] = - pcam->dyc[j + in];
2542 pcam->dxc[j + in + 5 * nrow - 1] = pcam->dxc[j + in + nrow];
2543 pcam->dyc[j + in + 5 * nrow - 1] = - pcam->dyc[j + in + nrow];
2544 pcam->dxc[j + in + 6 * nrow - 1] = pcam->dxc[j + in];
2545 pcam->dyc[j + in + 6 * nrow - 1] = - pcam->dyc[j + in];
2546 for(i=1; i<nrow; i++){
2547 pcam->dxc[j + in + i] = pcam->dxc[j + in] - i * dpsize;
2548 pcam->dyc[j + in + i] = pcam->dyc[j + in] + i * dpsize * sqrt(3.);
2549 pcam->dxc[j + in + i + nrow] = pcam->dxc[j + in + nrow] - i * 2 * dpsize;
2550 pcam->dyc[j + in + i + nrow] = pcam->dyc[j + in + nrow];
2551 pcam->dxc[j + in + 3 * nrow - 1 - i] = - pcam->dxc[j + in + i];
2552 pcam->dyc[j + in + 3 * nrow - 1- i] = pcam->dyc[j + in + i];
2553 pcam->dxc[j + in + i + 3 * nrow] = - pcam->dxc[j + in + i];
2554 pcam->dyc[j + in + i + 3 * nrow] = - pcam->dyc[j + in + i];
2555 pcam->dxc[j + in + 5 * nrow - 1 - i] = pcam->dxc[j + in + i + nrow];
2556 pcam->dyc[j + in + 5 * nrow - 1 - i] = - pcam->dyc[j + in + i + nrow];
2557 pcam->dxc[j + in + 6 * nrow - 1 - i] = pcam->dxc[j + in + i];
2558 pcam->dyc[j + in + 6 * nrow - 1 - i] = - pcam->dyc[j + in + i];
2559 }
2560 in = in + 6 * nrow;
2561 dstartx = dstartx + 2. * dpsize;
2562 nrow = nrow + 1;
2563 } /* end while */
2564
2565 } /* end if */
2566
2567 return(pcam->inumpixels);
2568
2569}
2570//!@}
2571
2572//!-----------------------------------------------------------
2573// @name bpoint_is_in_pix
2574//
2575// @desc check if a point (x,y) in camera coordinates is inside a given pixel
2576//
2577// @var *pcam structure camera containing all the
2578// camera information
2579// @var dx, dy point coordinates in centimeters
2580// @var ipixnum pixel number (starting at 0)
2581// @return TRUE if the point is inside the pixel, FALSE otherwise
2582//
2583// DP
2584//
2585// @date Thu Oct 14 16:59:04 CEST 1999
2586//------------------------------------------------------------
2587// @function
2588
2589//!@{
2590
2591/******** bpoint_is_in_pix() ***************************************/
2592
2593int bpoint_is_in_pix(double dx, double dy, int ipixnum, struct camera *pcam){
2594 /* return TRUE if point (dx, dy) is in pixel number ipixnum, else return FALSE (use camera coordinate system) */
2595 /* the pixel is assumed to be a "closed set" */
2596
2597 double a, b; /* a = length of one of the edges of one pixel, b = half the width of one pixel */
2598 double c, xx, yy; /* auxiliary variable */
2599
2600 b = pcam->dpixdiameter_cm / 2. * pcam->dpixsizefactor[ipixnum];
2601 a = pcam->dpixdiameter_cm / sqrt(3.) * pcam->dpixsizefactor[ipixnum];
2602 c = 1./sqrt(3.);
2603
2604 if((ipixnum < 0)||(ipixnum >= pcam->inumpixels)){
2605 fprintf(stderr, "Error in bpoint_is_in_pix: invalid pixel number %d\n", ipixnum);
2606 fprintf(stderr, "Exiting.\n");
2607 exit(203);
2608 }
2609 xx = dx - pcam->dxc[ipixnum];
2610 yy = dy - pcam->dyc[ipixnum];
2611
2612 if(((-b <= xx) && (xx <= 0.) && ((-c * xx - a) <= yy) && (yy <= ( c * xx + a))) ||
2613 ((0. < xx) && (xx <= b ) && (( c * xx - a) <= yy) && (yy <= (-c * xx + a))) ){
2614 return(TRUE); /* point is inside */
2615 }
2616 else{
2617 return(FALSE); /* point is outside */
2618 }
2619}
2620
2621//!@}
2622
2623//------------------------------------------------------------
2624// @name dist_r_P
2625//
2626// @desc distance straight line r - point P
2627//
2628// @date Sat Jun 27 05:58:56 MET DST 1998
2629// @function @code
2630//------------------------------------------------------------
2631// dist_r_P
2632//
2633// distance straight line r - point P
2634//------------------------------------------------------------
2635
2636float
2637dist_r_P(float a, float b, float c,
2638 float l, float m, float n,
2639 float x, float y, float z)
2640{
2641 return (
2642 sqrt((SQR((a-x)*m-(b-y)*l) +
2643 SQR((b-y)*n-(c-z)*m) +
2644 SQR((c-z)*l-(a-x)*n))/
2645 (SQR(l)+SQR(m)+SQR(n))
2646 )
2647 );
2648}
2649
2650//------------------------------------------------------------
2651// @name check_reflector_file
2652//
2653// @desc check if a given reflector file has the right signature
2654// @desc return TRUE or FALSE
2655//
2656// @date Mon Feb 14 16:44:21 CET 2000
2657// @function @code
2658//------------------------------------------------------------
2659
2660int check_reflector_file(FILE *infile){
2661
2662 char Signature[20]; // auxiliary variable
2663 char sign[20]; // auxiliary variable
2664
2665 strcpy(Signature, REFL_SIGNATURE);
2666
2667 strcpy(sign, Signature);
2668
2669 fread( (char *)sign, strlen(Signature), 1, infile);
2670
2671 if (strcmp(sign, Signature) != 0) {
2672 cout << "ERROR: Signature of .rfl file is not correct\n";
2673 cout << '"' << sign << '"' << '\n';
2674 cout << "should be: " << Signature << '\n';
2675 return(FALSE);
2676 }
2677
2678 fread( (char *)sign, 1, 1, infile);
2679
2680 return(TRUE);
2681
2682}
2683
2684//------------------------------------------------------------
2685// @name lin_interpol
2686//
2687// @desc interpolate linearly between two points returning the
2688// @desc y-value of the result
2689//
2690// @date Thu Feb 17 11:31:32 CET 2000
2691// @function @code
2692//------------------------------------------------------------
2693
2694float lin_interpol( float x1, float y1, float x2, float y2, float x){
2695
2696 if( (x2 - x1)<=0. ){ // avoid division by zero, return average
2697 cout << "Warning: lin_interpol was asked to interpolate between two points with x1>=x2.\n";
2698 return((y1+y2)/2.);
2699 }
2700 else{ // note: the check whether x1 < x < x2 is omitted for speed reasons
2701 return((float) (y1 + (y2-y1)/(x2-x1)*(x-x1)) );
2702 }
2703}
2704
2705
2706//------------------------------------------------------------
2707// @name produce_phes
2708//
2709// @desc read the photons of an event, pixelize them and simulate QE
2710// @desc return various statistics and the array of Photoelectrons
2711//
2712// @date Mon Feb 14 16:44:21 CET 2000
2713// @function @code
2714//------------------------------------------------------------
2715
2716int produce_phes( FILE *sp, // the input file
2717 struct camera *cam, // the camera layout
2718 float minwl_nm, // the minimum accepted wavelength
2719 float maxwl_nm, // the maximum accepted wavelength
2720 class MTrigger *trigger, // the generated phes
2721 class MFadc *fadc,
2722 int *itotnphe, // total number of produced photoelectrons
2723 float nphe[iMAXNUMPIX], // number of photoelectrons in each pixel
2724 int *incph, // total number of cph read
2725 float *tmin_ns, // minimum arrival time of all phes
2726 float *tmax_ns // maximum arrival time of all phes
2727 ){
2728
2729 static int i, k, ipixnum;
2730 static float cx, cy, wl, qe, t;
2731 static MCCphoton photon;
2732 static float **qept;
2733 static char flag[SIZE_OF_FLAGS + 1];
2734 static float radius;
2735
2736
2737 // reset variables
2738
2739 for ( i=0; i<cam->inumpixels; ++i ){
2740
2741 nphe[i] = 0.0;
2742
2743 }
2744
2745 *incph = 0;
2746
2747 radius = cam->dxc[cam->inumpixels-1]
2748 + 1.5*cam->dpixdiameter_cm*cam->dpixsizefactor[cam->inumpixels-1];
2749
2750 //- - - - - - - - - - - - - - - - - - - - - - - - -
2751 // read photons and "map" them into the pixels
2752 //--------------------------------------------------
2753
2754 // initialize CPhoton
2755
2756 photon.fill(0., 0., 0., 0., 0., 0., 0., 0.);
2757
2758 // read the photons data
2759
2760 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2761
2762 // loop over the photons
2763
2764 while ( !isA( flag, FLAG_END_OF_EVENT ) ) {
2765
2766 memcpy( (char*)&photon, flag, SIZE_OF_FLAGS );
2767
2768 fread( ((char*)&photon)+SIZE_OF_FLAGS, photon.mysize()-SIZE_OF_FLAGS, 1, sp );
2769
2770 // increase number of photons
2771
2772 (*incph)++;
2773
2774 // Chceck if photon is inside trigger time range
2775
2776 t = photon.get_t() ;
2777
2778 if (t-*tmin_ns>TOTAL_TRIGGER_TIME) {
2779
2780 // read next Photon
2781
2782 fread( flag, SIZE_OF_FLAGS, 1, sp );
2783
2784 // go to beginning of loop, the photon is lost
2785 continue;
2786 }
2787
2788 //
2789 // Pixelization
2790 //
2791
2792 cx = photon.get_x();
2793 cy = photon.get_y();
2794
2795 // get wavelength
2796
2797 wl = photon.get_wl();
2798
2799 // cout << "wl " << wl << " radius " << sqrt(cx*cx + cy*cy) << "\n";
2800
2801 // check if photon has valid wavelength and is inside outermost camera radius
2802
2803 if( (wl > maxwl_nm) || (wl < minwl_nm) || (sqrt(cx*cx + cy*cy) > radius ) ){
2804
2805 // cout << " lost first check\n";
2806
2807 // read next CPhoton
2808
2809 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2810
2811 // go to beginning of loop, the photon is lost
2812 continue;
2813
2814 }
2815
2816 ipixnum = -1;
2817
2818 for(i=0; i<cam->inumpixels; i++){
2819 if( bpoint_is_in_pix( cx, cy, i, cam) ){
2820 ipixnum = i;
2821 break;
2822 }
2823 }
2824
2825 if(ipixnum==-1){// the photon is in none of the pixels
2826
2827 // cout << " lost pixlization\n";
2828
2829 // read next CPhoton
2830
2831 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2832
2833 // go to beginning of loop, the photon is lost
2834 continue;
2835 }
2836
2837 if(ipixnum==0) {// the phton is in the central pixel, which is not used for trigger
2838 // read next CPhoton
2839
2840 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2841
2842 // go to beginning of loop, the photon is lost
2843 continue;
2844 }
2845 //+++
2846 // QE simulation
2847 //---
2848
2849 // set pointer to the QE table of the relevant pixel
2850
2851 qept = (float **)QE[ipixnum];
2852
2853 // check if wl is inside table; outside the table, QE is assumed to be zero
2854
2855 if((wl < qept[0][0]) || (wl > qept[0][pointsQE-1])){
2856
2857 // cout << " lost\n";
2858
2859 // read next Photon
2860
2861 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2862
2863 // go to beginning of loop
2864 continue;
2865
2866 }
2867
2868 // find data point in the QE table (-> k)
2869
2870 k = 1; // start at 1 because the condition was already tested for 0
2871 while (k < pointsQE-1 && qept[0][k] < wl){
2872 k++;
2873 }
2874
2875 // calculate the qe value between 0. and 1.
2876
2877 qe = lin_interpol(qept[0][k-1], qept[1][k-1], qept[0][k], qept[1][k], wl) / 100.0;
2878
2879 // if random > quantum efficiency, reject it
2880
2881 if ( (RandomNumber) > qe ) {
2882
2883 // cout << " lost\n";
2884
2885 // read next Photon
2886
2887 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2888
2889 // go to beginning of loop
2890 continue;
2891
2892 }
2893
2894 //+++
2895 // The photon has produced a photo electron
2896 //---
2897
2898 // cout << " accepted\n";
2899
2900 // increment the number of photoelectrons in the relevant pixel
2901
2902 nphe[ipixnum] += 1.0;
2903
2904 // store the new photoelectron
2905
2906 fadc->Fill(ipixnum,(t-*tmin_ns) , trigger->FillShow(ipixnum,t-*tmin_ns));
2907
2908 *itotnphe += 1;
2909
2910 // read next Photon
2911
2912 fread( flag, SIZE_OF_FLAGS, 1, sp );
2913
2914 } // end while, i.e. found end of event
2915
2916 return(0);
2917
2918}
2919
2920
2921//------------------------------------------------------------
2922// @name produce_nsbrates
2923//
2924// @desc read the starfield file, call produce_phes on it in,
2925// @desc different wavebands, calculate the nsbrates
2926//
2927// @date Mon Feb 14 16:44:21 CET 2000
2928// @function @code
2929//------------------------------------------------------------
2930
2931int produce_nsbrates( char *iname, // the starfield input file name
2932 struct camera *cam, // camera layout
2933 float rate_phepns[iMAXNUMPIX][iNUMWAVEBANDS] // the product of this function:
2934 // the NSB rates in phe/ns for each pixel
2935 ){
2936
2937 int i, j, k, ii; // counters
2938
2939 MTrigger trigger(Trigger_gate_length, Trigger_overlaping_time, Trigger_response_ampl, Trigger_response_fwhm);
2940 MFadc flashadc;
2941
2942 static float wl_nm[iNUMWAVEBANDS + 1] = { WAVEBANDBOUND1,
2943 WAVEBANDBOUND2,
2944 WAVEBANDBOUND3,
2945 WAVEBANDBOUND4,
2946 WAVEBANDBOUND5,
2947 WAVEBANDBOUND6 };
2948
2949 FILE *infile; // the input file
2950 fpos_t fileposition; // marker on the input file
2951 static char cflag[SIZE_OF_FLAGS + 1]; // auxiliary variable
2952 static MCEventHeader evth; // the event header
2953 static float nphe[iMAXNUMPIX]; // the number of photoelectrons in each pixel
2954 int itnphe; // total number of produced photoelectrons
2955 int itotnphe; // total number of produced photoelectrons after averaging
2956 int incph; // total number of cph read
2957 float tmin_ns; // minimum arrival time of all phes
2958 float tmax_ns; // maximum arrival time of all phes
2959 float integtime_ns; // integration time from the starfield generator
2960
2961 // open input file
2962
2963 log(SIGNATURE, "Opening starfield input \"rfl\" file %s\n", iname );
2964
2965 infile = fopen( iname, "r" );
2966
2967 // check if the satrfield input file exists
2968
2969 if ( infile == NULL ) {
2970
2971 log( SIGNATURE, "Cannot open starfield input file: %s\n", iname );
2972
2973 log( SIGNATURE, "There is not NSB from the Stars\n");
2974
2975 return (0);
2976 }
2977
2978 // get signature, and check it
2979
2980 if(check_reflector_file(infile)==FALSE){
2981 exit(1);
2982 }
2983
2984 // initialize flag
2985
2986 strcpy( cflag, " \0" );
2987
2988 // get flag
2989
2990 fread( cflag, SIZE_OF_FLAGS, 1, infile );
2991
2992 if ( ! feof(infile)){
2993
2994 // reading .rfl file
2995
2996 if(!isA( cflag, FLAG_START_OF_RUN )){
2997 error( SIGNATURE, "Expected start of run flag, but found: %s\n", cflag );
2998 }
2999 else { // found start of run
3000
3001 fread( cflag, SIZE_OF_FLAGS, 1, infile );
3002
3003 if( isA( cflag, FLAG_START_OF_EVENT )){ // there is a event
3004
3005 // get MCEventHeader
3006
3007 fread( (char*)&evth, evth.mysize(), 1, infile );
3008
3009 integtime_ns = evth.get_energy();
3010
3011 // memorize where we are in the file
3012
3013 if (fgetpos( infile, &fileposition ) != 0){
3014 error( SIGNATURE, "Cannot position in file ...\n");
3015 }
3016
3017 // loop over the wavebands
3018
3019 for(i=0; i<iNUMWAVEBANDS; i++){
3020
3021 // initialize the rate array
3022
3023 for(j = 0; j<cam->inumpixels; j++){ // loop over pixels
3024 rate_phepns[j][i] = 0.;
3025 }
3026
3027 itotnphe = 0;
3028
3029 // read the photons and produce the photoelectrons
3030 // - in order to average over the QE simulation, call the
3031 // production function iNUMNSBPRODCALLS times
3032
3033 for(ii=0; ii<iNUMNSBPRODCALLS; ii++){
3034
3035 // position the file pointer to the beginning of the photons
3036
3037 fsetpos( infile, &fileposition);
3038
3039 // produce photoelectrons
3040
3041 k = produce_phes( infile,
3042 cam,
3043 wl_nm[i],
3044 wl_nm[i+1],
3045 &trigger, // this is a dummy here
3046 &flashadc, // this is a dummy here
3047 &itnphe,
3048 nphe, // we want this!
3049 &incph,
3050 &tmin_ns,
3051 &tmax_ns );
3052
3053 if( k != 0 ){ // non-zero returnvalue means error
3054 cout << "Exiting.\n";
3055 exit(1);
3056 }
3057
3058 for(j = 0; j<cam->inumpixels; j++){ // loop over pixels
3059 rate_phepns[j][i] += nphe[j]/integtime_ns/(float)iNUMNSBPRODCALLS;
3060 }
3061
3062 itotnphe += itnphe;
3063
3064 } // end for(ii=0 ...
3065
3066 fprintf(stdout, "Starfield, %6f - %6f nm: %d photoelectrons for %6f ns integration time\n",
3067 wl_nm[i], wl_nm[i+1], itotnphe/iNUMNSBPRODCALLS, integtime_ns);
3068
3069 } // end for(i=0 ...
3070
3071 }
3072 else{
3073 cout << "Starfield file contains no event.\nExiting.\n";
3074 exit(1);
3075 } // end if( isA ... event
3076 } // end if ( isA ... run
3077 }
3078 else{
3079 cout << "Starfield file contains no run.\nExiting.\n";
3080 exit(1);
3081 }
3082
3083 fclose( infile );
3084
3085 return(0);
3086
3087}
3088
3089
3090//------------------------------------------------------------
3091// @name produce_nsb_phes
3092//
3093// @desc produce the photoelectrons from the nsbrates
3094//
3095// @date Thu Feb 17 17:10:40 CET 2000
3096// @function @code
3097//------------------------------------------------------------
3098
3099int produce_nsb_phes( float *atmin_ns,
3100 float *atmax_ns,
3101 float theta_rad,
3102 struct camera *cam,
3103 float nsbr_phepns[iMAXNUMPIX][iNUMWAVEBANDS],
3104 float difnsbr_phepns[iMAXNUMPIX],
3105 float extinction[iNUMWAVEBANDS],
3106 float fnpx[iMAXNUMPIX],
3107 MTrigger *trigger,
3108 MFadc *fadc,
3109 int *inphe,
3110 float base_mv[iMAXNUMPIX]){
3111
3112 float simtime_ns; // NSB simulation time
3113 int i, j, k, ii;
3114 float zenfactor; // correction factor calculated from the extinction
3115 int inumnsbphe; // number of photoelectrons caused by NSB
3116
3117 float t;
3118 TRandom random; // Random numbers generator
3119
3120 random.SetSeed ((UInt_t) (RandomNumber*1000));
3121
3122 ii = *inphe; // avoid dereferencing
3123
3124 // check if the arrival times are set; if not generate them
3125
3126 if(*atmin_ns <SIMTIMEOFFSET_NS || *atmin_ns > *atmax_ns){
3127 *atmin_ns = 0.;
3128 *atmax_ns = simtime_ns = TOTAL_TRIGGER_TIME;
3129
3130 }
3131 else{ // extend the event time window by the given offsets
3132
3133 *atmin_ns = *atmin_ns - SIMTIMEOFFSET_NS;
3134 *atmax_ns = *atmax_ns + SIMTIMEOFFSET_NS;
3135
3136 simtime_ns = *atmax_ns - *atmin_ns;
3137
3138 // make sure the simulated time is long enough for the FADC
3139 // simulation and not too long
3140
3141 if(simtime_ns< TOTAL_TRIGGER_TIME){
3142 *atmin_ns = *atmin_ns -(TOTAL_TRIGGER_TIME-simtime_ns)/2;
3143 *atmax_ns = *atmin_ns + TOTAL_TRIGGER_TIME;
3144 simtime_ns = TOTAL_TRIGGER_TIME;
3145 }
3146
3147 if(simtime_ns> TOTAL_TRIGGER_TIME){
3148 *atmax_ns =*atmin_ns + TOTAL_TRIGGER_TIME;
3149 simtime_ns = TOTAL_TRIGGER_TIME;
3150 }
3151
3152 }
3153
3154 // initialize baselines
3155
3156 for(i=0; i<cam->inumpixels; i++){
3157 base_mv[i] = 0.;
3158 }
3159
3160 // calculate baselines and generate phes
3161
3162 for(i=0; i<iNUMWAVEBANDS; i++){ // loop over the wavebands
3163
3164 // calculate the effect of the atmospheric extinction
3165
3166 zenfactor = pow(10., -0.4 * extinction[i]/cos(theta_rad) );
3167
3168 for(j=0; j<cam->inumpixels; j++){ // loop over the pixels
3169
3170 inumnsbphe = (int) ((zenfactor * nsbr_phepns[j][i] + difnsbr_phepns[j]/iNUMWAVEBANDS)
3171 * simtime_ns );
3172
3173 base_mv[j] += inumnsbphe;
3174
3175 // randomize
3176
3177 if (inumnsbphe>0.0){
3178 inumnsbphe = random.Poisson (inumnsbphe );
3179 }
3180
3181 // create the photoelectrons
3182
3183 for(k=0; k < inumnsbphe; k++){
3184
3185 t=(RandomNumber * simtime_ns);
3186
3187 (*fadc).Fill(j,t ,(*trigger).FillNSB(j,t));
3188
3189 ii++; // increment total number of photoelectons
3190
3191 fnpx[j] += 1.; // increment number of photoelectrons in this pixel
3192
3193 }
3194
3195 } // end for(j=0 ...
3196 } // end for(i=0 ...
3197
3198 // finish baseline calculation
3199
3200 for(i=0; i<cam->inumpixels; i++){
3201 base_mv[i] *= RESPONSE_FWHM * RESPONSE_AMPLITUDE / simtime_ns;
3202 }
3203
3204 *inphe = ii; // update the pointer
3205
3206 return(0);
3207}
3208
3209
3210// @endcode
3211
3212
3213//=------------------------------------------------------------
3214//!@subsection Log of this file.
3215
3216//!@{
3217//
3218// $Log: not supported by cvs2svn $
3219// Revision 1.23 2001/03/28 16:13:41 blanch
3220// While feeling the MMcFadeHeader branch the boolean conditoin was wrong. It has
3221// been solved.
3222//
3223// Revision 1.22 2001/03/20 18:52:43 blanch
3224// *** empty log message ***
3225//
3226// Revision 1.21 2001/03/19 19:53:03 blanch
3227// Some print outs have been removed.
3228//
3229// Revision 1.20 2001/03/19 19:30:06 magicsol
3230// Minor changes have been done to improve the FADC pedestals treatment.
3231//
3232// Revision 1.19 2001/03/05 11:14:41 magicsol
3233// I changed the position of readinf a parameter. It is a minnor change.
3234//
3235// Revision 1.18 2001/03/05 10:36:52 blanch
3236// A branch with information about the FADC simulation (MMcFadcHeader) is writen
3237// in the McHeaders tree of the aoutput root file.
3238// The NSB contribution is only applied if the the number of phe form the shower
3239// are above a given number.
3240//
3241// Revision 1.17 2001/02/23 11:05:57 magicsol
3242// Small changes due to slightly different output format and the introduction of
3243// pedesals for teh FADC.
3244//
3245// Revision 1.16 2001/01/18 18:44:40 magicsol
3246// *** empty log message ***
3247//
3248// Revision 1.15 2001/01/17 09:32:27 harald
3249// The changes are neccessary to have the same name for trees in MC and in
3250// data. So now there should be no differences in MC data and real data from
3251// FADC system.
3252//
3253// Revision 1.14 2001/01/15 12:33:34 magicsol
3254// Some modifications have been done to use the new (Dec'2000) Raw data format.
3255// There are also some minnors modifications to adapt the improvements in the
3256// MTrigger class (overlaping time and trigger cells).
3257//
3258// Revision 1.13 2000/10/25 08:14:23 magicsol
3259// The routine that produce poisson random numbers to decide how many phe
3260// form NSB are emmited in each pixel has been replaced. Now a ROOT routine
3261// is used.
3262//
3263// Revision 1.12 2000/09/22 17:40:18 harald
3264// Added a lot of changes done by oscar.
3265//
3266// Revision 1.11 2000/09/21 11:47:33 harald
3267// Oscar found some smaller errors in the calculation of the pixel shape and
3268// corrected it.
3269//
3270// $Log: not supported by cvs2svn $
3271// Revision 1.23 2001/03/28 16:13:41 blanch
3272// While feeling the MMcFadeHeader branch the boolean conditoin was wrong. It has
3273// been solved.
3274//
3275// Revision 1.22 2001/03/20 18:52:43 blanch
3276// *** empty log message ***
3277//
3278// Revision 1.21 2001/03/19 19:53:03 blanch
3279// Some print outs have been removed.
3280//
3281// Revision 1.20 2001/03/19 19:30:06 magicsol
3282// Minor changes have been done to improve the FADC pedestals treatment.
3283//
3284// Revision 1.19 2001/03/05 11:14:41 magicsol
3285// I changed the position of readinf a parameter. It is a minnor change.
3286//
3287// Revision 1.18 2001/03/05 10:36:52 blanch
3288// A branch with information about the FADC simulation (MMcFadcHeader) is writen
3289// in the McHeaders tree of the aoutput root file.
3290// The NSB contribution is only applied if the the number of phe form the shower
3291// are above a given number.
3292//
3293// Revision 1.17 2001/02/23 11:05:57 magicsol
3294// Small changes due to slightly different output format and the introduction of
3295// pedesals for teh FADC.
3296//
3297// Revision 1.16 2001/01/18 18:44:40 magicsol
3298// *** empty log message ***
3299//
3300// Revision 1.15 2001/01/17 09:32:27 harald
3301// The changes are neccessary to have the same name for trees in MC and in
3302// data. So now there should be no differences in MC data and real data from
3303// FADC system.
3304//
3305// Revision 1.14 2001/01/15 12:33:34 magicsol
3306// Some modifications have been done to use the new (Dec'2000) Raw data format.
3307// There are also some minnors modifications to adapt the improvements in the
3308// MTrigger class (overlaping time and trigger cells).
3309//
3310// Revision 1.13 2000/10/25 08:14:23 magicsol
3311// The routine that produce poisson random numbers to decide how many phe
3312// form NSB are emmited in each pixel has been replaced. Now a ROOT routine
3313// is used.
3314//
3315// Revision 1.10 2000/07/04 14:10:20 MagicSol
3316// Some changes have been done in the root output file. The RawEvt tree is only
3317// stored in the single trigger mode.
3318// The trigger input parameters are also given by the general input card.
3319// The diffuse NSB and the star NSB have been decoupled. Now the contribution of
3320// each one can be studied seperately.
3321//
3322// Revision 1.9 2000/06/13 13:25:24 blanch
3323// The multiple arrays have been replaced, since they do not work
3324// in alpha machines. Now we are using pointers and the command new
3325// to allocate memory.
3326//
3327// Revision 1.8 2000/05/11 13:57:27 blanch
3328// The option to loop over several trigger configurations has been included.
3329// Some non-sense with triggertime range has been solved.
3330// Montecarlo information and ADC counts are saved in a root file.
3331// There was a problem with the maximum number of phe that the program could analyse. Now there is not limit.
3332//
3333// Revision 1.7 2000/03/24 18:10:46 blanch
3334// A first FADC simulation and a trigger simulation are already implemented.
3335// The calculation of the Hillas Parameters have been removed, since it was decided that it should be in the analysis software.
3336// 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.
3337//
3338// Revision 1.6 2000/03/20 18:35:11 blanch
3339// 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.
3340//
3341// Revision 1.5 2000/02/18 17:40:35 petry
3342// This version includes drastic changes compared to camera.cxx 1.4.
3343// It is not yet finished and not immediately useful because the
3344// trigger simulation is not yet re-implemented. I had to take it
3345// out together with some other stuff in order to tidy the whole
3346// program up. This is not meant as an insult to anyone. I needed
3347// to do this in order to be able to work on it.
3348//
3349// This version has been put in the repository in order to be
3350// able to share the further development with others.
3351//
3352// If you need something working, wait or take an earlier one.
3353// See file README.
3354//
3355// Revision 1.4 2000/01/25 08:36:23 petry
3356// The pixelization in previous versions was buggy.
3357// This is the first version with a correct pixelization.
3358//
3359// Revision 1.3 2000/01/20 18:22:17 petry
3360// Found little bug which makes camera crash if it finds a photon
3361// of invalid wavelength. This bug is now fixed and the range
3362// of valid wavelengths extended to 290 - 800 nm.
3363// This is in preparation for the NSB simulation to come.
3364// Dirk
3365//
3366// Revision 1.2 1999/11/19 08:40:42 harald
3367// Now it is possible to compile the camera programm under osf1.
3368//
3369// Revision 1.1.1.1 1999/11/05 11:59:31 harald
3370// This the starting point for CVS controlled further developments of the
3371// camera program. The program was originally written by Jose Carlos.
3372// But here you can find a "rootified" version to the program. This means
3373// that there is no hbook stuff in it now. Also the output of the
3374// program changed to the MagicRawDataFormat.
3375//
3376// The "rootification" was done by Dirk Petry and Harald Kornmayer.
3377//
3378// Revision 1.3 1999/10/22 15:01:28 petry
3379// version sent to H.K. and N.M. on Fri Oct 22 1999
3380//
3381// Revision 1.2 1999/10/22 09:44:23 petry
3382// first synthesized version which compiles and runs without crashing;
3383//
3384// Revision 1.1.1.1 1999/10/21 16:35:10 petry
3385// first synthesised version
3386//
3387// Revision 1.13 1999/03/15 14:59:05 gonzalez
3388// camera-1_1
3389//
3390// Revision 1.12 1999/03/02 09:56:10 gonzalez
3391// *** empty log message ***
3392//
3393//
3394//!@}
3395
3396//=EOF
Note: See TracBrowser for help on using the repository browser.