83 Compute zenith angle map
85 The zenith angle of a position (ra,dec) depends on the declination and
86 the hour angle h and is given by
88 zenith(h,dec) = arccos( sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(h) )
90 The hour angle h (or local hour angle, LHA) is defined as the difference
91 between local siderial time (LST) and the Right Ascension
95 The map is computed for h=-ra which is equivalent to GST=lon (or LST=0).
96 In other words, the map corresponds to the time when ra=0 passes through
102 Number of Right Ascension pixels.
104 Number of Declination pixels.
106 Right Ascension pixel size in degrees.
108 Declination pixel size in degrees.
112 zmap : `~gammalib.GSkyMap`
113 Allsky map comprising the zenith angle for an hour angle of 0.
116 zmap = gammalib.GSkyMap(
'CAR',
'CEL',0.0,0.0,-dx,dy,nx,ny)
119 hours = [(float(i)+0.5)*dx
for i
in range(nx)]
120 decs = [(float(i)+0.5)*dy-90.0
for i
in range(ny)]
123 geolat = self[
'geolat'].real()
126 cos_lat = math.cos(geolat*gammalib.deg2rad)
127 sin_lat = math.sin(geolat*gammalib.deg2rad)
133 cos_dec = math.cos(dec*gammalib.deg2rad)
134 sin_dec = math.sin(dec*gammalib.deg2rad)
136 cos_h = math.cos(h*gammalib.deg2rad)
137 zenith = math.acos(sin_lat*sin_dec +
138 cos_lat*cos_dec*cos_h)*gammalib.rad2deg
143 self._log_header2(gammalib.EXPLICIT,
'Zenith angle map')
144 self._log_string(gammalib.EXPLICIT, str(zmap))
151 Compute the half length of the Right Ascension interval to exclude due
152 to the Sun constraint
154 The Sun zenith angle constraint implies an interval in Right Ascension
155 that is to be excluded (that's the interval during which it is day).
156 This method computes half the length of this interval in degrees.
160 time : `~gammalib.GTime()`
161 Time for which the Sun exclusion is to be computed
166 Right Ascension interval half length (degrees)
169 geolat = self[
'geolat'].real() * gammalib.deg2rad
170 sunzenith = self[
'sunzenith'].real() * gammalib.deg2rad
174 sun = gammalib.GSkyDir()
179 cos_sunzenith = math.cos(sunzenith)
180 sin_geolat = math.sin(geolat)
181 cos_geolat = math.cos(geolat)
182 sin_sundec = math.sin(sundec)
183 cos_sundec = math.cos(sundec)
188 nom = cos_sunzenith - sin_geolat * sin_sundec
189 denom = cos_geolat * cos_sundec
192 if arg >= -1.0
and arg <= 1.0:
193 dra = math.acos(arg) * gammalib.rad2deg
200 Compute the half length of the Right Ascension interval to exclude due
201 to the Moon constraint
203 The Moon zenith angle constraint implies an interval in Right Ascension
204 that is to be excluded. This method computes half the length of this
209 time : `~gammalib.GTime()`
210 Time for which the Moon exclusion is to be computed
215 Right Ascension interval half length (degrees)
218 geolat = self[
'geolat'].real() * gammalib.deg2rad
219 moonzenith = self[
'moonzenith'].real() * gammalib.deg2rad
223 moon = gammalib.GSkyDir()
228 cos_moonzenith = math.cos(moonzenith)
229 sin_geolat = math.sin(geolat)
230 cos_geolat = math.cos(geolat)
231 sin_moondec = math.sin(moondec)
232 cos_moondec = math.cos(moondec)
237 nom = cos_moonzenith - sin_geolat * sin_moondec
238 denom = cos_geolat * cos_moondec
241 if arg >= -1.0
and arg <= 1.0:
242 dra = math.acos(arg) * gammalib.rad2deg
282 Exclude Right Ascension interval from array of hour angles
286 hours : list of floats
289 Start of interval to exclude (degrees)
291 Stop of interval to exclude (degrees)
295 hours : list of floats
296 Array of hours with excluded Right Ascension interval
300 ra2inx = float(nhours)/360.0
307 if ra_start >= 0.0
and ra_stop <= 360.0:
308 inx_start = int(ra_start * ra2inx + 0.5)
309 inx_stop = int(ra_stop * ra2inx + 0.5)
310 for i
in range(inx_start,inx_stop):
317 inx_start = int((ra_start+360.0) * ra2inx + 0.5)
318 inx_stop = int(ra_stop * ra2inx + 0.5)
319 for i
in range(inx_start,nhours):
321 for i
in range(0,inx_stop):
327 elif ra_stop > 360.0:
328 inx_start = int(ra_start * ra2inx + 0.5)
329 inx_stop = int((ra_stop-360.0) * ra2inx + 0.5)
330 for i
in range(0,inx_stop):
332 for i
in range(inx_start,nhours):
340 Compute hour angle weights
342 Computes an array that specifies the time during which a given hour
343 angle was observed during the observing time interval [tmin,tmax].
344 The hour angle runs from 0 to 360 degrees, array values are in units
347 The method loops over the days in the time interval [tmin,tmax], with
348 time = tmin + i*86400 seconds. At each time step the position in Right
349 Ascension and Declination of the Sun is computed (the Sun's
350 Declination is in fact not used here).
352 An interval of [ra_sun-dra_sun, ra_sun+dra_sun] is assumed to be the
353 day. The method _sun_ra_exclusion() is used to compute dra_sun, which
354 is half of the length of the day in degrees (recall that 15 degrees
355 is one hour). The length of the day is computed using the sunzenith
359 self._log_header2(gammalib.NORMAL,
'Hour angle weights')
362 tref = gammalib.GTimeReference(self[
'mjdref'].real(),
's',
'TT',
'LOCAL')
365 tmin = self[
'tmin'].time(tref)
366 tmax = self[
'tmax'].time(tref)
374 ra2inx = float(nsteps)/360.0
375 weight = 24.0/float(nsteps)
378 hours = [0.0
for i
in range(nsteps)]
385 hours_time = [weight
for i
in range(nsteps)]
393 sun = gammalib.GSkyDir()
395 sun_ra = sun.ra_deg()
396 sun_dec = sun.dec_deg()
397 sun_ra_start = sun_ra - sun_dra
398 sun_ra_stop = sun_ra + sun_dra
406 moon = gammalib.GSkyDir()
408 moon_ra = moon.ra_deg()
409 moon_dec = moon.dec_deg()
410 moon_ra_start = moon_ra - moon_dra
411 moon_ra_stop = moon_ra + moon_dra
418 elongation = sun.dist_deg(moon)
419 fli = (1.0 - math.cos(elongation * gammalib.deg2rad))/2.0
427 if fli >= self[
'maxfli'].real():
433 for i
in range(nsteps):
434 hours[i] += hours_time[i]
435 dark_time += hours_time[i]
438 result = {
'time': time.copy(),
439 'sun_ra': sun_ra,
'sun_dec': sun_dec,
440 'moon_ra': moon_ra,
'moon_dec': moon_dec,
441 'elongation': elongation,
'fli': fli,
442 'sun_ra_start': sun_ra_start,
'sun_ra_stop': sun_ra_stop,
443 'moon_ra_start': moon_ra_start,
'moon_ra_stop': moon_ra_stop,
444 'dark_time' : dark_time}
450 logs =
'Sun=(%8.3f,%7.3f) Moon=(%8.3f,%7.3f) '\
451 'Sun_RA_excl=[%8.3f,%8.3f] Moon_RA_excl=[%8.3f,%8.3f] '\
452 'FLI=%4.2f Dark time=%5.2f h' % \
453 (sun_ra, sun_dec, moon_ra, moon_dec,
454 sun_ra_start, sun_ra_stop, moon_ra_start, moon_ra_stop,
456 self._log_value(gammalib.VERBOSE, time.utc(), logs)
462 dh = 360.0/float(nsteps)
463 for i
in range(nsteps):
464 hour_angle = {
'angle': dh*float(i),
'hours': hours[i]}
465 hour_angles.append(hour_angle)
469 for hour_angle
in hour_angles:
470 total += hour_angle[
'hours']
471 self._log_value(gammalib.EXPLICIT,
'Observing time', str(total)+
' h')
472 self._log_value(gammalib.EXPLICIT,
'Number of hour angle bins', len(hour_angles))
479 Compute visibility cube
481 Compute visibility cube by displacing the zenith angle map for all
482 hour angles. The visibility cube contains the number of hours a given
483 celestial position is visible under a given zenith angle interval.
484 Summing over all zenith angle intervals specifies for how long a given
485 celestial position will be visible.
488 self._log_header1(gammalib.TERSE,
'Compute visibility cube')
491 binsz = self[
'binsz'].real()
492 nx = int(360.0/binsz+0.5)
493 ny = int(180.0/binsz+0.5)
498 dz = self[
'dz'].real()
499 zmax = self[
'zmax'].real()
500 nz = int(zmax/dz+0.5)
504 self._log_header2(gammalib.NORMAL,
'Visibility cube dimensions')
505 self._log_value(gammalib.NORMAL,
'Number of RA bins', nx)
506 self._log_value(gammalib.NORMAL,
'Number of Dec bins', ny)
507 self._log_value(gammalib.NORMAL,
'Number of zenith angles', nz)
508 self._log_value(gammalib.NORMAL,
'RA pixel size', str(dx)+
' deg')
509 self._log_value(gammalib.NORMAL,
'Dec pixel size', str(dy)+
' deg')
510 self._log_value(gammalib.NORMAL,
'Zenith angle bin size', str(dz)+
' deg')
511 self._log_value(gammalib.NORMAL,
'Maximum zenith angle', str(zmax)+
' deg')
521 self.
_cube = gammalib.GSkyMap(
'CAR',
'CEL',0.0,0.0,-dx,dy,nx,ny,nz)
524 for hour_angle
in hour_angles:
527 shift = hour_angle[
'angle']
530 zmap_shift = gammalib.GSkyMap(
'CAR',
'CEL',shift,0.0,-dx,dy,nx,ny)
537 for i, zenith
in enumerate(zmap_shift):
540 self.
_cube[i,iz] += hour_angle[
'hours']
547 Save results in VISIBILITY FITS table
552 Result FITS file name
554 Overwrite existing file?
558 time = gammalib.GFitsTableStringCol(
'Time', nrows, 20)
559 mjd = gammalib.GFitsTableDoubleCol(
'MJD', nrows)
560 sun_ra = gammalib.GFitsTableDoubleCol(
'RA_sun', nrows)
561 sun_dec = gammalib.GFitsTableDoubleCol(
'DEC_sun', nrows)
562 moon_ra = gammalib.GFitsTableDoubleCol(
'RA_moon', nrows)
563 moon_dec = gammalib.GFitsTableDoubleCol(
'DEC_moon', nrows)
564 sun_ra_start = gammalib.GFitsTableDoubleCol(
'RA_sun_start', nrows)
565 sun_ra_stop = gammalib.GFitsTableDoubleCol(
'RA_sun_stop', nrows)
566 moon_ra_start = gammalib.GFitsTableDoubleCol(
'RA_moon_start', nrows)
567 moon_ra_stop = gammalib.GFitsTableDoubleCol(
'RA_moon_stop', nrows)
568 elongation = gammalib.GFitsTableDoubleCol(
'Elongation', nrows)
569 fli = gammalib.GFitsTableDoubleCol(
'FLI', nrows)
570 dark_time = gammalib.GFitsTableDoubleCol(
'Darktime', nrows)
578 sun_ra_start.unit(
'deg')
579 sun_ra_stop.unit(
'deg')
580 moon_ra_start.unit(
'deg')
581 moon_ra_stop.unit(
'deg')
582 elongation.unit(
'deg')
583 dark_time.unit(
'hours')
586 for i, result
in enumerate(self.
_results):
587 time[i] = result[
'time'].utc()
588 mjd[i] = result[
'time'].mjd()
589 sun_ra[i] = result[
'sun_ra']
590 sun_dec[i] = result[
'sun_dec']
591 moon_ra[i] = result[
'moon_ra']
592 moon_dec[i] = result[
'moon_dec']
593 sun_ra_start[i] = result[
'sun_ra_start']
594 sun_ra_stop[i] = result[
'sun_ra_stop']
595 moon_ra_start[i] = result[
'moon_ra_start']
596 moon_ra_stop[i] = result[
'moon_ra_stop']
597 elongation[i] = result[
'elongation']
598 fli[i] = result[
'fli']
599 dark_time[i] = result[
'dark_time']
602 table = gammalib.GFitsBinTable(nrows)
603 table.extname(
'VISIBILITY')
606 table.card(
'INSTRUME',
'CTA',
'Name of Instrument')
607 table.card(
'TELESCOP',
'CTA',
'Name of Telescope')
613 table.append(sun_dec)
614 table.append(moon_ra)
615 table.append(moon_dec)
616 table.append(sun_ra_start)
617 table.append(sun_ra_stop)
618 table.append(moon_ra_start)
619 table.append(moon_ra_stop)
620 table.append(elongation)
622 table.append(dark_time)
625 fits = gammalib.GFits(outfile)