示例#1
0
def define_constraints(minAltitude, earliestObs, latestObs):
    """
    Define various constraints to define 'observability'.

    Format for times: YYYY-MM-DD

    Parameters
    ----------
    minAltitude : int
        minimum local elevation in degree
    earliestObs : str
        Earliest time of observation
    latestObs : str
        Latest time of observation

    Returns
    -------
    constraints : list
        list of constraints
    earliestObs : Time object
        Earliest time of observation
    latestObs : Time object
        Latest time of observation
    """
    constraints = [AtNightConstraint.twilight_astronomical(),
                   AltitudeConstraint(min=minAltitude*u.deg)]
    return constraints, Time(earliestObs), Time(latestObs)
示例#2
0
def run_months(observers, nameList, args):
    targets = [FixedTarget(coord=lookuptarget(name),name=name) for name in nameList]
    targetLabelList, ylabelsize = makeTargetLabels(nameList,args)

    constraints = [
        AltitudeConstraint(min=args.minAlt*u.deg),
        AtNightConstraint.twilight_astronomical(),
    ]
    
    outfn = args.outFileNameBase+"_monthly.pdf"
    with PdfPages(outfn) as pdf:
        for observer in observers:
            observability_months_table = months_observable(constraints,observer,targets,time_grid_resolution=1*u.hour)

            observability_months_grid = numpy.zeros((len(targets),12))
            for i, observable in enumerate(observability_months_table):
                for jMonth in range(1,13):
                    observability_months_grid[i,jMonth-1] = jMonth in observable

            observable_targets = targets
            observable_target_labels = targetLabelList
            ever_observability_months_grid = observability_months_grid
            if args.onlyEverObservable:
                target_is_observable = numpy.zeros(len(targets))
                for iMonth in range(observability_months_grid.shape[1]):
                    target_is_observable += observability_months_grid[:,iMonth]
                target_is_observable = target_is_observable > 0. # change to boolean numpy array
                observable_targets = [x for x, o in zip(targets,target_is_observable) if o]
                observable_target_labels = [x for x, o in zip(targetLabelList,target_is_observable) if o]
                ever_observability_months_grid = observability_months_grid[target_is_observable,:]

            fig, ax = mpl.subplots(
                figsize=(8.5,11),
                gridspec_kw={
                    "top":0.92,
                    "bottom":0.03,
                    "left":0.13,
                    "right":0.98,
                },
                tight_layout=False,constrained_layout=False
            )
            extent = [-0.5, -0.5+12, -0.5, len(observable_targets)-0.5]
            ax.imshow(ever_observability_months_grid, extent=extent, origin="lower", aspect="auto", cmap=mpl.get_cmap("Greens"))
            ax.xaxis.tick_top()
            ax.invert_yaxis()
            ax.set_yticks(range(0,len(observable_targets)))
            ax.set_yticklabels(observable_target_labels, fontsize=ylabelsize)
            ax.set_xticks(range(12))
            ax.set_xticklabels(["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"])
            ax.set_xticks(numpy.arange(extent[0], extent[1]), minor=True)
            ax.set_yticks(numpy.arange(extent[2], extent[3]), minor=True)
            ax.grid(which="minor",color="black",ls="-", linewidth=1)
            ax.tick_params(axis='y', which='minor', left=False, right=False)
            ax.tick_params(axis='x', which='minor', bottom=False, top=False)
        
            fig.suptitle(f"Monthly Observability at {observer.name}")
            fig.text(1.0,0.0,"Constraints: Astronomical Twilight, Altitude $\geq {:.0f}^\circ$".format(args.minAlt),ha="right",va="bottom")
            pdf.savefig(fig)
        print(f"Writing out file: {outfn}")
示例#3
0
文件: whats_up.py 项目: lgbouma/obs
def compute_is_up(name, time):
    '''
    Computes what V<11 objects in a catalog are up right now.

    args:
        name (str): one in: ['messier', 'ngc']
        time (str): in 24hr format, e.g. "2017-04-17 21:00:00"

    returns:
        catalog with is_up calculated, sorted by v_mag.
    '''

    import datetime
    from astropy.time import Time
    from astroplan import FixedTarget
    from astropy.coordinates import SkyCoord
    from astroplan import Observer, FixedTarget, AltitudeConstraint, \
        AtNightConstraint, is_observable, is_always_observable, \
        months_observable

    assert name in ['messier', 'ngc']

    if name == 'messier':
        data_path = '../data/catalogs/messier.csv'
    elif name == 'ngc':
        data_path = '../data/catalogs/ngc.csv'

    df = pd.read_csv(data_path)
    # The search & target creation is slow for >~thousands of FixedTargets. NGC
    # catalog is 13226 objects. Take those with v_mag<11, since from Peyton we
    # likely won't go fainter.
    df = df.sort_values('v_mag')
    df = df[df['v_mag']<11]

    peyton = Observer(longitude=74.65139*u.deg, latitude=40.34661*u.deg,
        elevation=62*u.m, name='Peyton', timezone='US/Eastern')

    if name == 'ngc':
        ras = np.array(df['ra'])*u.hourangle
        decs = np.array(df['dec'])*u.degree
        names = np.array(df['ngc_id'])
    elif name == 'messier':
        ras = np.array(df['ra'])*u.hourangle
        decs = np.array(df['dec'])*u.degree
        names = np.array(df['messier_id'])

    targets = [FixedTarget(SkyCoord(ra=r, dec=d), name=n) for r, d, n in
            tuple(zip(ras, decs, names))]

    constraints = [AltitudeConstraint(10*u.deg, 82*u.deg),
            AtNightConstraint(max_solar_altitude=-3.*u.deg)]

    t_obs = Time(time)
    is_up = is_observable(constraints, peyton, targets, times=t_obs)

    df['is_up'] = is_up

    return df
示例#4
0
def minimal_example():
    apo = Observer.at_site('APO', timezone='US/Mountain')
    target = FixedTarget.from_name("HD 209458")

    primary_eclipse_time = Time(2452826.628514, format='jd')
    orbital_period = 3.52474859 * u.day
    eclipse_duration = 0.1277 * u.day

    hd209458 = EclipsingSystem(primary_eclipse_time=primary_eclipse_time,
                               orbital_period=orbital_period,
                               duration=eclipse_duration,
                               name='HD 209458 b')

    n_transits = 100  # This is the roughly number of transits per year

    obs_time = Time('2017-01-01 12:00')
    midtransit_times = hd209458.next_primary_eclipse_time(
        obs_time, n_eclipses=n_transits)

    import astropy.units as u
    min_local_time = dt.time(18, 0)  # 18:00 local time at APO (7pm)
    max_local_time = dt.time(8, 0)  # 08:00 local time at APO (5am)
    constraints = [
        AtNightConstraint.twilight_civil(),
        AltitudeConstraint(min=30 * u.deg),
        LocalTimeConstraint(min=min_local_time, max=max_local_time)
    ]

    # just at midtime
    b = is_event_observable(constraints, apo, target, times=midtransit_times)

    # completely observable transits
    observing_time = Time('2016-01-01 00:00')

    ing_egr = hd209458.next_primary_ingress_egress_time(observing_time,
                                                        n_eclipses=n_transits)

    ibe = is_event_observable(constraints,
                              apo,
                              target,
                              times_ingress_egress=ing_egr)

    oot_duration = 30 * u.minute
    oot_ing_egr = np.concatenate(
        (np.array(ing_egr[:, 0] - oot_duration)[:, None],
         np.array(ing_egr[:, 1] + oot_duration)[:, None]),
        axis=1)

    oibeo = is_event_observable(constraints,
                                apo,
                                target,
                                times_ingress_egress=oot_ing_egr)
    def __init__(self,
                 time_range,
                 targets,
                 site='cfht',
                 constraints=None,
                 supp_cols=None):

        # Get infos from the MasterFile
        if isinstance(targets, list):
            info = load_from_masterfile(*targets)
            supp_cols = supp_cols or [
                'pl_orbper', 'st_j', 'st_h', 'ra', 'dec', 'pl_eqt', 'st_teff'
            ]
        else:
            info = targets.copy()
            if supp_cols is None:
                supp_cols = list(info.keys())
                supp_cols.remove('pl_name')

        # Default constraint
        if constraints is None:
            constraints = [
                AtNightConstraint.twilight_nautical(),
                AirmassConstraint(max=2.5)
            ]

        # Define time constraint and append it
        t1, t2 = Time(time_range)
        constraints.append(TimeConstraint(t1, t2))

        # Convert to List_of_constraints (useful to print and save)
        constraints_list = List_of_constraints(constraints)

        # Save infos
        self.info = info
        self.constraints = constraints_list
        self.meta = {
            'Time_limits': [t1, t2],
            'Target_list': info['pl_name'].tolist(),
            'Site': site,
            **constraints_list.show()
        }
        self.supp_cols = supp_cols
        self.info_cols = ['pl_name'] + supp_cols
        self.obs = Observer.at_site(site)
        #         self.n_eclipses = n_eclipses

        # Resolve targets
        self.targets = [self.resolve_target(i) for i in range(len(targets))]
示例#6
0
def make_airmass_chart(name="WASP 4"):

    target = FixedTarget.from_name(name)
    observer = Observer.at_site('keck')

    constraints = [
        AltitudeConstraint(min=20 * u.deg, max=85 * u.deg),
        AtNightConstraint.twilight_civil()
    ]

    best_months = months_observable(constraints, observer, [target])

    # computed observability on "best_months" grid of 0.5 hr
    print('for {}, got best-months on 0.5 hour grid:'.format(name))
    print(best_months)
    print('where 1 = Jan, 2 = Feb, etc.')
示例#7
0
 def __init__(self,
              lat,
              lon,
              elevation,
              ra,
              dec,
              discDate,
              airmassConstraint=2):
     self.airmassConstraint = airmassConstraint
     self.altConstraint = math.degrees(math.asin(1 /
                                                 self.airmassConstraint))
     self.location = EarthLocation(lat=lat, lon=lon, height=elevation * u.m)
     self.discDate = discDate
     self.observer = Observer(location=self.location, name="LT")
     self.target = SkyCoord(ra=ra, dec=dec, unit=(u.hourangle, u.deg))
     self.constraints = [
         AirmassConstraint(self.airmassConstraint),
         AtNightConstraint.twilight_astronomical()
     ]
     print("Discovery Date :", discDate.value)
示例#8
0
def get_observability_fraction(name="WASP 4", site='keck', ra=None, dec=None,
                               start_time=Time('2019-09-13 20:00:00'),
                               end_time=Time('2020-07-31 20:00:00')):

    if isinstance(name,str) and ra is None and dec is None:
        target = FixedTarget.from_name(name)
    elif isinstance(ra,float) and isinstance(dec,float):
        target_coord = SkyCoord(ra=ra*u.deg, dec=dec*u.deg)
        target = FixedTarget(coord=target_coord, name=name)
    else:
        raise NotImplementedError('failed to make target')

    observer = Observer.at_site(site)

    constraints = [AltitudeConstraint(min=20*u.deg, max=85*u.deg),
                   AirmassConstraint(3),
                   AtNightConstraint.twilight_civil()]

    # over every day between start and end time, check if the observing
    # constraints are meetable.
    days = Time(
        np.arange(start_time.decimalyear, end_time.decimalyear,
                  1/(365.25)),
        format='decimalyear'
    )

    frac, ever_observable = [], []

    for day in days:

        table = observability_table(constraints, observer, [target],
                                    time_range=day)
        frac.append(float(table['fraction of time observable']))
        ever_observable.append(bool(table['ever observable']))

    ever_observable = np.array(ever_observable)
    frac = np.array(frac)

    return frac, ever_observable, days
示例#9
0
    def __init__(self,
                 t0=None,
                 period=None,
                 perr=None,
                 duration=None,
                 loc='Siding Spring Observatory',
                 timezone='Australia/NSW',
                 ra=None,
                 dec=None,
                 startdate=None,
                 starttime='0:00',
                 run_length=180,
                 el_limit=30,
                 toi=None):

        if toi is not None:
            self.set_params_from_toi(toi)

        else:

            self.epoch = Time(t0 + 2457000, format='jd')
            self.period = period * u.d
            if perr is not None:
                self.period_err = perr * u.d
            else:
                self.period_err = None

            self.duration = duration / 24 * u.d
            self.coords = [ra * u.deg, dec * u.deg]

        self.alt_limit = el_limit

        self.observatory = loc
        self.timezone = timezone

        self.obs_mid_times_utc = None
        self.obs_mid_uncerts = None
        self.obs_mid_times_local = None

        coord = SkyCoord(ra=self.coords[0], dec=self.coords[1])
        target = FixedTarget(coord, name='Target')

        SSO = Observer.at_site(self.observatory, timezone=self.timezone)

        planet = EclipsingSystem(primary_eclipse_time=self.epoch,
                                 orbital_period=self.period,
                                 duration=self.duration)

        starttime = startdate + ' ' + starttime
        self.start = Time(starttime)
        self.run_length = run_length * u.d

        n_transits = np.ceil(self.run_length / self.period)

        self.all_transit_times = planet.next_primary_eclipse_time(
            self.start, n_eclipses=n_transits)

        diff = self.all_transit_times - self.start - self.run_length
        real_trans = diff.value < 0
        if np.sum(real_trans) < 0.5:
            self.all_transit_times = None
            return
        else:
            self.all_transit_times = self.all_transit_times[real_trans]

        if self.period_err is not None:
            self.uncert_vals = (self.all_transit_times - self.epoch
                                ) * self.period_err / self.period * 1440

        constraints = [
            AtNightConstraint.twilight_nautical(),
            AltitudeConstraint(min=self.alt_limit * u.deg)
        ]

        obs_mid = is_event_observable(constraints,
                                      SSO,
                                      target,
                                      times=self.all_transit_times)[0]
        obs_start = is_event_observable(constraints,
                                        SSO,
                                        target,
                                        times=self.all_transit_times -
                                        0.5 * self.duration)[0]
        obs_end = is_event_observable(constraints,
                                      SSO,
                                      target,
                                      times=self.all_transit_times +
                                      0.5 * self.duration)[0]

        if np.sum(obs_mid * obs_start * obs_end) > 0:

            self.obs_airmass = np.zeros(
                (np.sum(obs_mid * obs_start * obs_end), 3))

            self.obs_mid_times_utc = self.all_transit_times[obs_mid *
                                                            obs_start *
                                                            obs_end]
            if self.period_err is not None:
                self.obs_mid_uncerts = self.uncert_vals[obs_mid * obs_start *
                                                        obs_end]

            for i in range(np.sum(obs_mid * obs_start * obs_end)):
                obs_airmass_mid = SSO.altaz(self.obs_mid_times_utc[i],
                                            coord).secz
                obs_airmass_start = SSO.altaz(
                    self.obs_mid_times_utc[i] - self.duration / 2, coord).secz
                obs_airmass_end = SSO.altaz(
                    self.obs_mid_times_utc[i] + self.duration / 2, coord).secz

                self.obs_airmass[i] = [
                    obs_airmass_start, obs_airmass_mid, obs_airmass_end
                ]

            # NEED A BARYCENTRIC CORRECTION

            tz = pytz.timezone('utc')

            dtime = self.obs_mid_times_utc.to_datetime()

            self.obs_mid_times_local = np.array([])

            for i in range(len(self.obs_mid_times_utc)):
                inoz = tz.localize(dtime[i])
                if self.period_err is not None:
                    indiv_uncert = self.obs_mid_uncerts[i]
                val = inoz.astimezone(pytz.timezone(self.timezone))
                self.obs_mid_times_local = np.append(
                    self.obs_mid_times_local,
                    val.strftime('%Y-%m-%d %H:%M:%S'))
