def visibility(ra, dec, observatory, time): source = SkyCoord(ra=Angle(ra * u.deg), dec=(dec * u.deg)) location = observatory.position time = Time(time) altaz = source.transform_to(AltAz(obstime=time, location=location)) altaz_sun = get_sun(time).transform_to( AltAz(obstime=time, location=location)) altaz_moon = get_moon(time).transform_to( AltAz(obstime=time, location=location)) delta_time = np.linspace(0, 24, 200) * u.hour frame = AltAz(obstime=time + delta_time, location=location) frame_night = source.transform_to(frame) frame_sun_night = get_sun(time + delta_time).transform_to(frame) frame_moon_night = get_moon(time + delta_time).transform_to(frame) moon_distance = np.mean( source.separation( SkyCoord( get_moon(time + delta_time).ra, get_moon(time + delta_time).dec))) sun_distance = np.mean( source.separation( SkyCoord( get_sun(time + delta_time).ra, get_sun(time + delta_time).dec))) date = ephem.Date(time.value) moon_phase = (date - ephem.previous_new_moon(date)) / ( ephem.next_new_moon(date) - ephem.previous_new_moon(date)) return altaz, delta_time, frame_night, frame_sun_night, moon_distance, sun_distance, moon_phase
def is_visible(self, orbit, time, limb_angle=None, sun_angle=None, moon_angle=None): """ checks if the GRB is visible above the Earth limb for the given times :param orbit: :param time: :returns: :rtype: """ horizon_angle = 90 - np.rad2deg( np.arccos((a_e / orbit.a).to(u.dimensionless_unscaled).value)) # add Earth limb restraint if limb_angle is not None: horizon_angle += limb_angle # deg pos = orbit.r_eci(time).to("km") sun_pos = None if sun_angle is not None: sun_pos = get_moon(time).cartesian.xyz.to("km").value.T moon_pos = None if moon_angle is not None: moon_pos = get_moon(time).cartesian.xyz.to("km").value.T return _is_visibile( pos.T, self.cart_position, horizon_angle, sun_angle, sun_pos, moon_angle, moon_pos, len(time), )
def plot_altitude(target_list={}, observatory=None, utc_offset=0, obs_time=None, show_sun=True, show_moon=True): """plot the position of science target during observation """ # define the observation time delta_hours = np.linspace(-12, 12, 100)*u.hour obstimes = obs_time + delta_hours - utc_offset # observertory altaz_frames = AltAz(location=observatory, obstime=obstimes) target_altaz_list = {} for name, skcoord in target_list.items(): target_altaz_list[name] = skcoord.transform_to(altaz_frames) fig = plt.figure(figsize=(12, 4)) ax = fig.add_subplot(121) for name, pos in target_altaz_list.items(): ax.scatter(delta_hours, pos.alt, label=name, s=8) ax.set_title("Observed on {}".format(obs_time.fits)) # get position of sun and moon sun = get_sun(obstimes).transform_to(altaz_frames) if show_sun: ax.plot(delta_hours, sun.alt, 'r', label='sun') if show_moon: moon = get_moon(obstimes).transform_to(altaz_frames) ax.plot(delta_hours, moon.alt, 'k--', label='moon') ax.fill_between(delta_hours.to('hr').value, -90, 90, sun.alt < -0*u.deg, color='0.5', zorder=0, alpha=0.5) ax.fill_between(delta_hours.to('hr').value, -90, 90, sun.alt < -18*u.deg, color='k', zorder=0, alpha=0.5) ax.set_xlabel('LST offset') ax.set_ylabel('Altitude') # ax.set_ylim(-10, 90) ax.legend(loc='upper right') # plt.tight_layout() ax = fig.add_subplot(122, projection='polar') for name, pos in target_altaz_list.items(): ax.plot(pos.az/180*np.pi, np.cos(pos.alt), label=name, marker='.', ms=8) if show_sun: ax.plot(sun.az/180*np.pi, np.cos(sun.alt), 'r.', label='sun') if show_moon: moon = get_moon(obstimes).transform_to(altaz_frames) ax.plot(moon.az/180*np.pi, np.cos(moon.alt), 'k--', label='moon') ax.set_ylim(0, 1) plt.show()
def moon_position_icrs(self): """ :return: moon position as SkyCood object in icrs frame """ tmp_moon = get_moon(self._time) #in ICRS return SkyCoord(tmp_moon.ra.deg, tmp_moon.dec.deg, unit='deg', frame='gcrs',obstime=self._time).icrs
def get(self, source_coord, frame): """Evaluate the constraint for given targets, a specific location and time. Parameters ----- source_coord : astropy.SkyCoord Coordinates of the target sources. frame : astropy.coordinates.builtin_frames.altaz.AltAz A coordinate or frame in the Altitude-Azimuth system. Returns ----- out : numpy.ndarray Array of boolean values. One entry for each input coordinate. The entry is True, if the source is observable according to the constrains, and False otherwise. """ # if frame is the same as before re-use Moon positions: if self._same_frame(frame): moon_altaz = self.moon_altaz # otherwise calculate new Moon positions: else: moon_altaz = get_moon(frame.obstime).transform_to(frame) self.moon_altaz = moon_altaz self.last_frame = frame source_altaz = source_coord.transform_to(frame) separation = source_altaz.separation(moon_altaz) observable = np.logical_or(separation <= self.limit_lo, separation >= self.limit_hi) #observable = np.array(observable, dtype=float) return observable
def get_planet_info(): planet_info = [] with solar_system_ephemeris.set('de432s'): for planet_name in planets: planet = get_body(planet_name, current_time, location) planet_info.append({ "name": planet_name, "lightMinutes": to_light_minutes(planet.distance), "xyz": get_xyz(planet) }) sun = get_sun(current_time) planet_info.append({ "name": "The Sun", "lightMinutes": to_light_minutes(sun.distance), "xyz": get_xyz(sun) }) moon = get_moon(current_time) planet_info.append({ "name": "The Moon", "lightMinutes": to_light_minutes(moon.distance), "xyz": get_xyz(moon) }) return json.dumps(planet_info)
def moon_distance(loc, t2, t3): # Get the distance to the moon via the umbra diameter estimate if isinstance(loc, type(u'')) or isinstance(loc, type('')): loc = EarthLocation.of_address(loc) # Location of Sun & Moon sun = get_sun(t2) moon = get_moon(t2, loc) # Umbra size, from time and location su = estimate_umbra(loc, t2, t3) # Constants in km re = R_earth.to(u.km).value ds = sun.distance.to(u.km).value rs = R_sun.to(u.km).value rm = 1738.1 dm = (2 * rm - su) * ds / (2 * (rs - rm)) + re print( 'Distance estimate: {:.7} km (Actual: {:.7}). Ratio: {:.2}. Difference: {:.7}' .format(dm, moon.distance, moon.distance / (dm * u.km), dm * u.km - moon.distance)) # moon.distance is from surface, not center return dm, moon.distance.to(u.km).value + re
def evaluateDay(thisDate): delta_midnight = np.linspace(-12, 12, 96) * u.hour tomorrow = thisDate + dt.timedelta(days=1) midnight = Time("{}-{}-{} 00:00:00".format(tomorrow.year, tomorrow.month, tomorrow.day)) - utcoffset moonIllum = moon_illumination( midnight) # assume constant illumination throughout the day # if (moonIllum > MAX_MOON_ILLUMINATION): # return 0 allDay = midnight + delta_midnight allDayFrame = AltAz(obstime=allDay, location=observerLocation) objectAltAziAllDay = objectToObserve.transform_to(allDayFrame) objectAltAllDay = objectAltAziAllDay.alt sunAltAllDay = get_sun(allDay).transform_to(allDayFrame).alt moonAltAziAllDay = get_moon(allDay).transform_to(allDayFrame) moonAltAllDay = moonAltAziAllDay.alt #moonIllumAllDay = moon.moon_illumination(allDay) objectVisible = objectAltAllDay > (OBJECT_MIN_ALT * u.deg) nightTime = sunAltAllDay < (MAX_SUN_ALT * u.deg) moonLess = moonAltAllDay < (MAX_MOON_ALT * u.deg) goodHours = np.sum(objectVisible & nightTime & moonLess) * 0.25 #deltaAngles = np.rad2deg(angleBetweenPolarVectors(objectAltAziAllDay,moonAltAziAllDay)) # Great circle angle between the moon and the object # fig1 = plt.figure(num=None, figsize=(10, 6), dpi=80, facecolor='w', edgecolor='k') # ax1 = fig1.add_subplot(1,1,1) # ax1.plot(delta_midnight,objectAltAllDay,color='blue') # ax1.plot(delta_midnight,sunAltAllDay,color='red') # ax1.plot(delta_midnight,moonAltAllDay,color='black') # ax1.plot(delta_midnight,np.rad2deg(deltaAngles),color='green') return goodHours
def onclick(event): #if not event.inaxes: if event.inaxes != ax1: return xint = np.floor(event.xdata + 0.5) yint = np.floor(event.ydata + 0.5) delta_midnight = np.linspace(-12, 12, 96) * u.hour tomorrow = firstSunday + dt.timedelta( days=yint + (xint * 7)) + dt.timedelta(days=1) midnight = Time("{}-{}-{} 00:00:00".format( tomorrow.year, tomorrow.month, tomorrow.day)) - utcoffset allDay = midnight + delta_midnight allDayFrame = AltAz(obstime=allDay, location=observerLocation) objectAltAziAllDay = objectToObserve.transform_to(allDayFrame) objectAltAllDay = objectAltAziAllDay.alt sunAltAllDay = get_sun(allDay).transform_to(allDayFrame).alt moonAltAziAllDay = get_moon(allDay).transform_to(allDayFrame) moonAltAllDay = moonAltAziAllDay.alt deltaAngles = np.rad2deg( angleBetweenPolarVectors(objectAltAziAllDay, moonAltAziAllDay) ) # Great circle angle between the moon and the object ax3.clear() ax3.plot(delta_midnight, objectAltAllDay, color='blue') ax3.plot(delta_midnight, sunAltAllDay, color='red') ax3.plot(delta_midnight, moonAltAllDay, color='black') ax3.plot(delta_midnight, deltaAngles, color='green') ax3.set_title( (firstSunday + dt.timedelta(days=yint + (xint * 7))).strftime("%B %d, %Y"), fontsize=8) ax3.set_ylabel('degrees', fontsize=8) ax3.set_xlabel('hours around midnight', fontsize=8) ax3.set_ylim(0, np.max([90, np.max(deltaAngles)]))
def moon_and_sun(time, RA, DEC): """ Input: astropy.time.Time object Uses astropy get_moon and get_sun for lat and lon, then transforms to AltAz frame """ moon = get_moon(time, location=APACHE) sun = get_sun(time) target = SkyCoord(RA, DEC, unit=u.deg, frame=moon.frame) #separations moon_dist = moon.distance.value moon_sep = moon.separation(target).degree sun_moon_sep = moon.separation(sun.transform_to(moon.frame)).degree sun_elong = target.separation(sun.transform_to(moon.frame)).degree #geocentric latitude and longitude moon_lat, moon_lon = (moon.geocentrictrueecliptic.lat.value, moon.geocentrictrueecliptic.lon.value) sun_lat, sun_lon = (sun.geocentrictrueecliptic.lat.value, sun.geocentrictrueecliptic.lon.value) #change to altaz frame moon_altaz = moon.transform_to(AltAz(obstime=time, location=APACHE)) sun_altaz = sun.transform_to(AltAz(obstime=time, location=APACHE)) moon_alt, moon_az = (moon_altaz.alt.value, moon_altaz.az.value) sun_alt, sun_az = (sun_altaz.alt.value, sun_altaz.az.value) return [ moon_lat, moon_lon, sun_lat, sun_lon, moon_alt, moon_az, sun_alt, sun_az, moon_dist, moon_sep, sun_moon_sep, sun_elong ]
def next_tile(self, date=None, ra_current=None, dec_current=None, weather=None, bright_time=False, limiting_magnitude=None): """ Find the next tile to be observed. This is what Jeeves is going to call each time. Add ra_current and dec_current (and weather). This is how Jeeves is going to call this method. """ # TODO: Now or in 10 minutes? if date: self.utc = Time(date, format='iso', scale='utc') else: self.utc = Time(Time.now(), format='iso', scale='utc') self.local_sidereal_time = self.utc.sidereal_time('mean', longitude=params.params['LON']).value self.moon = get_moon(self.utc) # ONLY BRIGHT TIME if bright_time: is_bright_time = self.check_if_moon_is_above_horizon(moon=self.moon, time=self.utc) if is_bright_time: pass else: print 'Dark time, Taipan is observing.' return None, None #~ self.weather_conditions() #~ if weather_data_filename: #~ self.weather_data=np.loadtxt(weather_data_filename) # STRING!! #~ else: #~ self.weather_data=None # Telescope position from Jeeves self.ra_current=ra_current self.dec_current=dec_current if ra_current is None: self.ra_current=self.local_sidereal_time if dec_current is None: self.dec_current=-30.0 # TODO self.limiting_magnitude=limiting_magnitude best_tile=self.find_best_tile() if best_tile is None: return None, None # Update list of observed tiles manage_list_of_observed_tiles.add_tile_id_internal_to_the_list({best_tile.TaipanTile.field_id}) json_filename = create_obs_config_json.create_ObsConfig_json(tile=best_tile, utc=self.utc) self.observed_tiles.add(best_tile.TaipanTile.field_id) #~ # PLOT #~ telescope_positions=[best_tile.TaipanTile.ra, best_tile.TaipanTile.dec, self.moon.ra.value, self.moon.dec.value, best_tile.angular_moon_distance] #~ visualization.plot_selected_tile_with_neighbourhood(moon=self.moon, lst=self.local_sidereal_time, best_tiles=self.best_tiles_to_observe_now, tiles=self.tiles, best_tile=best_tile, i=1, ra_current=self.ra_current, dec_current=self.dec_current, telescope_positions=telescope_positions, observed_tile_ids=self.observed_tiles) # TODO: what should be a format for Jeeves? return best_tile, json_filename
def check_moon(file, avoid=30. * u.degree): if not isinstance(avoid, u.Quantity): avoid = float(avoid) * u.degree else: avoid = avoid.to(u.degree) header = fits.getheader(file) mlo = EarthLocation.of_site('Keck Observatory') # Update later obstime = Time(header['DATE-OBS'], format='isot', scale='utc', location=mlo) moon = get_moon(obstime, mlo) if 'RA' in header.keys() and 'DEC' in header.keys(): coord_string = '{} {}'.format(header['RA'], header['DEC']) target = SkyCoord(coord_string, unit=(u.hourangle, u.deg)) else: ## Assume zenith target = SkyCoord(obstime.sidereal_time('apparent'), mlo.latitude) moon_alt = moon.transform_to(AltAz(obstime=obstime, location=mlo)).alt.to(u.deg) if moon_alt < 0 * u.degree: print('Moon is down') return True else: sep = target.separation(moon) print('Moon is up. Separation = {:.1f} deg'.format( sep.to(u.degree).value)) return (sep > avoid)
def _perform(self): """ Returns an Argument() with the parameters that depends on this operation. """ self.log.info(f"Running {self.__class__.__name__} action") lat=c.Latitude(self.action.args.kd.get('SITELAT'), unit=u.degree) lon=c.Longitude(self.action.args.kd.get('SITELONG'), unit=u.degree) height=float(self.action.args.kd.get('ALT-OBS')) * u.meter loc = c.EarthLocation(lon, lat, height) temperature=float(self.action.args.kd.get('AMBTEMP'))*u.Celsius pressure=self.cfg['Telescope'].getfloat('pressure', 700)*u.mbar altazframe = c.AltAz(location=loc, obstime=self.action.args.kd.obstime(), temperature=temperature, pressure=pressure) moon = c.get_moon(Time(self.action.args.kd.obstime()), location=loc) sun = c.get_sun(Time(self.action.args.kd.obstime())) moon_alt = ((moon.transform_to(altazframe).alt).to(u.degree)).value moon_separation = (moon.separation(self.action.args.header_pointing).to(u.degree)).value\ if self.action.args.header_pointing is not None else None # Moon illumination formula from Meeus, ÒAstronomical # Algorithms". Formulae 46.1 and 46.2 in the 1991 edition, # using the approximation cos(psi) \approx -cos(i). Error # should be no more than 0.0014 (p. 316). moon_illum = 50*(1 - np.sin(sun.dec.radian)*np.sin(moon.dec.radian)\ - np.cos(sun.dec.radian)*np.cos(moon.dec.radian)\ * np.cos(sun.ra.radian-moon.ra.radian)) self.action.args.moon_alt = moon_alt self.action.args.moon_separation = moon_separation self.action.args.moon_illum = moon_illum return self.action.args
def moon_phase_angle(time, ephemeris=None): """ Calculate lunar orbital phase in radians. Parameters ---------- time : `~astropy.time.Time` Time of observation ephemeris : str, optional Ephemeris to use. If not given, use the one set with `~astropy.coordinates.solar_system_ephemeris` (which is set to 'builtin' by default). Returns ------- i : float Phase angle of the moon [radians] """ # TODO: cache these sun/moon SkyCoord objects sun = get_sun(time) moon = get_moon(time, ephemeris=ephemeris) elongation = sun.separation(moon) return np.arctan2(sun.distance*np.sin(elongation), moon.distance - sun.distance*np.cos(elongation))
def draw_moon(ax, input_time, input_loc): moon = get_moon(time=input_time, location=input_loc) moon = SkyCoord(moon.ra, moon.dec, frame='gcrs').transform_to('icrs') ax.plot([moon.ra.radian], [-moon.dec.value + 45], color='yellow', linestyle='', marker='o')
def test_moon_separation(): time = Time('2003-04-05 06:07:08') apo = Observer.at_site("APO") altaz_frame = apo.altaz(time) moon = get_moon(time, apo.location).transform_to(altaz_frame) one_deg_away = SkyCoord(az=moon.az, alt=moon.alt + 1 * u.deg, frame=altaz_frame) five_deg_away = SkyCoord(az=moon.az + 5 * u.deg, alt=moon.alt, frame=altaz_frame) twenty_deg_away = SkyCoord(az=moon.az + 20 * u.deg, alt=moon.alt, frame=altaz_frame) constraint = MoonSeparationConstraint(min=2 * u.deg, max=10 * u.deg) is_constraint_met = constraint( apo, [one_deg_away, five_deg_away, twenty_deg_away], times=time) assert np.all(is_constraint_met == [False, True, False]) constraint = MoonSeparationConstraint(max=10 * u.deg) is_constraint_met = constraint( apo, [one_deg_away, five_deg_away, twenty_deg_away], times=time) assert np.all(is_constraint_met == [True, True, False]) constraint = MoonSeparationConstraint(min=2 * u.deg) is_constraint_met = constraint( apo, [one_deg_away, five_deg_away, twenty_deg_away], times=time) assert np.all(is_constraint_met == [False, True, True])
def calculate_az_el(self, name, time, alt_az_frame): """Calculates Azimuth and Elevation of the Specified Object at the Specified Time Parameters ---------- name : str Name of the Object being Tracked time : Time Current Time (only necessary for Sun/Moon Ephemeris) alt_az_frame : AltAz AltAz Frame Object Returns ------- (float, float) (az, el) Tuple """ if name == "Sun": alt_az = get_sun(time).transform_to(alt_az_frame) elif name == "Moon": alt_az = get_moon(time, self.location).transform_to(alt_az_frame) else: alt_az = self.sky_coords[self.sky_coord_names[name]].transform_to( alt_az_frame) return alt_az.az.degree, alt_az.alt.degree
def get_info_of_target(target, *args, **kwargs): ra = target.ra dec = target.dec coords = SkyCoord(ra=ra, dec=dec, unit=(u.degree, u.degree)) hanle = EarthLocation(lat=32.77889 * u.degree, lon=78.96472 * u.degree, height=4500 * u.m) iao = Observer(location=hanle, name="GIT", timezone="Asia/Kolkata") twilight_prime = iao.sun_rise_time( Time(datetime.utcnow()), which="next", horizon=sunrise_horizon * u.degree) - 12 * u.hour targets_rise_time = iao.target_rise_time(twilight_prime, coords, which="nearest", horizon=horizon * u.degree) targets_set_time = iao.target_set_time(targets_rise_time, coords, which="next", horizon=horizon * u.degree) rise_time_IST = (targets_rise_time + 5.5 * u.hour).isot set_time_IST = (targets_set_time + 5.5 * u.hour).isot tend = targets_set_time mooncoords = get_moon(tend, hanle) sep = mooncoords.separation(coords) print(target.name, rise_time_IST, set_time_IST, sep)
def moon_altaz(self, time, ephemeris=None): if not isinstance(time, Time): time = Time(time) moon = get_moon(time, location=self.location, ephemeris=ephemeris) return self.altaz(time, moon, grid=False)
def _get_obs_param(ra, dec, mjd): ''' get observing condition given tileid and time of observation ''' from astropy.time import Time from astropy.coordinates import EarthLocation, SkyCoord, AltAz, get_sun, get_moon kpno = EarthLocation.of_site('kitt peak') # get observing conditions coord = SkyCoord(ra=ra * u.deg, dec=dec * u.deg) utc_time = Time(mjd, format='mjd') # observed time (UTC) kpno_altaz = AltAz(obstime=utc_time, location=kpno) coord_altaz = coord.transform_to(kpno_altaz) airmass = coord_altaz.secz # sun sun = get_sun(utc_time) sun_altaz = sun.transform_to(kpno_altaz) sun_alt = sun_altaz.alt.deg sun_sep = sun.separation(coord).deg # sun separation # moon moon = get_moon(utc_time) moon_altaz = moon.transform_to(kpno_altaz) moon_alt = moon_altaz.alt.deg moon_sep = moon.separation(coord).deg #coord.separation(self.moon).deg elongation = sun.separation(moon) phase = np.arctan2(sun.distance * np.sin(elongation), moon.distance - sun.distance * np.cos(elongation)) moon_phase = phase.value moon_ill = (1. + np.cos(phase)) / 2. return airmass, moon_ill.value, moon_alt, moon_sep, sun_alt, sun_sep
def moonlight_veto(self, dt, debug=False): """ Check if the Moon period defined by the rise and set time correspond to a situation where the moon is too bright or too close from the source. If this is the case (too bright or too close), returns True (the veto is confirmed). """ too_bright = False too_close = False # Check moon illumination for t in dt: moonlight = moon_illumination(Df(t)) if (moonlight >= self.moon_maxlight): too_bright = True if (debug): print("Moonlight :", moonlight, " too bright ! -> confirmed") break # Check distance to source at rise and set for t in dt: moon_radec = get_moon(Df(t), self.site) dist = moon_radec.separation(self.target.coord) if dist <= self.moon_mindist: too_close = True if (debug): print(" Moon Distance : ", dist, "too close !") break return (too_bright, too_close)
def compute_sun_moon(self, trange, which='sun', dt_min=5): """ compute the position of the sun/moon from the location of the observatory between the specified time interval. :param iterable trange: list of 2 elements specifying the time range (UTC). Each of them can be either a `str` or `astropy.time.Time`. :param str which: celestial body to 'move'. Either 'sun' or 'moon' :param float dt_min: time resolution in minues. :returns: position of the sun/moon as observed from this location at the given time. :rtype astropy.coordinates.SkyCoord: """ start = time.time() # create the time object times = get_times(trange, dt_min) # define the observatory reference frame and move the sun obs_altaz = self.get_alt_az() if which.lower() == 'sun': skypos = get_sun(times).transform_to(obs_altaz) elif which.lower() == 'moon': skypos = get_moon(times).transform_to(obs_altaz) else: raise ValueError( "compute_sun_moon accepts either 'sun' or 'moon'. Got %s" % (which)) end = time.time() self.logger.debug( "Computing %s motion from %s to %s (res: %.2f min, %d steps). Took %.2f sec" % (which, times.min().iso, times.max().iso, dt_min, len(times), (end - start))) return skypos
def moon_phase_angle(time, ephemeris=None): """ Calculate lunar orbital phase in radians. Parameters ---------- time : `~astropy.time.Time` Time of observation location : `~astropy.coordinates.EarthLocation` Location of observer ephemeris : str, optional Ephemeris to use. If not given, use the one set with `~astropy.coordinates.solar_system_ephemeris` (which is set to 'builtin' by default). Returns ------- i : float Phase angle of the moon [radians] """ # TODO: cache these sun/moon SkyCoord objects sun = get_sun(time) moon = get_moon(time, ephemeris=ephemeris) elongation = sun.separation(moon) return np.arctan2(sun.distance * np.sin(elongation), moon.distance - sun.distance * np.cos(elongation))
def __init__(self, telLat, telLon, telElv, time, steps, sig1=.11, m1=1.7, t1=800, xlen=500, ylen=500, mag_range=(-3, 3), dec_range=(-20, 90), ra_range=(0,0), max_sun_alt = -15, timestep=.5): self.Bews = [] self.Bnss = [] self.Buds = [] self.xlen = xlen self.ylen = ylen self.mag_range = mag_range self.dec_range = dec_range self.telLat = telLat * u.deg self.telLon = telLon * u.deg self.telElv = telElv * u.m self.tel_loc = EarthLocation(lat=telLat * u.deg, lon=telLon * u.deg, height=telElv * u.m) self.err_sig = sig1 self.err_mag = m1 self.err_t1 = t1 self.time_info = None self.time_info = Time(time, location=self.tel_loc) self.delta_time = np.linspace(-12, 12, steps) * u.hour self.time_delt = self.delta_time[1]-self.delta_time[0] self.telFrame = AltAz(obstime=self.time_info + self.delta_time, location=self.tel_loc) #get indicies for when sky is dark self.sunaltazs = get_sun(self.delta_time+self.time_info).transform_to(self.telFrame) self.moonaltazs = get_moon(self.delta_time+self.time_info).transform_to(self.telFrame) dark_times = np.where((self.sunaltazs.alt < max_sun_alt * u.deg)) self.dark_times = self.telFrame.obstime.sidereal_time('apparent')[dark_times] self.max_sun_alt = max_sun_alt self.int_delta_time = np.append(np.arange(-12,12,timestep),12)*u.hour self.intTelFrame = AltAz(obstime=self.time_info + self.int_delta_time, location=self.tel_loc) self.intsunaltazs = get_sun(self.int_delta_time+self.time_info).transform_to(self.intTelFrame) int_dark_times = np.where((self.intsunaltazs.alt < max_sun_alt * u.deg)) self.int_dark_times = self.intTelFrame.obstime.sidereal_time('apparent')[int_dark_times] #the hour_correction is to shift the sky to include stars that have just barely risen hour_correction = 4 * u.hourangle #calculate the possible ra range of the telescope for the given night if ra_range: self.ra_range = ra_range else: self.ra_range = ((self.dark_times[0] - hour_correction).to('deg').value, (self.dark_times[-1] + hour_correction).to('deg').value) if self.ra_range[0] > self.ra_range[1]: self.ra_range = self.ra_range[::-1] self.catalogs = [] self.cat_names = [] self.star_dict = {}
def compute_constraint(self, times, observer, targets): """ Computes the observability of the moon given a minimum distance to the moon between self.min_dist (for illumination = 0) and self.max_dist (for illumination = 1) by interpolating an intermediate distance from those two values following a linear regression. @param times: the times to compute the constraint for @param observer: the observer to compute the constraint for @param targets: the list of targets to compute the constraint for @return: the positive mask for target being observable for the given times and observer given the constraint is matched """ # removed the location argument here, which causes small <1 deg # inaccuracies, but it is needed until astropy PR #5897 is released # which should be astropy 1.3.2 moon = get_moon(times) # note to future editors - the order matters here # moon.separation(targets) is NOT the same as targets.separation(moon) # the former calculates the separation in the frame of the moon coord # which is GCRS, and that is what we want. moon_separation = moon.separation(targets) illumination = moon_illumination(times) min_dist = self.min_dist.value + (self.max_dist.value - self.min_dist.value) * illumination mask = min_dist <= moon_separation.degree return mask
def test_moon_separation(): time = Time('2003-04-05 06:07:08') apo = Observer.at_site("APO") altaz_frame = apo.altaz(time) moon = get_moon(time, apo.location).transform_to(altaz_frame) one_deg_away = SkyCoord(az=moon.az, alt=moon.alt+1*u.deg, frame=altaz_frame) five_deg_away = SkyCoord(az=moon.az+5*u.deg, alt=moon.alt, frame=altaz_frame) twenty_deg_away = SkyCoord(az=moon.az+20*u.deg, alt=moon.alt, frame=altaz_frame) constraint = MoonSeparationConstraint(min=2*u.deg, max=10*u.deg) is_constraint_met = constraint(apo, [one_deg_away, five_deg_away, twenty_deg_away], times=time) assert np.all(is_constraint_met == [False, True, False]) constraint = MoonSeparationConstraint(max=10*u.deg) is_constraint_met = constraint(apo, [one_deg_away, five_deg_away, twenty_deg_away], times=time) assert np.all(is_constraint_met == [True, True, False]) constraint = MoonSeparationConstraint(min=2*u.deg) is_constraint_met = constraint(apo, [one_deg_away, five_deg_away, twenty_deg_away], times=time) assert np.all(is_constraint_met == [False, True, True])
def check_moon(file, avoid=30.*u.degree): if not isinstance(avoid, u.Quantity): avoid = float(avoid)*u.degree else: avoid = avoid.to(u.degree) header = fits.getheader(file) mlo = EarthLocation.of_site('Keck Observatory') # Update later obstime = Time(header['DATE-OBS'], format='isot', scale='utc', location=mlo) moon = get_moon(obstime, mlo) if 'RA' in header.keys() and 'DEC' in header.keys(): coord_string = '{} {}'.format(header['RA'], header['DEC']) target = SkyCoord(coord_string, unit=(u.hourangle, u.deg)) else: ## Assume zenith target = SkyCoord(obstime.sidereal_time('apparent'), mlo.latitude) moon_alt = moon.transform_to(AltAz(obstime=obstime, location=mlo)).alt.to(u.deg) if moon_alt < 0*u.degree: print('Moon is down') return True else: sep = target.separation(moon) print('Moon is up. Separation = {:.1f} deg'.format(sep.to(u.degree).value)) return (sep > avoid)
def visibility_table(observer, target, obstime, dt=1 * u.hour, dt_number=24): """Given a target and a date for observation returns.... Inputs: target: date: observer (optional): dt (optional): dt_number (optional: Outpus table """ utcoffset = observer.timezone.utcoffset(obstime.datetime).seconds * u.s delta_midnight = np.linspace(0, dt_number, dt_number + 1) * u.hour times = obstime + delta_midnight frame = AltAz(obstime=times, location=observer.location) moon_altazs = get_moon(times).transform_to(frame) sun_altazs = get_sun(times).transform_to(frame) target_altazs = target.coord.transform_to(frame) night = observer.is_night(times) up = observer.target_is_up(times, target) table = QTable() table['date'] = times # table['night'] = night table['target'] = target_altazs table['visible'] = up & night table['airmass'] = target_altazs.secz table['moon_separation'] = np.sqrt((target_altazs.alt - moon_altazs.alt)**2 + (target_altazs.az - moon_altazs.az)**2) table['moon_iluminationn'] = observer.moon_illumination(times) import pdb pdb.set_trace() return (table)
def moon_distance(ra=DEF__RA, dec=DEF__DEC, date=DEF__DATE, from_now=False): # check input(s) ra = DEF__RA if not isinstance(ra, float) else ra ra = MIN__RA if ra < MIN__RA else ra ra = MAX__RA if ra > MAX__RA else ra dec = DEF__DEC if not isinstance(dec, float) else dec dec = MIN__DEC if dec < MIN__DEC else dec dec = MAX__DEC if dec > MAX__DEC else dec date = DEF__DATE if (not isinstance(date, str) or date.strip() == '' or not re.search(ISO__PATTERN, date)) else date from_now = False if not isinstance(from_now, bool) else from_now # set default(s) _sep = None _time = Time(date) if from_now else Time(date.split()[0]) _time = Time(_time.iso) _time = Time(_time) + (1.0 * u.day * np.linspace(0.0, 1.0, AST__5_MINUTES)) # noinspection PyBroadException try: _moon_coord = get_moon(_time, location=KUIPER_OBSERVATORY) _obj_radec = SkyCoord(ra=ra*u.deg, dec=dec*u.deg) _sep = _obj_radec.separation(_moon_coord).deg except Exception: _sep = np.linspace(math.nan, math.nan, AST__5_MINUTES) # return array return _sep
def moonLC(time, loc): ''' ################################################################# # Desc: Return ALT, AZ of the moon at utc isot time, location. # # ------------------------------------------------------------- # # Imports: astropy.time.Time # # astropy.coordinates.(Earthlocation, AltAz, get_moon) # # ------------------------------------------------------------- # # Input # # ------------------------------------------------------------- # # time: str time format in ISOT, UTC # # loc: iterable floats position coordinate in [long, lat, alt] # # ------------------------------------------------------------- # # Output # # ------------------------------------------------------------- # # ALT, AZ: float alt-az coordinate position in degree # ################################################################# ''' from astropy.time import Time from astropy.coordinates import EarthLocation, AltAz, get_moon t = Time(time, format='isot', scale='utc') l = EarthLocation.from_geodetic(*loc) eq = get_moon(t, l, 'de440') lc = eq.transform_to(AltAz(obstime=t, location=l)) ALT, AZ = lc.alt.degree, lc.az.degree return ALT, AZ
def separateap(): for ctime in times: t = start + ctime frame = AltAz(obstime=t, location=berlin) sunaltaz = get_sun(t).transform_to(frame) if sunaltaz.alt < astronight: #sunaltazs.append(sunaltaz.alt) #print(sunaltaz) #print(sunaltaz.alt) #print('Moon phase angle:', moon_phase_angle(t, berlin)) lum = moon_illumination(t, berlin) #print('Moon illumination:', moon_illumination(t, berlin)) if lum < maxillum: delta.append(ctime) illum.append(lum) moon = get_moon(t, berlin) moonaltaz = moon.transform_to(frame) #print("Moon's Altitude = {0.alt:.2}".format(moonaltaz)) moonaltazs.append(moonaltaz.alt) # print(moonaltaz.alt) if mod == 'graph': pass elif mod == 'text' or mod == 'both': if moonaltaz.alt > Latitude(minalt * u.deg): dtxt.write('Date and time: ' + str(t) + '\n' + 'Altitude: ' + str(moonaltaz.alt) + '\n' + 'Illumination: ' + str(lum) + '\n \n') if mod == 'text': pass elif mod == 'graph' or mod == 'both': chobj(delta, illum, moonaltazs)
def moonEQC(time, loc): ''' ################################################################# # Desc: Return RA, DEC of the moon at utc isot time, location. # # ------------------------------------------------------------- # # Imports: astropy.time.Time # # astropy.coordinates.(Earthlocation, AltAz, get_moon) # # ------------------------------------------------------------- # # Input # # ------------------------------------------------------------- # # time: str time format in ISOT, UTC # # loc: iterable floats position coordinate in [long, lat, alt] # # ------------------------------------------------------------- # # Output # # ------------------------------------------------------------- # # RA, DEC: float equatorial coordinate position in degree # ################################################################# ''' from astropy.time import Time from astropy.coordinates import EarthLocation, AltAz, get_moon t = Time(time, format='isot', scale='utc') l = EarthLocation.from_geodetic(*loc) eq = get_moon(t, l, 'de440') aa = eq.transform_to(AltAz(obstime=t, location=l)) RA, DEC = eq.ra.degree, eq.dec.degree return RA, DEC
def moon_angle(obsnight, coords): obstime = Time(str(obsnight.obs_date).split()[0], scale='utc') mooncoord = get_moon(obstime) cs = SkyCoord('%s %s' % (coords[0], coords[1]), unit=(u.hourangle, u.deg)) return ('%.1f' % cs.separation(mooncoord).deg)
def get_moon_j2000(epoch, line1, line2, position=None): ''' Code to determine the apparent J2000 position for a given time and at a given position for the observatory. epoch needs to be a datetime or Time object. position is a list/tuple of X/Y/Z positions ''' from astropy.time import Time from astropy.coordinates import get_moon, EarthLocation import astropy.units as u import sys from datetime import datetime if type(epoch) is Time: epoch = epoch.datetime if position is None: position = get_nustar_location(epoch, line1, line2) # position in ECI coords t = Time(epoch) loc = eci2el(*position * u.km, t) moon_coords = get_moon(t, loc) # Get just the coordinates in degrees ra_moon, dec_moon = moon_coords.ra.degree * u.deg, moon_coords.dec.degree * u.deg return ra_moon, dec_moon
def get_moon_angle(file_name, number_of_files=100): df_SKY=pd.read_csv(file_name) new_SKY = df_SKY.query('OBJTYPE=="SKY".ljust(16)') DEC = np.array(new_SKY['DEC'].tolist()) FIBERID = np.array(new_SKY['FIBERID'].tolist()) MJD = np.array(new_SKY['MJD'].tolist()) RA = np.array(new_SKY['RA'].tolist()) plates = list(new_SKY['PLATE'][:number_of_files].values) mjds = list(new_SKY['MJD'][:number_of_files].values) fiberids = list(new_SKY['FIBERID'][:number_of_files].values) files = ['spec-%s-%s-%s.fits'%(plate,mjd,str(fiberid).zfill(4)) for plate,mjd,fiberid in zip(plates,mjds,fiberids)] #FINDING INTERPLATE SKY TIME fin_mean=[] #time for each moon sky observation interplate, used for moon angle for r in range(len(files)): #mechanization of ubiquitious exposure count sampling=fitsio.read_header(files[r],0) #finding number of exposures h_beg=[] h_end=[] mean_per=[] #time for each moon sky observation intraplate for k in range(4, sampling['NEXP']+4): #4 is constant for everything h=fitsio.read_header(files[3],k) h_beg.append(h['TAI-BEG']) #ONLY VARIES WITH PLATE NUMBER, different for k's h_end.append(h['TAI-END']) #ONLY VARIES WITH PLATE NUMBER, different for k's mean_times=(h['TAI-BEG']+h['TAI-END'])/2 mean_per.append(mean_times) tot=np.mean(mean_per) fin_mean.append(tot) #TAI TO MJD new_time=np.array(fin_mean) time_MJD=new_time/(86400) moon_coords1=[] moon_coords=[] for i in range (len(time_MJD)): t=Time(time_MJD[i], format='mjd') moon_coords1.append(get_moon(t)) moon_coords.append(moon_coords1[i].spherical) moon_coords=list(moon_coords) #print(moon_coords) moon_coords2=[] for i in range(len(moon_coords)): moon_coords2.append(moon_coords[i]._values) moon_coords2=np.array(moon_coords2) sky_coords=np.vstack((RA,DEC)).T #SPLITTING ARRAY new_sky_coords=sky_coords[:number_of_files] new_sky_RA = [item[0] for item in new_sky_coords] new_sky_DEC = [item[1] for item in new_sky_coords] moon_RA = [item[0] for item in moon_coords2] moon_DEC = [item[1] for item in moon_coords2] new_sky_RA=np.array(new_sky_RA)*(np.pi/180) new_sky_DEC=np.array(new_sky_DEC)*(np.pi/180) moon_RA=np.array(moon_RA)*(np.pi/180) moon_DEC=np.array(moon_DEC)*(np.pi/180) #MOON-SKY ANGLE CALCULATIONS moon_sky_angle=[] for i in range(len(new_sky_coords)): moon_sky_angle.append(np.arccos((np.sin(new_sky_RA[i])*np.sin(moon_RA[i]))+np.cos(new_sky_RA[i])*np.cos(moon_RA[i])*(np.cos(new_sky_DEC[i]-moon_DEC[i])))*(180/np.pi)) #list(moon_sky_angle) return (np.array(moon_sky_angle))
def test_regression_5889_5890(): # ensure we can represent all Representations and transform to ND frames greenwich = EarthLocation( *u.Quantity([3980608.90246817, -102.47522911, 4966861.27310067], unit=u.m)) times = Time("2017-03-20T12:00:00") + np.linspace(-2, 2, 3)*u.hour moon = get_moon(times, location=greenwich) targets = SkyCoord([350.7*u.deg, 260.7*u.deg], [18.4*u.deg, 22.4*u.deg]) targs2d = targets[:, np.newaxis] targs2d.transform_to(moon)
def test_regression_4926(): times = Time('2010-01-1') + np.arange(20)*u.day green = get_builtin_sites()['greenwich'] # this is the regression test moon = get_moon(times, green) # this is an additional test to make sure the GCRS->ICRS transform works for complex shapes moon.transform_to(ICRS()) # and some others to increase coverage of transforms moon.transform_to(HCRS(obstime="J2000")) moon.transform_to(HCRS(obstime=times))
def test_moon_veto(observer): mac = MoonAvoidance() time = Time('2016-08-13 10:00:00') moon = get_moon(time, observer.location) observation1 = Observation(Field('Sabik', '17h10m23s -15d43m30s')) # Sabik veto1, score1 = mac.get_score(time, observer, observation1, moon=moon) assert veto1 is True
def __init__(self, date=None, site='sutherland', targets=None, tz=2*u.h, **options): #res self.sitename = site.title() self.siteloc = EarthLocation.of_site(self.sitename) #TODO from time import timezone self.tz = tz #can you get this from the site location?? #obs = Observer(self.siteloc) self.targets = {} self.trajectories = {} self.plots = OrderedDict() if not date: now = datetime.now() #current local time #default behaviour of this function changes depending on the time of day. #if calling during early morning hours (at telescope) - let midnight refer to previous midnight #if calling during afternoon hours - let midnight refer to coming midnight d = now.day# + (now.hour > 7) #FIXME =32?? date = datetime(now.year, now.month, d, 0, 0, 0) else: raise NotImplementedError self.date = date self.midnight = midnight = Time(date) - tz #midnight UTC in local time #TODO: efficiency here. Dont need to plot everything over self.hours = h = np.linspace(-12, 12, 250) * u.h #variable time self.t = t = midnight + h self.tp = t.plot_date self.frames = AltAz(obstime=t, location=self.siteloc) #self.tmoon #collect name, coordinates in dict if not targets is None: self.add_coordinates(targets) #Get sun, moon coordinates sun = get_sun(t) self.sun = sun.transform_to(self.frames) #WARNING: slow!!!! #TODO: other bright stars / planets #get dawn / dusk times self.dusk, self.dawn = self.get_daylight() self.sunset, self.sunrise = self.dusk['sunset'], self.dawn['sunrise'] #get moon rise/set times, phase, illumination etc... self.moon = get_moon(t).transform_to(self.frames) self.mooning = self.get_moonlight() self.moon_phase, self.moon_ill = self.get_moon_phase() self.setup_figure() #HACK self.cid = self.figure.canvas.mpl_connect('draw_event', self._on_first_draw)
def test_moon_avoidance(observer): mac = MoonAvoidance() time = Time('2016-08-13 10:00:00') moon = get_moon(time, observer.location) observation1 = Observation(Field('HD189733', '20h00m43.7135s +22d42m39.0645s')) # HD189733 observation2 = Observation(Field('Hat-P-16', '00h38m17.59s +42d27m47.2s')) # Hat-P-16 veto1, score1 = mac.get_score(time, observer, observation1, moon=moon) veto2, score2 = mac.get_score(time, observer, observation2, moon=moon) assert veto1 is False and veto2 is False assert score2 > score1
def get_moon_phase(self): '''calculate moon phase and illumination at local midnight''' midnight = self.midnight altaz = AltAz(location=self.siteloc, obstime=midnight) moon = get_moon(midnight) moon = moon.transform_to(altaz) sun = get_sun(midnight) sun = sun.transform_to(altaz) # elongation = sun.separation(moon) #phase angle at midnight phase = np.arctan2(sun.distance * np.sin(elongation), moon.distance - sun.distance * np.cos(elongation)) ill = (1 + np.cos(phase)) / 2.0 return phase.value, ill.value
def compute_constraint(self, times, observer, targets): # removed the location argument here, which causes small <1 deg # innacuracies, but it is needed until astropy PR #5897 is released # which should be astropy 1.3.2 moon = get_moon(times, ephemeris=self.ephemeris) # note to future editors - the order matters here # moon.separation(targets) is NOT the same as targets.separation(moon) # the former calculates the separation in the frame of the moon coord # which is GCRS, and that is what we want. moon_separation = moon.separation(targets) if self.min is None and self.max is not None: mask = self.max >= moon_separation elif self.max is None and self.min is not None: mask = self.min <= moon_separation elif self.min is not None and self.max is not None: mask = ((self.min <= moon_separation) & (moon_separation <= self.max)) else: raise ValueError("No max and/or min specified in " "MoonSeparationConstraint.") return mask
def get_moon_j2000(epoch, line1, line2, position = None): ''' Code to determine the apparent J2000 position for a given time and at a given position for the observatory. epoch needs to be a datetime or Time object. position is a list/tuple of X/Y/Z positions ''' from astropy.time import Time from astropy.coordinates import get_moon, EarthLocation import astropy.units as u import sys from datetime import datetime if type(epoch) is Time: epoch = epoch.datetime if position is None: position = get_nustar_location(epoch, line1, line2) # position in ECI coords t=Time(epoch) loc = eci2el(*position*u.km,t) moon_coords = get_moon(t,loc) # Get just the coordinates in degrees ra_moon, dec_moon = moon_coords.ra.degree * u.deg, moon_coords.dec.degree*u.deg return ra_moon, dec_moon
def _update_queue(self, current_state): """Calculate greedy weighting of requests in the Pool using current telescope state only""" # store block index for which these values were calculated self.queue_block = block_index(current_state['current_time']) # check that the pool has fields in it if len(self.rp.pool) == 0: raise QueueEmptyError("No fields in pool") # join with fields so we have the information we need # make a copy so rp.pool and self.queue are not linked df = self.rp.pool.join(self.fields.fields, on='field_id').copy() df = self._update_overhead(current_state, df=df) # start with conservative altitude cut; # airmass weighting applied naturally below # also make a copy because otherwise it retains knowledge of # (discarded) previous reference and raises SettingWithCopyWarnings df = df.loc[df['altitude'] > 20, :].copy() if len(df) == 0: raise QueueEmptyError("No fields in queue above altitude cut") # if restricting to one program per block, drop other programs if self.block_programs: current_block_program = PROGRAM_BLOCK_SEQUENCE[ self.queue_block % LEN_BLOCK_SEQUENCE] df = df.loc[df['program_id'] == current_block_program, :] # use cadence functions to compute requests with active cadence windows # this is slow, so do it after our altitude cut in_window = {} for idx, row in df.iterrows(): # this is way, way slower # df['in_cadence_window'].ix[idx] = \ in_window[idx] = eval( '{}(row, current_state)'.format(row['cadence_func'])) cadence_cuts = pd.Series(in_window) # TODO: handle if cadence cuts returns no fields if np.sum(cadence_cuts) == 0: raise QueueEmptyError("No fields with observable cadence windows") # also make a copy because otherwise it retains knowledge of # (discarded) previous reference and raises SettingWithCopyWarnings df = df.loc[cadence_cuts, :].copy() # compute airmasses by field_id # airmass = zenith_angle_to_airmass(90. - df_alt) # airmass.name = 'airmass' # df = pd.merge(df, pd.DataFrame(airmass), # left_on='field_id', right_index=True) # airmass cut (or add airmass weighting to value below) # df = df[(df['airmass'] <= MAX_AIRMASS) & (df['airmass'] > 0)] # compute inputs for sky brightness sc = coord.SkyCoord(df['ra'], df['dec'], frame='icrs', unit='deg') sun = coord.get_sun(current_state['current_time']) sun_altaz = skycoord_to_altaz(sun, current_state['current_time']) moon = coord.get_moon(current_state['current_time'], location=P48_loc) moon_altaz = skycoord_to_altaz(moon, current_state['current_time']) df.loc[:, 'moonillf'] = astroplan.moon.moon_illumination( # Don't use P48_loc to avoid astropy bug: # https://github.com/astropy/astroplan/pull/213 current_state['current_time']) # current_state['current_time'], P48_loc) df.loc[:, 'moon_dist'] = sc.separation(moon).to(u.deg).value df.loc[:, 'moonalt'] = moon_altaz.alt.to(u.deg).value df.loc[:, 'sunalt'] = sun_altaz.alt.to(u.deg).value # compute sky brightness df.loc[:, 'sky_brightness'] = self.Sky.predict(df) #df = pd.merge(df, df_sky, left_on='field_id', right_index=True) # compute seeing at each pointing df.loc[:, 'seeing'] = seeing_at_pointing(current_state['current_zenith_seeing'], df['altitude']) #df_seeing.name = 'seeing' #df = pd.merge(df, df_seeing, left_on='field_id', right_index=True) df.loc[:, 'limiting_mag'] = limiting_mag(EXPOSURE_TIME, df['seeing'], df['sky_brightness'], filter_id=df['filter_id'], altitude=df['altitude'], SNR=5.) #df_limmag.name = 'limiting_mag' #df = pd.merge(df, df_limmag, left_on='field_id', right_index=True) df.loc[:, 'value'] = self._metric(df) self.queue = df
def log_pointing(self, state, request): record = {} # don't use request_id here, but # let sqlite create a unique non-null key # record['obsHistID'] = request['request_id'] record["sessionID"] = 0 record["propID"] = request["target_program_id"] record["fieldID"] = request["target_field_id"] record["fieldRA"] = np.radians(request["target_ra"]) record["fieldDec"] = np.radians(request["target_dec"]) record["filter"] = '"' + FILTER_ID_TO_NAME[request["target_filter_id"]] + '"' # times are recorded at start of exposure exposure_start = state["current_time"] - request["target_exposure_time"] # see note in utils.py exposure_start.delta_ut1_utc = 0.0 record["expDate"] = (exposure_start - self.survey_start_time).sec record["expMJD"] = exposure_start.mjd record["night"] = np.floor((exposure_start - self.survey_start_time).jd).astype(np.int) record["visitTime"] = request["target_exposure_time"].to(u.second).value record["visitExpTime"] = request["target_exposure_time"].to(u.second).value # compute some values we will need sc = coord.SkyCoord(record["fieldRA"] * u.radian, record["fieldDec"] * u.radian) altaz = skycoord_to_altaz(sc, exposure_start) pointing_seeing = seeing_at_pointing(state["current_zenith_seeing"].to(u.arcsec).value, altaz.alt.value) record["FWHMgeom"] = pointing_seeing record["FWHMeff"] = pointing_seeing # transparency # finRank record["airmass"] = altaz.secz.value # vSkyBright record["filtSkyBright"] = request["target_sky_brightness"] record["rotSkyPos"] = 0.0 # TODO: confirm record["rotTelPos"] = 0.0 # despite the docs, it seems lst is stored as radians record["lst"] = np.radians(exposure_start.sidereal_time("apparent").to(u.hourangle).value / 24.0 * 360.0) record["altitude"] = altaz.alt.to(u.radian).value record["azimuth"] = altaz.az.to(u.radian).value sun = coord.get_sun(exposure_start) sun_altaz = skycoord_to_altaz(sun, exposure_start) moon = coord.get_moon(exposure_start, P48_loc) moon_altaz = skycoord_to_altaz(moon, exposure_start) record["dist2Moon"] = sc.separation(moon).to(u.radian).value record["solarElong"] = sc.separation(sun).to(u.deg).value record["moonRA"] = moon.ra.to(u.radian).value record["moonDec"] = moon.dec.to(u.radian).value record["moonAlt"] = moon_altaz.alt.to(u.radian).value record["moonAZ"] = moon_altaz.az.to(u.radian).value # store tonight's mjd so that we can avoid recomputing moon # illumination, which profiling shows is weirdly expensive if np.floor(exposure_start.mjd) != self.mjd_tonight: self.moon_illumination_tonight = ( astroplan.moon.moon_illumination( # Don't use P48_loc to avoid astropy bug: # https://github.com/astropy/astroplan/pull/213 # exposure_start, P48_loc) * 100. exposure_start ) * 100.0 ) self.mjd_tonight = np.floor(exposure_start.mjd) record["moonPhase"] = self.moon_illumination_tonight record["sunAlt"] = sun_altaz.alt.to(u.radian).value record["sunAz"] = sun_altaz.az.to(u.radian).value # phaseAngle, rScatter, mieScatter, moonBright, darkBright # rawSeeing # wind # humidity if self.prev_obs is not None: sc_prev = coord.SkyCoord(self.prev_obs["fieldRA"] * u.radian, self.prev_obs["fieldDec"] * u.radian) record["slewDist"] = sc.separation(sc_prev).to(u.radian).value record["slewTime"] = record["expDate"] - (self.prev_obs["expDate"] + self.prev_obs["visitTime"]) record["fiveSigmaDepth"] = request["target_limiting_mag"] record["ditheredRA"] = 0.0 record["ditheredDec"] = 0.0 # ztf_sim specific keywords! record["requestNumberTonight"] = request["target_request_number_tonight"] record["totalRequestsTonight"] = request["target_total_requests_tonight"] record["metricValue"] = request["target_metric_value"] # use placeholders to create the INSERT query columns = ", ".join(record.keys()) placeholders = "{" + "}, {".join(record.keys()) + "}" query = "INSERT INTO Summary ({}) VALUES ({})".format(columns, placeholders) query_filled = query.format(**record) self.conn.execute(query_filled) # save record for next obs self.prev_obs = record pass
# evenly spaced times between noon on July 12 and noon on July 13: from astropy.coordinates import get_sun delta_midnight = np.linspace(-12, 12, 1000)*u.hour times_July12_to_13 = midnight + delta_midnight frame_July12_to_13 = AltAz(obstime=times_July12_to_13, location=bear_mountain) sunaltazs_July12_to_13 = get_sun(times_July12_to_13).transform_to(frame_July12_to_13) ############################################################################## # Do the same with `~astropy.coordinates.get_moon` to find when the moon is # up. Be aware that this will need to download a 10MB file from the internet # to get a precise location of the moon. from astropy.coordinates import get_moon moon_July12_to_13 = get_moon(times_July12_to_13) moonaltazs_July12_to_13 = moon_July12_to_13.transform_to(frame_July12_to_13) ############################################################################## # Find the alt,az coordinates of M33 at those same times: m33altazs_July12_to_13 = m33.transform_to(frame_July12_to_13) ############################################################################## # Make a beautiful figure illustrating nighttime and the altitudes of M33 and # the Sun over that time: plt.plot(delta_midnight, sunaltazs_July12_to_13.alt, color='r', label='Sun') plt.plot(delta_midnight, moonaltazs_July12_to_13.alt, color=[0.75]*3, ls='--', label='Moon') plt.scatter(delta_midnight, m33altazs_July12_to_13.alt, c=m33altazs_July12_to_13.az, label='M33', lw=0, s=8,
def simulate_a_telescope(name, altitude, longitude, latitude, filter, time_start, time_end, sampling, event, location, bad_weather_percentage=0.0, minimum_alt=20, moon_windows_avoidance=20, maximum_moon_illumination=100.0): """ Simulate a telescope. More details in the telescopes module. The observations simulation are made for the full time windows, then limitation are applied : - Sun has to be below horizon : Sun< -18 - Moon has to be more than the moon_windows_avoidance distance from the target - Observations altitude of the target have to be bigger than minimum_alt :param str name: the name of the telescope. :param float altitude: the altitude in meters if the telescope :param float longitude: the longitude in degree of the telescope location :param float latitude: the latitude in degree of the telescope location :param str filter: the filter used for observations :param float time_start: the start of observations in JD :param float time_end: the end of observations in JD :param float sampling: the hour sampling. :param object event: the microlensing event you look at :param str location: the location of the telescope. If it is 'Space', then the observations are made continuously given the observing windows and the sampling. :param float bad_weather_percentage: the percentage of bad nights :param float minimum_alt: the minimum altitude ini degrees that your telescope can go to. :param float moon_windows_avoidance: the minimum distance in degrees accepted between the target and the Moon :param float maximum_moon_illumination: the maximum Moon brightness you allow in percentage :return: a telescope object :rtype: object """ # fake lightcurve if location != 'Space': earth_location = EarthLocation(lon=longitude * astropy.units.deg, lat=latitude * astropy.units.deg, height=altitude * astropy.units.m) target = SkyCoord(event.ra, event.dec, unit='deg') minimum_sampling = min(4.0, sampling) ratio_sampling = np.round(sampling / minimum_sampling) time_of_observations = time_simulation(time_start, time_end, minimum_sampling, bad_weather_percentage) time_convertion = Time(time_of_observations, format='jd').isot telescope_altaz = target.transform_to(AltAz(obstime=time_convertion, location=earth_location)) altazframe = AltAz(obstime=time_convertion, location=earth_location) Sun = get_sun(Time(time_of_observations, format='jd')).transform_to(altazframe) Moon = get_moon(Time(time_of_observations, format='jd')).transform_to(altazframe) Moon_illumination = moon_illumination(Sun, Moon) Moon_separation = target.separation(Moon) observing_windows = np.where((telescope_altaz.alt > minimum_alt * astropy.units.deg) & (Sun.alt < -18 * astropy.units.deg) & (Moon_separation > moon_windows_avoidance * astropy.units.deg) & (Moon_illumination<maximum_moon_illumination) )[0] time_of_observations = time_of_observations[observing_windows][::ratio_sampling] else: time_of_observations = np.arange(time_start, time_end, sampling / (24.0)) lightcurveflux = np.ones((len(time_of_observations), 3)) * 42 lightcurveflux[:, 0] = time_of_observations telescope = telescopes.Telescope(name=name, camera_filter=filter, light_curve_flux=lightcurveflux) return telescope
def test_regression_5209(): "check that distances are not lost on SkyCoord init" time = Time('2015-01-01') moon = get_moon(time) new_coord = SkyCoord([moon]) assert_quantity_allclose(new_coord[0].distance, moon.distance)
def get_observation(self, time=None, show_all=False, reread_fields_file=False): """Get a valid observation Args: time (astropy.time.Time, optional): Time at which scheduler applies, defaults to time called show_all (bool, optional): Return all valid observations along with merit value, defaults to False to only get top value reread_fields_file (bool, optional): If targets file should be reread before getting observation, default False. Returns: tuple or list: A tuple (or list of tuples) with name and score of ranked observations """ if reread_fields_file: self.logger.debug("Rereading fields file") # The setter method on `fields_file` will force a reread self.fields_file = self.fields_file if time is None: time = current_time() valid_obs = {obs: 1.0 for obs in self.observations} best_obs = [] common_properties = { 'end_of_night': self.observer.tonight(time=time, horizon=-18 * u.degree)[-1], 'moon': get_moon(time, self.observer.location) } for constraint in listify(self.constraints): self.logger.debug("Checking Constraint: {}".format(constraint)) for obs_name, observation in self.observations.items(): if obs_name in valid_obs: self.logger.debug("\tObservation: {}".format(obs_name)) veto, score = constraint.get_score( time, self.observer, observation, **common_properties) self.logger.debug("\t\tScore: {}\tVeto: {}".format(score, veto)) if veto: self.logger.debug("\t\t{} vetoed by {}".format(obs_name, constraint)) del valid_obs[obs_name] continue valid_obs[obs_name] += score for obs_name, score in valid_obs.items(): valid_obs[obs_name] += self.observations[obs_name].priority if len(valid_obs) > 0: # Sort the list by highest score (reverse puts in correct order) best_obs = sorted(valid_obs.items(), key=lambda x: x[1])[::-1] top_obs = best_obs[0] # Check new best against current_observation if self.current_observation is not None \ and top_obs[0] != self.current_observation.name: # Favor the current observation if still available end_of_next_set = time + self.current_observation.set_duration if self.observation_available(self.current_observation, end_of_next_set): # If current is better or equal to top, use it if self.current_observation.merit >= top_obs[1]: best_obs.insert(0, self.current_observation) # Set the current self.current_observation = self.observations[top_obs[0]] self.current_observation.merit = top_obs[1] else: if self.current_observation is not None: # Favor the current observation if still available end_of_next_set = time + self.current_observation.set_duration if end_of_next_set < common_properties['end_of_night'] and \ self.observation_available(self.current_observation, end_of_next_set): self.logger.debug("Reusing {}".format(self.current_observation)) best_obs = [(self.current_observation.name, self.current_observation.merit)] else: self.logger.warning("No valid observations found") self.current_observation = None if not show_all and len(best_obs) > 0: best_obs = best_obs[0] return best_obs