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

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