示例#10
0
def vis(date, objects, obj_tab):

    #This tool is designed for the Magellan Telescope @ Las Camapanas Observatory, in Chile
    las = Observer.at_site('LCO')
    #both las and los are the locations of MagAO, but one is used for the plot and the other for the time
    lco = EarthLocation.of_site('Las Campanas Observatory')

    userEntered_list = list(objects.split(","))
    target_list = userEntered_list

    targets = []
    for i in range(1, len(obj_tab)):
        ra = (obj_tab.iloc[i, 2])[1:] + ' hours'
        dec = (obj_tab.iloc[i, 3])[1:] + ' degrees'
        print(ra + ',' + dec)
        targets.append(
            FixedTarget(coord=SkyCoord(ra=ra, dec=dec),
                        name=target_list[i - 1]))

    constraints = [
        AltitudeConstraint(10 * u.deg, 80 * u.deg),
        AirmassConstraint(5),
        AtNightConstraint.twilight_civil()
    ]

    start_time = las.sun_set_time(Time(date), which='nearest')
    end_time = las.sun_rise_time(Time(date), which='nearest')
    date = start_time.iso[:10] + ' to ' + end_time.iso[:10]

    time_range = Time([start_time, end_time])

    # In[ ]:

    delta_t = end_time - start_time
    observe_time = start_time + delta_t * np.linspace(0, 1, 75)

    # In[ ]:

    # Are targets *ever* observable in the time range?
    ever_observable = is_observable(constraints,
                                    las,
                                    targets,
                                    time_range=time_range)

    # Are targets *always* observable in the time range?
    always_observable = is_always_observable(constraints,
                                             las,
                                             targets,
                                             time_range=time_range)

    # During what months are the targets ever observable?
    best_months = months_observable(constraints, las, targets)

    # In[ ]:

    table = observability_table(constraints,
                                las,
                                targets,
                                time_range=time_range)
    print(table)

    table = table.to_pandas()

    np.savetxt(
        'static/data/visibility.txt',
        table,
        fmt="%-30s",
        header=
        'Target name                  ever observable                always observable              fraction of time observable'
    )
示例#11
0
for i in range(0, l):
    targs.append(
        FixedTarget(coord=SkyCoord(ra=(t[i]['ra']),
                                   dec=(t[i]['dec']),
                                   unit=(u.hourangle, u.deg)),
                    name=t[i]['alt_name'] + " [" + t[i]['iau_name'] + ", " +
                    t[i]['ra'] + ", " + t[i]['dec'] + "]"))
    # Accounting for the fact that ra is in [hour min sec] and dec is in [deg arcmin arcsec]
    # the "name" attribute is all of the information just smashed together and I know it's unclean, please don't judge me

    # print((targs[len(targs)-1].name)) # This was just to check where errors occurred

time_range = Time(["2018-04-15 00:01", "2018-04-30 23:59"])
# This just takes the whole swath of time, not refining it or anything

cons = [AirmassConstraint(2), AtNightConstraint.twilight_astronomical()]
# don't use civil twilight because astronomers aren't civil

obs_tab = observability_table(cons, kitt, targs, time_range=time_range)
# print(obs_tab)

obs_targs = []
total_save = []
# total_save is to keep all the data, not just some of it

for i in range(0, len(obs_tab)):
    if obs_tab[i]['ever observable']:
        obs_targs.append([
            obs_tab[i]['target name'],
            obs_tab[i]['fraction of time observable']
        ])
示例#12
0
from astroplan import time_grid_from_range
from astroplan import (AltitudeConstraint, AtNightConstraint, Constraint)
from astroplan import (is_observable, is_always_observable, months_observable,
                       observability_table)

import pylab as pl
pl.ion()

observer = Observer.at_site('GBT', timezone='US/Eastern')

time1 = astropy.time.Time('2021-02-01', location=observer.location)
time2 = astropy.time.Time('2021-07-31', location=observer.location)
time_range = astropy.time.Time([time1, time2])

GBTNight = AtNightConstraint()
GBTNight.max_solar_altitude = 5 * u.deg


class GBT3hoursAfterSunset(Constraint):
    """
    Constraint requiring 3hrs setup for MUSTANG
    """
    def compute_constraint(self, times, observer, targets):

        # we want the time since the sun went below 5 deg,
        # which is enough to start cooling the dish
        sunset = observer.sun_set_time(times, horizon=5 * u.deg)

        mask = times > sunset + astropy.time.TimeDelta(3 * u.hour)
示例#13
0
def get_transit_observability(site,
                              ra,
                              dec,
                              name,
                              t_mid_0,
                              period,
                              duration,
                              n_transits=100,
                              obs_start_time=Time(
                                  dt.datetime.today().isoformat()),
                              min_local_time=dt.time(16, 0),
                              max_local_time=dt.time(9, 0),
                              min_altitude=20 * u.deg,
                              oot_duration=30 * u.minute,
                              minokmoonsep=30 * u.deg):
    """
    note: barycentric corrections not yet implemented. (could do this myself!)
    -> 16 minutes of imprecision is baked into this observability calculator!

    args:

        site (astroplan.observer.Observer)

        ra, dec (units u.deg), e.g.:
            ra=101.28715533*u.deg, dec=16.71611586*u.deg,
        or can also accept
            ra="17 56 35.51", dec="-29 32 21.5"

        name (str), e.g., "Sirius"

        t_mid_0 (float): in BJD_TDB, preferably (but see note above).

        period (astropy quantity, units time)

        duration (astropy quantity, units time)

        n_transits (int): number of transits forward extrapolated to

        obs_start_time (astropy.Time object): when to start calculation from

        min_local_time, max_local_time: earliest time when you think observing
        is OK. E.g., 16:00 local and 09:00 local are earliest and latest. Note
        this constraint is a bit silly, since the astroplan "AtNightConstraint"
        is imposed automatically. As implemented, these are ignored.

        min_altitude (astropy quantity, units deg): 20 degrees is the more
        relevant constraint.

        oot_duration (astropy quantity, units time): with which to brack
        transit observations, to get an OOT baseline.
    """

    if (isinstance(ra, u.quantity.Quantity)
            and isinstance(dec, u.quantity.Quantity)):
        target_coord = SkyCoord(ra=ra, dec=dec)
    elif (isinstance(ra, str) and isinstance(dec, str)):
        target_coord = SkyCoord(ra=ra, dec=dec, unit=(u.hourangle, u.deg))
    else:
        raise NotImplementedError

    target = FixedTarget(coord=target_coord, name=name)

    primary_eclipse_time = Time(t_mid_0, format='jd')

    system = EclipsingSystem(primary_eclipse_time=primary_eclipse_time,
                             orbital_period=period,
                             duration=duration,
                             name=name)

    midtransit_times = system.next_primary_eclipse_time(obs_start_time,
                                                        n_eclipses=n_transits)

    # for the time being, omit any local time constraints.
    constraints = [
        AtNightConstraint.twilight_civil(),
        AltitudeConstraint(min=min_altitude),
        MoonSeparationConstraint(min=minokmoonsep)
    ]
    #constraints = [AtNightConstraint.twilight_civil(),
    #               AltitudeConstraint(min=min_altitude),
    #               LocalTimeConstraint(min=min_local_time, max=max_local_time)]

    # observable just at midtime (bottom)
    b = is_event_observable(constraints, site, target, times=midtransit_times)

    # observable full transits (ingress, bottom, egress)
    ing_egr = system.next_primary_ingress_egress_time(obs_start_time,
                                                      n_eclipses=n_transits)

    ibe = is_event_observable(constraints,
                              site,
                              target,
                              times_ingress_egress=ing_egr)

    # get moon separation over each transit. take minimum moon sep at
    # ing/tmid/egr as the moon separation.
    moon_tmid = get_moon(midtransit_times, location=site.location)
    moon_separation_tmid = moon_tmid.separation(target_coord)

    moon_ing = get_moon(ing_egr[:, 0], location=site.location)
    moon_separation_ing = moon_ing.separation(target_coord)

    moon_egr = get_moon(ing_egr[:, 1], location=site.location)
    moon_separation_egr = moon_egr.separation(target_coord)

    moon_separation = np.round(
        np.array(
            [moon_separation_tmid, moon_separation_ing,
             moon_separation_egr]).min(axis=0), 0).astype(int)

    moon_illumination = np.round(
        100 * moon.moon_illumination(midtransit_times), 0).astype(int)

    # completely observable transits (OOT, ingress, bottom, egress, OOT)
    oot_ing_egr = np.concatenate(
        (np.array(ing_egr[:, 0] - oot_duration)[:, None],
         np.array(ing_egr[:, 1] + oot_duration)[:, None]),
        axis=1)

    oibeo = is_event_observable(constraints,
                                site,
                                target,
                                times_ingress_egress=oot_ing_egr)

    ing_tmid_egr = np.concatenate(
        (np.array(ing_egr[:, 0])[:, None], np.array(midtransit_times)[:, None],
         np.array(ing_egr[:, 1])[:, None]),
        axis=1)

    return ibe, oibeo, ing_tmid_egr, moon_separation, moon_illumination
示例#14
0
    # TODO select proper coordinates: load from params_star.csv
    # TODO select proper observer place (ground, space)
    coords = "1:12:43.2 +1:12:43"
    target = FixedTarget(SkyCoord(coords, unit=(u.deg, u.deg)))
    # TODO select proper time
    n_transits = 100  # This is the roughly number of transits per year
    obs_time = Time('2017-01-01 12:00')
    # TODO bulk to file
    midtransit_times = system.next_primary_eclipse_time(obs_time,
                                                        n_eclipses=n_transits)
    ingress_egress_times = system.next_primary_ingress_egress_time(
        obs_time, n_eclipses=n_transits)
    # TODO select local times somehow
    min_local_time = dt.time(19, 0)  # 19:00 local time at APO (7pm)
    max_local_time = dt.time(0, 0)  # 00:00 local time at APO (midnight)
    constraints = [
        AtNightConstraint.twilight_civil(),
        AltitudeConstraint(min=30 * u.deg),
        LocalTimeConstraint(min=min_local_time, max=max_local_time)
    ]
    midtime_observable = astroplan.is_event_observable(constraints,
                                                       observer_site,
                                                       target,
                                                       times=midtransit_times)
    entire_observable = astroplan.is_event_observable(
        constraints,
        observer_site,
        target,
        times=midtransit_times,
        times_ingress_egress=ingress_egress_times)
示例#15
0
    def _schedule_thread(self):
        # only constraint is the night
        if self._twilight == 'astronomical':
            constraints = [AtNightConstraint.twilight_astronomical()]
        elif self._twilight == 'nautical':
            constraints = [AtNightConstraint.twilight_nautical()]
        else:
            raise ValueError('Unknown twilight type.')

        # we don't need any transitions
        transitioner = Transitioner()

        # run forever
        while not self.closing.is_set():
            # need update?
            if self._need_update:
                # reset need for update
                self._need_update = False

                # get start time for scheduler
                start = self._schedule_start
                now_plus_safety = Time.now() + self._safety_time * u.second
                if start is None or start < now_plus_safety:
                    # if no ETA exists or is in the past, use safety time
                    start = now_plus_safety
                end = start + TimeDelta(self._schedule_range * u.hour)

                # remove currently running block and filter by start time
                blocks = []
                for b in filter(
                        lambda b: b.configuration['request']['id'] != self.
                        _current_task_id, self._blocks):
                    time_constraint_found = False
                    # loop all constraints
                    for c in b.constraints:
                        if isinstance(c, TimeConstraint):
                            # we found a time constraint
                            time_constraint_found = True

                            # does the window start before the end of the scheduling range?
                            if c.min < end:
                                # yes, store block and break loop
                                blocks.append(b)
                                break
                    else:
                        # loop has finished without breaking
                        # if no time constraint has been found, we still take the block
                        if time_constraint_found is False:
                            blocks.append(b)

                # log it
                log.info(
                    'Calculating schedule for %d schedulable block(s) starting at %s...',
                    len(blocks), start)

                # init scheduler and schedule
                scheduler = SequentialScheduler(constraints,
                                                self.observer,
                                                transitioner=transitioner)
                time_range = Schedule(start, end)
                schedule = scheduler(blocks, time_range)

                # update
                self._task_archive.update_schedule(schedule.scheduled_blocks,
                                                   start)
                if len(schedule.scheduled_blocks) > 0:
                    log.info('Finished calculating schedule for %d block(s):',
                             len(schedule.scheduled_blocks))
                    for i, block in enumerate(schedule.scheduled_blocks, 1):
                        log.info('  #%d: %s to %s (%.1f)',
                                 block.configuration['request']['id'],
                                 block.start_time, block.end_time,
                                 block.priority)
                else:
                    log.info('Finished calculating schedule for 0 blocks.')

            # sleep a little
            self.closing.wait(1)
