예제 #1
0
# make the observing time - Local time.
start_time_mst = Time('2017-06-17 18:30')
end_time_mst = Time('2017-06-21 06:00')
night_time = end_time_mst - start_time_mst
observable_time_mst = start_time_mst + night_time * np.linspace(0, 1, 75)

# convert everything to UTC
start_time_utc = mst2utc(start_time_mst)
end_time_utc = mst2utc(end_time_mst)
observable_time_utc = mst2utc(observable_time_mst)

time_range = Time([start_time_utc, end_time_utc])

# now we figure out what is observable at all with some simple constraints
constraint = [
    AtNightConstraint.twilight_civil(),
    AirmassConstraint(max=2.5, boolean_constraint=True)
]

observable = astroplan.is_observable(constraint,
                                     kpno,
                                     targets,
                                     time_range=time_range)

data['Observable'] = observable
data.to_csv('updated.csv')

if 0:

    # now we make the exposure times
    exp_time_single = 12 * u.second
예제 #2
0
def observation_schedule(
        followup_requests,
        instrument,
        observation_start=Time.now(),
        observation_end=Time.now() + TimeDelta(12 * u.hour),
        output_format='csv',
        figsize=(10, 8),
):
    """Create a schedule to display observations for a particular instrument
    Parameters
    ----------
    followup_requests : skyportal.models.followup_request.FollowupRequest
        The planned observations associated with the request
    instrument : skyportal.models.instrument.Instrument
        The instrument that the request is made based on
    observation_start: astropy.time.Time
        Start time for the observations
    observation_end: astropy.time.Time
        End time for the observations
    output_format : str, optional
        "csv", "pdf" or "png" -- determines the format of the returned observation plan
    figsize : tuple, optional
        Matplotlib figsize of the pdf/png created
    Returns
    -------
    dict
        success : bool
            Whether the request was successful or not, returning
            a sensible error in 'reason'
        name : str
            suggested filename based on `instrument` and `output_format`
        data : str
            binary encoded data for the file (to be streamed)
        reason : str
            If not successful, a reason is returned.
    """

    location = EarthLocation.from_geodetic(
        instrument.telescope.lon * u.deg,
        instrument.telescope.lat * u.deg,
        instrument.telescope.elevation * u.m,
    )
    observer = Observer(location=location, name=instrument.name)

    global_constraints = [
        AirmassConstraint(max=2.50, boolean_constraint=False),
        AtNightConstraint.twilight_civil(),
        MoonSeparationConstraint(min=10.0 * u.deg),
    ]

    blocks = []
    read_out = 10.0 * u.s

    for ii, followup_request in enumerate(followup_requests):
        obj = followup_request.obj
        coord = SkyCoord(ra=obj.ra * u.deg, dec=obj.dec * u.deg)
        target = FixedTarget(coord=coord, name=obj.id)

        payload = followup_request.payload
        allocation = followup_request.allocation
        requester = followup_request.requester

        if "start_date" in payload:
            start_date = Time(payload["start_date"], format='isot')
            if start_date > observation_end:
                continue

        if "end_date" in payload:
            end_date = Time(payload["end_date"], format='isot')
            if end_date < observation_start:
                continue

        if "priority" in payload:
            priority = payload["priority"]
        else:
            priority = 1

        # make sure to invert priority (priority = 5.0 is max, priority = 1.0 is min)
        priority = 5.0 / priority

        if "exposure_time" in payload:
            exposure_time = payload["exposure_time"] * u.s
        else:
            exposure_time = 3600 * u.s

        if "exposure_counts" in payload:
            exposure_counts = payload["exposure_counts"]
        else:
            exposure_counts = 1

        # get extra constraints
        constraints = []
        if "minimum_lunar_distance" in payload:
            constraints.append(
                MoonSeparationConstraint(
                    min=payload['minimum_lunar_distance'] * u.deg))

        if "maximum_airmass" in payload:
            constraints.append(
                AirmassConstraint(max=payload['maximum_airmass'],
                                  boolean_constraint=False))

        if "observation_choices" in payload:
            configurations = [{
                'requester': requester.username,
                'group_id': allocation.group_id,
                'request_id': followup_request.id,
                'filter': bandpass,
            } for bandpass in payload["observation_choices"]]
        else:
            configurations = [{
                'requester': requester.username,
                'group_id': allocation.group_id,
                'request_id': followup_request.id,
                'filter': 'default',
            }]

        for configuration in configurations:
            b = ObservingBlock.from_exposures(
                target,
                priority,
                exposure_time,
                exposure_counts,
                read_out,
                configuration=configuration,
            )
            blocks.append(b)

    # Initialize a transitioner object with the slew rate and/or the
    # duration of other transitions (e.g. filter changes)
    slew_rate = 2.0 * u.deg / u.second
    transitioner = Transitioner(slew_rate,
                                {'filter': {
                                    'default': 10 * u.second
                                }})

    # Initialize the sequential scheduler with the constraints and transitioner
    prior_scheduler = PriorityScheduler(constraints=global_constraints,
                                        observer=observer,
                                        transitioner=transitioner)
    # Initialize a Schedule object, to contain the new schedule
    priority_schedule = Schedule(observation_start, observation_end)

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

    if output_format in ["png", "pdf"]:
        matplotlib.use("Agg")
        fig = plt.figure(figsize=figsize, constrained_layout=False)
        plot_schedule_airmass(priority_schedule, show_night=True)
        plt.legend(loc="upper right")
        buf = io.BytesIO()
        fig.savefig(buf, format=output_format)
        plt.close(fig)
        buf.seek(0)

        return {
            "success": True,
            "name": f"schedule_{instrument.name}.{output_format}",
            "data": buf.read(),
            "reason": "",
        }
    elif output_format == "csv":
        try:
            schedule_table = priority_schedule.to_table(show_transitions=False,
                                                        show_unused=False)
        except Exception as e:
            raise ValueError(
                f'Scheduling failed: there are probably no observable targets: {str(e)}.'
            )

        schedule = []
        for block in schedule_table:
            target = block["target"]
            if target == "TransitionBlock":
                continue

            filt = block["configuration"]["filter"]
            request_id = block["configuration"]["request_id"]
            group_id = block["configuration"]["group_id"]
            requester = block["configuration"]["requester"]

            obs_start = Time(block["start time (UTC)"], format='iso')
            obs_end = Time(block["end time (UTC)"], format='iso')
            exposure_time = int(block["duration (minutes)"] * 60.0)

            c = SkyCoord(ra=block["ra"] * u.degree,
                         dec=block["dec"] * u.degree,
                         frame='icrs')
            ra = c.ra.to_string(unit=u.hour, sep=':')
            dec = c.dec.to_string(unit=u.degree, sep=':')

            observation = {
                'request_id': request_id,
                'group_id': group_id,
                'object_id': target,
                'ra': ra,
                'dec': dec,
                'epoch': 2000,
                'observation_start': obs_start,
                'observation_end': obs_end,
                'exposure_time': exposure_time,
                'filter': filt,
                'requester': requester,
            }
            schedule.append(observation)

        df = pd.DataFrame(schedule)
        with tempfile.NamedTemporaryFile(mode='w',
                                         suffix='.' + output_format) as f:
            df.to_csv(f.name)
            f.flush()

            with open(f.name, mode='rb') as g:
                csv_content = g.read()

        return {
            "success": True,
            "name": f"schedule_{instrument.name}.{output_format}",
            "data": csv_content,
            "reason": "",
        }
예제 #3
0
def create_at_night_constraint(*values):
    return AtNightConstraint.twilight_civil()