| 1 | /* ---------------------------------------------------------------------- | 
|---|
| 2 | * | 
|---|
| 3 | *  Created:  Thu May  7 16:24:22 1998 | 
|---|
| 4 | *  Author:   Jose Carlos Gonzalez | 
|---|
| 5 | *  Purpose:  Program for reflector simulation | 
|---|
| 6 | *  Notes:    See files README for details | 
|---|
| 7 | * | 
|---|
| 8 | * ---------------------------------------------------------------------- | 
|---|
| 9 | * | 
|---|
| 10 | *  Modified: Tue Jan 16 10:10:10 2001 | 
|---|
| 11 | *  Authors:  Denis Bastieri + Ciro Bigongiari | 
|---|
| 12 | *  Purpose:  Program for reflector simulation (Single file input) | 
|---|
| 13 | * | 
|---|
| 14 | * ---------------------------------------------------------------------- | 
|---|
| 15 | * | 
|---|
| 16 | *  Modified: October 2002 | 
|---|
| 17 | *  Author:   Abelardo Moralejo | 
|---|
| 18 | *  Version 0.6: introduced a run header and changed event header to keep | 
|---|
| 19 | *  all information from CORSIKA. In addition, now the magic.def, axisdev.dat | 
|---|
| 20 | *  and reflectivity.dat are attached at the end of the reflector output file | 
|---|
| 21 | *  to keep also all the parameters with which the program is run. | 
|---|
| 22 | * | 
|---|
| 23 | * ---------------------------------------------------------------------- | 
|---|
| 24 | */ | 
|---|
| 25 |  | 
|---|
| 26 | #include <stdio.h> | 
|---|
| 27 | #include <stdlib.h> | 
|---|
| 28 | #include <string.h> | 
|---|
| 29 | #include <math.h> | 
|---|
| 30 | #include "version.h" | 
|---|
| 31 | #include "diag.h" | 
|---|
| 32 | #include "init.h" | 
|---|
| 33 | #include "header.h" | 
|---|
| 34 |  | 
|---|
| 35 | #define MAX(x,y) ((x)>(y)? (x) : (y)) | 
|---|
| 36 | #define MIN(x,y) ((x)>(y)? (y) : (x)) | 
|---|
| 37 |  | 
|---|
| 38 | FILE *rflfile = NULL,           /*  reflector (output) file     */ | 
|---|
| 39 | *cerfile = NULL;                /*  current cerfile             */ | 
|---|
| 40 |  | 
|---|
| 41 | cphoton *CPhotons = NULL;                 /*  cphoton array     */ | 
|---|
| 42 | static photon Photons[PH_IN_DATABLOCK];   /*  photon array      */ | 
|---|
| 43 |  | 
|---|
| 44 | static long readp = 0L;         /*  read ptr (on cerfile)       */ | 
|---|
| 45 | static long writep = 0L;        /*  write ptr (on rflfile)      */ | 
|---|
| 46 |  | 
|---|
| 47 | extern CerEventHeader *cheadp;  /*  var inited in header.c      */ | 
|---|
| 48 | extern RflEventHeader *rheadp;  /*  var inited in header.c      */ | 
|---|
| 49 | extern void SetAtmModel(int model, float ol); /*  from atm.c    */ | 
|---|
| 50 |  | 
|---|
| 51 | /*  Prototypes  */ | 
|---|
| 52 | void clean(void); | 
|---|
| 53 | FILE *GetNextFile(char *cername); | 
|---|
| 54 | static int GetEvent(void); | 
|---|
| 55 | static int ProcessEvent(CerEventHeader *cheadp, FILE *cerfile, FILE *rflfile); | 
|---|
| 56 | void attach(FILE *f1, FILE *f2); | 
|---|
| 57 |  | 
|---|
| 58 |  | 
|---|
| 59 | FILE *chkf = NULL; | 
|---|
| 60 | long myloop; | 
|---|
| 61 |  | 
|---|
| 62 | Event_end* evt_end; | 
|---|
| 63 |  | 
|---|
| 64 | main(void) | 
|---|
| 65 | { | 
|---|
| 66 | extern char axisdev_filename[256], reflectivity_filename[256]; | 
|---|
| 67 | extern char geo_filename[256]; | 
|---|
| 68 | FILE *dummy; | 
|---|
| 69 | long event = 0L;            /*  event counter       */ | 
|---|
| 70 |  | 
|---|
| 71 | /*  Read init & geometry parms, init files and vars */ | 
|---|
| 72 | init(NULL); | 
|---|
| 73 |  | 
|---|
| 74 | /*    chkf = fopen("check", "w");   */ | 
|---|
| 75 |  | 
|---|
| 76 | /*  Processing loop */ | 
|---|
| 77 | while(GetEvent()) | 
|---|
| 78 | { | 
|---|
| 79 | if (event >= max_Events) | 
|---|
| 80 | { | 
|---|
| 81 | fwrite(FLAG_END_OF_RUN, SIZE_OF_FLAGS, 1, rflfile); | 
|---|
| 82 | break; | 
|---|
| 83 | } | 
|---|
| 84 | if (ProcessEvent(cheadp, cerfile, rflfile)) | 
|---|
| 85 | event++; | 
|---|
| 86 | if (event % SHOW_ME == 0) | 
|---|
| 87 | Log(INFO_EVENT_LOG, | 
|---|
| 88 | cheadp->RunNumber, cheadp->EvtNumber, cheadp->Etotal); | 
|---|
| 89 | } | 
|---|
| 90 |  | 
|---|
| 91 | /*  Writing final flags  */ | 
|---|
| 92 | fwrite(FLAG_END_OF_FILE, SIZE_OF_FLAGS, 1, rflfile); | 
|---|
| 93 |  | 
|---|
| 94 | /* Attach parameter files used for running the program: */ | 
|---|
| 95 | dummy = fopen (geo_filename,"r"); | 
|---|
| 96 | attach (rflfile, dummy); | 
|---|
| 97 | fclose(dummy); | 
|---|
| 98 |  | 
|---|
| 99 | dummy = fopen (axisdev_filename,"r"); | 
|---|
| 100 | attach (rflfile, dummy); | 
|---|
| 101 | fclose(dummy); | 
|---|
| 102 |  | 
|---|
| 103 | dummy = fopen (reflectivity_filename,"r"); | 
|---|
| 104 | attach (rflfile, dummy); | 
|---|
| 105 | fclose(dummy); | 
|---|
| 106 |  | 
|---|
| 107 | /*  Close reflector output file  */ | 
|---|
| 108 | Log(RFLF_CLOSE_LOG); | 
|---|
| 109 | fclose(rflfile); | 
|---|
| 110 | /*    fclose(chkf);   */ | 
|---|
| 111 |  | 
|---|
| 112 | /*  Clean memory and exit  */ | 
|---|
| 113 | clean(); | 
|---|
| 114 | Message(RFL__EXIT__MSG, QUOTE(PROGRAM), QUOTE(VERSION)); | 
|---|
| 115 |  | 
|---|
| 116 | } /*  end of main  */ | 
|---|
| 117 |  | 
|---|
| 118 | static int ProcessEvent(CerEventHeader *cheadp, FILE *cerfile, FILE *rflfile) | 
|---|
| 119 | {   extern int absorption(float wlen, float height, float theta); | 
|---|
| 120 | extern int ph2cph(photon *ph, cphoton *cph); | 
|---|
| 121 | extern float Omega[3][3]; | 
|---|
| 122 | extern float OmegaI[3][3]; | 
|---|
| 123 | extern float OmegaCT[3][3]; | 
|---|
| 124 | extern float OmegaICT[3][3]; | 
|---|
| 125 | extern void makeOmega(float theta, float phi); | 
|---|
| 126 | extern void makeOmegaI(float theta, float phi); | 
|---|
| 127 |  | 
|---|
| 128 | extern int wobble_position; | 
|---|
| 129 |  | 
|---|
| 130 | /*  Various counters: phs = absphs + refphs[0..3] + cphs  */ | 
|---|
| 131 | long phs,                   /*  Number of incoming photons  */ | 
|---|
| 132 | absphs,                     /*  Photons absorbed            */ | 
|---|
| 133 | refphs[4],                  /*  Photons not reflected       */ | 
|---|
| 134 | cphs;                       /*  Number of cphotons          */ | 
|---|
| 135 |  | 
|---|
| 136 | /* AM, Nov 2002 */ | 
|---|
| 137 | /* Counters of the number of cphs produced by different particle types: */ | 
|---|
| 138 | long | 
|---|
| 139 | mu_cphs,                    /* by muons  */ | 
|---|
| 140 | el_cphs,                    /* by electrons  */ | 
|---|
| 141 | other_cphs;                 /* by other particles  */ | 
|---|
| 142 |  | 
|---|
| 143 |  | 
|---|
| 144 | int parent_id;              /* Id of the particle producing the C-photon */ | 
|---|
| 145 |  | 
|---|
| 146 | FILE *tmpf=NULL;            /*  Temp fp to handle o/f       */ | 
|---|
| 147 | size_t read;                /*  items read: != 1 on error   */ | 
|---|
| 148 | int overflow=0,             /*  how many o/f on cphs        */ | 
|---|
| 149 | ref_type,                   /*  ret value from reflection   */ | 
|---|
| 150 | ph;                         /*  photon number               */ | 
|---|
| 151 |  | 
|---|
| 152 | float first = 1e8f,         /*  Photon arrival times        */ | 
|---|
| 153 | last  = 0; | 
|---|
| 154 |  | 
|---|
| 155 | /*  photon quantities  */ | 
|---|
| 156 | float wlen,                 /*  photon wavelength   */ | 
|---|
| 157 | theta;                      /*  photon zenith angle */ | 
|---|
| 158 |  | 
|---|
| 159 | float tel_theta, tel_phi;   /* Indicate telescope orientation, following | 
|---|
| 160 | * Corsika's criterium: theta is the zenith | 
|---|
| 161 | * angle, but phi is the azimuth of the vector | 
|---|
| 162 | * along the telescope axis going from the | 
|---|
| 163 | * camera to the dish, measured from north, | 
|---|
| 164 | * anticlockwise (0-2pi). | 
|---|
| 165 | */ | 
|---|
| 166 |  | 
|---|
| 167 | /*  Reset counters and set fileptr  */ | 
|---|
| 168 | phs= absphs= refphs[0]= refphs[1]= refphs[2]= refphs[3]= cphs= 0; | 
|---|
| 169 | writep = ftell(rflfile); | 
|---|
| 170 |  | 
|---|
| 171 | /*  Translate the EVTH from cerfile to rflfile  */ | 
|---|
| 172 | TranslateHeader(rheadp, cheadp); | 
|---|
| 173 |  | 
|---|
| 174 | if (is_Fixed_Target) | 
|---|
| 175 | { | 
|---|
| 176 | tel_theta = fixed_Theta; | 
|---|
| 177 | tel_phi   = fixed_Phi; | 
|---|
| 178 | } | 
|---|
| 179 | else  /* Use the direction of the primary if no telescope | 
|---|
| 180 | * orientation is given: */ | 
|---|
| 181 | { | 
|---|
| 182 | tel_theta = cheadp->Theta; | 
|---|
| 183 | tel_phi   = cheadp->Phi; | 
|---|
| 184 | } | 
|---|
| 185 |  | 
|---|
| 186 | /* AM, Nov 2002: added wobble mode option. It refers | 
|---|
| 187 | * to wobble position +-1, 3 defined in TDAS  01-05 */ | 
|---|
| 188 |  | 
|---|
| 189 | switch (wobble_position) | 
|---|
| 190 | { | 
|---|
| 191 | case 1: | 
|---|
| 192 | tel_theta = acos(cos(tel_theta)/1.000024369); | 
|---|
| 193 | tel_phi  -= atan(0.006981317/sin(tel_theta)); | 
|---|
| 194 | break; | 
|---|
| 195 | case -1: | 
|---|
| 196 | tel_theta = acos(cos(tel_theta)/1.000024369); | 
|---|
| 197 | tel_phi  += atan(0.006981317/sin(tel_theta)); | 
|---|
| 198 | break; | 
|---|
| 199 | case 3: | 
|---|
| 200 | tel_theta += 0.006981317;  /* 0.4 degrees */ | 
|---|
| 201 | break; | 
|---|
| 202 | default: | 
|---|
| 203 | break; | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | /* AM, Nov 2004: in case of wobble mode, change also the telescope | 
|---|
| 207 | * theta and phi in the container to be written to the output file | 
|---|
| 208 | * (rheadp) ! | 
|---|
| 209 | */ | 
|---|
| 210 |  | 
|---|
| 211 | rheadp->telescopeTheta = tel_theta; | 
|---|
| 212 | rheadp->telescopePhi = tel_phi; | 
|---|
| 213 |  | 
|---|
| 214 | /* Calculate OmegaCT matrices  */ | 
|---|
| 215 | /* AM 11/2002 : added PI to 2nd argument in makeOmega, to take | 
|---|
| 216 | * into account that theta and phi from Corsika indicate the | 
|---|
| 217 | * direction of the momentum (hence, downgoing) of the primary | 
|---|
| 218 | * particle, phi measured from positive x axis, anticlockwise, and | 
|---|
| 219 | * theta measured from negative z axis (see Corsika manual). In the | 
|---|
| 220 | * call to makeOmega, the second argument must be the azimuth of the | 
|---|
| 221 | * telescope up-going pointing direction. | 
|---|
| 222 | */ | 
|---|
| 223 |  | 
|---|
| 224 | makeOmega(tel_theta, tel_phi+M_PI); | 
|---|
| 225 | makeOmegaI(tel_theta, tel_phi+M_PI); | 
|---|
| 226 |  | 
|---|
| 227 | memcpy( OmegaCT, Omega, 9*sizeof(float) ); | 
|---|
| 228 | memcpy( OmegaICT, OmegaI, 9*sizeof(float) ); | 
|---|
| 229 |  | 
|---|
| 230 | /* ADDED AM May 2002: now we take into account the telescope | 
|---|
| 231 | * position chosen in the Corsika input card via the CERTEL | 
|---|
| 232 | * option, which must be supplied also in the reflector input | 
|---|
| 233 | * card with the option "telescope_position x y". Otherwise | 
|---|
| 234 | * x = y = 0 is assumed, which is the standard mode of | 
|---|
| 235 | * generation for MAGIC. | 
|---|
| 236 | * Here we change rheadp so that the CorePos written to the | 
|---|
| 237 | * .rfl file is referred to the telescope position. However, | 
|---|
| 238 | * I believe that the original "CorePos" vector points | 
|---|
| 239 | * from the core to the origin of coordinates of Corsika, and | 
|---|
| 240 | * therefore after the subtraction of (Telescope_x,Telescope_y) | 
|---|
| 241 | * the resulting vector CorePos  points from the core to the | 
|---|
| 242 | * telescope! | 
|---|
| 243 | */ | 
|---|
| 244 |  | 
|---|
| 245 | rheadp->CorePos[0][0] += Telescope_x; | 
|---|
| 246 | rheadp->CorePos[1][0] += Telescope_y; | 
|---|
| 247 |  | 
|---|
| 248 | /* Initialize cphoton counters: */ | 
|---|
| 249 | el_cphs = mu_cphs = other_cphs = 0; | 
|---|
| 250 |  | 
|---|
| 251 | /*  Loop on data blocks  */ | 
|---|
| 252 |  | 
|---|
| 253 | while(1 == (read = fread(Photons, sizeof(Photons), 1, cerfile))) | 
|---|
| 254 | /*  Loop on phs inside block: exit when wlength is 0  */ | 
|---|
| 255 | { | 
|---|
| 256 | /* If "event end" flag is found, read relevant quantities | 
|---|
| 257 | * from event end subblock (added June 2002, AM): | 
|---|
| 258 | */ | 
|---|
| 259 |  | 
|---|
| 260 | if (strncmp((char *)Photons, "EVTE", 4) == 0 ) | 
|---|
| 261 | { | 
|---|
| 262 | evt_end = (Event_end*) Photons; | 
|---|
| 263 | rheadp->longi_Nmax = evt_end->longi_Nmax; | 
|---|
| 264 | rheadp->longi_t0   = evt_end->longi_t0; | 
|---|
| 265 | rheadp->longi_tmax = evt_end->longi_tmax; | 
|---|
| 266 | rheadp->longi_a    = evt_end->longi_a; | 
|---|
| 267 | rheadp->longi_b    = evt_end->longi_b; | 
|---|
| 268 | rheadp->longi_c    = evt_end->longi_c; | 
|---|
| 269 | rheadp->longi_chi2 = evt_end->longi_chi2; | 
|---|
| 270 | break; | 
|---|
| 271 | } | 
|---|
| 272 |  | 
|---|
| 273 | for (ph=0; ph<PH_IN_DATABLOCK; ph++) | 
|---|
| 274 | { | 
|---|
| 275 | /* Added July 2002, AM: check integrity of photon info: | 
|---|
| 276 | Sometimes we found NaN values inside cerXXXXX file. | 
|---|
| 277 | */ | 
|---|
| 278 | if (isnan(Photons[ph].w) || isnan(Photons[ph].x) || | 
|---|
| 279 | isnan(Photons[ph].y) || isnan(Photons[ph].u) || | 
|---|
| 280 | isnan(Photons[ph].v) || isnan(Photons[ph].t) || | 
|---|
| 281 | isnan(Photons[ph].h)) | 
|---|
| 282 | { | 
|---|
| 283 | printf("Warning: skipped one photon because its data contained Not-a-Number!\n"); | 
|---|
| 284 | continue; | 
|---|
| 285 | } | 
|---|
| 286 |  | 
|---|
| 287 | if (! (Photons[ph].w > 0.) ) break; | 
|---|
| 288 |  | 
|---|
| 289 | CPhotons[cphs].w = Photons[ph].w; | 
|---|
| 290 |  | 
|---|
| 291 | /* AM Nov 2002: now we read the type of particle which produced | 
|---|
| 292 | * the Cherenkov photon : | 
|---|
| 293 | */ | 
|---|
| 294 | parent_id = (int)Photons[ph].w/100000; | 
|---|
| 295 | Photons[ph].w = wlen = (float) fmod(Photons[ph].w, 1000.); | 
|---|
| 296 |  | 
|---|
| 297 | /* AM Nov 2001: we found that sometimes the value | 
|---|
| 298 | stored in Photons[ph].w is not correct, and can result in a | 
|---|
| 299 | wavelength beyond 600 nm, which makes the program crash later. | 
|---|
| 300 |  | 
|---|
| 301 | AM July 2002: we now simply skip the photon if the wavelength | 
|---|
| 302 | is not in the expected range, which we now take from the corsika | 
|---|
| 303 | event header (just in case we would change it in the future). | 
|---|
| 304 |  | 
|---|
| 305 | AM Nov 2002: Changed the w range to the fixed values 290 and | 
|---|
| 306 | 600 nm. The StarFieldAdder cer files cannot be read otherwise, | 
|---|
| 307 | because the w range is not written in their headers. | 
|---|
| 308 | */ | 
|---|
| 309 |  | 
|---|
| 310 | if (wlen < 290 || wlen > 600) | 
|---|
| 311 | continue; | 
|---|
| 312 |  | 
|---|
| 313 |  | 
|---|
| 314 | /* ADDED AM May 2002: now we take into account the telescope | 
|---|
| 315 | * position chosen in the Corsika input card via the CERTEL | 
|---|
| 316 | * option, which must be supplied also in the reflector input | 
|---|
| 317 | * card with the option "telescope_position x y". Otherwise | 
|---|
| 318 | * x = y = 0 is assumed, which is the standard mode of | 
|---|
| 319 | * generation for MAGIC. | 
|---|
| 320 | */ | 
|---|
| 321 |  | 
|---|
| 322 | Photons[ph].x -= cheadp->CorePos[0][0]+Telescope_x; | 
|---|
| 323 | Photons[ph].y -= cheadp->CorePos[1][0]+Telescope_y; | 
|---|
| 324 |  | 
|---|
| 325 | /*  Increment number of photons     */ | 
|---|
| 326 | phs++; | 
|---|
| 327 |  | 
|---|
| 328 | /*  Calculate some quantities  */ | 
|---|
| 329 | theta = (float) acos(sqrt( | 
|---|
| 330 | MAX(0., 1.f - Photons[ph].u*Photons[ph].u | 
|---|
| 331 | - Photons[ph].v*Photons[ph].v))); | 
|---|
| 332 |  | 
|---|
| 333 | /*  Check absorption  */ | 
|---|
| 334 |  | 
|---|
| 335 |  | 
|---|
| 336 | if (absorption(wlen, Photons[ph].h, theta)) | 
|---|
| 337 | absphs++; | 
|---|
| 338 |  | 
|---|
| 339 | /*  Check reflection  */ | 
|---|
| 340 | else if (0 != (ref_type = | 
|---|
| 341 | ph2cph(&Photons[ph], &CPhotons[cphs]))) | 
|---|
| 342 | refphs[ref_type-1]++; | 
|---|
| 343 |  | 
|---|
| 344 | else                /*      Photon passed   */ | 
|---|
| 345 | { | 
|---|
| 346 | Debug("Ph %d\t%f\t%f\t%f\t%f\t%f\n",ph, | 
|---|
| 347 | Photons[ph].x,Photons[ph].y, | 
|---|
| 348 | Photons[ph].u,Photons[ph].v,theta); | 
|---|
| 349 | Debug("CPh %d\t%d\t%f\t%f\n\n",cphs,ph,CPhotons[cphs].x, | 
|---|
| 350 | CPhotons[cphs].y); | 
|---|
| 351 |  | 
|---|
| 352 | /* AM Nov 2002: We now count for every event how many | 
|---|
| 353 | * photons were produced by each type. | 
|---|
| 354 | */ | 
|---|
| 355 |  | 
|---|
| 356 | switch (parent_id) | 
|---|
| 357 | { | 
|---|
| 358 | case 2: | 
|---|
| 359 | el_cphs ++; | 
|---|
| 360 | break; | 
|---|
| 361 | case 3: | 
|---|
| 362 | el_cphs ++; | 
|---|
| 363 | break; | 
|---|
| 364 | case 5: | 
|---|
| 365 | mu_cphs ++; | 
|---|
| 366 | break; | 
|---|
| 367 | case 6: | 
|---|
| 368 | mu_cphs ++; | 
|---|
| 369 | break; | 
|---|
| 370 | default: | 
|---|
| 371 | other_cphs++; | 
|---|
| 372 | } | 
|---|
| 373 |  | 
|---|
| 374 | /*  Update first/last arrival times  */ | 
|---|
| 375 | if (first > CPhotons[cphs].t) first = CPhotons[cphs].t; | 
|---|
| 376 | if ( last < CPhotons[cphs].t)  last = CPhotons[cphs].t; | 
|---|
| 377 |  | 
|---|
| 378 | /*  Update cphs */ | 
|---|
| 379 | if (++cphs == NR_OF_CPHOTONS) /*  Overflow  */ | 
|---|
| 380 | { | 
|---|
| 381 | /*  if it is the first o/f open a tempfile  */ | 
|---|
| 382 | if (overflow++ == 0) | 
|---|
| 383 | { Log("Spooling... "); | 
|---|
| 384 | tmpf = tmpfile(); | 
|---|
| 385 | if (tmpf == NULL) FatalError(TEMP_ERROR_FTL);  } | 
|---|
| 386 |  | 
|---|
| 387 | /*  Write now the cphoton array     */ | 
|---|
| 388 | fwrite(CPhotons, sizeof(cphoton), NR_OF_CPHOTONS, tmpf); | 
|---|
| 389 |  | 
|---|
| 390 | /*  Reset the cphs counter  */ | 
|---|
| 391 | cphs = 0; | 
|---|
| 392 |  | 
|---|
| 393 | } /*  if overflow  */ | 
|---|
| 394 | } /*  else (=Photon passed)  */ | 
|---|
| 395 | } /*  end of loop inside datablock    */ | 
|---|
| 396 | } /*  end of loop on datablocks           */ | 
|---|
| 397 |  | 
|---|
| 398 | /*  Check if there was an error while reading cerfile  */ | 
|---|
| 399 | if (read != 1) fseek(rflfile, writep, SEEK_SET); | 
|---|
| 400 |  | 
|---|
| 401 | else                        /*  no error: write the new event       */ | 
|---|
| 402 |  | 
|---|
| 403 | {                         /*  Write "start of event" flag  */ | 
|---|
| 404 | fwrite(FLAG_START_OF_EVENT, SIZE_OF_FLAGS, 1, rflfile); | 
|---|
| 405 |  | 
|---|
| 406 | /*  Update arrival times  */ | 
|---|
| 407 | rheadp->TimeFirst = first; | 
|---|
| 408 | rheadp->TimeLast  = last; | 
|---|
| 409 |  | 
|---|
| 410 | /*  Update RflEventHeader with info on ph/cph nrs and write it  */ | 
|---|
| 411 | rheadp->CORSIKAPhs   = phs; | 
|---|
| 412 | rheadp->AtmAbsPhs    = absphs; | 
|---|
| 413 | rheadp->MirrAbsPhs   = refphs[0]; | 
|---|
| 414 | rheadp->OutOfMirrPhs = refphs[1]; | 
|---|
| 415 | rheadp->BlackSpotPhs = refphs[2]; | 
|---|
| 416 | rheadp->OutOfChamPhs = refphs[3]; | 
|---|
| 417 | rheadp->CPhotons     = (long) overflow * NR_OF_CPHOTONS + cphs; | 
|---|
| 418 |  | 
|---|
| 419 | if (rheadp->CPhotons > 0.) | 
|---|
| 420 | { | 
|---|
| 421 | /* Fill in relative fraction of each particle type producing | 
|---|
| 422 | * Cherenkov light in this even: | 
|---|
| 423 | */ | 
|---|
| 424 | rheadp->elec_cph_fraction = (float)el_cphs/(float)rheadp->CPhotons; | 
|---|
| 425 | rheadp->muon_cph_fraction = (float)mu_cphs/(float)rheadp->CPhotons; | 
|---|
| 426 | rheadp->other_cph_fraction = (float)other_cphs/(float)rheadp->CPhotons; | 
|---|
| 427 | } | 
|---|
| 428 | else | 
|---|
| 429 | { | 
|---|
| 430 | rheadp->elec_cph_fraction = 0.; | 
|---|
| 431 | rheadp->muon_cph_fraction = 0.; | 
|---|
| 432 | rheadp->other_cph_fraction = 0.; | 
|---|
| 433 | } | 
|---|
| 434 |  | 
|---|
| 435 | fwrite(rheadp, sizeof(RflEventHeader), 1, rflfile); | 
|---|
| 436 |  | 
|---|
| 437 | /*        for (myloop=0; myloop<sizeof(RflEventHeader)/4; myloop++) | 
|---|
| 438 | *        fprintf(chkf, "%e ", *((float *)rheadp+myloop)); | 
|---|
| 439 | *        fputc('\n', chkf); | 
|---|
| 440 | */ | 
|---|
| 441 |  | 
|---|
| 442 | /*  If there was an overflow, append data from tempfile   */ | 
|---|
| 443 | if (overflow) | 
|---|
| 444 | { | 
|---|
| 445 | /*  Unload data from CPhotons  */ | 
|---|
| 446 | fwrite(CPhotons, sizeof(cphoton), cphs, tmpf); | 
|---|
| 447 |  | 
|---|
| 448 | /*  Transfer data  */ | 
|---|
| 449 | fseek(tmpf, 0L, SEEK_SET); /*  Start from the beginning  */ | 
|---|
| 450 | while (overflow--) | 
|---|
| 451 | { | 
|---|
| 452 | fread (CPhotons, sizeof(cphoton), NR_OF_CPHOTONS, tmpf); | 
|---|
| 453 | fwrite(CPhotons, sizeof(cphoton), NR_OF_CPHOTONS, rflfile); | 
|---|
| 454 | } | 
|---|
| 455 |  | 
|---|
| 456 | /*  Reload data in CPhotons    */ | 
|---|
| 457 | fread (CPhotons, sizeof(cphoton), cphs, tmpf); | 
|---|
| 458 |  | 
|---|
| 459 | /*  Close (and delete) temp file  */ | 
|---|
| 460 | fclose(tmpf); | 
|---|
| 461 | } | 
|---|
| 462 |  | 
|---|
| 463 | /*  Write (remaining) cphotons  */ | 
|---|
| 464 |  | 
|---|
| 465 | fwrite(CPhotons, sizeof(cphoton), cphs, rflfile); | 
|---|
| 466 |  | 
|---|
| 467 | /*  Write "end of event" flag  */ | 
|---|
| 468 | fwrite(FLAG_END_OF_EVENT, SIZE_OF_FLAGS, 1, rflfile); | 
|---|
| 469 |  | 
|---|
| 470 | Debug(">>> %6ld = %6ld + %6ld + %6ld + %6ld + %6ld + %6f\n", | 
|---|
| 471 | phs, absphs, | 
|---|
| 472 | refphs[0], refphs[1], refphs[2], refphs[3], | 
|---|
| 473 | rheadp->CPhotons); } | 
|---|
| 474 |  | 
|---|
| 475 | return read == 1; | 
|---|
| 476 | } /*  end of ProcessEvent  */ | 
|---|
| 477 |  | 
|---|
| 478 | static int GetEvent(void) | 
|---|
| 479 | { | 
|---|
| 480 | int found = FALSE,          /*  event found           */ | 
|---|
| 481 | isWrong = FALSE;            /*  cerfile is wrong      */ | 
|---|
| 482 | static int newFile = TRUE;  /*  if TRUE, check if cerfile is valid    */ | 
|---|
| 483 |  | 
|---|
| 484 | RflRunHeader RflRunHead; | 
|---|
| 485 |  | 
|---|
| 486 | const char *AtmModelNames[]={"ATM_NOATMOSPHERE","ATM_90PERCENT","ATM_CORSIKA"}; | 
|---|
| 487 | extern char atmosphere[256];  /* current atm. model */ | 
|---|
| 488 | int model=0; | 
|---|
| 489 |  | 
|---|
| 490 | do | 
|---|
| 491 | { | 
|---|
| 492 | /* In case the just-opened file is a valid cerfile, | 
|---|
| 493 | starting with a RUNH, loop until a valid event is found: | 
|---|
| 494 | id est with: first_Event <= EvtNumber <= last_Event | 
|---|
| 495 | and             low_Ecut <=  Etotal   <= high_Ecut | 
|---|
| 496 | If the search was successful, "found" is set to TRUE. | 
|---|
| 497 | If there are reading errors, "isWrong" is set to TRUE. */ | 
|---|
| 498 |  | 
|---|
| 499 | if (newFile | 
|---|
| 500 | && (1 != fread(cheadp, sizeof(CerEventHeader), 1, cerfile) | 
|---|
| 501 | || strncmp(cheadp->EVTH, "RUNH", 4))) | 
|---|
| 502 | {   isWrong = TRUE;   } | 
|---|
| 503 |  | 
|---|
| 504 | else do | 
|---|
| 505 | { | 
|---|
| 506 | if (newFile) | 
|---|
| 507 | { | 
|---|
| 508 | while (strcmp(atmosphere, AtmModelNames[model])) | 
|---|
| 509 | if (++model == sizeof(AtmModelNames)/sizeof(AtmModelNames[0])) | 
|---|
| 510 | { | 
|---|
| 511 | model = 0; | 
|---|
| 512 | Error(" *** Atm model \"%s\" not found.\n", atmosphere); | 
|---|
| 513 | break; | 
|---|
| 514 | } | 
|---|
| 515 |  | 
|---|
| 516 | /* Write Reflector "run header" (one per cer file!): */ | 
|---|
| 517 | memcpy(&RflRunHead, cheadp, sizeof(RflRunHead)); | 
|---|
| 518 | RflRunHead.wobble_mode = wobble_position; | 
|---|
| 519 | RflRunHead.atmospheric_model = model; | 
|---|
| 520 | fwrite(&RflRunHead, sizeof(RflRunHead), 1, rflfile); | 
|---|
| 521 |  | 
|---|
| 522 | /* Set up atmosphere (do some necessary calculations) once we | 
|---|
| 523 | * read in the observation level from the run header: | 
|---|
| 524 | */ | 
|---|
| 525 |  | 
|---|
| 526 | Log("Setting atm model \"%s\" and observation level %.0f cm.\n", AtmModelNames[model], RflRunHead.HeightLev[0]); | 
|---|
| 527 | SetAtmModel(model,RflRunHead.HeightLev[0]); | 
|---|
| 528 |  | 
|---|
| 529 | } | 
|---|
| 530 |  | 
|---|
| 531 | /*  Push fileptr in case it is a "EVTH"  */ | 
|---|
| 532 | readp = ftell(cerfile); | 
|---|
| 533 |  | 
|---|
| 534 | /*  Error: exit loop  */ | 
|---|
| 535 | if (1 != fread(cheadp, sizeof(CerEventHeader), 1, cerfile)) | 
|---|
| 536 | {   isWrong = TRUE;    break;   } | 
|---|
| 537 |  | 
|---|
| 538 | /*  Ok: set found at TRUE and exit loop  */ | 
|---|
| 539 | if (strncmp(cheadp->EVTH, "EVTH", 4) == 0 | 
|---|
| 540 | && first_Event <= (long)cheadp->EvtNumber | 
|---|
| 541 | &&                       (long)cheadp->EvtNumber <= last_Event | 
|---|
| 542 | &&    low_Ecut <= cheadp->Etotal | 
|---|
| 543 | &&                       cheadp->Etotal <= high_Ecut) | 
|---|
| 544 | {   found = TRUE;   } | 
|---|
| 545 |  | 
|---|
| 546 | /*  File is finished: exit loop  */ | 
|---|
| 547 | else if (strncmp(cheadp->EVTH, "RUNE", 4) == 0) | 
|---|
| 548 | break; | 
|---|
| 549 |  | 
|---|
| 550 | } while(found == FALSE); | 
|---|
| 551 |  | 
|---|
| 552 | /*  If there was an error, log it  */ | 
|---|
| 553 | if (isWrong) Log(CERF_ERROR_LOG, cername); | 
|---|
| 554 |  | 
|---|
| 555 | /*  If a new event was not found, get, if any, a new cerfile. | 
|---|
| 556 | "newFile" is set in this case, to check the validity of | 
|---|
| 557 | just-opened cerfile.  If GetNextFile return a NULL (no | 
|---|
| 558 | new cerfile), then exit thoroughly.  */ | 
|---|
| 559 |  | 
|---|
| 560 | if (found) newFile = FALSE; | 
|---|
| 561 | else | 
|---|
| 562 | {   if ((cerfile=GetNextFile(cername)) == NULL) break; | 
|---|
| 563 | newFile = TRUE;   } | 
|---|
| 564 |  | 
|---|
| 565 | } while(found == FALSE); | 
|---|
| 566 |  | 
|---|
| 567 | return found; | 
|---|
| 568 | }   /*  end of GetEvent  */ | 
|---|
| 569 |  | 
|---|
| 570 | /*  Files are all CER-like files (cerfiles). | 
|---|
| 571 | Filenames are written one per line and may be followed | 
|---|
| 572 | by a ",FIRST_EVT,LAST_EVT" directive, such as: | 
|---|
| 573 | -> cer19999 15 167 | 
|---|
| 574 | telling to deal with events from 15 to 167 in file "cer19999" | 
|---|
| 575 | The file list may be appended to the input file or can be stored | 
|---|
| 576 | in a separate file pointed by an '@' directive contained in the | 
|---|
| 577 | input file.  In both cases, file referral follows the tag | 
|---|
| 578 | "cer_files".  Files not accessible are thoroughly skipped. | 
|---|
| 579 | GetNextFile gets and opens the next readable cerfile.  */ | 
|---|
| 580 |  | 
|---|
| 581 | FILE *GetNextFile(char *cername) | 
|---|
| 582 | {   FILE *inputfile = NULL;             /*  return value (cerfile ptr)  */ | 
|---|
| 583 | char *value_ptr;            /*  ptr at parm value   */ | 
|---|
| 584 | extern char line[];         /*  white chars (init)  */ | 
|---|
| 585 | extern char whites[];       /*  parsing buf. (init) */ | 
|---|
| 586 |  | 
|---|
| 587 | /*  Close, if any, the previous cerfile, writing "END_OF_RUN".  */ | 
|---|
| 588 | if (cerfile) | 
|---|
| 589 | {   fclose(cerfile); | 
|---|
| 590 | fwrite(FLAG_END_OF_RUN, SIZE_OF_FLAGS, 1, rflfile);  } | 
|---|
| 591 |  | 
|---|
| 592 | /*  Parse next line in filelist  */ | 
|---|
| 593 | do | 
|---|
| 594 | {   if (fgets(line, LINE_MAX_LENGTH, filelist) == NULL) break; | 
|---|
| 595 | if ((value_ptr=strtok(line, whites)) == NULL) continue; | 
|---|
| 596 |  | 
|---|
| 597 | /*  If you found a line with some meaning, try to open the file  */ | 
|---|
| 598 | if ((inputfile=fopen(value_ptr, "r")) == NULL) | 
|---|
| 599 | Message(CERF_NFND__MSG, value_ptr); | 
|---|
| 600 |  | 
|---|
| 601 | else        /*  Cerfile is readable  */ | 
|---|
| 602 | {   /*  Store its name in "cername"  */ | 
|---|
| 603 | Log(CERF_OPEN__LOG, strcpy(cername, value_ptr)); | 
|---|
| 604 |  | 
|---|
| 605 | /*  Read, if any, event bounds   */ | 
|---|
| 606 | if ((value_ptr=strtok(NULL, whites)) == NULL) | 
|---|
| 607 | {   first_Event = 0; | 
|---|
| 608 | last_Event  = 1000000;   } | 
|---|
| 609 | else | 
|---|
| 610 | {   first_Event = atol(value_ptr); | 
|---|
| 611 | value_ptr = strtok(NULL, whites); | 
|---|
| 612 | last_Event = value_ptr ? atol(value_ptr) : 1000000;  } | 
|---|
| 613 |  | 
|---|
| 614 | /*  Check boundaries  */ | 
|---|
| 615 | if (first_Event > last_Event) | 
|---|
| 616 | {   Error(EVTN_WRONG_ERR, first_Event, last_Event, cername); | 
|---|
| 617 | first_Event = 0; | 
|---|
| 618 | last_Event  = 1000000;  }}} | 
|---|
| 619 |  | 
|---|
| 620 | while (inputfile == NULL);  /*  Loop until a readable file is found  */ | 
|---|
| 621 |  | 
|---|
| 622 | /*  If a new cerfile is met, write "START_OF_RUN"  */ | 
|---|
| 623 | if (inputfile) fwrite(FLAG_START_OF_RUN, SIZE_OF_FLAGS, 1, rflfile); | 
|---|
| 624 |  | 
|---|
| 625 | return inputfile; | 
|---|
| 626 | }   /*  end of GetNextFile  */ | 
|---|
| 627 |  | 
|---|
| 628 | /*  This function frees up allocated memory before exiting  */ | 
|---|
| 629 |  | 
|---|
| 630 | void clean(void) | 
|---|
| 631 | {   Message(MEM__FREE__MSG); | 
|---|
| 632 |  | 
|---|
| 633 | if (ct_data) | 
|---|
| 634 | {   free(ct_data);          Log(VECT_FREE__LOG, "ct_data");  } | 
|---|
| 635 |  | 
|---|
| 636 | if (Reflectivity[0]) | 
|---|
| 637 | {   free(Reflectivity[0]);  Log(VECT_FREE__LOG, "Reflectivity[0]");  } | 
|---|
| 638 | if (Reflectivity[1]) | 
|---|
| 639 | {   free(Reflectivity[1]);  Log(VECT_FREE__LOG, "Reflectivity[1]");  } | 
|---|
| 640 |  | 
|---|
| 641 | if (AxisDeviation[0]) | 
|---|
| 642 | {   free(AxisDeviation[0]); Log(VECT_FREE__LOG, "AxisDeviation[0]");  } | 
|---|
| 643 | if (AxisDeviation[1]) | 
|---|
| 644 | {   free(AxisDeviation[1]); Log(VECT_FREE__LOG, "AxisDeviation[1]");  } | 
|---|
| 645 |  | 
|---|
| 646 | if (CPhotons) | 
|---|
| 647 | {   free(CPhotons);         Log(VECT_FREE__LOG, "CPhotons");  } | 
|---|
| 648 | }   /*  end of clean  */ | 
|---|
| 649 |  | 
|---|