示例#16
0
文件: staralt.py 项目: japp/staralt
def observability(data):
    """
    Test the observability of a list of objects for a single date

    Parameters
    ----------
    data : POST data format

        Observatory, date, limits and objects
        data = {
            'observatory' : 'OT',
            'date' : '2020-06-11 00:16:30',
            'date_end' : '2020-06-11 03:44:26',
            'altitude_lower_limit' : '30',
            'altitude_higher_limit' : '90',
            'twilight_type' : 'astronomical',
            'objects' : [{
                    'name' : 'Kelt 8b',
                    'RA' : 283.30551667 ,
                    'Dec' : 24.12738139
                    },
                    (more objects...)
                ]
            }

    Returns
    -------
    observability : dict
        Dictionary with the observability and moon distance for all objects
        {
            'V0879 Cas' : {
                'observability' : 'True', 'moon_separation' : 30.4
            },
            'RU Scl' : {
                'observability' : 'True', 'moon_separation' : 10.8
            }
        }

    """

    import astropy.units as u
    from astroplan import FixedTarget
    from astroplan import (AltitudeConstraint, AtNightConstraint)
    from astroplan import is_observable, is_always_observable

    # Site location
    location = get_location(data['observatory'])

    time_range = Time([data['date'], data['date_end']])

    if 'twilight_type' not in data.keys():
        data['twilight_type'] = 'astronomical'

    if data['twilight_type'] == 'civil':
        twilight_constraint = AtNightConstraint.twilight_civil()
    elif data['twilight_type'] == 'nautical':
        twilight_constraint = AtNightConstraint.twilight_nautical()
    else:
        twilight_constraint = AtNightConstraint.twilight_astronomical()

    # Observation constraints
    constraints = [
        AltitudeConstraint(
            int(data['altitude_lower_limit']) * u.deg,
            int(data['altitude_higher_limit']) * u.deg), twilight_constraint
    ]

    # Dictionary with star name and observability (bool str)
    result = {}

    # Moon location for the observation date
    middle_observing_time = time_range[-1] - (time_range[-1] -
                                              time_range[0]) / 2
    moon = location.moon_altaz(middle_observing_time)

    for target in data['objects']:
        # Object coordinates
        coords = SkyCoord(ra=target['RA'] * u.deg, dec=target['Dec'] * u.deg)
        fixed_target = [FixedTarget(coord=coords, name=target['name'])]

        if 'transit' in target.keys():
            time_range = Time(
                [target['transit']['t_early'], target['transit']['t_late']])
            # Are targets *always* observable in the time range?
            observable = is_always_observable(constraints,
                                              location,
                                              fixed_target,
                                              time_range=time_range)
        else:
            time_range = Time([data['date'], data['date_end']])
            # Are targets *ever* observable in the time range?
            observable = is_observable(constraints,
                                       location,
                                       fixed_target,
                                       time_range=time_range)

        moon_separation = moon.separation(coords)

        result[target['name']] = {
            'observable': str(observable[0]),
            'moon_separation': moon_separation.degree
        }

    return result
示例#17
0
params.w = 90
params.ecc = 0
params.a = float(((G * M_star * (params.per * u.day)**2) /
                  (4 * np.pi**2))**(1 / 3) / R_star)

from astroplan import time_grid_from_range, observability_table

n_objects_per_night = int(sys.argv[-1])
print(n_objects_per_night)
airmass_cutoff = 3.5
fraction_cloudy = 0.3
n_years = 1
n_trials = 15

constraints = [
    AtNightConstraint.twilight_nautical(),
    AirmassConstraint(max=airmass_cutoff)
]

start_time = Time('2020-01-01 08:00')  # near local midnight
end_time = Time('2021-01-01 08:00')  # near local midnight

n_transits = []

for trial in range(n_trials):
    target_inds_observed = set([])

    obs_database = {
        name: dict(times=[], fluxes=[], model=[], transit=False)
        for name in table['spc']
    }
