From 6aea183e98818868934a5b4422768208c1473794 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 7 Jun 2021 15:04:26 +1000 Subject: [PATCH 1/5] add script --- scripts/dwf.py | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 scripts/dwf.py diff --git a/scripts/dwf.py b/scripts/dwf.py new file mode 100644 index 00000000..d5ac6598 --- /dev/null +++ b/scripts/dwf.py @@ -0,0 +1,114 @@ +""" +""" +import time +from datetime import datetime + +from panoptes.utils.time import current_time +from panoptes.utils.utils import altaz_to_radec + +from huntsman.pocs.scheduler.observation.base import Observation +from huntsman.pocs.utils.huntsman import create_huntsman_pocs + +SLEEP_INTERVAL = 10 + +FILTER_NAMES = {"huntsmanpi005": "g_band", + "huntsmanpi007": "g_band", + "huntsmanpi008": "r_band", + "huntsmanpi009": "r_band", + "huntsmanpi011": "r_band"} + +OBSERVATION_CONFIG = [] + + +def get_focus_coords(huntsman): + """ Get coordinates for initial focus. """ + coarse_focus_config = huntsman.get_config('focusing.coarse') + + # Get timeout, alt, and az from config dict. + coarse_focus_alt = coarse_focus_config['alt'] + coarse_focus_az = coarse_focus_config['az'] + + # Convert altaz coordinates to radec. + coarse_focus_coords = altaz_to_radec(alt=coarse_focus_alt, az=coarse_focus_az, + location=huntsman.observatory.earth_location, + obstime=current_time()) + + return coarse_focus_coords + + +class DwfScheduler(): + """ Hardcode the field configs here for simplicity. """ + + def __init__(self, observations, times_start, times_end): + self._observations = observations + self._times_start = times_start + self._times_end = times_end + + def get_observation(self): + """ Get an observation to observe now! """ + time_now = datetime.now() + + valid_obs = None + for i in range(len(self._observations)): + + obs = self._observations[i] + + if (time_now > self._times_start[i]) and (time_now < self._times_end[i]): + valid_obs = obs + + if valid_obs: + # Remove the observation so we don't accidentally observe it again + del self._observations[i] + + return valid_obs + + +if __name__ == "__main__": + + huntsman = create_huntsman_pocs() + + observations = [] + times_start = [] + times_end = [] + for obs_config in OBSERVATION_CONFIG: + times_start.append(obs_config.pop("time_start")) + times_end.append(obs_config.pop("time_end")) + observations.append(Observation(filter_names_per_camera=FILTER_NAMES, **obs_config)) + + scheduler = DwfScheduler(observations=observations, times_start=times_start, + times_end=times_end) + + # Open the dome + huntsman.observatory.dome.open() + + # Prepare the cameras + huntsman.observatory.prepare_cameras() + + # Move FWs to their separate positions + for cam_name, filter_name in FILTER_NAMES.items(): + huntsman.cameras[cam_name].filterwheel.move_to(filter_name, blocking=True) + + # Slew to focus + huntsman.observatory.mount.set_target_coordinates(get_focus_coords(huntsman)) + huntsman.observatory.mount.slew_to_target() + + # Do coarse focus + # Use a bad filter name (not None) to make the code use the current filter in each camera + huntsman.observatory.autofocus_cameras(filter_name="notafiltername", coarse=True) + + # Do fine focus + # We may have to do this several times per night, so monitor the FITS images as they come in + huntsman.observatory.autofocus_cameras(filter_name="notafiltername") + + # Start the observation loop + while True: + + observation = scheduler.get_observation() + + if observation is None: + huntsman.logger.debug(f"No valid observation. Sleeping for {SLEEP_INTERVAL}s.") + time.sleep(SLEEP_INTERVAL) + continue + + huntsman.logger.info(f"Taking observation: {observation}") + huntsman.observatory.take_observation_block(observation, skip_focus=True) From 1d4ea1b8de47c8f9afe7bc1cf2a3563a5ae8e47a Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 7 Jun 2021 16:26:43 +1000 Subject: [PATCH 2/5] update script --- scripts/dwf.py | 97 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/scripts/dwf.py b/scripts/dwf.py index d5ac6598..afc0348f 100644 --- a/scripts/dwf.py +++ b/scripts/dwf.py @@ -1,15 +1,21 @@ """ """ import time +from copy import deepcopy from datetime import datetime +from pytz import timezone +from dateutil import parser as date_parser -from panoptes.utils.time import current_time +from panoptes.utils.library import load_module +from panoptes.utils.time import current_time, wait_for_events from panoptes.utils.utils import altaz_to_radec -from huntsman.pocs.scheduler.observation.base import Observation from huntsman.pocs.utils.huntsman import create_huntsman_pocs +from huntsman.pocs.observatory import HuntsmanObservatory SLEEP_INTERVAL = 10 +FOCUS_TIMEOUT = 600 +TIMEZONE = timezone('Australia/Sydney') FILTER_NAMES = {"huntsmanpi005": "g_band", "huntsmanpi007": "g_band", @@ -20,24 +26,19 @@ OBSERVATION_CONFIG = [] -def get_focus_coords(huntsman): - """ Get coordinates for initial focus. """ - coarse_focus_config = huntsman.get_config('focusing.coarse') - - # Get timeout, alt, and az from config dict. - coarse_focus_alt = coarse_focus_config['alt'] - coarse_focus_az = coarse_focus_config['az'] - - # Convert altaz coordinates to radec. - coarse_focus_coords = altaz_to_radec(alt=coarse_focus_alt, az=coarse_focus_az, - location=huntsman.observatory.earth_location, - obstime=current_time()) - - return coarse_focus_coords +OBSERVATION_CONFIG = [{"observation": + {"name": "spica", + "type": "huntsman.pocs.scheduler.observation.base.Observation"}, + "field": {"name": "spica", + "type": "huntsman.pocs.scheduler.field.Field", + "position": "13h26m20s -11d16m21s"}, + "time_start": "2021-06-07 16:05", + "time_end": "2021-06-07 16:25"} + ] class DwfScheduler(): - """ Hardcode the field configs here for simplicity. """ + """ Class to return valid observations based on local time. """ def __init__(self, observations, times_start, times_end): self._observations = observations @@ -46,7 +47,7 @@ def __init__(self, observations, times_start, times_end): def get_observation(self): """ Get an observation to observe now! """ - time_now = datetime.now() + time_now = datetime.now(TIMEZONE) valid_obs = None for i in range(len(self._observations)): @@ -63,21 +64,57 @@ def get_observation(self): return valid_obs -if __name__ == "__main__": - - huntsman = create_huntsman_pocs() +def create_scheduler(): + """ Create the DWF scheduler object. """ observations = [] times_start = [] times_end = [] - for obs_config in OBSERVATION_CONFIG: - times_start.append(obs_config.pop("time_start")) - times_end.append(obs_config.pop("time_end")) - observations.append(Observation(filter_names_per_camera=FILTER_NAMES, **obs_config)) + + for config in deepcopy(OBSERVATION_CONFIG): + + time_start = date_parser.parse(config.pop("time_start")) + time_end = date_parser.parse(config.pop("time_end")) + + times_start.append(time_start) + times_end.append(time_end) + + field_config = config["field"] + FieldClass = load_module(field_config.pop("type")) + field = FieldClass(**field_config) + + obs_config = config["observation"] + ObsClass = load_module(obs_config.pop("type")) + obs = ObsClass(filter_names_per_camera=FILTER_NAMES, field=field, **obs_config) + observations.append(obs) scheduler = DwfScheduler(observations=observations, times_start=times_start, times_end=times_end) + return scheduler + + +def get_focus_coords(huntsman): + """ Get coordinates for initial focus. """ + coarse_focus_config = huntsman.get_config('focusing.coarse') + + # Get timeout, alt, and az from config dict. + coarse_focus_alt = coarse_focus_config['alt'] + coarse_focus_az = coarse_focus_config['az'] + + # Convert altaz coordinates to radec. + coarse_focus_coords = altaz_to_radec(alt=coarse_focus_alt, az=coarse_focus_az, + location=huntsman.observatory.earth_location, + obstime=current_time()) + + return coarse_focus_coords + + +if __name__ == "__main__": + + huntsman = create_huntsman_pocs(with_dome=True, simulators=["weather", "power"]) + scheduler = create_scheduler() + # Open the dome huntsman.observatory.dome.open() @@ -86,19 +123,21 @@ def get_observation(self): # Move FWs to their separate positions for cam_name, filter_name in FILTER_NAMES.items(): - huntsman.cameras[cam_name].filterwheel.move_to(filter_name, blocking=True) + huntsman.observatory.cameras[cam_name].filterwheel.move_to(filter_name, blocking=True) # Slew to focus huntsman.observatory.mount.set_target_coordinates(get_focus_coords(huntsman)) huntsman.observatory.mount.slew_to_target() # Do coarse focus - # Use a bad filter name (not None) to make the code use the current filter in each camera - huntsman.observatory.autofocus_cameras(filter_name="notafiltername", coarse=True) + # Use super method to override filter wheel move + events = super(HuntsmanObservatory, huntsman.observatory).autofocus_cameras(coarse=True) + wait_for_events(list(events.values()), timeout=FOCUS_TIMEOUT) # Do fine focus # We may have to do this several times per night, so monitor the FITS images as they come in - huntsman.observatory.autofocus_cameras(filter_name="notafiltername") + events = super(HuntsmanObservatory, huntsman.observatory).autofocus_cameras() + wait_for_events(list(events.values()), timeout=FOCUS_TIMEOUT) # Start the observation loop while True: From 3493de41780ab263265360eae601be021001204e Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 7 Jun 2021 17:16:26 +1000 Subject: [PATCH 3/5] update targets --- scripts/dwf.py | 57 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/scripts/dwf.py b/scripts/dwf.py index afc0348f..aeda2829 100644 --- a/scripts/dwf.py +++ b/scripts/dwf.py @@ -1,10 +1,10 @@ """ """ +import yaml import time from copy import deepcopy -from datetime import datetime +from datetime import datetime, timedelta from pytz import timezone -from dateutil import parser as date_parser from panoptes.utils.library import load_module from panoptes.utils.time import current_time, wait_for_events @@ -16,6 +16,8 @@ SLEEP_INTERVAL = 10 FOCUS_TIMEOUT = 600 TIMEZONE = timezone('Australia/Sydney') +DATE_BEGIN = datetime(2021, 6, 7, tzinfo=TIMEZONE) # Change as needed +FIELDS_FILE = "/huntsman/conf_files/fields.yaml" FILTER_NAMES = {"huntsmanpi005": "g_band", "huntsmanpi007": "g_band", @@ -23,18 +25,16 @@ "huntsmanpi009": "r_band", "huntsmanpi011": "r_band"} -OBSERVATION_CONFIG = [] - -OBSERVATION_CONFIG = [{"observation": - {"name": "spica", - "type": "huntsman.pocs.scheduler.observation.base.Observation"}, - "field": {"name": "spica", - "type": "huntsman.pocs.scheduler.field.Field", - "position": "13h26m20s -11d16m21s"}, - "time_start": "2021-06-07 16:05", - "time_end": "2021-06-07 16:25"} - ] +TEST_OBSERVATION_CONFIGS = [{"observation": + {"name": "spica", + "type": "huntsman.pocs.scheduler.observation.base.Observation"}, + "field": {"name": "spica", + "type": "huntsman.pocs.scheduler.field.Field", + "position": "13h26m20s -11d16m21s"}, + "time_start": "16:05:00", + "time_end": "18:25:00"} + ] class DwfScheduler(): @@ -47,7 +47,7 @@ def __init__(self, observations, times_start, times_end): def get_observation(self): """ Get an observation to observe now! """ - time_now = datetime.now(TIMEZONE) + time_now = datetime.now(TIMEZONE).replace(tzinfo=TIMEZONE) valid_obs = None for i in range(len(self._observations)): @@ -56,6 +56,7 @@ def get_observation(self): if (time_now > self._times_start[i]) and (time_now < self._times_end[i]): valid_obs = obs + break if valid_obs: # Remove the observation so we don't accidentally observe it again @@ -64,17 +65,35 @@ def get_observation(self): return valid_obs -def create_scheduler(): +def parse_date(date): + """ Parse the date from the fields config file. """ + + hour, minute, sec = [int(_) for _ in date.split(":")] + + td = timedelta(hours=hour, minutes=minute, seconds=sec) + if hour < 12: + td += timedelta(days=1) + + return DATE_BEGIN + td + + +def create_scheduler(observation_configs=None): """ Create the DWF scheduler object. """ observations = [] times_start = [] times_end = [] - for config in deepcopy(OBSERVATION_CONFIG): + if observation_configs is None: + with open(FIELDS_FILE, 'r') as f: + observation_configs = yaml.safe_load(f) + else: + observation_configs = deepcopy(observation_configs) + + for config in observation_configs: - time_start = date_parser.parse(config.pop("time_start")) - time_end = date_parser.parse(config.pop("time_end")) + time_start = parse_date(config.pop("time_start")) + time_end = parse_date(config.pop("time_end")) times_start.append(time_start) times_end.append(time_end) @@ -112,7 +131,7 @@ def get_focus_coords(huntsman): if __name__ == "__main__": - huntsman = create_huntsman_pocs(with_dome=True, simulators=["weather", "power"]) + huntsman = create_huntsman_pocs(with_dome=True, simulators=["weather", "power", "night"]) scheduler = create_scheduler() # Open the dome From 0215c94ce9ea38faca02647cd4af4ce979a86cfa Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 7 Jun 2021 18:51:32 +1000 Subject: [PATCH 4/5] unpark mount --- scripts/dwf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/dwf.py b/scripts/dwf.py index aeda2829..56ae4bd1 100644 --- a/scripts/dwf.py +++ b/scripts/dwf.py @@ -145,6 +145,7 @@ def get_focus_coords(huntsman): huntsman.observatory.cameras[cam_name].filterwheel.move_to(filter_name, blocking=True) # Slew to focus + huntsman.observatory.mount.unpark() huntsman.observatory.mount.set_target_coordinates(get_focus_coords(huntsman)) huntsman.observatory.mount.slew_to_target() From dbf483041baccc1e22bda5771ff941c5caa3960d Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 7 Jun 2021 21:01:39 +1000 Subject: [PATCH 5/5] fix bug --- scripts/dwf.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/dwf.py b/scripts/dwf.py index 56ae4bd1..65540af7 100644 --- a/scripts/dwf.py +++ b/scripts/dwf.py @@ -13,8 +13,8 @@ from huntsman.pocs.utils.huntsman import create_huntsman_pocs from huntsman.pocs.observatory import HuntsmanObservatory -SLEEP_INTERVAL = 10 -FOCUS_TIMEOUT = 600 +SLEEP_INTERVAL = 60 +FOCUS_TIMEOUT = 900 TIMEZONE = timezone('Australia/Sydney') DATE_BEGIN = datetime(2021, 6, 7, tzinfo=TIMEZONE) # Change as needed FIELDS_FILE = "/huntsman/conf_files/fields.yaml" @@ -61,6 +61,8 @@ def get_observation(self): if valid_obs: # Remove the observation so we don't accidentally observe it again del self._observations[i] + del self._times_start[i] + del self._times_end[i] return valid_obs