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

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