示例#18
0
文件: plan.py 项目: franpoz/SHERLOCK
def create_observation_observables(object_id,
                                   object_dir,
                                   since,
                                   name,
                                   epoch,
                                   epoch_low_err,
                                   epoch_up_err,
                                   period,
                                   period_low_err,
                                   period_up_err,
                                   duration,
                                   observatories_file,
                                   timezone,
                                   latitude,
                                   longitude,
                                   altitude,
                                   max_days,
                                   min_altitude,
                                   moon_min_dist,
                                   moon_max_dist,
                                   transit_fraction,
                                   baseline,
                                   error_alert=True):
    """

    @param object_id: the candidate id
    @param object_dir: the candidate directory
    @param since: starting plan date
    @param name: the name given to the candidate
    @param epoch: the candidate epoch
    @param epoch_low_err: the candidate epoch's lower error
    @param epoch_up_err: the candidate epoch's upper error
    @param period: the candidate period
    @param period_low_err: the candidate period's lower error
    @param period_up_err: the candidate period's upper error
    @param duration: the candidate duration
    @param observatories_file: the file containing the observatories file (csv format)
    @param timezone: the timezone of the observatory (if observatories_file=None)
    @param latitude: the latitude of the observatory (if observatories_file=None)
    @param longitude: the longitude of the observatory (if observatories_file=None)
    @param altitude: the altitude of the observatory (if observatories_file=None)
    @param max_days: the maximum number of days to compute the observables
    @param min_altitude: the minimum altitude of the target above the horizon
    @param moon_min_dist: the minimum moon distance for moon illumination = 0
    @param moon_max_dist: the minimum moon distance for moon illumination = 1
    @param transit_fraction: the minimum transit observability (0.25 for at least ingress/egress, 0.5 for ingress/egress
    + midtime, 1 for ingress, egress and midtime).
    @param baseline: the required baseline in hours.
    @param: error_alert: whether to create the alert date to signal imprecise observations
    @return: the generated data and target folders
    """
    if observatories_file is not None:
        observatories_df = pd.read_csv(observatories_file, comment='#')
    else:
        observatories_df = pd.DataFrame(
            columns=['name', 'tz', 'lat', 'long', 'alt'])
        observatories_df = observatories_df.append("Obs-1", timezone, latitude,
                                                   longitude, altitude)
    # TODO probably convert epoch to proper JD
    mission, mission_prefix, id_int = LcBuilder().parse_object_info(object_id)
    if mission == "TESS":
        primary_eclipse_time = Time(epoch, format='btjd', scale="tdb")
    elif mission == "Kepler" or mission == "K2":
        primary_eclipse_time = Time(epoch, format='bkjd', scale="tdb")
    else:
        primary_eclipse_time = Time(epoch, format='jd')
    target = FixedTarget(SkyCoord(coords, unit=(u.deg, u.deg)))
    n_transits = int(max_days // period)
    system = EclipsingSystem(primary_eclipse_time=primary_eclipse_time,
                             orbital_period=u.Quantity(period, unit="d"),
                             duration=u.Quantity(duration, unit="h"),
                             name=name)
    observables_df = pd.DataFrame(columns=[
        'observatory', 'timezone', 'start_obs', 'end_obs', 'ingress', 'egress',
        'midtime', "midtime_up_err_h", "midtime_low_err_h", 'twilight_evening',
        'twilight_morning', 'observable', 'moon_phase', 'moon_dist'
    ])
    plan_dir = object_dir + "/plan"
    images_dir = plan_dir + "/images"
    if os.path.exists(plan_dir):
        shutil.rmtree(plan_dir, ignore_errors=True)
    os.mkdir(plan_dir)
    if os.path.exists(images_dir):
        shutil.rmtree(images_dir, ignore_errors=True)
    os.mkdir(images_dir)
    alert_date = None
    for index, observatory_row in observatories_df.iterrows():
        observer_site = Observer(latitude=observatory_row["lat"],
                                 longitude=observatory_row["lon"],
                                 elevation=u.Quantity(observatory_row["alt"],
                                                      unit="m"))
        midtransit_times = system.next_primary_eclipse_time(
            since, n_eclipses=n_transits)
        ingress_egress_times = system.next_primary_ingress_egress_time(
            since, n_eclipses=n_transits)
        constraints = [
            AtNightConstraint.twilight_nautical(),
            AltitudeConstraint(min=min_altitude * u.deg),
            MoonIlluminationSeparationConstraint(
                min_dist=moon_min_dist * u.deg, max_dist=moon_max_dist * u.deg)
        ]
        moon_for_midtransit_times = get_moon(midtransit_times)
        moon_dist_midtransit_times = moon_for_midtransit_times.separation(
            SkyCoord(star_df.iloc[0]["ra"], star_df.iloc[0]["dec"],
                     unit="deg"))
        moon_phase_midtransit_times = np.round(
            astroplan.moon_illumination(midtransit_times), 2)
        transits_since_epoch = np.round(
            (midtransit_times - primary_eclipse_time).jd / period)
        midtransit_time_low_err = np.round(
            (((transits_since_epoch * period_low_err)**2 + epoch_low_err**2)
             **(1 / 2)) * 24, 2)
        midtransit_time_up_err = np.round(
            (((transits_since_epoch * period_up_err)**2 + epoch_up_err**2)
             **(1 / 2)) * 24, 2)
        low_err_delta = TimeDelta(midtransit_time_low_err * 3600, format='sec')
        up_err_delta = TimeDelta(midtransit_time_up_err * 3600, format='sec')
        i = 0
        for midtransit_time in midtransit_times:
            twilight_evening = observer_site.twilight_evening_nautical(
                midtransit_time)
            twilight_morning = observer_site.twilight_morning_nautical(
                midtransit_time)
            ingress = ingress_egress_times[i][0]
            egress = ingress_egress_times[i][1]
            lowest_ingress = ingress - low_err_delta[i]
            highest_egress = egress + up_err_delta[i]
            if error_alert and (highest_egress - lowest_ingress).jd > 0.33:
                alert_date = midtransit_time if (alert_date is None) or (
                    alert_date is not None
                    and alert_date >= midtransit_time) else alert_date
                break
            else:
                baseline_low = lowest_ingress - baseline * u.hour
                baseline_up = highest_egress + baseline * u.hour
                transit_times = baseline_low + (
                    baseline_up - baseline_low) * np.linspace(0, 1, 100)
                observable_transit_times = astroplan.is_event_observable(
                    constraints, observer_site, target, times=transit_times)[0]
                observable_transit_times_true = np.argwhere(
                    observable_transit_times)
                observable = len(observable_transit_times_true) / 100
                if observable < transit_fraction:
                    i = i + 1
                    continue
                start_obs = transit_times[observable_transit_times_true[0]][0]
                end_obs = transit_times[observable_transit_times_true[
                    len(observable_transit_times_true) - 1]][0]
                start_plot = baseline_low
                end_plot = baseline_up
                if twilight_evening > start_obs:
                    start_obs = twilight_evening
                if twilight_morning < end_obs:
                    end_obs = twilight_morning
            moon_dist = round(moon_dist_midtransit_times[i].degree)
            moon_phase = moon_phase_midtransit_times[i]
            # TODO get is_event_observable for several parts of the transit (ideally each 5 mins) to get the proper observable percent. Also with baseline
            if observatory_row["tz"] is not None and not np.isnan(
                    observatory_row["tz"]):
                observer_timezone = observatory_row["tz"]
            else:
                observer_timezone = get_offset(observatory_row["lat"],
                                               observatory_row["lon"],
                                               midtransit_time.datetime)
            observables_df = observables_df.append(
                {
                    "observatory":
                    observatory_row["name"],
                    "timezone":
                    observer_timezone,
                    "ingress":
                    ingress.isot,
                    "start_obs":
                    start_obs.isot,
                    "end_obs":
                    end_obs.isot,
                    "egress":
                    egress.isot,
                    "midtime":
                    midtransit_time.isot,
                    "midtime_up_err_h":
                    str(int(midtransit_time_up_err[i] // 1)) + ":" +
                    str(int(midtransit_time_up_err[i] % 1 * 60)).zfill(2),
                    "midtime_low_err_h":
                    str(int(midtransit_time_low_err[i] // 1)) + ":" +
                    str(int(midtransit_time_low_err[i] % 1 * 60)).zfill(2),
                    "twilight_evening":
                    twilight_evening.isot,
                    "twilight_morning":
                    twilight_morning.isot,
                    "observable":
                    observable,
                    "moon_phase":
                    moon_phase,
                    "moon_dist":
                    moon_dist
                },
                ignore_index=True)
            plot_time = start_plot + (end_plot - start_plot) * np.linspace(
                0, 1, 100)
            plt.tick_params(labelsize=6)
            airmass_ax = plot_airmass(target,
                                      observer_site,
                                      plot_time,
                                      brightness_shading=False,
                                      altitude_yaxis=True)
            airmass_ax.axvspan(twilight_morning.plot_date,
                               end_plot.plot_date,
                               color='white')
            airmass_ax.axvspan(start_plot.plot_date,
                               twilight_evening.plot_date,
                               color='white')
            airmass_ax.axvspan(twilight_evening.plot_date,
                               twilight_morning.plot_date,
                               color='gray')
            airmass_ax.axhspan(1. / np.cos(np.radians(90 - min_altitude)),
                               5.0,
                               color='green')
            airmass_ax.get_figure().gca().set_title("")
            airmass_ax.get_figure().gca().set_xlabel("")
            airmass_ax.get_figure().gca().set_ylabel("")
            airmass_ax.set_xlabel("")
            airmass_ax.set_ylabel("")
            xticks = []
            xticks_labels = []
            xticks.append(start_obs.plot_date)
            hour_min_sec_arr = start_obs.isot.split("T")[1].split(":")
            xticks_labels.append("T1_" + hour_min_sec_arr[0] + ":" +
                                 hour_min_sec_arr[1])
            plt.axvline(x=start_obs.plot_date, color="violet")
            xticks.append(end_obs.plot_date)
            hour_min_sec_arr = end_obs.isot.split("T")[1].split(":")
            xticks_labels.append("T1_" + hour_min_sec_arr[0] + ":" +
                                 hour_min_sec_arr[1])
            plt.axvline(x=end_obs.plot_date, color="violet")
            if start_plot < lowest_ingress < end_plot:
                xticks.append(lowest_ingress.plot_date)
                hour_min_sec_arr = lowest_ingress.isot.split("T")[1].split(":")
                xticks_labels.append("T1_" + hour_min_sec_arr[0] + ":" +
                                     hour_min_sec_arr[1])
                plt.axvline(x=lowest_ingress.plot_date, color="red")
            if start_plot < ingress < end_plot:
                xticks.append(ingress.plot_date)
                hour_min_sec_arr = ingress.isot.split("T")[1].split(":")
                xticks_labels.append("T1_" + hour_min_sec_arr[0] + ":" +
                                     hour_min_sec_arr[1])
                plt.axvline(x=ingress.plot_date, color="orange")
            if start_plot < midtransit_time < end_plot:
                xticks.append(midtransit_time.plot_date)
                hour_min_sec_arr = midtransit_time.isot.split("T")[1].split(
                    ":")
                xticks_labels.append("T0_" + hour_min_sec_arr[0] + ":" +
                                     hour_min_sec_arr[1])
                plt.axvline(x=midtransit_time.plot_date, color="black")
            if start_plot < egress < end_plot:
                xticks.append(egress.plot_date)
                hour_min_sec_arr = egress.isot.split("T")[1].split(":")
                xticks_labels.append("T4_" + hour_min_sec_arr[0] + ":" +
                                     hour_min_sec_arr[1])
                plt.axvline(x=egress.plot_date, color="orange")
            if start_plot < highest_egress < end_plot:
                xticks.append(highest_egress.plot_date)
                hour_min_sec_arr = highest_egress.isot.split("T")[1].split(":")
                xticks_labels.append("T4_" + hour_min_sec_arr[0] + ":" +
                                     hour_min_sec_arr[1])
                plt.axvline(x=highest_egress.plot_date, color="red")
            airmass_ax.xaxis.set_tick_params(labelsize=5)
            airmass_ax.set_xticks([])
            airmass_ax.set_xticklabels([])
            degrees_ax = get_twin(airmass_ax)
            degrees_ax.yaxis.set_tick_params(labelsize=6)
            degrees_ax.set_yticks([1., 1.55572383, 2.])
            degrees_ax.set_yticklabels([90, 50, 30])
            fig = matplotlib.pyplot.gcf()
            fig.set_size_inches(1.25, 0.75)
            plt.savefig(plan_dir + "/images/" + observatory_row["name"] + "_" +
                        str(midtransit_time.isot)[:-4] + ".png",
                        bbox_inches='tight')
            plt.close()
            i = i + 1
    observables_df = observables_df.sort_values(["midtime", "observatory"],
                                                ascending=True)
    observables_df.to_csv(plan_dir + "/observation_plan.csv", index=False)
    print("Observation plan created in directory: " + object_dir)
    return observatories_df, observables_df, alert_date, plan_dir, images_dir
示例#19
0
def plan_when_transits_will_occur(
        filename='targets.txt',
        observatory='Southern African Large Telescope',
        start='2017-06-22',
        end='2017-06-28',
        airmass_limit=2.5,
        moon_distance=10,
        do_secondary=True,
        method='by_night'):
    '''
    Plan when targets will be visibile and transiting from a site. 
    
    Inputs
    ------
    filename : str
        A plain text file with the following columns:
            target : The name of the target (e.g. J0555-57).
            RA     : The right ascension of the target (e.g. 05h55m32.62s).
            DEC    : The declination of the target (e.g. -57d17m26.1s).
            epoch* : The epoch of the transit. Youc can either use:
                         epoch_HJD-2400000 : HJD - 24500000
                         epoch_BJD-2455000 : MJD
            Period : The period of the system (days).
            Secondary : can be True or False depending on whether you want
                        to see when the secondary transits will be.
    observatory : str
        The observatory you are observing from. See later for list of available
        observatories (accepted by astropy).    
    start : str
        The first night of observation (e.g. 2017-08-31).
    end : str
        The last night of observation (e.g. 2017-09-10).
    airmass_limit : float
        The maximum airmass you want to observe through. 
    moon_distance : float
        The closest the target can be t the moon in arcmins.
    do_secondary = True:
        Look for secondary eclipses assuming circularised orbits. 
        
    Available observator names are:
         'ALMA',
         'Anglo-Australian Observatory',
         'Apache Point',
         'Apache Point Observatory',
         'Atacama Large Millimeter Array',
         'BAO',
         'Beijing XingLong Observatory',
         'Black Moshannon Observatory',
         'CHARA',
         'Canada-France-Hawaii Telescope',
         'Catalina Observatory',
         'Cerro Pachon',
         'Cerro Paranal',
         'Cerro Tololo',
         'Cerro Tololo Interamerican Observatory',
         'DCT',
         'Discovery Channel Telescope',
         'Dominion Astrophysical Observatory',
         'Gemini South',
         'Hale Telescope',
         'Haleakala Observatories',
         'Happy Jack',
         'Jansky Very Large Array',
         'Keck Observatory',
         'Kitt Peak',
         'Kitt Peak National Observatory',
         'La Silla Observatory',
         'Large Binocular Telescope',
         'Las Campanas Observatory',
         'Lick Observatory',
         'Lowell Observatory',
         'Manastash Ridge Observatory',
         'McDonald Observatory',
         'Medicina',
         'Medicina Dish',
         'Michigan-Dartmouth-MIT Observatory',
         'Mount Graham International Observatory',
         'Mt Graham',
         'Mt. Ekar 182 cm. Telescope',
         'Mt. Stromlo Observatory',
         'Multiple Mirror Telescope',
         'NOV',
         'National Observatory of Venezuela',
         'Noto',
         'Observatorio Astronomico Nacional, San Pedro Martir',
         'Observatorio Astronomico Nacional, Tonantzintla',
         'Palomar',
         'Paranal Observatory',
         'Roque de los Muchachos',
         'SAAO',
         'SALT',
         'SRT',
         'Siding Spring Observatory',
         'Southern African Large Telescope',
         'Subaru',
         'Subaru Telescope',
         'Sutherland',
         'Vainu Bappu Observatory',
         'Very Large Array',
         'W. M. Keck Observatory',
         'Whipple',
         'Whipple Observatory',
         'aao',
         'alma',
         'apo',
         'bmo',
         'cfht',
         'ctio',
         'dao',
         'dct',
         'ekar',
         'example_site',
         'flwo',
         'gemini_north',
         'gemini_south',
         'gemn',
         'gems',
         'greenwich',
         'haleakala',
         'irtf',
         'keck',
         'kpno',
         'lapalma',
         'lasilla',
         'lbt',
         'lco',
         'lick',
         'lowell',
         'mcdonald',
         'mdm',
         'medicina',
         'mmt',
         'mro',
         'mso',
         'mtbigelow',
         'mwo',
         'noto',
         'ohp',
         'paranal',
         'salt',
         'sirene',
         'spm',
         'srt',
         'sso',
         'tona',
         'vbo',
         'vla'.
    '''
    ###################
    # Try reading table
    ###################
    try:
        target_table = Table.read(filename, format='ascii')
    except:
        raise ValueError(
            'I cant open the target file (make sure its ascii with the following first line:\ntarget		RA		DEC		epoch_HJD-2400000	Period		Secondary'
        )

##############################
# try reading observation site
##############################
    try:
        observation_site = coord.EarthLocation.of_site(observatory)
        observation_handle = Observer(location=observation_site)
        observation_handle1 = Observer.at_site(observatory)
    except:
        print(coord.EarthLocation.get_site_names())
        raise ValueError('The site is not understood')

###################################
# Try reading start and end times
###################################
    try:
        start_time = Time(start + ' 12:01:00', location=observation_site)
        end_time = Time(end + ' 12:01:00', location=observation_site)
        number_of_nights = int(end_time.jd - start_time.jd)
        time_range = Time([start + ' 12:01:00', end + ' 12:01:00'])
        print('Number of nights: {}'.format(number_of_nights))
    except:
        raise ValueError('Start and end times not understood')

#####################
# Now do constraints
#####################
#try:

    constraints = [
        AltitudeConstraint(0 * u.deg, 90 * u.deg),
        AirmassConstraint(3),
        AtNightConstraint.twilight_civil()
    ]
    #except:
    #	raise ValueError('Unable to get set constraints')

    if method == 'by_night':
        for i in range(number_of_nights):
            start_time_tmp = start_time + TimeDelta(
                i,
                format='jd')  #  get start time (doesent need to be accurate)
            end_time_tmp = start_time + TimeDelta(
                i + 1,
                format='jd')  #  get start time (doesent need to be accurate)
            print('#' * 80)
            start_time_tmpss = start_time_tmp.datetime.ctime().split(
            )  # ['Fri', 'Dec', '24', '12:00:00', '2010']
            print('Night {} - {} {} {} {}'.format(i + 1, start_time_tmpss[0],
                                                  start_time_tmpss[2],
                                                  start_time_tmpss[1],
                                                  start_time_tmpss[-1]))
            print('#' * 80)

            # Now print Almnac information (sunset and end of evening twilight
            print('Almnac:')
            sun_set = observation_handle.sun_set_time(start_time_tmp,
                                                      which='next')
            print('Sunset:\t\t\t\t\t\t\t' + sun_set.utc.datetime.ctime())

            twilight_evening_astronomical = observation_handle.twilight_evening_astronomical(
                start_time_tmp, which='next')  # -18
            twilight_evening_nautical = observation_handle.twilight_evening_nautical(
                start_time_tmp, which='next')  # -12
            twilight_evening_civil = observation_handle.twilight_evening_civil(
                start_time_tmp, which='next')  # -6 deg
            print('Civil evening twilight (-6 deg) (U.T.C):\t\t' +
                  twilight_evening_civil.utc.datetime.ctime())
            print('Nautical evening twilight (-12 deg) (U.T.C):\t\t' +
                  twilight_evening_nautical.utc.datetime.ctime())
            print('Astronomical evening twilight (-18 deg) (U.T.C):\t' +
                  twilight_evening_astronomical.utc.datetime.ctime())
            print('\n')

            twilight_morning_astronomical = observation_handle.twilight_morning_astronomical(
                start_time_tmp, which='next')  # -18
            twilight_morning_nautical = observation_handle.twilight_morning_nautical(
                start_time_tmp, which='next')  # -12
            twilight_morning_civil = observation_handle.twilight_morning_civil(
                start_time_tmp, which='next')  # -6 deg
            print('Astronomical morning twilight (-18 deg) (U.T.C):\t' +
                  twilight_morning_astronomical.utc.datetime.ctime())
            print('Nautical morning twilight (-12 deg) (U.T.C):\t\t' +
                  twilight_morning_nautical.utc.datetime.ctime())
            print('Civil morning twilight (-6 deg) (U.T.C):\t\t' +
                  twilight_morning_civil.utc.datetime.ctime())
            sun_rise = observation_handle.sun_rise_time(start_time_tmp,
                                                        which='next')
            print('Sunrise:\t\t\t\t\t\t' + sun_rise.utc.datetime.ctime())
            print('\n')

            # stuff for creating plot
            plot_mids = []
            plot_names = []
            plot_widths = []

            for j in range(len(target_table)):
                # Extract information
                star_coordinates = coord.SkyCoord('{} {}'.format(
                    target_table['RA'][j], target_table['DEC'][j]),
                                                  unit=(u.hourangle, u.deg),
                                                  frame='icrs')
                star_fixed_coord = FixedTarget(coord=star_coordinates,
                                               name=target_table['target'][j])

                ####################
                # Get finder image
                ####################
                '''
                plt.close()
                try:
                finder_image = plot_finder_image(star_fixed_coord,reticle=True,fov_radius=10*u.arcmin)
                except:
                pass
                plt.savefig(target_table['target'][j]+'_finder_chart.eps')
                '''

                P = target_table['Period'][j]
                Secondary_transit = target_table['Secondary'][j]
                transit_half_width = TimeDelta(
                    target_table['width'][j] * 60 * 60 / 2,
                    format='sec')  # in seconds for a TimeDelta

                # now convert T0 to HJD -> JD -> BJD so we can cout period
                if 'epoch_HJD-2400000' in target_table.colnames:
                    #print('Using HJD-2400000')
                    T0 = target_table['epoch_HJD-2400000'][j]
                    T0 = Time(T0 + 2400000, format='jd')  # HJD given by WASP
                    ltt_helio = T0.light_travel_time(star_coordinates,
                                                     'heliocentric',
                                                     location=observation_site)
                    T0 = T0 - ltt_helio  # HJD -> JD
                    ltt_bary = T0.light_travel_time(star_coordinates,
                                                    'barycentric',
                                                    location=observation_site)
                    T0 = T0 + ltt_bary  # JD -> BJD
                elif 'epoch_BJD-2455000' in target_table.colnames:
                    #print('Using BJD-2455000')
                    T0 = target_table['epoch_BJD-2455000'][j] + 2455000
                    T0 = Time(T0, format='jd')  # BJD
                else:
                    print('\n\n\n\n FAILE\n\n\n\n')
                    continue

                ##########################################################
                # Now start from T0 and count in periods to find transits
                ##########################################################
                # convert star and end time to BJD
                ltt_bary_start_time = start_time_tmp.light_travel_time(
                    star_coordinates, 'barycentric',
                    location=observation_site)  # + TimeDelta(i,format='jd')
                start_time_bary = start_time_tmp + ltt_bary_start_time  # + TimeDelta(i,format='jd') #  convert start time to BJD

                ltt_bary_end_time_tmp = end_time_tmp.light_travel_time(
                    star_coordinates, 'barycentric',
                    location=observation_site)  # + TimeDelta(i,format='jd')
                end_time_bary = end_time_tmp + ltt_bary_start_time  #+ TimeDelta(i+1,format='jd') #  convert end time to BJD and add 1 day 12pm -> 12pm the next day

                elapsed = end_time_bary - start_time_bary  # now this is 24 hours from the start day 12:00 pm

                # now count transits
                time = Time(T0.jd, format='jd')  # make a temporary copy
                transits = []
                primary_count, secondary_count = 0, 0
                while time.jd < end_time_bary.jd:
                    if (time.jd > start_time_bary.jd) and (time.jd <
                                                           end_time_bary.jd):
                        if is_observable(constraints,
                                         observation_handle,
                                         [star_fixed_coord],
                                         times=[time])[0] == True:
                            transits.append(time)
                            primary_count += 1
                    if Secondary_transit == 'yes':
                        timesecondary = time + TimeDelta(P / 2, format='jd')
                        if (timesecondary.jd > start_time_bary.jd) and (
                                timesecondary.jd < end_time_bary.jd):
                            if is_observable(constraints,
                                             observation_handle,
                                             [star_fixed_coord],
                                             times=[timesecondary])[0] == True:
                                transits.append(timesecondary)
                                secondary_count += 1

                    time = time + TimeDelta(P,
                                            format='jd')  # add another P to T0

                # Now find visible transits
                transits = [
                    i for i in transits
                    if is_observable(constraints,
                                     observation_handle, [star_fixed_coord],
                                     times=[i])[0] == True
                ]

                if len(transits) == 0:
                    message = '{} has no transits.'.format(
                        target_table['target'][j])
                    print('-' * len(message))
                    print(message)
                    print('-' * len(message))
                    print('\n')
                    plt.close()
                    continue
                else:
                    message = '{} has {} primary transits and {} secondary transits.'.format(
                        target_table['target'][j], primary_count,
                        secondary_count)
                    print('-' * len(message))
                    print(message)
                    print('RA: {}'.format(target_table['RA'][j]))
                    print('DEC: {}'.format(target_table['DEC'][j]))
                    print('Epoch: 2000')
                    print('T0 (BJD): {}'.format(T0.jd))
                    print('Period: {}'.format(P))
                    print('Transit width (hr): {}'.format(
                        target_table['width'][j]))
                    print('-' * len(message))
                    print('\n')

                for i in transits:
                    # currently transit times are in BJD (need to convert to HJD to check
                    ltt_helio = i.light_travel_time(star_coordinates,
                                                    'barycentric',
                                                    location=observation_site)
                    ii = i - ltt_helio
                    ltt_helio = ii.light_travel_time(star_coordinates,
                                                     'heliocentric',
                                                     location=observation_site)
                    ii = ii + ltt_helio

                    transit_1 = i - transit_half_width - TimeDelta(
                        7200, format='sec')  # ingress - 2 hr
                    transit_2 = i - transit_half_width - TimeDelta(
                        3600, format='sec')  # ingress - 2 hr
                    transit_3 = i - transit_half_width  # ingress
                    transit_4 = i + transit_half_width  # egress
                    transit_5 = i + transit_half_width + TimeDelta(
                        3600, format='sec')  # ingress - 2 hr
                    transit_6 = i + transit_half_width + TimeDelta(
                        7200, format='sec')  # ingress - 2 hr

                    if (((i.jd - time.jd) / P) - np.floor(
                        (i.jd - time.jd) / P) < 0.1) or ((
                            (i.jd - time.jd) / P) - np.floor(
                                (i.jd - time.jd) / P) > 0.9):
                        print('Primary Transit:')
                        print('-' * len('Primary Transit'))
                    if 0.4 < ((i.jd - time.jd) / P) - np.floor(
                        (i.jd - time.jd) / P) < 0.6:
                        print('Secondary Transit')
                        print('-' * len('Secondary Transit'))

                    ##################
                    # now get sirmass
                    ##################
                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=transit_1, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        transit_1, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Ingress - 2hr (U.T.C):\t\t\t\t\t' +
                          transit_1.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))

                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=transit_2, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        transit_2, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Ingress - 1hr (U.T.C):\t\t\t\t\t' +
                          transit_2.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))

                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=transit_3, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        transit_3, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Ingress (U.T.C):\t\t\t\t\t' +
                          transit_3.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))

                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=i, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        i, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Mid transit (U.T.C):\t\t\t\t\t' +
                          i.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))

                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=transit_4, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        transit_4, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Egress (U.T.C):\t\t\t\t\t\t' +
                          transit_4.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))

                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=transit_5, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        transit_5, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Egress + 1hr (U.T.C):\t\t\t\t\t' +
                          transit_5.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))

                    altaz = star_coordinates.transform_to(
                        AltAz(obstime=transit_6, location=observation_site))
                    hourangle = observation_handle1.target_hour_angle(
                        transit_6, star_coordinates)
                    hourangle = 24 * hourangle.degree / 360
                    if hourangle > 12:
                        hourangle -= 24
                    print('Egress + 2hr (U.T.C):\t\t\t\t\t' +
                          transit_6.utc.datetime.ctime() +
                          '\tAirmass: {:.2f}\tHA:{:.2f}'.format(
                              altaz.secz, hourangle))
                    print('HJD {} (to check with http://var2.astro.cz/)\n'.
                          format(ii.jd))

                    # append stuff for plots
                    plot_mids.append(i)  # astropy Time
                    plot_names.append(target_table['target'][j])
                    plot_widths.append(target_table['width'][j])

            # Now plot

            plt.close()
            if len(plot_mids) == 0:
                continue
            date_formatter = dates.DateFormatter('%H:%M')
            #ax.xaxis.set_major_formatter(date_formatter)

            # now load dummy transit lightcurves
            xp, yp = np.load('lc.npy')
            xs, ys = np.load('lcs.npy')

            # x = np.linspace(0, 2*np.pi, 400)
            # y = np.sin(x**2)

            subplots_adjust(hspace=0.000)
            number_of_subplots = len(
                plot_names)  # number of targets transiting that night

            time = sun_set + np.linspace(-1, 14,
                                         100) * u.hour  # take us to sunset
            for i, v in enumerate(xrange(number_of_subplots)):
                # exctract params
                width = plot_widths[v]
                name = plot_names[v]
                mid = plot_mids[v]

                # now set up dummy lc plot
                x_tmp = mid + xp * (width /
                                    2) * u.hour  # get right width in hours

                # now set up axis
                v = v + 1
                ax1 = subplot(number_of_subplots, 1, v)
                ax1.xaxis.set_major_formatter(date_formatter)

                if v == 1:
                    ax1.set_title(start)

                # plot transit model
                ax1.plot_date(x_tmp.plot_date, ys, 'k-')

                # plot continuum
                #xx  =time.plot_date
                #xx = [uu for uu in xx if (uu<min(x_tmp.plot_date)) or (uu>max(x_tmp.plot_date))]

                #ax1.plot_date(xx, np.ones(len(xx)),'k--', alpha=0.3)
                ax1.set_xlim(min(time.plot_date), max(time.plot_date))
                #ax1.plot_date(mid.plot_date, 0.5, 'ro')
                plt.setp(ax1.get_xticklabels(), rotation=30, ha='right')
                ax1.set_ylabel(name, rotation=45, labelpad=20)

                twilights = [
                    (sun_set.datetime, 0.0),
                    (twilight_evening_civil.datetime, 0.1),
                    (twilight_evening_nautical.datetime, 0.2),
                    (twilight_evening_astronomical.datetime, 0.3),
                    (twilight_morning_astronomical.datetime, 0.4),
                    (twilight_morning_nautical.datetime, 0.3),
                    (twilight_morning_civil.datetime, 0.2),
                    (sun_rise.datetime, 0.1),
                ]

                for ii, twii in enumerate(twilights[1:], 1):
                    ax1.axvspan(twilights[ii - 1][0],
                                twilights[ii][0],
                                ymin=0,
                                ymax=1,
                                color='grey',
                                alpha=twii[1])

                ax1.grid(alpha=0.5)
                ax1.get_yaxis().set_ticks([])
                if v != number_of_subplots:
                    ax1.get_xaxis().set_ticks([])

            plt.xlabel('Time [U.T.C]')
            #plt.tight_layout()
            #plt.savefig('test.eps',format='eps')
            plt.show()
