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": "", }
configuration={'SNR': '%.4f' % data['SNR'].values[index]}) blocks.append(b) # now we make a transitioner slew_rate = .5 * u.deg / u.second setup_time = {'default': 160 * u.second} transitioner = Transitioner(slew_rate) ''' # now we do the scheduling seq_scheduler = SequentialScheduler(constraints=constraint, observer=kpno, transitioner=transitioner) sequential_schedule = Schedule(start_time_utc, end_time_utc) try: seq_scheduler(blocks, sequential_schedule) except ValueError: print(sequential_schedule.to_table()) ''' # Initialize the priority scheduler with the constraints and transitioner prior_scheduler = PriorityScheduler(constraints=constraint, observer=kpno, transitioner=transitioner) # Initialize a Schedule object, to contain the new schedule priority_schedule = Schedule(start_time_utc, end_time_utc) try: prior_scheduler(blocks, priority_schedule) except ValueError: print(priority_schedule.to_table())
constraints=[first_half_night]) blocks.append(b) b = ObservingBlock.from_exposures(m13, priority, m13_exp, n, read_out, configuration={'filter': bandpass}, constraints=[first_half_night]) blocks.append(b) slew_rate = .8 * u.deg / u.second transitioner = Transitioner( slew_rate, { 'filter': { ('B', 'G'): 10 * u.second, ('G', 'R'): 10 * u.second, 'default': 30 * u.second } }) seq_scheduler = SequentialScheduler(constraints=global_constraints, observer=apo, transitioner=transitioner) sequential_schedule = Schedule(noon_before, noon_after) print(seq_scheduler(blocks, sequential_schedule)) print(sequential_schedule.to_table())
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 = kp, transitioner = transitioner) # Initialize a Schedule object, to contain the new schedule priority_schedule = Schedule(tstart, tend) # Call the schedule with the observing blocks and schedule to schedule the blocks prior_scheduler(blocks, priority_schedule) fid = open(outfile,'w') for schedule in priority_schedule.to_table(): tar = schedule["target"] if tar == "TransitionBlock": continue idx = np.where(targets["objectID"] == tar)[0] target = targets[idx] filt = schedule["configuration"]["filter"] obsstart, obsend = Time(schedule["start time (UTC)"]), Time(schedule["end time (UTC)"]) expt = int(schedule["duration (minutes)"]*60.0) c = SkyCoord(ra=target["ra"][0]*u.degree, dec=target["dec"][0]*u.degree, frame='icrs') ra = c.ra.to_string(unit=u.hour, sep=':') dec = c.dec.to_string(unit=u.degree, sep=':')
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