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

Last change on this file since 702 was 696, checked in by blanch, 24 years ago
*** empty log message ***
File size: 92.3 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.22 $
24// $Author: blanch $
25// $Date: 2001-03-20 18:52:43 $
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 char inname[256]; //@< input file name
388 char starfieldname[256]; //@< starfield input file name
389
390 char datname[256]; //@< data (ASCII) output file name
391
392 char rootname[256] ; //@< ROOT file name
393 char rootname_loop[256] ; //@< ROOT file name
394
395 char parname[256]; //@< parameters file name
396
397 char nsbpathname[256]; //@< directory with the dataabse for th NSB
398
399 char flag[SIZE_OF_FLAGS + 1]; //@< flags in the .rfl file
400
401 FILE *inputfile; //@< stream for the input file
402 ofstream datafile; //@< stream for the data file
403
404 MCEventHeader mcevth; //@< Event Header class (MC)
405 MCCphoton cphoton; //@< Cherenkov Photon class (MC)
406
407 int inumphe; //@< number of photoelectrons in an event from showers
408 float inumphensb; //@< number of photoelectrons in an event from nsb
409
410 float arrtmin_ns; //@ arrival time of the first photoelectron
411 float arrtmax_ns; //@ arrival time of the last photoelectron
412
413 float thetaCT, phiCT; //@< parameters of a given shower
414 float thetashw, phishw; //@< parameters of a given shower
415 float coreD, coreX, coreY; //@< core position
416 float impactD; //@< impact parameter
417 float l1, m1, n1; //@< auxiliary variables
418 float l2, m2, n2; //@< auxiliary variables
419 float num, den; //@< auxiliary variables
420
421 int nshow=0; //@< partial number of shower in a given run
422 int ntshow=0; //@< total number of showers
423 int ncph=0; //@< partial number of photons in a given run
424 int ntcph=0; //@< total number of photons
425
426 int i, j, k; //@< simple counters
427
428 int simulateNSB; //@< Will we simulate NSB?
429 int nphe2NSB; //@< From how many ohe will we simulate NSB?
430 float meanNSB; //@< diffuse NSB mean value (phe per ns per central pixel)
431 float diffnsb_phepns[iMAXNUMPIX]; //@< diffuse NSB values for each pixel
432 //@< derived from meanNSB
433 float nsbrate_phepns[iMAXNUMPIX][iNUMWAVEBANDS]; //@< non-diffuse nsb
434 //@< photoelectron rates
435 float nsb_phepns[iMAXNUMPIX]; //@< NSB values for each pixel
436
437 Float_t nsb_trigresp[TRIGGER_TIME_SLICES]; //@< array to write the trigger
438 //@< response from the database
439 Float_t nsb_fadcresp[(Int_t) SLICES_MFADC]; //@< array to write the fadc
440 //@< response from the database
441 Byte_t trigger_map[((Int_t)(TRIGGER_PIXELS/8))+1];//@< Pixels on when the
442 //@< camera triggers
443 Float_t fadc_elecnoise[CAMERA_PIXELS]; //@< Electronic niose for each pixel
444 Float_t fadc_pedestals[CAMERA_PIXELS]; //@< array for fadc pedestals values
445
446 float ext[iNUMWAVEBANDS] = { //@< average atmospheric extinction in each waveband
447 EXTWAVEBAND1,
448 EXTWAVEBAND2,
449 EXTWAVEBAND3,
450 EXTWAVEBAND4,
451 EXTWAVEBAND5
452 };
453
454 float qThreshold; //@< Threshold value
455 float qTailCut; //@< Tail Cut value
456 int nIslandsCut; //@< Islands Cut value
457 int countIslands; //@< Will we count the islands?
458 int anaPixels;
459
460 float fCorrection; //@< Factor to apply to pixel values (def. 1.)
461
462 int ntrigger = 0; //@< number of triggers in the whole file
463 int btrigger = 0; //@< trigger flag
464 int ithrescount; //@< counter for loop over threshold trigger
465 int imulticount; //@< counter for loop over multiplicity trigger
466 int itopocount; //@< counter for loop over topology trigger
467 int icontrigger; //@< number of trigger conditions to be analised
468 UShort_t numPix; //@< number of sets of fadc written counts
469
470 float fpixelthres[TRIGGER_PIXELS];
471
472 TArrayC *fadcValues; //@< the analog Fadc siganl for pixels
473
474 float plateScale_cm2deg; //@< plate scale (deg/cm)
475 float degTriggerZone; //@< trigger area in the camera (radius, in deg.)
476
477 int still_in_loop = FALSE;
478
479 struct camera cam; // structure holding the camera definition
480
481
482 //!@' @#### Definition of variables for |getopt()|.
483 //@'
484
485 int ch, errflg = 0; //@< used by getopt
486
487 //!@' @#### Initialisation of some variables
488 //@'
489
490 for(i=0;i<iMAXNUMPIX;i++)
491 for(j=0;j<iNUMWAVEBANDS;j++)
492 nsbrate_phepns[i][j]=0.0; //@< Starlight rates initialised at 0.0
493
494 /*!@'
495
496 @#### Beginning of the program.
497
498 We start with the main program. First we (could) make some
499 presentation, and follows the reading of the parameters file (now
500 from the |stdin|), the reading of the CT parameters file, and the
501 creation of the output file, where the processed data will be
502 stored.
503
504 */
505
506 //++
507 // START
508 //--
509
510 // make unbuffered output
511
512 cout.setf ( ios::stdio );
513
514 // parse command line options (see reflector.h)
515
516 parname[0] = '\0';
517
518 optarg = NULL;
519 while ( !errflg && ((ch = getopt(argc, argv, COMMAND_LINE_OPTIONS)) != -1) )
520 switch (ch) {
521 case 'f':
522 strcpy(parname, optarg);
523 break;
524 case 'h':
525 usage();
526 break;
527 default :
528 errflg++;
529 }
530
531 // show help if error
532
533 if ( errflg>0 )
534 usage();
535
536 // make some sort of presentation
537
538 present();
539
540 // read parameters file
541
542 if ( strlen(parname) < 1 )
543 readparam(NULL);
544 else
545 readparam(parname);
546
547 // read data from file or from STDIN?
548
549 Data_From_STDIN = get_data_from_stdin();
550
551 // write all images, even those without trigger?
552
553 Write_All_Images = get_write_all_images();
554
555 // write all data (i.e., ph.e.s in pixels)
556
557 Write_All_Data = get_write_all_data();
558
559 Write_McEvt = get_write_McEvt() ;
560 Write_McTrig = get_write_McTrig() ;
561 Write_McFADC = get_write_McFadc() ;
562 Write_RawEvt = get_write_RawEvt() ;
563
564 FADC_Scan = get_FADC_Scan();
565 Trigger_Scan = get_Trigger_Scan();
566
567 get_FADC_properties( &FADC_response_ampl, &FADC_response_fwhm);
568
569 get_Trigger_properties( &Trigger_gate_length, &Trigger_overlaping_time, &Trigger_response_ampl, &Trigger_response_fwhm);
570
571 Trigger_Loop = get_Trigger_Loop(&Trigger_loop_lthres, &Trigger_loop_uthres, &Trigger_loop_lmult, &Trigger_loop_umult, &Trigger_loop_ltop, &Trigger_loop_utop);
572
573 icontrigger =(Trigger_loop_uthres-Trigger_loop_lthres+1)*
574 (Trigger_loop_umult-Trigger_loop_lmult+1)*
575 (Trigger_loop_utop-Trigger_loop_ltop+1);
576
577 if (!Trigger_Loop){
578 get_Trigger_Single (&Trigger_threshold, &Trigger_multiplicity, &Trigger_topology);
579 icontrigger=1;
580 }
581
582 // get filenames
583
584 strcpy( inname, get_input_filename() );
585 strcpy( starfieldname, get_starfield_filename() );
586 strcpy( datname, get_data_filename() );
587 strcpy( rootname, get_root_filename() );
588 strcpy( rootname_loop, get_loop_filename() );
589 strcpy( ct_filename, get_ct_filename() );
590 strcpy( nsbpathname, get_nsb_directory() );
591
592 // get different parameters of the simulation
593
594 qThreshold = get_threshold();
595 qTailCut = get_tail_cut();
596 simulateNSB = get_nsb( &meanNSB, &nphe2NSB );
597 countIslands = get_islands_cut( &nIslandsCut );
598
599 // get selections on the parameters
600
601 Select_Energy = get_select_energy( &Select_Energy_le, &Select_Energy_ue);
602
603 // log filenames information
604
605 log(SIGNATURE,
606 "%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",
607 "Filenames",
608 "In", inname,
609 "Stars", starfieldname,
610 "NSB database", nsbpathname,
611 "CT", ct_filename,
612 "Data", datname,
613 "ROOT", rootname
614 );
615
616 // log Trigger information
617
618 if (Trigger_Loop) {
619 log(SIGNATURE,
620 "%s:\n\t%20s: %i - %i\n\t%20s: %i - %i\n\t%20s: %i - %i\n\t%20s\n",
621 "Trigger Loop mode",
622 "Threshold",Trigger_loop_lthres,Trigger_loop_uthres,
623 "Multiplicity",Trigger_loop_lmult,Trigger_loop_umult,
624 "Topology",Trigger_loop_ltop,Trigger_loop_utop,
625 rootname_loop);
626 }
627 else{
628 log(SIGNATURE,
629 "%s:\n\t%20s: %f\n\t%20s: %i\n\t%20s: %i\n",
630 "Single Trigger mode",
631 "Threshold",Trigger_threshold,
632 "Multiplicity",Trigger_multiplicity,
633 "Topology",Trigger_topology);
634 }
635
636 // log flags information
637
638 log(SIGNATURE,
639 "%s:\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n",
640 "Flags",
641 "Data_From_STDIN", ONoff(Data_From_STDIN),
642 "Write_All_Images", ONoff(Write_All_Images),
643 "Write_All_Data", ONoff(Write_All_Data));
644
645 // log flags information
646
647 log(SIGNATURE,
648 "%s:\n\t%20s: %s\n\t%20s: %s\n\t%20s: %s\n",
649 "Root output",
650 "Write_McEvt", ONoff(Write_McEvt),
651 "Write_McTrig", ONoff(Write_McTrig),
652 "Write_McFADC", ONoff(Write_McFADC),
653 "Write_RawEvt", ONoff(Write_RawEvt));
654
655 // log parameters information
656
657 log(SIGNATURE,
658 "%s:\n\t%20s: %f\n\t%20s: %f\n\t%20s: %f %s\n\t%20s: %f %s\n",
659 "Parameters",
660 "q0 (Threshold)", qThreshold,
661 "t0 (Tail-cut)", qTailCut,
662 "NSB (phes/pixel)", meanNSB, ONoff(simulateNSB),
663 "i0 (Islands-cut)", nIslandsCut, ONoff(countIslands));
664
665 // log selections
666
667 log(SIGNATURE,
668 "%s:\n\t%20s: %s (%f:%f)\n",
669 "Selections:",
670 "Energy", ONoff(Select_Energy), Select_Energy_le, Select_Energy_ue);
671
672 // Definition and initialization of array to save trigger statistics
673
674 int ***ntriggerloop;
675
676 ntriggerloop= new int ** [(int) (Trigger_loop_uthres+1-Trigger_loop_lthres)];
677 for (ithrescount=0;ithrescount<=Trigger_loop_uthres-Trigger_loop_lthres;ithrescount++){
678 ntriggerloop[ithrescount]= new int * [Trigger_loop_umult-Trigger_loop_lmult+1];
679 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
680 ntriggerloop[ithrescount][imulticount]= new int [Trigger_loop_utop-Trigger_loop_ltop+1];
681 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
682 ntriggerloop[ithrescount][imulticount][itopocount]=0;
683 }
684 }
685 }
686
687 // set all random numbers seeds
688
689 setall( get_seeds(0), get_seeds(1) );
690
691 // get list of showers to evt. skip
692
693 nSkip = get_nskip_showers();
694
695 if (nSkip > 0) {
696 Skip = new int[ nSkip ];
697 get_skip_showers( Skip );
698
699 log(SIGNATURE, "There are some showers to skip:\n");
700 for (i=0; i<nSkip; ++i)
701 log(SIGNATURE, "\tshower # %d\n", Skip[i]);
702 }
703
704
705 // read parameters from the ct.def file
706
707 read_ct_file();
708
709 // read camera setup
710
711 read_pixels(&cam);
712
713 Int_t Lev0, Lev1, Lev2 ;
714
715 fadcValues = new TArrayC(FADC_SLICES);
716
717 // number of pixels for parameters
718
719 anaPixels = get_ana_pixels();
720 anaPixels = (anaPixels == -1) ? ct_NPixels : anaPixels;
721
722 // initialise ROOT
723
724 TROOT simple("simple", "MAGIC Telescope Monte Carlo");
725
726 // initialise instance of Trigger and FADC classes
727
728 MTrigger Trigger(Trigger_gate_length, Trigger_overlaping_time,
729 Trigger_response_ampl, Trigger_response_fwhm); //@< A instance of the Class MTrigger
730
731 // Initialise McTrig information class if we want to save trigger informtion
732
733 MMcTrig **McTrig;
734 MMcTrigHeader **HeaderTrig;
735 MMcFadcHeader **HeaderFadc;
736
737 if (Write_McTrig){
738
739 McTrig = new MMcTrig * [icontrigger];
740
741 for (i=0;i<icontrigger;i++) {
742 McTrig[i] = new MMcTrig();
743 }
744
745 HeaderTrig = new MMcTrigHeader * [icontrigger];
746
747 for (i=0;i<icontrigger;i++) {
748 HeaderTrig[i] = new MMcTrigHeader();
749 }
750 }
751
752 if (Write_McFADC){
753
754 HeaderFadc = new MMcFadcHeader * [icontrigger];
755
756 for (i=0;i<icontrigger;i++) {
757 HeaderFadc[i] = new MMcFadcHeader();
758 }
759 }
760
761 MFadc fadc(FADC_response_ampl,FADC_response_fwhm) ; //@< A instance of the Class MFadc
762
763 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
764 //
765 // Set the FADC pedestals for that run
766 // Some modifications
767 // mut be done to simulate a more realistic distribution of the pedestals.
768 // This simualtion is done int the SetPedestals methode inside the
769 // class MFadc
770 // Currentlly a input_pedestal array is declared with the pedestals.
771 // Thy can also be set randomly following a flat distribution.
772 //
773 /////////////////////////////////////////////////////////////////////
774
775 Float_t input_pedestals[CAMERA_PIXELS];
776
777 for(i=0;i<CAMERA_PIXELS;i++)
778 input_pedestals[i]=10.5;
779
780 fadc.SetPedestals(input_pedestals);
781
782 // Prepare the raw data output
783
784 // Header branch
785
786 MRawEvtHeader **EvtHeader;
787
788 if (Write_RawEvt) {
789 EvtHeader = new MRawEvtHeader * [icontrigger];
790
791 for (i=0;i<icontrigger;i++) {
792 EvtHeader[i] = new MRawEvtHeader();
793 }
794 }
795
796 // Data branch
797
798 MRawEvtData **EvtData; // Data branch
799
800 if (Write_RawEvt) {
801 EvtData = new MRawEvtData * [icontrigger];
802
803 for (i=0;i<icontrigger;i++) {
804 EvtData[i] = new MRawEvtData();
805 }
806 }
807
808 MMcEvt *McEvt = new MMcEvt ();
809
810 //
811 // initalize a temporal ROOT file
812 //
813
814 TFile outfile_temp ( rootname , "RECREATE" );
815
816 Int_t bsize=128000; Int_t split=1;
817
818 // create a Tree for the Header Event
819 TTree HeaderTree("McHeaders","Monte Carlo Header of Run");
820
821 // define branches of Header Tree
822
823 char help[4];
824
825 if(!Trigger_Loop && Write_McTrig){
826
827 HeaderTree.Branch("MMcTrigHeader","MMcTrigHeader",
828 &HeaderTrig[0], bsize, split);
829 }
830 if (Trigger_Loop && Write_McTrig){
831 for(char branchname[20],i=0;i<icontrigger;i++){
832
833 sprintf(help,"%i",i+1);
834 strcpy (branchname, "MMcTrigHeader");
835 strcat (branchname, & help[0]);
836 strcat (branchname, ".");
837 HeaderTree.Branch(branchname,"MMcTrigHeader",
838 &HeaderTrig[i], bsize, split);
839 }
840 }
841
842 if(!Trigger_Loop && Write_McFADC){
843
844 HeaderTree.Branch("MMcFadcHeader","MMcFadcHeader",
845 &HeaderFadc[0], bsize, split);
846 }
847 if (Trigger_Loop && Write_McFADC){
848 for(char branchname[20],i=0;i<icontrigger;i++){
849
850 sprintf(help,"%i",i+1);
851 strcpy (branchname, "MMcFadcHeader");
852 strcat (branchname, & help[0]);
853 strcat (branchname, ".");
854 HeaderTree.Branch(branchname,"MMcFadcHeader",
855 &HeaderFadc[i], bsize, split);
856 }
857 }
858
859 // Fill branches for MMcTrigHeader
860
861 if(!Trigger_Loop && Write_McTrig){
862
863 HeaderTrig[0]->SetTopology((Short_t) Trigger_topology);
864 HeaderTrig[0]->SetMultiplicity((Short_t) Trigger_multiplicity);
865 for(i=0;i<TRIGGER_PIXELS;i++){
866 fpixelthres[i]=(Float_t)Trigger_threshold;
867 }
868 HeaderTrig[0]->SetThreshold( fpixelthres);
869 HeaderTrig[0]->SetAmplitud(Trigger_response_ampl);
870 HeaderTrig[0]->SetFwhm(Trigger_response_fwhm);
871 HeaderTrig[0]->SetOverlap(Trigger_overlaping_time);
872 HeaderTrig[0]->SetGate(Trigger_gate_length);
873 }
874 if(Trigger_Loop && Write_McTrig){
875
876 for (int iconcount=0,ithrescount=0;ithrescount<=Trigger_loop_uthres-Trigger_loop_lthres;ithrescount++){
877 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
878 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
879 HeaderTrig[iconcount]->SetTopology((Short_t) itopocount+Trigger_loop_ltop);
880 HeaderTrig[iconcount]->SetMultiplicity((Short_t) imulticount+Trigger_loop_lmult);
881 for(i=0;i<TRIGGER_PIXELS;i++){
882 fpixelthres[i]=(Float_t)(ithrescount+Trigger_loop_lthres);
883 }
884 HeaderTrig[iconcount]->SetThreshold( fpixelthres);
885 HeaderTrig[iconcount]->SetAmplitud(Trigger_response_ampl);
886 HeaderTrig[iconcount]->SetFwhm(Trigger_response_fwhm);
887 HeaderTrig[iconcount]->SetOverlap(Trigger_overlaping_time);
888 HeaderTrig[iconcount]->SetGate(Trigger_gate_length);
889 iconcount++;
890 }
891 }
892 }
893 }
894
895 // Fill branches for MMcFadcHeader
896
897 for(i=0;i<CAMERA_PIXELS;i++){
898 fadc_elecnoise[i]=2.0;
899 }
900 fadc.GetPedestals(&fadc_pedestals[0]);
901
902 if(!Trigger_Loop && Write_McFADC){
903
904 HeaderFadc[0]->SetShape(0.0);
905 HeaderFadc[0]->SetAmplitud(FADC_response_ampl);
906 HeaderFadc[0]->SetFwhm(FADC_response_fwhm);
907 HeaderFadc[0]->SetPedestal(&fadc_pedestals[0],anaPixels);
908 HeaderFadc[0]->SetElecNoise(&fadc_elecnoise[0],anaPixels);
909 }
910 if(Trigger_Loop && Write_McTrig){
911
912 for (int iconcount=0,ithrescount=0;ithrescount<=Trigger_loop_uthres-Trigger_loop_lthres;ithrescount++){
913 for (imulticount=0;imulticount<=Trigger_loop_umult-Trigger_loop_lmult;imulticount++){
914 for(itopocount=0;itopocount<=Trigger_loop_utop-Trigger_loop_ltop;itopocount++){
915 HeaderFadc[iconcount]->SetShape(0.0);
916 HeaderFadc[iconcount]->SetAmplitud(Trigger_response_ampl);
917 HeaderFadc[iconcount]->SetFwhm(Trigger_response_fwhm);
918 HeaderFadc[iconcount]->SetPedestal(&fadc_pedestals[0],anaPixels);
919 HeaderFadc[iconcount]->SetElecNoise(&fadc_elecnoise[0],anaPixels);
920 iconcount++;
921 }
922 }
923 }
924 }
925
926 // Fill the Header Tree with the current leaves of each branch
927 HeaderTree.Fill() ;
928
929
930 // create a Tree for the Event data stream
931 TTree EvtTree("Events","Normal Triggered Events");
932
933 if (Write_McEvt){
934
935 EvtTree.Branch("MMcEvt","MMcEvt",
936 &McEvt, bsize, split);
937 }
938
939 if(!Trigger_Loop){
940
941 if (Write_RawEvt){
942 EvtTree.Branch("MRawEvtHeader","MRawEvtHeader",
943 &EvtHeader[0], bsize, split);
944 EvtTree.Branch("MRawEvtData","MRawEvtData",
945 &EvtData[0], bsize, split);
946 }
947 if (Write_McTrig){
948 EvtTree.Branch("MMcTrig","MMcTrig",
949 &McTrig[0], bsize, split);
950 }
951 }
952 else{
953 if (Write_McTrig){
954 for(char branchname[10],i=0;i<icontrigger;i++){
955
956 sprintf(help,"%i",i+1);
957 strcpy (branchname, "MMcTrig");
958 strcat (branchname, & help[0]);
959 strcat (branchname, ".");
960 EvtTree.Branch(branchname,"MMcTrig",
961 &McTrig[i], bsize, split);
962 }
963 }
964 }
965
966 if (Trigger_Loop && Write_RawEvt){
967 for(char branchname[15],i=0;i<icontrigger;i++){
968
969 sprintf(help,"%i",i+1);
970 strcpy (branchname, "MRawEvtHeader");
971 strcat (branchname, & help[0]);
972 strcat (branchname, ".");
973 EvtTree.Branch(branchname,"MRawEvtHeader",
974 &EvtHeader[i], bsize, split);
975 }
976 for(char branchname[15],i=0;i<icontrigger;i++){
977
978 sprintf(help,"%i",i+1);
979 strcpy (branchname, "MRawEvtData");
980 strcat (branchname, & help[0]);
981 strcat (branchname, ".");
982 EvtTree.Branch(branchname,"MRawEvtData",
983 &EvtData[i], bsize, split);
984 }
985 }
986
987 unsigned short ulli = 0 ;
988
989 TApplication theAppTrigger("App", &argc, argv);
990
991 if (gROOT->IsBatch()) {
992 fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]);
993 // return 1;
994 }
995
996 if(FADC_Scan){
997 TApplication theAppFadc("App", &argc, argv);
998
999 if (gROOT->IsBatch()) {
1000 fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]);
1001 // return 1;
1002 }
1003 }
1004
1005 // set plate scale (deg/cm) and trigger area (deg)
1006
1007 plateScale_cm2deg = ( ct_Type == 0 ) ? (0.244/2.1) : 0.030952381;
1008
1009 if ( ! get_trigger_radius( &degTriggerZone ) )
1010 degTriggerZone = ( ct_Type == 0 ) ? (5.0) : (5.0);
1011
1012 if ( ! get_correction( &fCorrection ) )
1013 fCorrection = 1.0;
1014
1015 // prepare the NSB simulation
1016
1017 // Instance of the Mlons class
1018 MLons lons(Trigger_response_ampl, Trigger_response_fwhm,
1019 MFADC_RESPONSE_AMPLITUDE, MFADC_RESPONSE_FWHM);
1020
1021 lons.SetPath(nsbpathname);
1022
1023 if( simulateNSB ){
1024
1025 //
1026 // Calculate the non-diffuse NSB photoelectron rates
1027 //
1028
1029 k = produce_nsbrates( starfieldname,
1030 &cam,
1031 nsbrate_phepns );
1032
1033 if (k != 0){
1034 cout << "Error when reading starfield... \nExiting.\n";
1035 exit(1);
1036 }
1037
1038 // calculate diffuse rate correcting for the pixel size
1039
1040 for(i=0; i<cam.inumpixels; i++){
1041 diffnsb_phepns[i] = meanNSB *
1042 cam.dpixsizefactor[i] * cam.dpixsizefactor[i];
1043 }
1044
1045 // calculate nsb rate including diffuse and starlight
1046 for(i=0; i<cam.inumpixels;i++){
1047 nsb_phepns[i]= diffnsb_phepns[i];
1048 for(j=0;j<iNUMWAVEBANDS;j++)
1049 nsb_phepns[i]=nsb_phepns[i]+ nsbrate_phepns[i][j];
1050 }
1051 }
1052
1053 //
1054 // Read the reflector file with the Cherenkov data
1055 //
1056
1057 // select input file
1058
1059 if ( Data_From_STDIN ) {
1060
1061 inputfile = stdin;
1062
1063 }
1064 else{
1065
1066 log( SIGNATURE, "Opening input \"rfl\" file %s\n", inname );
1067 inputfile = fopen( inname, "r" );
1068 if ( inputfile == NULL )
1069 error( SIGNATURE, "Cannot open input file: %s\n", inname );
1070
1071 }
1072
1073 // get signature, and check it
1074
1075 if(check_reflector_file( inputfile )==FALSE){
1076 exit(1);
1077 }
1078
1079 // open data file
1080
1081 log( SIGNATURE, "Opening data \"dat\" file %s\n", datname );
1082 datafile.open( datname );
1083
1084 if ( datafile.bad() )
1085 error( SIGNATURE, "Cannot open data file: %s\n", datname );
1086
1087 // initializes flag
1088
1089 strcpy( flag, " \0" );
1090
1091 // allocate space for PMTs numbers of pixels
1092
1093 fnpix = new float [ ct_NPixels ];
1094
1095
1096 //!@' @#### Main loop.
1097 //@'
1098
1099 // get flag
1100
1101 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1102
1103 // loop over the file
1104
1105 still_in_loop = TRUE;
1106
1107 while (
1108 ((! Data_From_STDIN) && ( !feof(inputfile) ))
1109 ||
1110 (Data_From_STDIN && still_in_loop)
1111 ) {
1112
1113 // reading .rfl files
1114 if(!isA( flag, FLAG_START_OF_RUN )){
1115
1116 // We exit
1117 //error( SIGNATURE, "Expected start of run flag, but found: %s\n", flag );
1118 // We break the main loop
1119 cout<<"Warning: Expected start of run flag, but found:"<<flag<<endl;
1120 cout<<" We break the main loop"<<endl;
1121 break;
1122 }
1123 else { // found start of run
1124
1125 nshow=0;
1126
1127 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1128
1129 while( isA( flag, FLAG_START_OF_EVENT )){ // while there is a next event
1130
1131 //
1132 // Clear Trigger and Fadc
1133 //
1134 Trigger.Reset() ;
1135 Trigger.ClearFirst();
1136 Trigger.ClearZero();
1137 fadc.Reset() ;
1138
1139 ++nshow;
1140 log(SIGNATURE, "Event %d(+%d)\n", nshow, ntshow);
1141
1142 // get MCEventHeader
1143
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 ulli,
1446 ulli,
1447 (UInt_t) ncph,
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 ulli,
1562 ulli,
1563 (UInt_t) ncph,
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
1579 //
1580 // if a first level trigger occurred, then
1581 // 1. do some other stuff (not implemented)
1582 // 2. start the gui tool
1583
1584 if(FADC_Scan){
1585 if ( Lev0 > 0 ) {
1586 fadc.ShowSignal( McEvt, (Float_t) 60. ) ;
1587 }
1588 }
1589
1590 if(Trigger_Scan){
1591 if ( Lev0 > 0 ) {
1592 Trigger.ShowSignal(McEvt) ;
1593 }
1594 }
1595
1596 // clear all
1597 if (Write_RawEvt) EvtHeader[0]->Clear() ;
1598 if (Write_RawEvt) EvtData[0]->DeletePixels();
1599 if (Write_McEvt) McEvt->Clear() ;
1600 }
1601 if (Write_McTrig) McTrig[0]->Clear() ;
1602 }
1603
1604#ifdef __DEBUG__
1605 printf("\n");
1606
1607 for ( ici=0; ici<PIX_ARRAY_SIDE; ++ici ) {
1608
1609 for ( icj=0; icj<PIX_ARRAY_SIDE; ++icj ) {
1610
1611 if ( (int)pixels[ici][icj][PIXNUM] > -1 ) {
1612
1613 if ( fnpix[(int)pixels[ici][icj][PIXNUM]] > 0. ) {
1614
1615 printf ("@@ %4d %4d %10f %10f %4f (%4d %4d)\n", nshow,
1616 (int)pixels[ici][icj][PIXNUM],
1617 pixels[ici][icj][PIXX],
1618 pixels[ici][icj][PIXY],
1619 fnpix[(int)pixels[ici][icj][PIXNUM]], ici, icj);
1620
1621 }
1622 }
1623 }
1624 }
1625
1626 for (i=0; i<ct_NPixels; ++i) {
1627 printf("%d (%d): ", i, npixneig[i]);
1628 for (j=0; j<npixneig[i]; ++i)
1629 printf(" %d", pixneig[i][j]);
1630 printf("\n");
1631 }
1632
1633#endif // __DEBUG__
1634
1635
1636 // look for the next event
1637
1638 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1639
1640 } // end while there is a next event
1641
1642 if( !isA( flag, FLAG_END_OF_RUN )){
1643 error( SIGNATURE, "Expected end of run flag, but found: %s\n", flag );
1644 }
1645 else { // found end of run
1646 ntshow += nshow;
1647 log(SIGNATURE, "End of this run with %d events . . .\n", nshow);
1648
1649 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1650
1651 if( isA( flag, FLAG_END_OF_FILE ) ){ // end of file
1652 log(SIGNATURE, "End of file . . .\n");
1653 still_in_loop = FALSE;
1654
1655 if ((! Data_From_STDIN) && ( !feof(inputfile) )){
1656
1657 // we have concatenated input files.
1658 // get signature of the next part and check it.
1659
1660 if(check_reflector_file( inputfile )==FALSE){
1661 exit(1);
1662 }
1663
1664 }
1665
1666 fread( flag, SIZE_OF_FLAGS, 1, inputfile );
1667
1668 } // end if found end of file
1669 } // end if found end of run
1670
1671 } // end if else found start of run
1672 } // end big while loop
1673
1674 //++
1675 // put the Event to the root file
1676 //--
1677
1678 outfile_temp.Write() ;
1679 outfile_temp.Close() ;
1680
1681
1682 // close input file
1683
1684 log( SIGNATURE, "%d event(s), with a total of %d C.photons\n",
1685 ntshow, ntcph );
1686 datafile<<ntshow<<" event(s), with a total of "<<ntcph<<" C.photons"<<endl;
1687 if (Trigger_Loop){
1688 log( SIGNATURE, "Trigger Mode. \n");
1689 log( SIGNATURE, "Fraction of triggers: \n");
1690 datafile<<"Fraction of triggers: "<<endl;
1691 for (ithrescount=Trigger_loop_lthres;ithrescount<=Trigger_loop_uthres;ithrescount++){
1692 for (imulticount=Trigger_loop_lmult;imulticount<=Trigger_loop_umult;imulticount++){
1693 for(itopocount=Trigger_loop_ltop;itopocount<=Trigger_loop_utop;itopocount++){
1694 log( SIGNATURE, "Thres %d, Multi %d, Topo %d: %5.1f%% (%d out of %d)\n",
1695 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);
1696 datafile<<"Thres "<<ithrescount<<", Multi "<<imulticount<<", Topo"<<itopocount<<": ";
1697 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;
1698 }
1699 }
1700 }
1701 }
1702 else{
1703 log( SIGNATURE, "Fraction of triggers: %5.1f%% (%d out of %d)\n",
1704 ((float)ntrigger) / ((float)ntshow) * 100.0, ntrigger, ntshow);
1705 datafile<<"Fraction of triggers: "<<((float)ntrigger) / ((float)ntshow) * 100.0<<" ("<<ntrigger<<" out of "<<ntshow<<" )"<<endl;
1706 }
1707
1708 // close files
1709
1710 log( SIGNATURE, "Closing files\n" );
1711
1712 if( ! Data_From_STDIN ){
1713 fclose( inputfile );
1714 }
1715 datafile.close();
1716
1717 // program finished
1718
1719 log( SIGNATURE, "Done.\n");
1720
1721 return( 0 );
1722}
1723//!@}
1724
1725// @T \newpage
1726
1727//!@subsection Functions definition.
1728
1729//!-----------------------------------------------------------
1730// @name present
1731//
1732// @desc Make some presentation
1733//
1734// @date Sat Jun 27 05:58:56 MET DST 1998
1735//------------------------------------------------------------
1736// @function
1737
1738//!@{
1739void
1740present(void)
1741{
1742 cout << "##################################################\n"
1743 << SIGNATURE << '\n' << '\n'
1744 << "Processor of the reflector output\n"
1745 << "J C Gonzalez, Jun 1998\n"
1746 << "##################################################\n\n"
1747 << flush ;
1748}
1749//!@}
1750
1751
1752//!-----------------------------------------------------------
1753// @name usage
1754//
1755// @desc show help
1756//
1757// @date Tue Dec 15 16:23:30 MET 1998
1758//------------------------------------------------------------
1759// @function
1760
1761//!@{
1762void
1763usage(void)
1764{
1765 present();
1766 cout << "\nusage ::\n\n"
1767 << "\t camera "
1768 << " [ -@ paramfile ] "
1769 << " [ -h ] "
1770 << "\n\n or \n\n"
1771 << "\t camera < paramfile"
1772 << "\n\n";
1773 exit(0);
1774}
1775//!@}
1776
1777
1778//!-----------------------------------------------------------
1779// @name log
1780//
1781// @desc function to send log information
1782//
1783// @var funct Name of the caller function
1784// @var fmt Format to be used (message)
1785// @var ... Other information to be shown
1786//
1787// @date Sat Jun 27 05:58:56 MET DST 1998
1788//------------------------------------------------------------
1789// @function
1790
1791//!@{
1792void
1793log(const char *funct, char *fmt, ...)
1794{
1795 va_list args;
1796
1797 // Display the name of the function that called error
1798 printf("[%s]: ", funct);
1799
1800 // Display the remainder of the message
1801 va_start(args, fmt);
1802 vprintf(fmt, args);
1803 va_end(args);
1804}
1805//!@}
1806
1807
1808//!-----------------------------------------------------------
1809// @name error
1810//
1811// @desc function to send an error message, and abort the program
1812//
1813// @var funct Name of the caller function
1814// @var fmt Format to be used (message)
1815// @var ... Other information to be shown
1816//
1817// @date Sat Jun 27 05:58:56 MET DST 1998
1818//------------------------------------------------------------
1819// @function
1820
1821//!@{
1822void
1823error(const char *funct, char *fmt, ...)
1824{
1825 va_list args;
1826
1827 // Display the name of the function that called error
1828 fprintf(stdout, "ERROR in %s: ", funct);
1829
1830 // Display the remainder of the message
1831 va_start(args, fmt);
1832 vfprintf(stdout, fmt, args);
1833 va_end(args);
1834
1835 perror(funct);
1836
1837 exit(1);
1838}
1839//!@}
1840
1841
1842//!-----------------------------------------------------------
1843// @name isA
1844//
1845// @desc returns TRUE(FALSE), if the flag is(is not) the given
1846//
1847// @var s1 String to be searched
1848// @var flag Flag to compare with string s1
1849// @return TRUE: both strings match; FALSE: oth.
1850//
1851// @date Wed Jul 8 15:25:39 MET DST 1998
1852//------------------------------------------------------------
1853// @function
1854
1855//!@{
1856int
1857isA( char * s1, const char * flag ) {
1858 return ( (strncmp((char *)s1, flag, SIZE_OF_FLAGS)==0) ? 1 : 0 );
1859}
1860//!@}
1861
1862
1863//!-----------------------------------------------------------
1864// @name read_ct_file
1865//
1866// @desc read CT definition file
1867//
1868// @date Sat Jun 27 05:58:56 MET DST 1998
1869//------------------------------------------------------------
1870// @function
1871
1872//!@{
1873void
1874read_ct_file(void)
1875{
1876 char line[LINE_MAX_LENGTH]; //@< line to get from the ctin
1877 char token[ITEM_MAX_LENGTH]; //@< a single token
1878 int i, j; //@< dummy counters
1879
1880 log( "read_ct_file", "start.\n" );
1881
1882 ifstream ctin ( ct_filename );
1883
1884 if ( ctin.bad() )
1885 error( "read_ct_file",
1886 "Cannot open CT def. file: %s\n", ct_filename );
1887
1888 // loop till the "end" directive is reached
1889
1890 while (!ctin.eof()) {
1891
1892 // get line from stdin
1893
1894 ctin.getline(line, LINE_MAX_LENGTH);
1895
1896 // look for each item at the beginning of the line
1897
1898 for (i=0; i<=define_mirrors; i++)
1899 if (strstr(line, CT_ITEM_NAMES[i]) == line)
1900 break;
1901
1902 // if it is not a valid line, just ignore it
1903
1904 if (i == define_mirrors+1)
1905 continue;
1906
1907 // case block for each directive
1908
1909 switch ( i ) {
1910
1911 case type: // <type of telescope> (0:CT1 ¦ 1:MAGIC)
1912
1913 // get focal distance
1914
1915 sscanf(line, "%s %d", token, &ct_Type);
1916
1917 log( "read_ct_file", "<Type of Telescope>: %s\n",
1918 ((ct_Type==0) ? "CT1" : "MAGIC") );
1919
1920 break;
1921
1922 case focal_distance: // <focal distance> [cm]
1923
1924 // get focal distance
1925
1926 sscanf(line, "%s %f", token, &ct_Focal_mean);
1927
1928 log( "read_ct_file", "<Focal distance>: %f cm\n", ct_Focal_mean );
1929
1930 break;
1931
1932 case focal_std: // s(focal distance) [cm]
1933
1934 // get focal distance
1935
1936 sscanf(line, "%s %f", token, &ct_Focal_std);
1937
1938 log( "read_ct_file", "s(Focal distance): %f cm\n", ct_Focal_std );
1939
1940 break;
1941
1942 case point_spread: // <point spread> [cm]
1943
1944 // get point spread
1945
1946 sscanf(line, "%s %f", token, &ct_PSpread_mean);
1947
1948 log( "read_ct_file", "<Point spread>: %f cm\n", ct_PSpread_mean );
1949
1950 break;
1951
1952 case point_std: // s(point spread) [cm]
1953
1954 // get point spread
1955
1956 sscanf(line, "%s %f", token, &ct_PSpread_std);
1957
1958 log( "read_ct_file", "s(Point spread): %f cm\n", ct_PSpread_std );
1959
1960 break;
1961
1962 case adjustment_dev: // s(adjustment_dev) [cm]
1963
1964 // get point spread
1965
1966 sscanf(line, "%s %f", token, &ct_Adjustment_std);
1967
1968 log( "read_ct_file", "s(Adjustment): %f cm\n", ct_Adjustment_std );
1969
1970 break;
1971
1972 case black_spot: // radius of the black spot in the center [cm]
1973
1974 // get black spot radius
1975
1976 sscanf(line, "%s %f", token, &ct_BlackSpot_rad);
1977
1978 log( "read_ct_file", "Radius of the black spots: %f cm\n",
1979 ct_BlackSpot_rad);
1980
1981 break;
1982
1983 case r_mirror: // radius of the mirrors [cm]
1984
1985 // get radius of mirror
1986
1987 sscanf(line, "%s %f", token, &ct_RMirror);
1988
1989 log( "read_ct_file", "Radii of the mirrors: %f cm\n", ct_RMirror );
1990
1991 break;
1992
1993 case n_mirrors: // number of mirrors
1994
1995 // get the name of the output_file from the line
1996
1997 sscanf(line, "%s %d", token, &ct_NMirrors);
1998
1999 log( "read_ct_file", "Number of mirrors: %d\n", ct_NMirrors );
2000
2001 break;
2002
2003 case camera_width: // camera width [cm]
2004
2005 // get the name of the ct_file from the line
2006
2007 sscanf(line, "%s %f", token, &ct_CameraWidth);
2008
2009 log( "read_ct_file", "Camera width: %f cm\n", ct_CameraWidth );
2010
2011 break;
2012
2013 case n_pixels: // number of pixels
2014
2015 // get the name of the output_file from the line
2016
2017 sscanf(line, "%s %d", token, &ct_NPixels);
2018
2019 log( "read_ct_file", "Number of pixels: %d\n", ct_NPixels );
2020
2021 break;
2022
2023 case n_centralpixels: // number of central pixels
2024
2025 // get the name of the output_file from the line
2026
2027 sscanf(line, "%s %d", token, &ct_NCentralPixels);
2028
2029 log( "read_ct_file", "Number of central pixels: %d\n", ct_NCentralPixels );
2030
2031 break;
2032
2033 case n_gappixels: // number of gap pixels
2034
2035 // get the name of the output_file from the line
2036
2037 sscanf(line, "%s %d", token, &ct_NGapPixels);
2038
2039 log( "read_ct_file", "Number of gap pixels: %d\n", ct_NGapPixels );
2040
2041 break;
2042
2043 case pixel_width: // pixel width [cm]
2044
2045 // get the name of the ct_file from the line
2046
2047 sscanf(line, "%s %f", token, &ct_PixelWidth);
2048
2049 ct_PixelWidth_corner_2_corner = ct_PixelWidth / cos(RAD(30.0));
2050 ct_PixelWidth_corner_2_corner_half =
2051 ct_PixelWidth_corner_2_corner * 0.50;
2052 ct_Apot = ct_PixelWidth / 2;
2053 ct_2Apot = ct_Apot * 2.0;
2054
2055 log( "read_ct_file", "Pixel width: %f cm\n", ct_PixelWidth );
2056
2057 break;
2058
2059 case define_mirrors: // read table with the parameters of the mirrors
2060
2061 log( "read_ct_file", "Table of mirrors data:\n" );
2062
2063 // check whether the number of mirrors was already set
2064
2065 if ( ct_NMirrors == 0 )
2066 error( "read_ct_file", "NMirrors was not set.\n" );
2067
2068 // allocate memory for paths list
2069
2070 log( "read_ct_file", "Allocating memory for ct_data\n" );
2071
2072 ct_data = new float*[ct_NMirrors];
2073
2074 for (i=0; i<ct_NMirrors; i++)
2075 ct_data[i] = new float[CT_NDATA];
2076
2077 // read data
2078
2079 log( "read_ct_file", "Reading mirrors data...\n" );
2080
2081 for (i=0; i<ct_NMirrors; i++)
2082 for (j=0; j<CT_NDATA; j++)
2083 ctin >> ct_data[i][j];
2084
2085 break;
2086
2087 } // switch ( i )
2088
2089 } // end while
2090
2091 // end
2092
2093 log( "read_ct_file", "done.\n" );
2094
2095 return;
2096}
2097//!@}
2098
2099
2100//!-----------------------------------------------------------
2101// @name read_pixels
2102//
2103// @desc read pixels data
2104//
2105// @date Fri Mar 12 16:33:34 MET 1999
2106//------------------------------------------------------------
2107// @function
2108
2109//!@{
2110void
2111read_pixels(struct camera *pcam)
2112{
2113 ifstream qefile;
2114 char line[LINE_MAX_LENGTH];
2115 int n, i, j, icount;
2116 float qe;
2117
2118 //------------------------------------------------------------
2119 // first, pixels' coordinates
2120
2121 pcam->inumpixels = ct_NPixels;
2122 pcam->inumcentralpixels = ct_NCentralPixels;
2123 pcam->inumgappixels = ct_NGapPixels;
2124 pcam->inumbigpixels = ct_NPixels - ct_NCentralPixels - ct_NGapPixels;
2125 pcam->dpixdiameter_cm = ct_PixelWidth;
2126
2127 // initialize pixel numbers
2128
2129 pixary = new float* [2*ct_NCentralPixels];
2130 for ( i=0; i<2*ct_NCentralPixels; ++i )
2131 pixary[i] = new float[2];
2132
2133 pixneig = new int* [ct_NCentralPixels];
2134 for ( i=0; i<ct_NCentralPixels; ++i ) {
2135 pixneig[i] = new int[6];
2136 for ( j=0; j<6; ++j )
2137 pixneig[i][j] = -1;
2138 }
2139
2140 npixneig = new int[ct_NCentralPixels];
2141 for ( i=0; i<ct_NCentralPixels; ++i )
2142 npixneig[i] = 0;
2143
2144 // generate all coordinates
2145
2146 igen_pixel_coordinates(pcam);
2147
2148
2149 // calculate tables of neighbours
2150
2151#ifdef __DEBUG__
2152 for ( n=0 ; n<ct_NPixels ; ++n ) {
2153 cout << "Para el pixel " << n << ": ";
2154 for ( i=n+1 ; (i<ct_NPixels)&&(npixneig[n]<6) ; ++i) {
2155 if ( pixels_are_neig(n,i) == TRUE ) {
2156 pixneig[n][npixneig[n]] = i;
2157 pixneig[i][npixneig[i]] = n;
2158 cout << i << ' ';
2159 ++npixneig[n];
2160 ++npixneig[i];
2161 }
2162 }
2163 cout << endl << flush;
2164 }
2165#else // ! __DEBUG__
2166 for ( n=0 ; n<ct_NCentralPixels ; ++n )
2167 for ( i=n+1 ; (i<ct_NCentralPixels)&&(npixneig[n]<6) ; ++i)
2168 if ( pixels_are_neig(n,i) == TRUE ) {
2169 pixneig[n][npixneig[n]] = i;
2170 pixneig[i][npixneig[i]] = n;
2171 ++npixneig[n];
2172 ++npixneig[i];
2173 }
2174#endif // ! __DEBUG__
2175
2176#ifdef __DEBUG__
2177 for ( n=0 ; n<ct_NPixels ; ++n ) {
2178 cout << n << ':';
2179 for ( j=0; j<npixneig[n]; ++j)
2180 cout << ' ' << pixneig[n][j];
2181 cout << endl << flush;
2182 }
2183#endif // __DEBUG__
2184
2185 //------------------------------------------------------------
2186 // second, pixels' QE
2187
2188 // try to open the file
2189
2190 log("read_pixels", "Opening the file \"%s\" . . .\n", QE_FILE);
2191
2192 qefile.open( QE_FILE );
2193
2194 // if it is wrong or does not exist, exit
2195
2196 if ( qefile.bad() )
2197 error( "read_pixels", "Cannot open \"%s\". Exiting.\n", QE_FILE );
2198
2199 // read file
2200
2201 log("read_pixels", "Reading data . . .\n");
2202
2203 i=-1;
2204 icount = 0;
2205
2206 while ( ! qefile.eof() ) {
2207
2208 // get line from the file
2209
2210 qefile.getline(line, LINE_MAX_LENGTH);
2211
2212 // skip if comment
2213
2214 if ( *line == '#' )
2215 continue;
2216
2217 // if it is the first valid value, it is the number of QE data points
2218
2219 if ( i < 0 ) {
2220
2221 // get the number of datapoints
2222
2223 sscanf(line, "%d", &pointsQE);
2224
2225 // allocate memory for the table of QEs
2226
2227 QE = new float ** [ct_NPixels];
2228
2229 for ( i=0; i<ct_NPixels; ++i ) {
2230 QE[i] = new float * [2];
2231 QE[i][0] = new float[pointsQE];
2232 QE[i][1] = new float[pointsQE];
2233 }
2234
2235 QElambda = new float [pointsQE];
2236
2237 for ( i=0; i<pointsQE; ++i ) {
2238 qefile.getline(line, LINE_MAX_LENGTH);
2239 sscanf(line, "%f", &QElambda[i]);
2240 }
2241
2242 i=0;
2243
2244 continue;
2245 }
2246
2247 // get the values (num-pixel, num-datapoint, QE-value)
2248
2249 if( sscanf(line, "%d %d %f", &i, &j, &qe) != 3 )
2250 break;
2251
2252 if ( ((i-1) < ct_NPixels) && ((i-1) > -1) &&
2253 ((j-1) < pointsQE) && ((j-1) > -1) ) {
2254 QE[i-1][0][j-1] = QElambda[j-1];
2255 QE[i-1][1][j-1] = qe;
2256 }
2257
2258 if ( i > ct_NPixels) break;
2259
2260 icount++;
2261
2262 }
2263
2264 if(icount/pointsQE < ct_NPixels){
2265 error( "read_pixels", "The quantum efficiency file is faulty\n (found only %d pixels instead of %d).\n",
2266 icount/pointsQE, ct_NPixels );
2267 }
2268
2269 // close file
2270
2271 qefile.close();
2272
2273 // test QE
2274
2275 for(icount=0; icount< ct_NPixels; icount++){
2276 for(i=0; i<pointsQE; i++){
2277 if( QE[icount][0][i] < 100. || QE[icount][0][i] > 1000. ||
2278 QE[icount][1][i] < 0. || QE[icount][1][i] > 100.){
2279 error( "read_pixels", "The quantum efficiency file is faulty\n pixel %d, point %d is % f, %f\n",
2280 icount, i, QE[icount][0][i], QE[icount][1][i] );
2281 }
2282 }
2283 }
2284
2285 // end
2286
2287 log("read_pixels", "Done.\n");
2288
2289}
2290//!@}
2291
2292
2293//!-----------------------------------------------------------
2294// @name pixels_are_neig
2295//
2296// @desc check whether two pixels are neighbours
2297//
2298// @var pix1 Number of the first pixel
2299// @var pix2 Number of the second pixel
2300// @return TRUE: both pixels are neighbours; FALSE: oth.
2301//
2302// @date Wed Sep 9 17:58:37 MET DST 1998
2303//------------------------------------------------------------
2304// @function
2305
2306//!@{
2307int
2308pixels_are_neig(int pix1, int pix2)
2309{
2310 if ( sqrt(SQR( pixary[pix1][0] - pixary[pix2][0] ) +
2311 SQR( pixary[pix1][1] - pixary[pix2][1] ) )
2312 > ct_PixelWidth_corner_2_corner )
2313 return ( FALSE );
2314 else
2315 return ( TRUE );
2316}
2317//!@}
2318
2319//!-----------------------------------------------------------
2320// @name igen_pixel_coordinates
2321//
2322// @desc generate the pixel center coordinates
2323//
2324// @var *pcam structure camera containing all the
2325// camera information
2326// @return total number of pixels
2327//
2328// DP
2329//
2330// @date Thu Oct 14 10:41:03 CEST 1999
2331//------------------------------------------------------------
2332// @function
2333
2334//!@{
2335/******** igen_pixel_coordinates() *********************************/
2336
2337int igen_pixel_coordinates(struct camera *pcam) {
2338 /* generate pixel coordinates, return value is number of pixels */
2339
2340 int i, itot_inside_ring, iN, in, ipixno, iring_no, ipix_in_ring, isegment;
2341 float fsegment_fract;
2342 double dtsize;
2343 double dhsize;
2344 double dpsize;
2345 double dxfirst_pix;
2346 double dyfirst_pix;
2347 double ddxseg1, ddxseg2, ddxseg3, ddxseg4, ddxseg5, ddxseg6;
2348 double ddyseg1, ddyseg2, ddyseg3, ddyseg4, ddyseg5, ddyseg6;
2349
2350
2351 double dstartx, dstarty; /* for the gap pixels and outer pixels */
2352 int j, nrow;
2353
2354 dpsize = pcam->dpixdiameter_cm;
2355 dtsize = dpsize * sqrt(3.) / 2.;
2356 dhsize = dpsize / 2.;
2357
2358 /* Loop over central pixels to generate co-ordinates */
2359
2360 for(ipixno=1; ipixno <= pcam->inumcentralpixels; ipixno++){
2361
2362 /* Initialise variables. The central pixel = ipixno 1 in ring iring_no 0 */
2363
2364 pcam->dpixsizefactor[ipixno-1] = 1.;
2365
2366 in = 0;
2367
2368 i = 0;
2369 itot_inside_ring = 0;
2370 iring_no = 0;
2371
2372 /* Calculate the number of pixels out to and including the ring containing pixel number */
2373 /* ipixno e.g. for pixel number 17 in ring number 2 itot_inside_ring = 19 */
2374
2375 while (itot_inside_ring == 0){
2376
2377 iN = 3*(i*(i+1)) + 1;
2378
2379 if (ipixno <= iN){
2380 iring_no = i;
2381 itot_inside_ring = iN;
2382 }
2383
2384 i++;
2385 }
2386
2387
2388 /* Find the number of pixels which make up ring number iring_no e.g. ipix_in_ring = 6 for ring 1 */
2389
2390 ipix_in_ring = 0;
2391 for (i = 0; i < iring_no; ++i){
2392
2393 ipix_in_ring = ipix_in_ring + 6;
2394 }
2395
2396 /* The camera is viewed as 6 radial segments ("pie slices"). Knowing the number of pixels in its */
2397 /* ring calculate which segment the pixel ipixno is in. Then find how far across this segment it is */
2398 /* as a fraction of the number of pixels in this sixth of the ring (ask SMB). */
2399
2400 isegment = 0;
2401 fsegment_fract = 0.;
2402 if (iring_no > 0) {
2403
2404 isegment = (int)((ipixno - itot_inside_ring + ipix_in_ring - 0.5) / iring_no + 1); /* integer division ! numbering starts at 1 */
2405
2406 fsegment_fract = (ipixno - (itot_inside_ring - ipix_in_ring)) - ((isegment-1)*iring_no) - 1 ;
2407
2408 }
2409
2410 /* the first pixel in each ring lies on the positive x axis at a distance dxfirst_pix = iring_no * the */
2411 /* pixel width (flat to flat) dpsize. */
2412
2413 dxfirst_pix = dpsize*iring_no;
2414 dyfirst_pix = 0.;
2415
2416 /* the vector between the first and last pixels in a segment n is (ddxsegn, ddysegn) */
2417
2418 ddxseg1 = - dhsize*iring_no;
2419 ddyseg1 = dtsize*iring_no;
2420 ddxseg2 = -dpsize*iring_no;
2421 ddyseg2 = 0.;
2422 ddxseg3 = ddxseg1;
2423 ddyseg3 = -ddyseg1;
2424 ddxseg4 = -ddxseg1;
2425 ddyseg4 = -ddyseg1;
2426 ddxseg5 = -ddxseg2;
2427 ddyseg5 = 0.;
2428 ddxseg6 = -ddxseg1;
2429 ddyseg6 = ddyseg1;
2430
2431 /* to find the position of pixel ipixno take the position of the first pixel in the ring and move */
2432 /* anti-clockwise around the ring by adding the segment to segment vectors. */
2433
2434 switch (isegment) {
2435
2436 case 0:
2437
2438 pcam->dxc[ipixno-1] = 0.;
2439 pcam->dyc[ipixno-1] = 0.;
2440
2441 case 1:
2442 pcam->dxc[ipixno-1] = dxfirst_pix - dhsize*fsegment_fract;
2443 pcam->dyc[ipixno-1] = dyfirst_pix + dtsize*fsegment_fract;
2444
2445 break;
2446
2447 case 2:
2448
2449 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 - dpsize*fsegment_fract;
2450 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + 0.;
2451
2452 break;
2453
2454 case 3:
2455
2456 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 - dhsize*fsegment_fract;
2457 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 - dtsize*fsegment_fract;
2458
2459 break;
2460
2461 case 4:
2462
2463 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + dhsize*fsegment_fract;
2464 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 - dtsize*fsegment_fract;
2465
2466 break;
2467
2468 case 5:
2469
2470 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + ddxseg4 + dpsize*fsegment_fract;
2471 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 + ddyseg4 + 0.;
2472
2473 break;
2474
2475 case 6:
2476
2477 pcam->dxc[ipixno-1] = dxfirst_pix + ddxseg1 + ddxseg2 + ddxseg3 + ddxseg4 + ddxseg5 + dhsize*fsegment_fract;
2478 pcam->dyc[ipixno-1] = dyfirst_pix + ddyseg1 + ddyseg2 + ddyseg3 + ddyseg4 + ddyseg5 + dtsize*fsegment_fract;
2479
2480 break;
2481
2482 default:
2483
2484 fprintf(stderr, "ERROR: problem in coordinate generation for pixel %d\n", ipixno);
2485 return(0);
2486
2487 } /* end switch */
2488
2489 } /* end for */
2490
2491 dstartx = pcam->dxc[pcam->inumcentralpixels - 1] + dhsize;
2492 dstarty = pcam->dyc[pcam->inumcentralpixels - 1] + dtsize;
2493
2494 if(pcam->inumgappixels > 0){ /* generate the positions of the gap pixels */
2495
2496 j = pcam->inumcentralpixels;
2497
2498 for(i=0; i<pcam->inumgappixels; i=i+6){
2499 pcam->dxc[j + i ] = dstartx + 2. * (i/6 + 1) * dpsize;
2500 pcam->dyc[j + i ] = dstarty;
2501 pcam->dpixsizefactor[j + i] = 1.;
2502 pcam->dxc[j + i + 1] = pcam->dxc[j + i ] / 2.;
2503 pcam->dyc[j + i + 1] = sqrt(3.) * pcam->dxc[j + i + 1];
2504 pcam->dpixsizefactor[j + i + 1] = 1.;
2505 pcam->dxc[j + i + 2] = - pcam->dxc[j + i + 1];
2506 pcam->dyc[j + i + 2] = pcam->dyc[j + i + 1];
2507 pcam->dpixsizefactor[j + i+ 2] = 1.;
2508 pcam->dxc[j + i + 3] = - pcam->dxc[j + i];
2509 pcam->dyc[j + i + 3] = dstarty;
2510 pcam->dpixsizefactor[j + i+ 3] = 1.;
2511 pcam->dxc[j + i + 4] = pcam->dxc[j + i + 2];
2512 pcam->dyc[j + i + 4] = - pcam->dyc[j + i + 2];
2513 pcam->dpixsizefactor[j + i+ 4] = 1.;
2514 pcam->dxc[j + i + 5] = pcam->dxc[j + i + 1];
2515 pcam->dyc[j + i + 5] = - pcam->dyc[j + i + 1];
2516 pcam->dpixsizefactor[j + i + 5] = 1.;
2517 } /* end for */
2518 } /* end if */
2519
2520 /* generate positions of the outer pixels */
2521
2522 if( pcam->inumbigpixels > 0 ){
2523
2524 j = pcam->inumcentralpixels + pcam->inumgappixels;
2525
2526 for(i=0; i<pcam->inumbigpixels; i++){
2527 pcam->dpixsizefactor[j + i] = 2.;
2528 }
2529
2530 in = 0;
2531
2532 nrow = (int) ceil(dstartx / 2. / dpsize);
2533
2534 while(in < pcam->inumbigpixels){
2535
2536 pcam->dxc[j + in] = dstartx + dpsize;
2537 pcam->dyc[j + in] = dstarty + 2 * dpsize / sqrt(3.);
2538 pcam->dxc[j + in + nrow] = dstartx / 2. - dpsize / 2.;
2539 pcam->dyc[j + in + nrow] = sqrt(3.)/2. * dstartx + 2.5 * dpsize/sqrt(3.);
2540 pcam->dxc[j + in + 3 * nrow - 1] = - pcam->dxc[j + in];
2541 pcam->dyc[j + in + 3 * nrow - 1] = pcam->dyc[j + in];
2542 pcam->dxc[j + in + 3 * nrow] = - pcam->dxc[j + in];
2543 pcam->dyc[j + in + 3 * nrow] = - pcam->dyc[j + in];
2544 pcam->dxc[j + in + 5 * nrow - 1] = pcam->dxc[j + in + nrow];
2545 pcam->dyc[j + in + 5 * nrow - 1] = - pcam->dyc[j + in + nrow];
2546 pcam->dxc[j + in + 6 * nrow - 1] = pcam->dxc[j + in];
2547 pcam->dyc[j + in + 6 * nrow - 1] = - pcam->dyc[j + in];
2548 for(i=1; i<nrow; i++){
2549 pcam->dxc[j + in + i] = pcam->dxc[j + in] - i * dpsize;
2550 pcam->dyc[j + in + i] = pcam->dyc[j + in] + i * dpsize * sqrt(3.);
2551 pcam->dxc[j + in + i + nrow] = pcam->dxc[j + in + nrow] - i * 2 * dpsize;
2552 pcam->dyc[j + in + i + nrow] = pcam->dyc[j + in + nrow];
2553 pcam->dxc[j + in + 3 * nrow - 1 - i] = - pcam->dxc[j + in + i];
2554 pcam->dyc[j + in + 3 * nrow - 1- i] = pcam->dyc[j + in + i];
2555 pcam->dxc[j + in + i + 3 * nrow] = - pcam->dxc[j + in + i];
2556 pcam->dyc[j + in + i + 3 * nrow] = - pcam->dyc[j + in + i];
2557 pcam->dxc[j + in + 5 * nrow - 1 - i] = pcam->dxc[j + in + i + nrow];
2558 pcam->dyc[j + in + 5 * nrow - 1 - i] = - pcam->dyc[j + in + i + nrow];
2559 pcam->dxc[j + in + 6 * nrow - 1 - i] = pcam->dxc[j + in + i];
2560 pcam->dyc[j + in + 6 * nrow - 1 - i] = - pcam->dyc[j + in + i];
2561 }
2562 in = in + 6 * nrow;
2563 dstartx = dstartx + 2. * dpsize;
2564 nrow = nrow + 1;
2565 } /* end while */
2566
2567 } /* end if */
2568
2569 return(pcam->inumpixels);
2570
2571}
2572//!@}
2573
2574//!-----------------------------------------------------------
2575// @name bpoint_is_in_pix
2576//
2577// @desc check if a point (x,y) in camera coordinates is inside a given pixel
2578//
2579// @var *pcam structure camera containing all the
2580// camera information
2581// @var dx, dy point coordinates in centimeters
2582// @var ipixnum pixel number (starting at 0)
2583// @return TRUE if the point is inside the pixel, FALSE otherwise
2584//
2585// DP
2586//
2587// @date Thu Oct 14 16:59:04 CEST 1999
2588//------------------------------------------------------------
2589// @function
2590
2591//!@{
2592
2593/******** bpoint_is_in_pix() ***************************************/
2594
2595int bpoint_is_in_pix(double dx, double dy, int ipixnum, struct camera *pcam){
2596 /* return TRUE if point (dx, dy) is in pixel number ipixnum, else return FALSE (use camera coordinate system) */
2597 /* the pixel is assumed to be a "closed set" */
2598
2599 double a, b; /* a = length of one of the edges of one pixel, b = half the width of one pixel */
2600 double c, xx, yy; /* auxiliary variable */
2601
2602 b = pcam->dpixdiameter_cm / 2. * pcam->dpixsizefactor[ipixnum];
2603 a = pcam->dpixdiameter_cm / sqrt(3.) * pcam->dpixsizefactor[ipixnum];
2604 c = 1./sqrt(3.);
2605
2606 if((ipixnum < 0)||(ipixnum >= pcam->inumpixels)){
2607 fprintf(stderr, "Error in bpoint_is_in_pix: invalid pixel number %d\n", ipixnum);
2608 fprintf(stderr, "Exiting.\n");
2609 exit(203);
2610 }
2611 xx = dx - pcam->dxc[ipixnum];
2612 yy = dy - pcam->dyc[ipixnum];
2613
2614 if(((-b <= xx) && (xx <= 0.) && ((-c * xx - a) <= yy) && (yy <= ( c * xx + a))) ||
2615 ((0. < xx) && (xx <= b ) && (( c * xx - a) <= yy) && (yy <= (-c * xx + a))) ){
2616 return(TRUE); /* point is inside */
2617 }
2618 else{
2619 return(FALSE); /* point is outside */
2620 }
2621}
2622
2623//!@}
2624
2625//------------------------------------------------------------
2626// @name dist_r_P
2627//
2628// @desc distance straight line r - point P
2629//
2630// @date Sat Jun 27 05:58:56 MET DST 1998
2631// @function @code
2632//------------------------------------------------------------
2633// dist_r_P
2634//
2635// distance straight line r - point P
2636//------------------------------------------------------------
2637
2638float
2639dist_r_P(float a, float b, float c,
2640 float l, float m, float n,
2641 float x, float y, float z)
2642{
2643 return (
2644 sqrt((SQR((a-x)*m-(b-y)*l) +
2645 SQR((b-y)*n-(c-z)*m) +
2646 SQR((c-z)*l-(a-x)*n))/
2647 (SQR(l)+SQR(m)+SQR(n))
2648 )
2649 );
2650}
2651
2652//------------------------------------------------------------
2653// @name check_reflector_file
2654//
2655// @desc check if a given reflector file has the right signature
2656// @desc return TRUE or FALSE
2657//
2658// @date Mon Feb 14 16:44:21 CET 2000
2659// @function @code
2660//------------------------------------------------------------
2661
2662int check_reflector_file(FILE *infile){
2663
2664 char Signature[20]; // auxiliary variable
2665 char sign[20]; // auxiliary variable
2666
2667 strcpy(Signature, REFL_SIGNATURE);
2668
2669 strcpy(sign, Signature);
2670
2671 fread( (char *)sign, strlen(Signature), 1, infile);
2672
2673 if (strcmp(sign, Signature) != 0) {
2674 cout << "ERROR: Signature of .rfl file is not correct\n";
2675 cout << '"' << sign << '"' << '\n';
2676 cout << "should be: " << Signature << '\n';
2677 return(FALSE);
2678 }
2679
2680 fread( (char *)sign, 1, 1, infile);
2681
2682 return(TRUE);
2683
2684}
2685
2686//------------------------------------------------------------
2687// @name lin_interpol
2688//
2689// @desc interpolate linearly between two points returning the
2690// @desc y-value of the result
2691//
2692// @date Thu Feb 17 11:31:32 CET 2000
2693// @function @code
2694//------------------------------------------------------------
2695
2696float lin_interpol( float x1, float y1, float x2, float y2, float x){
2697
2698 if( (x2 - x1)<=0. ){ // avoid division by zero, return average
2699 cout << "Warning: lin_interpol was asked to interpolate between two points with x1>=x2.\n";
2700 return((y1+y2)/2.);
2701 }
2702 else{ // note: the check whether x1 < x < x2 is omitted for speed reasons
2703 return((float) (y1 + (y2-y1)/(x2-x1)*(x-x1)) );
2704 }
2705}
2706
2707
2708//------------------------------------------------------------
2709// @name produce_phes
2710//
2711// @desc read the photons of an event, pixelize them and simulate QE
2712// @desc return various statistics and the array of Photoelectrons
2713//
2714// @date Mon Feb 14 16:44:21 CET 2000
2715// @function @code
2716//------------------------------------------------------------
2717
2718int produce_phes( FILE *sp, // the input file
2719 struct camera *cam, // the camera layout
2720 float minwl_nm, // the minimum accepted wavelength
2721 float maxwl_nm, // the maximum accepted wavelength
2722 class MTrigger *trigger, // the generated phes
2723 class MFadc *fadc,
2724 int *itotnphe, // total number of produced photoelectrons
2725 float nphe[iMAXNUMPIX], // number of photoelectrons in each pixel
2726 int *incph, // total number of cph read
2727 float *tmin_ns, // minimum arrival time of all phes
2728 float *tmax_ns // maximum arrival time of all phes
2729 ){
2730
2731 static int i, k, ipixnum;
2732 static float cx, cy, wl, qe, t;
2733 static MCCphoton photon;
2734 static float **qept;
2735 static char flag[SIZE_OF_FLAGS + 1];
2736 static float radius;
2737
2738
2739 // reset variables
2740
2741 for ( i=0; i<cam->inumpixels; ++i ){
2742
2743 nphe[i] = 0.0;
2744
2745 }
2746
2747 *incph = 0;
2748
2749 radius = cam->dxc[cam->inumpixels-1]
2750 + 1.5*cam->dpixdiameter_cm*cam->dpixsizefactor[cam->inumpixels-1];
2751
2752 //- - - - - - - - - - - - - - - - - - - - - - - - -
2753 // read photons and "map" them into the pixels
2754 //--------------------------------------------------
2755
2756 // initialize CPhoton
2757
2758 photon.fill(0., 0., 0., 0., 0., 0., 0., 0.);
2759
2760 // read the photons data
2761
2762 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2763
2764 // loop over the photons
2765
2766 while ( !isA( flag, FLAG_END_OF_EVENT ) ) {
2767
2768 memcpy( (char*)&photon, flag, SIZE_OF_FLAGS );
2769
2770 fread( ((char*)&photon)+SIZE_OF_FLAGS, photon.mysize()-SIZE_OF_FLAGS, 1, sp );
2771
2772 // increase number of photons
2773
2774 (*incph)++;
2775
2776 // Chceck if photon is inside trigger time range
2777
2778 t = photon.get_t() ;
2779
2780 if (t-*tmin_ns>TOTAL_TRIGGER_TIME) {
2781
2782 // read next Photon
2783
2784 fread( flag, SIZE_OF_FLAGS, 1, sp );
2785
2786 // go to beginning of loop, the photon is lost
2787 continue;
2788 }
2789
2790 //
2791 // Pixelization
2792 //
2793
2794 cx = photon.get_x();
2795 cy = photon.get_y();
2796
2797 // get wavelength
2798
2799 wl = photon.get_wl();
2800
2801 // cout << "wl " << wl << " radius " << sqrt(cx*cx + cy*cy) << "\n";
2802
2803 // check if photon has valid wavelength and is inside outermost camera radius
2804
2805 if( (wl > maxwl_nm) || (wl < minwl_nm) || (sqrt(cx*cx + cy*cy) > radius ) ){
2806
2807 // cout << " lost first check\n";
2808
2809 // read next CPhoton
2810
2811 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2812
2813 // go to beginning of loop, the photon is lost
2814 continue;
2815
2816 }
2817
2818 ipixnum = -1;
2819
2820 for(i=0; i<cam->inumpixels; i++){
2821 if( bpoint_is_in_pix( cx, cy, i, cam) ){
2822 ipixnum = i;
2823 break;
2824 }
2825 }
2826
2827 if(ipixnum==-1){// the photon is in none of the pixels
2828
2829 // cout << " lost pixlization\n";
2830
2831 // read next CPhoton
2832
2833 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2834
2835 // go to beginning of loop, the photon is lost
2836 continue;
2837 }
2838
2839 if(ipixnum==0) {// the phton is in the central pixel, which is not used for trigger
2840 // read next CPhoton
2841
2842 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2843
2844 // go to beginning of loop, the photon is lost
2845 continue;
2846 }
2847 //+++
2848 // QE simulation
2849 //---
2850
2851 // set pointer to the QE table of the relevant pixel
2852
2853 qept = (float **)QE[ipixnum];
2854
2855 // check if wl is inside table; outside the table, QE is assumed to be zero
2856
2857
2858 if((wl < qept[0][0]) || (wl > qept[0][pointsQE-1])){
2859
2860 // cout << " lost\n";
2861
2862 // read next Photon
2863
2864 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2865
2866 // go to beginning of loop
2867 continue;
2868
2869 }
2870
2871 // find data point in the QE table (-> k)
2872
2873 k = 1; // start at 1 because the condition was already tested for 0
2874 while (k < pointsQE-1 && qept[0][k] < wl){
2875 k++;
2876 }
2877
2878 // calculate the qe value between 0. and 1.
2879
2880 qe = lin_interpol(qept[0][k-1], qept[1][k-1], qept[0][k], qept[1][k], wl) / 100.0;
2881
2882 // if random > quantum efficiency, reject it
2883
2884 if ( (RandomNumber) > qe ) {
2885
2886 // cout << " lost\n";
2887
2888 // read next Photon
2889
2890 fread ( flag, SIZE_OF_FLAGS, 1, sp );
2891
2892 // go to beginning of loop
2893 continue;
2894
2895 }
2896
2897 //+++
2898 // The photon has produced a photo electron
2899 //---
2900
2901 // cout << " accepted\n";
2902
2903 // increment the number of photoelectrons in the relevant pixel
2904
2905 nphe[ipixnum] += 1.0;
2906
2907 // store the new photoelectron
2908
2909 fadc->Fill(ipixnum,(t-*tmin_ns) , trigger->FillShow(ipixnum,t-*tmin_ns));
2910
2911 *itotnphe += 1;
2912
2913 // read next Photon
2914
2915 fread( flag, SIZE_OF_FLAGS, 1, sp );
2916
2917 } // end while, i.e. found end of event
2918
2919 return(0);
2920
2921}
2922
2923
2924//------------------------------------------------------------
2925// @name produce_nsbrates
2926//
2927// @desc read the starfield file, call produce_phes on it in,
2928// @desc different wavebands, calculate the nsbrates
2929//
2930// @date Mon Feb 14 16:44:21 CET 2000
2931// @function @code
2932//------------------------------------------------------------
2933
2934int produce_nsbrates( char *iname, // the starfield input file name
2935 struct camera *cam, // camera layout
2936 float rate_phepns[iMAXNUMPIX][iNUMWAVEBANDS] // the product of this function:
2937 // the NSB rates in phe/ns for each pixel
2938 ){
2939
2940 int i, j, k, ii; // counters
2941
2942 MTrigger trigger(Trigger_gate_length, Trigger_overlaping_time, Trigger_response_ampl, Trigger_response_fwhm);
2943 MFadc flashadc;
2944
2945 static float wl_nm[iNUMWAVEBANDS + 1] = { WAVEBANDBOUND1,
2946 WAVEBANDBOUND2,
2947 WAVEBANDBOUND3,
2948 WAVEBANDBOUND4,
2949 WAVEBANDBOUND5,
2950 WAVEBANDBOUND6 };
2951
2952 FILE *infile; // the input file
2953 fpos_t fileposition; // marker on the input file
2954 static char cflag[SIZE_OF_FLAGS + 1]; // auxiliary variable
2955 static MCEventHeader evth; // the event header
2956 static float nphe[iMAXNUMPIX]; // the number of photoelectrons in each pixel
2957 int itnphe; // total number of produced photoelectrons
2958 int itotnphe; // total number of produced photoelectrons after averaging
2959 int incph; // total number of cph read
2960 float tmin_ns; // minimum arrival time of all phes
2961 float tmax_ns; // maximum arrival time of all phes
2962 float integtime_ns; // integration time from the starfield generator
2963
2964 // open input file
2965
2966 log(SIGNATURE, "Opening starfield input \"rfl\" file %s\n", iname );
2967
2968 infile = fopen( iname, "r" );
2969
2970 // check if the satrfield input file exists
2971
2972 if ( infile == NULL ) {
2973
2974 log( SIGNATURE, "Cannot open starfield input file: %s\n", iname );
2975
2976 log( SIGNATURE, "There is not NSB from the Stars\n");
2977
2978 return (0);
2979 }
2980
2981 // get signature, and check it
2982
2983 if(check_reflector_file(infile)==FALSE){
2984 exit(1);
2985 }
2986
2987 // initialize flag
2988
2989 strcpy( cflag, " \0" );
2990
2991 // get flag
2992
2993 fread( cflag, SIZE_OF_FLAGS, 1, infile );
2994
2995 if ( ! feof(infile)){
2996
2997 // reading .rfl file
2998
2999 if(!isA( cflag, FLAG_START_OF_RUN )){
3000 error( SIGNATURE, "Expected start of run flag, but found: %s\n", cflag );
3001 }
3002 else { // found start of run
3003
3004 fread( cflag, SIZE_OF_FLAGS, 1, infile );
3005
3006 if( isA( cflag, FLAG_START_OF_EVENT )){ // there is a event
3007
3008 // get MCEventHeader
3009
3010 fread( (char*)&evth, evth.mysize(), 1, infile );
3011
3012 integtime_ns = evth.get_energy();
3013
3014 // memorize where we are in the file
3015
3016 if (fgetpos( infile, &fileposition ) != 0){
3017 error( SIGNATURE, "Cannot position in file ...\n");
3018 }
3019
3020 // loop over the wavebands
3021
3022 for(i=0; i<iNUMWAVEBANDS; i++){
3023
3024 // initialize the rate array
3025
3026 for(j = 0; j<cam->inumpixels; j++){ // loop over pixels
3027 rate_phepns[j][i] = 0.;
3028 }
3029
3030 itotnphe = 0;
3031
3032 // read the photons and produce the photoelectrons
3033 // - in order to average over the QE simulation, call the
3034 // production function iNUMNSBPRODCALLS times
3035
3036 for(ii=0; ii<iNUMNSBPRODCALLS; ii++){
3037
3038 // position the file pointer to the beginning of the photons
3039
3040 fsetpos( infile, &fileposition);
3041
3042 // produce photoelectrons
3043
3044 k = produce_phes( infile,
3045 cam,
3046 wl_nm[i],
3047 wl_nm[i+1],
3048 &trigger, // this is a dummy here
3049 &flashadc, // this is a dummy here
3050 &itnphe,
3051 nphe, // we want this!
3052 &incph,
3053 &tmin_ns,
3054 &tmax_ns );
3055
3056 if( k != 0 ){ // non-zero returnvalue means error
3057 cout << "Exiting.\n";
3058 exit(1);
3059 }
3060
3061 for(j = 0; j<cam->inumpixels; j++){ // loop over pixels
3062 rate_phepns[j][i] += nphe[j]/integtime_ns/(float)iNUMNSBPRODCALLS;
3063 }
3064
3065 itotnphe += itnphe;
3066
3067 } // end for(ii=0 ...
3068
3069 fprintf(stdout, "Starfield, %6f - %6f nm: %d photoelectrons for %6f ns integration time\n",
3070 wl_nm[i], wl_nm[i+1], itotnphe/iNUMNSBPRODCALLS, integtime_ns);
3071
3072 } // end for(i=0 ...
3073
3074 }
3075 else{
3076 cout << "Starfield file contains no event.\nExiting.\n";
3077 exit(1);
3078 } // end if( isA ... event
3079 } // end if ( isA ... run
3080 }
3081 else{
3082 cout << "Starfield file contains no run.\nExiting.\n";
3083 exit(1);
3084 }
3085
3086 fclose( infile );
3087
3088 return(0);
3089
3090}
3091
3092
3093//------------------------------------------------------------
3094// @name produce_nsb_phes
3095//
3096// @desc produce the photoelectrons from the nsbrates
3097//
3098// @date Thu Feb 17 17:10:40 CET 2000
3099// @function @code
3100//------------------------------------------------------------
3101
3102int produce_nsb_phes( float *atmin_ns,
3103 float *atmax_ns,
3104 float theta_rad,
3105 struct camera *cam,
3106 float nsbr_phepns[iMAXNUMPIX][iNUMWAVEBANDS],
3107 float difnsbr_phepns[iMAXNUMPIX],
3108 float extinction[iNUMWAVEBANDS],
3109 float fnpx[iMAXNUMPIX],
3110 MTrigger *trigger,
3111 MFadc *fadc,
3112 int *inphe,
3113 float base_mv[iMAXNUMPIX]){
3114
3115 float simtime_ns; // NSB simulation time
3116 int i, j, k, ii;
3117 float zenfactor; // correction factor calculated from the extinction
3118 int inumnsbphe; // number of photoelectrons caused by NSB
3119
3120 float t;
3121 TRandom random; // Random numbers generator
3122
3123 random.SetSeed ((UInt_t) (RandomNumber*1000));
3124
3125 ii = *inphe; // avoid dereferencing
3126
3127 // check if the arrival times are set; if not generate them
3128
3129 if(*atmin_ns <SIMTIMEOFFSET_NS || *atmin_ns > *atmax_ns){
3130 *atmin_ns = 0.;
3131 *atmax_ns = simtime_ns = TOTAL_TRIGGER_TIME;
3132
3133 }
3134 else{ // extend the event time window by the given offsets
3135
3136 *atmin_ns = *atmin_ns - SIMTIMEOFFSET_NS;
3137 *atmax_ns = *atmax_ns + SIMTIMEOFFSET_NS;
3138
3139 simtime_ns = *atmax_ns - *atmin_ns;
3140
3141 // make sure the simulated time is long enough for the FADC
3142 // simulation and not too long
3143
3144 if(simtime_ns< TOTAL_TRIGGER_TIME){
3145 *atmin_ns = *atmin_ns -(TOTAL_TRIGGER_TIME-simtime_ns)/2;
3146 *atmax_ns = *atmin_ns + TOTAL_TRIGGER_TIME;
3147 simtime_ns = TOTAL_TRIGGER_TIME;
3148 }
3149
3150 if(simtime_ns> TOTAL_TRIGGER_TIME){
3151 *atmax_ns =*atmin_ns + TOTAL_TRIGGER_TIME;
3152 simtime_ns = TOTAL_TRIGGER_TIME;
3153 }
3154
3155 }
3156
3157 // initialize baselines
3158
3159 for(i=0; i<cam->inumpixels; i++){
3160 base_mv[i] = 0.;
3161 }
3162
3163 // calculate baselines and generate phes
3164
3165 for(i=0; i<iNUMWAVEBANDS; i++){ // loop over the wavebands
3166
3167 // calculate the effect of the atmospheric extinction
3168
3169 zenfactor = pow(10., -0.4 * extinction[i]/cos(theta_rad) );
3170
3171 for(j=0; j<cam->inumpixels; j++){ // loop over the pixels
3172
3173 inumnsbphe = (int) ((zenfactor * nsbr_phepns[j][i] + difnsbr_phepns[j]/iNUMWAVEBANDS)
3174 * simtime_ns );
3175
3176 base_mv[j] += inumnsbphe;
3177
3178 // randomize
3179
3180 if (inumnsbphe>0.0){
3181 inumnsbphe = random.Poisson (inumnsbphe );
3182 }
3183
3184 // create the photoelectrons
3185
3186 for(k=0; k < inumnsbphe; k++){
3187
3188 t=(RandomNumber * simtime_ns);
3189
3190 (*fadc).Fill(j,t ,(*trigger).FillNSB(j,t));
3191
3192 ii++; // increment total number of photoelectons
3193
3194 fnpx[j] += 1.; // increment number of photoelectrons in this pixel
3195
3196 }
3197
3198 } // end for(j=0 ...
3199 } // end for(i=0 ...
3200
3201 // finish baseline calculation
3202
3203 for(i=0; i<cam->inumpixels; i++){
3204 base_mv[i] *= RESPONSE_FWHM * RESPONSE_AMPLITUDE / simtime_ns;
3205 }
3206
3207 *inphe = ii; // update the pointer
3208
3209 return(0);
3210}
3211
3212
3213// @endcode
3214
3215
3216//=------------------------------------------------------------
3217//!@subsection Log of this file.
3218
3219//!@{
3220//
3221// $Log: not supported by cvs2svn $
3222// Revision 1.21 2001/03/19 19:53:03 blanch
3223// Some print outs have been removed.
3224//
3225// Revision 1.20 2001/03/19 19:30:06 magicsol
3226// Minor changes have been done to improve the FADC pedestals treatment.
3227//
3228// Revision 1.19 2001/03/05 11:14:41 magicsol
3229// I changed the position of readinf a parameter. It is a minnor change.
3230//
3231// Revision 1.18 2001/03/05 10:36:52 blanch
3232// A branch with information about the FADC simulation (MMcFadcHeader) is writen
3233// in the McHeaders tree of the aoutput root file.
3234// The NSB contribution is only applied if the the number of phe form the shower
3235// are above a given number.
3236//
3237// Revision 1.17 2001/02/23 11:05:57 magicsol
3238// Small changes due to slightly different output format and the introduction of
3239// pedesals for teh FADC.
3240//
3241// Revision 1.16 2001/01/18 18:44:40 magicsol
3242// *** empty log message ***
3243//
3244// Revision 1.15 2001/01/17 09:32:27 harald
3245// The changes are neccessary to have the same name for trees in MC and in
3246// data. So now there should be no differences in MC data and real data from
3247// FADC system.
3248//
3249// Revision 1.14 2001/01/15 12:33:34 magicsol
3250// Some modifications have been done to use the new (Dec'2000) Raw data format.
3251// There are also some minnors modifications to adapt the improvements in the
3252// MTrigger class (overlaping time and trigger cells).
3253//
3254// Revision 1.13 2000/10/25 08:14:23 magicsol
3255// The routine that produce poisson random numbers to decide how many phe
3256// form NSB are emmited in each pixel has been replaced. Now a ROOT routine
3257// is used.
3258//
3259// Revision 1.12 2000/09/22 17:40:18 harald
3260// Added a lot of changes done by oscar.
3261//
3262// Revision 1.11 2000/09/21 11:47:33 harald
3263// Oscar found some smaller errors in the calculation of the pixel shape and
3264// corrected it.
3265//
3266// $Log: not supported by cvs2svn $
3267// Revision 1.21 2001/03/19 19:53:03 blanch
3268// Some print outs have been removed.
3269//
3270// Revision 1.20 2001/03/19 19:30:06 magicsol
3271// Minor changes have been done to improve the FADC pedestals treatment.
3272//
3273// Revision 1.19 2001/03/05 11:14:41 magicsol
3274// I changed the position of readinf a parameter. It is a minnor change.
3275//
3276// Revision 1.18 2001/03/05 10:36:52 blanch
3277// A branch with information about the FADC simulation (MMcFadcHeader) is writen
3278// in the McHeaders tree of the aoutput root file.
3279// The NSB contribution is only applied if the the number of phe form the shower
3280// are above a given number.
3281//
3282// Revision 1.17 2001/02/23 11:05:57 magicsol
3283// Small changes due to slightly different output format and the introduction of
3284// pedesals for teh FADC.
3285//
3286// Revision 1.16 2001/01/18 18:44:40 magicsol
3287// *** empty log message ***
3288//
3289// Revision 1.15 2001/01/17 09:32:27 harald
3290// The changes are neccessary to have the same name for trees in MC and in
3291// data. So now there should be no differences in MC data and real data from
3292// FADC system.
3293//
3294// Revision 1.14 2001/01/15 12:33:34 magicsol
3295// Some modifications have been done to use the new (Dec'2000) Raw data format.
3296// There are also some minnors modifications to adapt the improvements in the
3297// MTrigger class (overlaping time and trigger cells).
3298//
3299// Revision 1.13 2000/10/25 08:14:23 magicsol
3300// The routine that produce poisson random numbers to decide how many phe
3301// form NSB are emmited in each pixel has been replaced. Now a ROOT routine
3302// is used.
3303//
3304// Revision 1.10 2000/07/04 14:10:20 MagicSol
3305// Some changes have been done in the root output file. The RawEvt tree is only
3306// stored in the single trigger mode.
3307// The trigger input parameters are also given by the general input card.
3308// The diffuse NSB and the star NSB have been decoupled. Now the contribution of
3309// each one can be studied seperately.
3310//
3311// Revision 1.9 2000/06/13 13:25:24 blanch
3312// The multiple arrays have been replaced, since they do not work
3313// in alpha machines. Now we are using pointers and the command new
3314// to allocate memory.
3315//
3316// Revision 1.8 2000/05/11 13:57:27 blanch
3317// The option to loop over several trigger configurations has been included.
3318// Some non-sense with triggertime range has been solved.
3319// Montecarlo information and ADC counts are saved in a root file.
3320// There was a problem with the maximum number of phe that the program could analyse. Now there is not limit.
3321//
3322// Revision 1.7 2000/03/24 18:10:46 blanch
3323// A first FADC simulation and a trigger simulation are already implemented.
3324// The calculation of the Hillas Parameters have been removed, since it was decided that it should be in the analysis software.
3325// 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.
3326//
3327// Revision 1.6 2000/03/20 18:35:11 blanch
3328// 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.
3329//
3330// Revision 1.5 2000/02/18 17:40:35 petry
3331// This version includes drastic changes compared to camera.cxx 1.4.
3332// It is not yet finished and not immediately useful because the
3333// trigger simulation is not yet re-implemented. I had to take it
3334// out together with some other stuff in order to tidy the whole
3335// program up. This is not meant as an insult to anyone. I needed
3336// to do this in order to be able to work on it.
3337//
3338// This version has been put in the repository in order to be
3339// able to share the further development with others.
3340//
3341// If you need something working, wait or take an earlier one.
3342// See file README.
3343//
3344// Revision 1.4 2000/01/25 08:36:23 petry
3345// The pixelization in previous versions was buggy.
3346// This is the first version with a correct pixelization.
3347//
3348// Revision 1.3 2000/01/20 18:22:17 petry
3349// Found little bug which makes camera crash if it finds a photon
3350// of invalid wavelength. This bug is now fixed and the range
3351// of valid wavelengths extended to 290 - 800 nm.
3352// This is in preparation for the NSB simulation to come.
3353// Dirk
3354//
3355// Revision 1.2 1999/11/19 08:40:42 harald
3356// Now it is possible to compile the camera programm under osf1.
3357//
3358// Revision 1.1.1.1 1999/11/05 11:59:31 harald
3359// This the starting point for CVS controlled further developments of the
3360// camera program. The program was originally written by Jose Carlos.
3361// But here you can find a "rootified" version to the program. This means
3362// that there is no hbook stuff in it now. Also the output of the
3363// program changed to the MagicRawDataFormat.
3364//
3365// The "rootification" was done by Dirk Petry and Harald Kornmayer.
3366//
3367// Revision 1.3 1999/10/22 15:01:28 petry
3368// version sent to H.K. and N.M. on Fri Oct 22 1999
3369//
3370// Revision 1.2 1999/10/22 09:44:23 petry
3371// first synthesized version which compiles and runs without crashing;
3372//
3373// Revision 1.1.1.1 1999/10/21 16:35:10 petry
3374// first synthesised version
3375//
3376// Revision 1.13 1999/03/15 14:59:05 gonzalez
3377// camera-1_1
3378//
3379// Revision 1.12 1999/03/02 09:56:10 gonzalez
3380// *** empty log message ***
3381//
3382//
3383//!@}
3384
3385//=EOF
Note: See TracBrowser for help on using the repository browser.