示例#20
0
    async def _schedule(self):
        """Actually do the scheduling, usually run in a separate process."""

        # only global constraint is the night
        if self._twilight == "astronomical":
            constraints = [AtNightConstraint.twilight_astronomical()]
        elif self._twilight == "nautical":
            constraints = [AtNightConstraint.twilight_nautical()]
        else:
            raise ValueError("Unknown twilight type.")

        # make shallow copies of all blocks and loop them
        copied_blocks = [copy.copy(block) for block in self._blocks]
        for block in copied_blocks:
            # astroplan's PriorityScheduler expects lower priorities to be more important, so calculate
            # 1000 - priority
            block.priority = 1000.0 - block.priority
            if block.priority < 0:
                block.priority = 0

            # it also doesn't match the requested observing windows exactly, so we make them a little smaller.
            for constraint in block.constraints:
                if isinstance(constraint, TimeConstraint):
                    constraint.min += 30 * u.second
                    constraint.max -= 30 * u.second

        # get start time for scheduler
        start = self._schedule_start
        now_plus_safety = Time.now() + self._safety_time * u.second
        if start is None or start < now_plus_safety:
            # if no ETA exists or is in the past, use safety time
            start = now_plus_safety

        # get running scheduled block, if any
        if self._current_task_id is None:
            log.info("No running block found.")
            running_task = None
        else:
            # get running task from archive
            log.info("Trying to find running block in current schedule...")
            now = Time.now()
            tasks = await self._task_archive.get_pending_tasks(
                now, now, include_running=True)
            if self._current_task_id in tasks:
                running_task = tasks[self._current_task_id]
            else:
                log.info("Running block not found in last schedule.")
                running_task = None

        # if start is before end time of currently running block, change that
        if running_task is not None:
            log.info("Found running block that ends at %s.", running_task.end)

            # get block end plus some safety
            block_end = running_task.end + 10.0 * u.second
            if start < block_end:
                start = block_end
                log.info(
                    "Start time would be within currently running block, shifting to %s.",
                    start.isot)

        # calculate end time
        end = start + TimeDelta(self._schedule_range * u.hour)

        # remove currently running block and filter by start time
        blocks = []
        for b in filter(
                lambda x: x.configuration["request"]["id"] != self.
                _current_task_id, copied_blocks):
            time_constraint_found = False
            # loop all constraints
            for c in b.constraints:
                if isinstance(c, TimeConstraint):
                    # we found a time constraint
                    time_constraint_found = True

                    # does the window start before the end of the scheduling range?
                    if c.min < end:
                        # yes, store block and break loop
                        blocks.append(b)
                        break
            else:
                # loop has finished without breaking
                # if no time constraint has been found, we still take the block
                if time_constraint_found is False:
                    blocks.append(b)

        # if need new update, skip here
        if self._need_update:
            log.info("Not running scheduler, since update was requested.")
            return

        # no blocks found?
        if len(blocks) == 0:
            log.info("No blocks left for scheduling.")
            await self._task_archive.update_schedule([], start)
            return

        # log it
        log.info(
            "Calculating schedule for %d schedulable block(s) starting at %s...",
            len(blocks), start)

        # we don't need any transitions
        transitioner = Transitioner()

        # create scheduler
        scheduler = PriorityScheduler(constraints,
                                      self.observer,
                                      transitioner=transitioner)

        # run scheduler
        time_range = Schedule(start, end)
        loop = asyncio.get_running_loop()
        schedule = await loop.run_in_executor(None, scheduler, blocks,
                                              time_range)

        # if need new update, skip here
        if self._need_update:
            log.info(
                "Not using scheduler results, since update was requested.")
            return

        # update
        await self._task_archive.update_schedule(schedule.scheduled_blocks,
                                                 start)
        if len(schedule.scheduled_blocks) > 0:
            log.info("Finished calculating schedule for %d block(s):",
                     len(schedule.scheduled_blocks))
            for i, block in enumerate(schedule.scheduled_blocks, 1):
                log.info(
                    "  #%d: %s to %s (%.1f)",
                    block.configuration["request"]["id"],
                    block.start_time.strftime("%H:%M:%S"),
                    block.end_time.strftime("%H:%M:%S"),
                    block.priority,
                )
        else:
            log.info("Finished calculating schedule for 0 blocks.")
示例#21
0
from django.test import TestCase

from mop.toolbox.obs_details import all_night_moon_sep, calculate_visibility
from mop.toolbox.LCO_obs_locs import choose_loc

OGG = choose_loc('OGG')
v_test_target = ['Sirius', 100.7362500 * u.deg, -16.6459444 * u.deg]
v_date = Time("2019-12-25 00:00:00", scale='utc')
v_coords = SkyCoord(v_test_target[1], v_test_target[2], frame='icrs')
v_obs_begin = OGG.twilight_evening_astronomical(v_date, which='nearest')
v_obs_end = OGG.twilight_morning_astronomical(v_date, which='next')
v_observing_range = [v_obs_begin, v_obs_end]
constraints = [
    AirmassConstraint(2.0),
    AltitudeConstraint(20 * u.deg, 85 * u.deg),
    AtNightConstraint.twilight_astronomical()
]
ever_observable = is_observable(constraints,
                                OGG,
                                v_coords,
                                time_range=v_observing_range)

v_fail_start = Time("2019-12-24 10:00:00", scale='utc')
v_fail_end = Time("2019-12-25 10:00:00", scale='utc')


class TestVisibilityCalc(TestCase):
    def test_timeobj(self):
        self.assertEqual(v_date.scale, 'utc')
        self.assertEqual(v_date.value, '2019-12-25 00:00:00.000')
示例#22
0
    async def get_schedulable_blocks(self) -> List[ObservingBlock]:
        """Returns list of schedulable blocks.

        Returns:
            List of schedulable blocks
        """

        # check
        if self._portal_instrument_type is None:
            raise ValueError("No instrument type for portal set.")

        # get data
        schedulable = await self._portal_get(
            urljoin(self._url, "/api/requestgroups/schedulable_requests/"))

        # get proposal priorities
        data = await self._portal_get(urljoin(self._url, "/api/proposals/"))
        tac_priorities = {p["id"]: p["tac_priority"] for p in data["results"]}

        # loop all request groups
        blocks = []
        for group in schedulable:
            # get base priority, which is tac_priority * ipp_value
            proposal = group["proposal"]
            if proposal not in tac_priorities:
                log.error('Could not find proposal "%s".', proposal)
                continue
            base_priority = group["ipp_value"] * tac_priorities[proposal]

            # loop all requests in group
            for req in group["requests"]:
                # still pending?
                if req["state"] != "PENDING":
                    continue

                # duration
                duration = req["duration"] * u.second

                # time constraints
                time_constraints = [
                    TimeConstraint(Time(wnd["start"]), Time(wnd["end"]))
                    for wnd in req["windows"]
                ]

                # loop configs
                for cfg in req["configurations"]:
                    # get instrument and check, whether we schedule it
                    instrument = cfg["instrument_type"]
                    if instrument.lower(
                    ) != self._portal_instrument_type.lower():
                        continue

                    # target
                    t = cfg["target"]
                    target = SkyCoord(t["ra"] * u.deg,
                                      t["dec"] * u.deg,
                                      frame=t["type"].lower())

                    # constraints
                    c = cfg["constraints"]
                    constraints = []
                    if "max_airmass" in c and c["max_airmass"] is not None:
                        constraints.append(
                            AirmassConstraint(max=c["max_airmass"],
                                              boolean_constraint=False))
                    if "min_lunar_distance" in c and c[
                            "min_lunar_distance"] is not None:
                        constraints.append(
                            MoonSeparationConstraint(
                                min=c["min_lunar_distance"] * u.deg))
                    if "max_lunar_phase" in c and c[
                            "max_lunar_phase"] is not None:
                        constraints.append(
                            MoonIlluminationConstraint(
                                max=c["max_lunar_phase"]))
                        # if max lunar phase <= 0.4 (which would be DARK), we also enforce the sun to be <-18 degrees
                        if c["max_lunar_phase"] <= 0.4:
                            constraints.append(
                                AtNightConstraint.twilight_astronomical())

                    # priority is base_priority times duration in minutes
                    # priority = base_priority * duration.value / 60.
                    priority = base_priority

                    # create block
                    block = ObservingBlock(
                        FixedTarget(target, name=req["id"]),
                        duration,
                        priority,
                        constraints=[*constraints, *time_constraints],
                        configuration={"request": req},
                    )
                    blocks.append(block)

        # return blocks
        return blocks
def get_event_observability(
    eventclass,
    site, ra, dec, name, t_mid_0, period, duration, n_transits=100,
    obs_start_time=Time(dt.datetime.today().isoformat()),
    min_altitude = None,
    oot_duration = 30*u.minute,
    minokmoonsep = 30*u.deg,
    max_airmass = None,
    twilight_limit = 'nautical'):
    """
    note: barycentric corrections not yet implemented. (could do this myself!)
    -> 16 minutes of imprecision is baked into this observability calculator!

    args:

        eventclass: e.g., "OIBE". Function does NOT return longer events.

        site (astroplan.observer.Observer)

        ra, dec (units u.deg), e.g.:
            ra=101.28715533*u.deg, dec=16.71611586*u.deg,
        or can also accept
            ra="17 56 35.51", dec="-29 32 21.5"

        name (str), e.g., "Sirius"

        t_mid_0 (float): in BJD_TDB, preferably (but see note above).

        period (astropy quantity, units time)

        duration (astropy quantity, units time)

        n_transits (int): number of transits forward extrapolated to

        obs_start_time (astropy.Time object): when to start calculation from

        min_altitude (astropy quantity, units deg): 20 degrees is the more
        relevant constraint.

        max_airmass: e.g., 2.5. One of max_airmass or min_altitude is required.

        oot_duration (astropy quantity, units time): with which to brack
        transit observations, to get an OOT baseline.

        twilight_limit: 'astronomical', 'nautical', 'civil' for -18, -12, -6
        deg.
    """
    if eventclass not in [
        'OIBEO', 'OIBE', 'IBEO', 'IBE', 'BEO', 'OIB', 'OI', 'EO'
    ]:
        raise AssertionError

    if (isinstance(ra, u.quantity.Quantity) and
        isinstance(dec, u.quantity.Quantity)
    ):
        target_coord = SkyCoord(ra=ra, dec=dec)
    elif (isinstance(ra, str) and
          isinstance(dec, str)
    ):
        target_coord = SkyCoord(ra=ra, dec=dec, unit=(u.hourangle, u.deg))
    else:
        raise NotImplementedError

    if (
        not isinstance(max_airmass, float)
        or isinstance(min_altitude, u.quantity.Quantity)
    ):
        raise NotImplementedError

    target = FixedTarget(coord=target_coord, name=name)

    primary_eclipse_time = Time(t_mid_0, format='jd')

    system = EclipsingSystem(primary_eclipse_time=primary_eclipse_time,
                             orbital_period=period, duration=duration,
                             name=name)

    midtransit_times = system.next_primary_eclipse_time(
        obs_start_time, n_eclipses=n_transits)

    # for the time being, omit any local time constraints.
    if twilight_limit == 'astronomical':
        twilight_constraint = AtNightConstraint.twilight_astronomical()
    elif twilight_limit == 'nautical':
        twilight_constraint = AtNightConstraint.twilight_nautical()
    else:
        raise NotImplementedError('civil twilight is janky.')

    constraints = [twilight_constraint,
                   AltitudeConstraint(min=min_altitude),
                   AirmassConstraint(max=max_airmass),
                   MoonSeparationConstraint(min=minokmoonsep)]

    # tabulate ingress and egress times.
    ing_egr = system.next_primary_ingress_egress_time(
        obs_start_time, n_eclipses=n_transits
    )

    oibeo_window = np.concatenate(
        (np.array(ing_egr[:,0] - oot_duration)[:,None],
         np.array(ing_egr[:,1] + oot_duration)[:,None]),
        axis=1)
    oibe_window = np.concatenate(
        (np.array(ing_egr[:,0] - oot_duration)[:,None],
         np.array(ing_egr[:,1])[:,None]),
        axis=1)
    ibeo_window = np.concatenate(
        (np.array(ing_egr[:,0])[:,None],
         np.array(ing_egr[:,1] + oot_duration)[:,None]),
        axis=1)
    oib_window = np.concatenate(
        (np.array(ing_egr[:,0] - oot_duration)[:,None],
         np.array(midtransit_times)[:,None]),
        axis=1)
    beo_window = np.concatenate(
        (np.array(midtransit_times)[:,None],
         np.array(ing_egr[:,1] + oot_duration)[:,None]),
        axis=1)
    ibe_window = ing_egr
    oi_window = np.concatenate(
        (np.array(ing_egr[:,0] - oot_duration)[:,None],
        np.array(ing_egr[:,0])[:,None]),
        axis=1)
    eo_window = np.concatenate(
        (np.array(ing_egr[:,1])[:,None],
        np.array(ing_egr[:,1] + oot_duration)[:,None]),
        axis=1)

    keys = ['oibeo','oibe','ibeo','oib','beo','ibe','oi','eo']
    windows = [oibeo_window, oibe_window, ibeo_window,
               oib_window, beo_window, ibe_window, oi_window, eo_window]
    is_obs_dict = {}
    for key, window in zip(keys, windows):
        is_obs_dict[key] = np.array(
            is_event_observable(constraints, site, target,
                                times_ingress_egress=window)
        ).flatten()

    is_obs_df = pd.DataFrame(is_obs_dict)

    is_obs_df['ing'] = ing_egr[:,0]
    is_obs_df['egr'] = ing_egr[:,1]
    is_obs_df['isoing'] = Time(ing_egr[:,0], format='iso')
    is_obs_df['isoegr'] = Time(ing_egr[:,1], format='iso')

    # this function returns the observable events that are LONGEST. e.g.,
    # during an OIBEO transit you COULD observe just OIB, but why would you?

    if eventclass == 'OIBEO':
        event_ind = np.array(is_obs_df[eventclass.lower()])[None,:]
    elif eventclass in ['IBEO', 'OIBE']:
        event_ind = np.array(
            is_obs_df[eventclass.lower()] & ~is_obs_df['oibeo']
        )[None,:]
    elif eventclass in ['IBE', 'OIB', 'BEO']:
        event_ind = np.array(
            is_obs_df[eventclass.lower()]
            & ~is_obs_df['oibeo']
            & ~is_obs_df['oibe']
            & ~is_obs_df['ibeo']
        )[None,:]
    elif eventclass in ['OI', 'EO']:
        event_ind = np.array(
            is_obs_df[eventclass.lower()]
            & ~is_obs_df['oibeo']
            & ~is_obs_df['oibe']
            & ~is_obs_df['ibeo']
            & ~is_obs_df['oib']
            & ~is_obs_df['ibe']
            & ~is_obs_df['beo']
        )[None,:]

    # get moon separation over each transit. take minimum moon sep at
    # ing/tmid/egr as the moon separation.
    moon_tmid = get_moon(midtransit_times, location=site.location)
    moon_separation_tmid = moon_tmid.separation(target_coord)

    moon_ing = get_moon(ing_egr[:,0], location=site.location)
    moon_separation_ing = moon_ing.separation(target_coord)

    moon_egr = get_moon(ing_egr[:,1], location=site.location)
    moon_separation_egr = moon_egr.separation(target_coord)

    moon_separation = np.round(np.array(
        [moon_separation_tmid, moon_separation_ing,
         moon_separation_egr]).min(axis=0),0).astype(int)

    moon_illumination = np.round(
        100*moon.moon_illumination(midtransit_times),0).astype(int)

    # completely observable transits (OOT, ingress, bottom, egress, OOT)
    oibeo = is_event_observable(constraints, site, target,
                                times_ingress_egress=oibeo_window)

    ing_tmid_egr = np.concatenate(
        (np.array(ing_egr[:,0])[:,None],
         np.array(midtransit_times)[:,None],
         np.array(ing_egr[:,1])[:,None]),
        axis=1)

    target_window = np.array(windows)[
        int(np.argwhere(np.array(keys)==eventclass.lower())), :, :
    ]

    return (
        event_ind, oibeo, ing_tmid_egr, target_window,
        moon_separation, moon_illumination
    )
示例#24
0
文件: staralt.py 项目: japp/staralt
def observability_objects(data):
    """
    Test the observability of a list of objects for a single date

    Parameters
    ----------
    data : POST data format

    data = {
        'observatory' : 'OT',
        'altitude_lower_limit' : '30',
        'altitude_higher_limit' : '90',
        'objects' : [{
                'name' : 'Kelt 8b',
                'RA' : 283.30551667 ,
                'Dec' : 24.12738139,
                'dates' : [
                        ['2020-06-11 00:16:30', '2020-06-11 03:44:26'],
                        ['2020-06-14 06:07:56', '2020-06-14 09:35:53']
                    ]
                },
                {
                    'name' : 'TIC 123456789',
                    'RA' : 13.13055667 ,
                    'Dec' : 24.13912738,
                    'dates' : [
                        ['2020-06-11 23:59:59']
                    ]
                }
            ]
        }

    Returns
    -------
    observability : dict
        Dictionary with the observability and moon distance for all objects

        {'V0879 Cas' : {
                'observability' : 'True', 'moon_separation' : 30.4
            },
        'RU Scl' : {
            'observability' : 'True', 'moon_separation' : 10.8
            }
        }

    """

    import astropy.units as u
    from astroplan import FixedTarget
    from astroplan import (AltitudeConstraint, AtNightConstraint)
    from astroplan import is_observable, is_always_observable

    # Site location
    location = get_location(data['observatory'])

    # dict of observability for each target
    observabilities = {}

    if 'twilight_type' not in data.keys():
        data['twilight_type'] = 'astronomical'

    if data['twilight_type'] == 'civil':
        twilight_constraint = AtNightConstraint.twilight_civil()
    elif data['twilight_type'] == 'nautical':
        twilight_constraint = AtNightConstraint.twilight_nautical()
    else:
        twilight_constraint = AtNightConstraint.twilight_astronomical()

    # Observation constraints
    constraints = [
        AltitudeConstraint(
            float(data['altitude_lower_limit']) * u.deg,
            float(data['altitude_higher_limit']) * u.deg), twilight_constraint
    ]

    for target in data['objects']:

        coords = SkyCoord(ra=target['RA'] * u.deg, dec=target['Dec'] * u.deg)
        fixed_target = [FixedTarget(coord=coords, name=target['name'])]

        observabilities[target['name']] = []

        for date in target['dates']:

            # time range for transits
            # Always observable for time range
            if len(date) > 1:
                # If exoplanet transit, test observability always during transit,
                # if not, test observability *ever* during night
                time_range = Time([date[0], date[1]])

                # Are targets *always* observable in the time range?
                observable = is_always_observable(constraints,
                                                  location,
                                                  fixed_target,
                                                  time_range=time_range)

            # No time range, *ever* observabable during the night
            # Observability is test from sunset to sunrise
            # Default time resolution is 0.5h
            else:
                sunset = location.sun_set_time(Time(date[0]))
                sunrise = location.sun_rise_time(Time(date[0]), 'next')
                time_range = Time([sunset, sunrise])
                observable = is_observable(constraints,
                                           location,
                                           fixed_target,
                                           time_range=time_range)

            # Moon location for the observation date
            moon = location.moon_altaz(Time(date[0]))
            moon_separation = moon.separation(coords)

            observabilities[target['name']].append({
                'observable':
                str(observable[0]),
                'moon_separation':
                moon_separation.degree
            })

    return observabilities
示例#25
0
def observability(self, json_exoplanet_array, longitude, latitude, elevation, start_date, end_date, min_altitude, max_altitude, resolution):
    '''background task to (slowly) find planet observabilities'''
    
    # create Observer instance
    if elevation is None: elevation = 0
    custom_location = Observer(longitude=longitude*u.deg, latitude=latitude*u.deg, elevation=elevation*u.m)

    # time range
    if start_date is not None: start_date = Time(datetime.combine(datetime.fromisoformat(start_date), datetime.min.time()), out_subfmt='date')
    else: start_date = Time(datetime.combine(datetime.now(), datetime.min.time()), out_subfmt='date')
    if end_date is not None: end_date = Time(datetime.combine(datetime.fromisoformat(end_date), datetime.min.time()), out_subfmt='date')
    else: end_date = start_date + 30*u.day
    time_range = Time([start_date, end_date])

    # altitude and night time constraints
    if min_altitude is None: min_altitude = 0
    if max_altitude is None: max_altitude = 90
    constraints = [AltitudeConstraint(min_altitude*u.deg, max_altitude*u.deg), AtNightConstraint.twilight_astronomical()]
    
    # calculate if observable within lookahead time from now
    if resolution is None: resolution = 0.5
    
    # since we had to use a json string as argument, recreate the custom_exoplanet_array from the json
    custom_exoplanet_array = []
    json_unload = json.loads(json_exoplanet_array) # unpack json to make a dictionary
    for dict_ in json_unload:
        planet = Exoplanet()
        # copy properties back over from dictionary
        for prop, val in dict_.items(): functions.rsetattr(planet, prop, val)
        custom_exoplanet_array.append(planet)

    # trying to split array into chunks so we can say the task has been completed to the nearest percent
    num_chunks = round(len(custom_exoplanet_array)/800 * (resolution/0.5)**-1 * ((end_date-start_date).jd/30)**2 * 10)
    if num_chunks == 0: num_chunks = 1
    exoplanet_array_chunks = np.array_split(custom_exoplanet_array, num_chunks) # split exoplanet array into num_chunk parts

    planets_done = 0 # planets calculated for so far
    planets_lost = 0 # planets removed so far

    recombined_chunks = []
    for chunk in exoplanet_array_chunks:
        # make an array of FixedTarget instances
        target_table = []
        for planet in chunk:
            target_table.append((planet.name, planet.host.ra, planet.host.dec))
        targets = [FixedTarget(coord=SkyCoord(ra=ra*u.deg, dec=dec*u.deg), name=name)
                   for name, ra, dec in target_table]

        # calculate
        ever_observable = is_observable(constraints, custom_location, targets, time_range=time_range, time_grid_resolution=resolution*u.hour)

        # note unobservables
        to_pop = []
        for i in range(len(chunk)):
            chunk[i].observable = bool(ever_observable[i])
            if chunk[i].observable == False:
                to_pop.append(i)
        # remove unobservables
        chunk = np.delete(chunk, to_pop)

        # record numbers
        planets_done += len(targets)
        planets_lost += len(targets) - len(chunk)

        # write json
        recombined_chunks += chunk.tolist()
        observable_exoplanet_array = [planet for planet in recombined_chunks if planet.observable]
        json_exoplanet_array = functions.planet_array_to_json_array(observable_exoplanet_array, 'host_')

        # graph of decision metric vs rank
        tooltip_dict = {
            'name'            : [],
            'mass'            : [],
            'radius'          : [],
            'orbital_period'  : [],
            'semi_major_axis' : [],
            'temp_calculated' : [],
            'detection_type'  : [],
            'decision_metric' : [],
            'filter'          : [],
            't_exp'           : [],
        }
        graph = functions.metric_rank_bar_graph(observable_exoplanet_array, tooltip_dict)

        # update status
        self.update_state(state='PROGRESS',
                          meta={'current'         : planets_done,
                                'removed'         : planets_lost,
                                'total'           : len(custom_exoplanet_array),
                                'exoplanet_array' : json_exoplanet_array,
                                'graph'           : graph,
                                'finished'        : 'n'})
    
    return {'current': planets_done, 'removed': planets_lost, 'total': len(custom_exoplanet_array), 'exoplanet_array': json_exoplanet_array, 'graph': graph, 'finished': 'y'}
示例#26
0
def find_observability(exoplanet_array, default_lookahead, longitude, latitude,
                       elevation, start_date, end_date, min_altitude,
                       max_altitude, resolution, flash, display):
    '''Function to calculate'''
    '''# find timezone
    timezone_name = tf.timezone_at(lng=longitude, lat=latitude)
    delta_degree = 1
    while timezone_name is None:
        delta_degree += 1
        timezone_name = tf.closest_timezone_at(lng=longitude, lat=latitude, delta_degree=delta_degree)
    if flash: flash.append('Timezone   : ' + timezone_name)
    print(timezone_name)'''

    # create Observer instance
    if elevation is None: elevation = 0
    custom_location = Observer(longitude=longitude * u.deg,
                               latitude=latitude * u.deg,
                               elevation=elevation * u.m)

    # make an array of FixedTarget instances
    target_table = []
    for planet in exoplanet_array:
        target_table.append((planet.name, planet.host.ra, planet.host.dec))
    targets = [
        FixedTarget(coord=SkyCoord(ra=ra * u.deg, dec=dec * u.deg), name=name)
        for name, ra, dec in target_table
    ]

    # time range
    if start_date is not None:
        start_date = Time(datetime.combine(start_date, datetime.min.time()),
                          out_subfmt='date')
    else:
        start_date = Time(datetime.combine(datetime.now(),
                                           datetime.min.time()),
                          out_subfmt='date')
    if end_date is not None:
        end_date = Time(datetime.combine(end_date, datetime.min.time()),
                        out_subfmt='date')
    else:
        end_date = start_date + default_lookahead * u.day
    time_range = Time([start_date, end_date])
    #time_range_int = # no. days as an int
    if display:
        flash.append('Start date : ' + str(start_date.iso))
        flash.append('End date   : ' + str(end_date.iso))

    # altitude and night time constraints
    if min_altitude is None: min_altitude = 0
    if max_altitude is None: max_altitude = 90
    constraints = [
        AltitudeConstraint(min_altitude * u.deg, max_altitude * u.deg),
        AtNightConstraint.twilight_astronomical()
    ]

    # calculate if observable within lookahead time from now
    if resolution is None: resolution = 0.5

    # new route, faster by not bothering to recheck planets already found to be observable
    # UPDATE, ASTROPY IS ALREADY OPTIMISED FOR THIS, THIS TAKES 10 TIMES LONGER, LEAVING IN FOR DEMONSTRATION PURPOSES ONLY (commented out lines in 'old route' are also only for demonstrating the difference)
    # start = time.perf_counter()
    # ever_observable = [False] * len(exoplanet_array)
    # day = 0
    # while start_date + day*u.day != end_date:
    #     print(str(start_date + day*u.day) + ', ' + str(end_date))
    #     for i in range(len(ever_observable)):
    #         if ever_observable[i] == False:
    #             ever_observable[i] = is_observable(constraints, custom_location, [targets[i]], time_range=Time([start_date+day*u.day, start_date+(day+1)*u.day]), time_grid_resolution=resolution*u.hour)[0]
    #             print(str(day) + ', ' + str(i) + ', ' + targets[i].name + ', ' + str(ever_observable[i]))
    #     day += 1
    # end = time.perf_counter()
    # print(str(end - start) + ' seconds fast')

    # new route, faster by not bothering to recheck planets already found to be observable
    # UPDATE, ASTROPY IS ALREADY OPTIMISED FOR THIS, THIS TAKES 10 TIMES LONGER, LEAVING IN FOR DEMONSTRATION PURPOSES ONLY (commented out lines in 'old route' are also only for demonstrating the difference)
    # start = time.perf_counter()
    # ever_observable = [False] * len(exoplanet_array)
    # day = 0
    # for i in range(len(ever_observable)):
    #     for day in range(30):
    #         print(str(start_date + day*u.day) + ', ' + str(end_date))

    #         if ever_observable[i] == False:
    #             ever_observable[i] = is_observable(constraints, custom_location, [targets[i]], time_range=Time([start_date+day*u.day, start_date+(day+1)*u.day]), time_grid_resolution=resolution*u.hour)[0]
    #             print(str(day) + ', ' + str(i) + ', ' + targets[i].name + ', ' + str(ever_observable[i]))
    #         else: break
    # end = time.perf_counter()
    # print(str(end - start) + ' seconds fast')

    # trying to split array into chunks so we can say the task has been completed to the nearest percent
    # tosplit_target_array = copy.deepcopy(targets)
    # start = time.perf_counter()
    # target_chunks = np.array_split(tosplit_target_array, 10) # split targets into 10 parts (not 100, this makes the calculation time too long)
    # for i in range(len(target_chunks)):
    #     is_observable(constraints, custom_location, target_chunks[i].tolist(), time_range=time_range, time_grid_resolution=resolution*u.hour)
    #     #print('%i calculated' %i)
    # end = time.perf_counter()
    # print(str(end - start) + ' seconds fast')

    # old route, slow, commented out lines are for demonstrating that it is better than a manual method by a factor of 10
    start = time.perf_counter()
    ever_observable = is_observable(constraints,
                                    custom_location,
                                    targets,
                                    time_range=time_range,
                                    time_grid_resolution=resolution * u.hour)
    end = time.perf_counter()
    print(str(end - start) + ' seconds slow')

    for i in range(len(exoplanet_array)):
        exoplanet_array[i].observable = ever_observable[i]
    if display: flash.append('Timing resolution = {} hrs'.format(resolution))
示例#27
0
def construct_plan(data,
                   site,
                   start_time,
                   end_time,
                   constraints=None,
                   max_priority=3):
    if constraints is None:
        constraints = [
            AltitudeConstraint(10 * u.deg, 80 * u.deg),
            AirmassConstraint(5),
            AtNightConstraint.twilight_civil()
        ]

    data = data.sort_values(by=["Add. Data Priority", "RA"], ascending=[1, 1])

    time_range = Time([start_time, end_time])

    # targets.lis format:
    # NAME
    # <RA hh:mm:ss.ss> <DEC dd:mm:ss.s>
    # <HMJD/BMJD T0 err P err
    #
    # NAME...
    # ENTRY = "{}\n{} {}\n{} linear {} {} {} {}\n\n"
    targets_list = ""
    targets_prg = ""
    targets_notes = ""
    for name, row in data.iterrows():
        row['RA'], row['Dec'] = row['RA'].replace(" ",
                                                  ":"), row['Dec'].replace(
                                                      " ", ":")

        target = FixedTarget(coord=SkyCoord(ra=Angle(row['RA'],
                                                     unit='hourangle'),
                                            dec=Angle(row['Dec'],
                                                      unit='degree')),
                             name=name)

        # Does the target rise above the horizon?
        ever_observable = is_observable(constraints,
                                        site,
                                        target,
                                        time_range=time_range)

        # Parse the ephemeris data
        try:
            T0, T0_err = row['T(0) +/- (d)'].replace(" ", "").split("(")
            calendar, T0 = T0.split("=")
            T0_err = T0_err.replace(")", "")

            N = len(T0.split(".")[1]) - len(T0_err)
            T0_err = "0.{}{}".format(("0" * N), T0_err)

            P, P_err = row['P +/- (d)'].split("(")
            P_err = P_err.replace(")", "")

            M = len(P.split(".")[1]) - len(P_err)
            P_err = "0.{}{}".format(("0" * M), P_err)
        except ValueError:
            print("Failed to extract row! {}".format(name))
            continue

        # Get the priority of this system
        try:
            priority = int(row['Add. Data Priority'])
        except ValueError:
            continue

        # Logic about if we want to use this target
        writeme = ever_observable[0] and (priority <= max_priority)

        # If true, add to the list
        if writeme:
            # Output data formats
            line = "{}\n{} {}\n{} linear {} {} {} {}\n\n".format(
                name, row['RA'], row['Dec'], calendar, T0, T0_err, P, P_err)
            prgline = "{}\n0.7 1.3 3 8\n\n".format(name)
            notesline = '{}: "{}"\n\n\n'.format(name, row['Target Notes'])

            targets_list += line
            targets_prg += prgline
            targets_notes += notesline

    # Write out files
    with open(os.path.join('OUTPUT', 'targets.lis'), 'w') as f:
        f.write(targets_list)
    with open(os.path.join('OUTPUT', 'targets.prg'), 'w') as f:
        f.write(targets_prg)
    with open(os.path.join('OUTPUT', 'targets.txt'), 'w') as f:
        f.write(targets_notes)
示例#28
0
def main(event, context):
    filename = 'MS190311l-1-Preliminary'

    # Get targetlist
    target_list = 'triggers/%s_bayestar.csv'%filename # replace with your object key
    s3 = boto3.resource('s3')
    print(target_list)
    s3.Bucket(bucketname).download_file(target_list, '/tmp/%s_targetlist.csv'%filename)

    galaxies = Table.read('/tmp/%s_targetlist.csv'%filename)
    del galaxies['col0']
    galaxies = np.array(galaxies.as_array().tolist())

    """Get the full galaxy list, and find which are good to observe at NOT"""

    # Setup observer
    time = Time.now()
    NOT = Observer.at_site("lapalma")

    tel_constraints = [AtNightConstraint.twilight_civil(), AirmassConstraint(max = 5)]



    # Check if nighttime
    if not NOT.is_night(time):
        sunset_tonight = NOT.sun_set_time(time, which='nearest')
        dt_sunset = (sunset_tonight - time)
        print("Daytime at the NOT! Preparing a plan for observations starting next sunset in ~ %s hours."%(int(dt_sunset.sec/3600)))
        time = sunset_tonight + 5*u.minute
    else:
        print("It's nighttime at the NOT! Preparing a plan immeidately.")


    # Get target list
    galaxycoord=SkyCoord(ra=galaxies[:, 1]*u.deg,dec=galaxies[:, 2]*u.deg)
    targets = [FixedTarget(coord=SkyCoord(ra=ra*u.deg, dec=dec*u.deg), name=int(name))
               for name, ra, dec in galaxies[:, :3]]

    # Construct astroplan OBs
    blocks = []
    exposure = 300*u.second
    read_out = 20 * u.second
    for priority, targ in enumerate(targets):
        for bandpass in ['r']:

            b = ObservingBlock.from_exposures(
                targ,
                priority,
                exposure,
                1,
                read_out,
                configuration={'filter': bandpass})

            blocks.append(b)

    # Transitioner between targets
    slew_rate = 10.8*u.deg/u.second
    transitioner = Transitioner(
        slew_rate, {
            'filter': {
                ('g', 'r'): 30 * u.second,
                ('i', 'z'): 30 * u.second,
                'default': 30 * u.second
            }
        })


    # Initialize the priority scheduler with the constraints and transitioner
    prior_scheduler = SequentialScheduler(constraints = tel_constraints,
                                        observer = NOT,
                                        transitioner = transitioner)

    # Initialize a Schedule object, to contain the new schedule around night
    night_length = NOT.sun_set_time(time, which='nearest') - NOT.sun_rise_time(time, which='nearest')
    noon_before = time - 4 * u.hour
    noon_after = time + 16 * u.hour

    priority_schedule = Schedule(noon_before, noon_after)

    # Call the schedule with the observing blocks and schedule to schedule the blocks
    prior_scheduler(blocks, priority_schedule)

    # Remove transition blocks to read observing order
    priority_schedule_table = priority_schedule.to_table()
    mask = priority_schedule_table["target"] != "TransitionBlock"
    pruned_schedule = priority_schedule_table[mask]
    idxs = np.arange(0, len(pruned_schedule["target"]))

    # pl.figure(figsize = (14,6))
    # plot_schedule_airmass(priority_schedule, show_night=True)
    # pl.legend(loc = "upper right")
    # schedule_path = filename+"schedule.pdf"
    # pl.savefig(schedule_path)
    # pl.clf()
    # print("Finished preparing an observing plan.")

    # s3.Bucket(bucketname).upload_file(schedule_path, 'triggers/%s'%schedule_path)



    instrumements = ["ALFOSC"]
    nothing_to_observe = True
    for tel in range(0, len(instrumements)):
        print("Writing a plan for {}".format(instrumements[tel]))
        outlist = [0]*galaxies.shape[0]
        for i in range(tel, galaxies.shape[0], len(instrumements)):
            ra = Angle(galaxies[i, 1] * u.deg)
            dec = Angle(galaxies[i, 2] * u.deg)
            mask = pruned_schedule['target'].astype("int") == int(galaxies[i, 0])
            targ_row = pruned_schedule[mask]
            idx = idxs[mask]

            # Get observing scheduling rank and airmass at observing time.
            try:
                airm = NOT.altaz(Time(targ_row["start time (UTC)"].data), targets[i]).secz
                t_s = targ_row["start time (UTC)"].data
                t_e = targ_row["end time (UTC)"].data

            except:
                print("GLADE target name %s not found in schedule. Probably not visible. Replacing entry with -99"%(galaxies[i, 0]))
                idx = -99
                airm = -99


            outlist[i] = int(galaxies[i, 0]), ra.to_string(
                unit=u.hourangle, sep=':', precision=2, pad=True), dec.to_string(
                    sep=':', precision=2, alwayssign=True,
                    pad=True), idx, airm, galaxies[i, 3], galaxies[i, 4], galaxies[
                        i, 5], t_s, t_e


        header = ["GladeID", "RA", "Dec", "Observing number", "Airmass at observing time", "Distance", "B-band luminosity", "Probability", "Schduled integration start", "Schduled integration end"]
        outframe = Table(np.array(outlist), names=header)
        csv_path = filename+"_schedule.csv"
        ascii.write(outframe, "/tmp/"+csv_path, format='csv', overwrite=True, fast_writer=False)

        s3.Bucket(bucketname).upload_file("/tmp/"+csv_path, 'triggers/%s'%csv_path)


    return
示例#29
0
文件: staralt.py 项目: japp/staralt
def observability_dates(data):
    """
    Test the observability of a single objects for several nights

    If the first element of 'dates' contains a single date, then
    the observability is test as *ever* for the night. 
    If a time range is given, observability is test as *always* for the time range

    Parameters
    ----------
    data : POST data format

        # data for transiting planet, time range constrained
        data = {
            'name' : 'Kelt 8b',
            'RA' : 283.30551667 ,
            'Dec' : 24.12738139,
            'observatory' : 'OT',
            'altitude_lower_limit' : '30',
            'altitude_higher_limit' : '90',
            'twilight_type' : 'astronomical',
            'dates' : [
                    ['2020-06-11 00:16:30', '2020-06-11 03:44:26'],
                    ['2020-06-14 06:07:56', '2020-06-14 09:35:53']
                ]
            }
        
        # data for ordinary target, twilight constrained
        # single date list

        data = {
            'name' : 'KIC8012732',
            'RA' : 284.72949583 ,
            'Dec' : 43.86421667,
            'observatory' : 'OT',
            'altitude_lower_limit' : '30',
            'altitude_higher_limit' : '90',
            'dates' : [
                        ['2020-06-11 23:00:00']
                    ]
            }

    Returns
    -------
    observability : dict
        Dictionary with the observability and moon distance for all objects

        {'V0879 Cas' : {
                'observability' : 'True', 'moon_separation' : 30.4
            },
        'RU Scl' : {
                'observability' : 'True', 'moon_separation' : 10.8
            }
        }

    """

    import astropy.units as u
    from astroplan import FixedTarget
    from astroplan import (AltitudeConstraint, AtNightConstraint)
    from astroplan import is_observable, is_always_observable

    # Site location
    location = get_location(data['observatory'])

    coords = SkyCoord(ra=data['RA'] * u.deg, dec=data['Dec'] * u.deg)
    fixed_target = [FixedTarget(coord=coords, name=data['name'])]

    # List of dates of observability
    observabilities = []

    if 'twilight_type' not in data.keys():
        data['twilight_type'] = 'astronomical'

    if data['twilight_type'] == 'civil':
        twilight_constraint = AtNightConstraint.twilight_civil()
    elif data['twilight_type'] == 'nautical':
        twilight_constraint = AtNightConstraint.twilight_nautical()
    else:
        twilight_constraint = AtNightConstraint.twilight_astronomical()

    # Observation constraints
    constraints = [
        AltitudeConstraint(
            float(data['altitude_lower_limit']) * u.deg,
            float(data['altitude_higher_limit']) * u.deg), twilight_constraint
    ]

    for date in data['dates']:

        # time range for transits
        # Always observable for time range
        if len(data['dates'][0]) > 0:

            # If exoplanet transits, check for observability always during transit,
            # if not, check observability *ever* during night
            time_range = Time([date[0], date[1]])

            # Are targets *always* observable in the time range?
            observable = is_always_observable(constraints,
                                              location,
                                              fixed_target,
                                              time_range=time_range)

        # No time range, *ever* observabable during the night
        else:
            observable = is_observable(constraints,
                                       location,
                                       fixed_target,
                                       times=Time(date[0]))

        # Moon location for the observation date
        moon = location.moon_altaz(Time(date[0]))
        moon_separation = moon.separation(coords)

        observabilities.append({
            'observable': str(observable[0]),
            'moon_separation': moon_separation.degree
        })

    return observabilities
示例#30
0
def send_database_report(event):
    """Send a message to Slack with details of the database pointings and visibility."""
    title = ['*Visibility for event {}*'.format(event.name)]

    # Basic details
    details = []
    filepath = None
    with db.open_session() as session:
        # Query Event table entries
        db_events = session.query(
            db.Event).filter(db.Event.name == event.name).all()

        details += [
            'Number of entries in the events table: {}'.format(len(db_events))
        ]

        if len(db_events) == 0:
            # Uh-oh
            details += ['*ERROR: Nothing found in database*']
        else:
            # This event should be the latest added
            db_event = db_events[-1]

            # Get Mpointings
            db_mpointings = db_event.mpointings

            details += [
                'Number of targets for this event: {}'.format(
                    len(db_mpointings))
            ]

            if len(db_mpointings) == 0:
                # It might be because it's a retraction, so we've removed the previous pointings
                if event.type == 'GW_RETRACTION':
                    details += ['- Previous targets removed successfully']
                # Or it might be because no tiles passed the filter
                elif (event.strategy['on_grid']
                      and event.strategy['prob_limit'] > 0
                      and max(event.full_table['prob']) <
                      event.strategy['prob_limit']):
                    details += [
                        '- No tiles passed the probability limit ' +
                        '({:.1f}%, '.format(event.strategy['prob_limit'] * 100)
                        + 'highest had {:.1f}%)'.format(
                            max(event.full_table['prob']) * 100),
                    ]
                else:
                    # Uh-oh
                    details += ['- *ERROR: No Mpointings found in database*']

            else:
                # Get the Mpointing coordinates
                ras = [mpointing.ra for mpointing in db_mpointings]
                decs = [mpointing.dec for mpointing in db_mpointings]
                coords = SkyCoord(ras, decs, unit='deg')

                for site in ['La Palma']:  # TODO: should be in params
                    details += ['Predicted visibility from {}:'.format(site)]

                    # Create Astroplan Observer
                    observer = Observer.at_site(site.lower().replace(' ', ''))

                    # Create visibility constraints
                    min_alt = float(
                        event.strategy['constraints_dict']['min_alt']) * u.deg
                    max_sunalt = float(event.strategy['constraints_dict']
                                       ['max_sunalt']) * u.deg
                    alt_constraint = AltitudeConstraint(min=min_alt)
                    night_constraint = AtNightConstraint(
                        max_solar_altitude=max_sunalt)
                    constraints = [alt_constraint, night_constraint]

                    # Check visibility until the stop time
                    start_time = event.strategy['start_time']
                    stop_time = event.strategy['stop_time']
                    details += [
                        '- Valid dates: {} to {}'.format(
                            start_time.datetime.strftime('%Y-%m-%d'),
                            stop_time.datetime.strftime('%Y-%m-%d'))
                    ]

                    if event.strategy['stop_time'] < Time.now():
                        # The Event pointings will have expired
                        delta = Time.now() - event.strategy['stop_time']
                        details[-1] += ' _(expired {:.1f} days ago)_'.format(
                            delta.to('day').value)

                    mps_visible_mask = is_observable(
                        constraints,
                        observer,
                        coords,
                        time_range=[start_time, stop_time])
                    details += [
                        '- Targets visible during valid period: {}/{}'.format(
                            sum(mps_visible_mask), len(db_mpointings))
                    ]

                    if event.strategy['on_grid']:
                        # Find the total probibility for all tiles
                        mp_tiles = np.array(
                            [mp.grid_tile.name for mp in db_mpointings])
                        total_prob = event.grid.get_probability(
                            list(mp_tiles)) * 100
                        details += [
                            '- Total probability in all tiles: {:.1f}%'.format(
                                total_prob)
                        ]

                        # Get visible mp tile names
                        mp_tiles_visible = mp_tiles[mps_visible_mask]
                        visible_prob = event.grid.get_probability(
                            list(mp_tiles_visible)) * 100
                        details += [
                            '- Probability in visible tiles: {:.1f}%'.format(
                                visible_prob)
                        ]

                        # Get non-visible mp tile names
                        mps_notvisible_tonight_mask = np.invert(
                            mps_visible_mask)
                        mp_tiles_notvisible = mp_tiles[
                            mps_notvisible_tonight_mask]

                        # Get all non-visible tiles
                        tiles_visible_mask = is_observable(
                            constraints,
                            observer,
                            event.grid.coords,
                            time_range=[start_time, stop_time])
                        tiles_notvisible_mask = np.invert(tiles_visible_mask)
                        tiles_notvisible = np.array(
                            event.grid.tilenames)[tiles_notvisible_mask]

                        # Create a plot of the tiles, showing visibility tonight
                        # TODO: multiple sites? Need multiple plots or one combined?
                        filename = event.name + '_tiles.png'
                        filepath = os.path.join(params.FILE_PATH, filename)
                        event.grid.plot(
                            filename=filepath,
                            plot_skymap=True,
                            highlight=[mp_tiles_visible, mp_tiles_notvisible],
                            highlight_color=['blue', 'red'],
                            color={
                                tilename: '0.5'
                                for tilename in tiles_notvisible
                            },
                        )

    message_text = '\n'.join(title + details)

    # Send the message, with the plot attached if one was generated
    send_slack_msg(message_text, filepath=filepath)