Skip to content

Commit

Permalink
Merge pull request #303 from bryanmiller/GSCHED-413
Browse files Browse the repository at this point in the history
Fix setting observing mode from atom configs
  • Loading branch information
sraaphorst authored Aug 29, 2023
2 parents 9582f1f + 8cb0915 commit 50814cc
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 24 deletions.
18 changes: 5 additions & 13 deletions scheduler/core/components/optimizer/greedymax.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import numpy as np
import numpy.typing as npt
from lucupy.minimodel import (NIR_INSTRUMENTS, Group, NightIndex, Observation, ObservationClass, ObservationID,
ObservationStatus, Program, QAState, Sequence, Site, UniqueGroupID, Wavelengths)
ObservationStatus, Program, QAState, Sequence, Site, UniqueGroupID, Wavelengths,
ObservationMode)
from lucupy.minimodel.resource import Resource
from lucupy.types import Interval, ZeroTime

Expand All @@ -26,15 +27,6 @@
logger = logger_factory.create_logger(__name__)


@final
class Mode(str, Enum):
"""
TODO: Get rid of this later as per GSCHED-413.
"""
SPECTROSCOPY = 'spectroscopy'
IMAGING = 'imaging'


@final
@dataclass(frozen=True)
class ObsPlanData:
Expand Down Expand Up @@ -134,14 +126,14 @@ def first_nonzero_time(inlist: List[timedelta]) -> int:
@staticmethod
def num_nir_standards(exec_sci: timedelta,
wavelengths: Wavelengths = frozenset(),
mode: Mode = Mode.SPECTROSCOPY) -> int:
mode: ObservationMode = ObservationMode.LONGSLIT) -> int:
"""
Calculated the number of NIR standards from the length of the NIR science and the mode
"""
n_std = 0

# TODO: need mode or other info to distinguish imaging from spectroscopy
if mode == Mode.IMAGING:
if mode == ObservationMode.IMAGING:
time_per_standard = timedelta(hours=2.0)
else:
if all(wave <= 2.5 for wave in wavelengths):
Expand Down Expand Up @@ -222,7 +214,7 @@ def _exec_time_remaining(self,
# How many standards are needed?
# TODO: need mode or other info to distinguish imaging from spectroscopy
if exec_sci_nir > ZeroTime and len(part_times) > 0:
n_std = self.num_nir_standards(exec_sci_nir, wavelengths=group.wavelengths(), mode=Mode.SPECTROSCOPY)
n_std = self.num_nir_standards(exec_sci_nir, wavelengths=group.wavelengths(), mode=group.obs_mode())

# if only partner standards, set n_std to the number of standards in group (e.g. specphots)
if nprt > 0 and nsci == 0:
Expand Down
23 changes: 15 additions & 8 deletions scheduler/core/programprovider/ocs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,10 @@ def find_filter(filter_input: str, filter_dict: Mapping[str, float]) -> Optional
fpu = instrument
else:
if instrument in OcsProgramProvider.FPU_FOR_INSTRUMENT:
if OcsProgramProvider.FPU_FOR_INSTRUMENT[instrument] in data:
if OcsProgramProvider._FPUKeys.CUSTOM in data:
# This will assign the MDF name to the FPU
fpu = data[OcsProgramProvider._FPUKeys.CUSTOM]
elif OcsProgramProvider.FPU_FOR_INSTRUMENT[instrument] in data:
fpu = data[OcsProgramProvider.FPU_FOR_INSTRUMENT[instrument]]
else:
# TODO: Might need to raise an exception here. Check code with science.
Expand Down Expand Up @@ -549,15 +552,18 @@ def search_list(val, alist):
return any(val in elem for elem in alist)

def determine_mode(inst: str) -> ObservationMode:

# print(f'inst: {inst} dispersers: {dispersers}')
# print(f'\t fpus: {fpus}')
obs_mode = ObservationMode.UNKNOWN
if search_list('GMOS', inst):
if 'MIRROR' in dispersers:
if 'GMOS' in inst:
if 'Mirror' in dispersers or 'MIRROR' in dispersers:
obs_mode = ObservationMode.IMAGING
elif search_list('arcsec', fpus):
obs_mode = ObservationMode.LONGSLIT
elif search_list('IFU', fpus):
obs_mode = ObservationMode.IFU
elif 'CUSTOM_MASK' in fpus:
elif search_list('G', fpus):
obs_mode = ObservationMode.MOS
elif inst in ["GSAOI", "'Alopeke", "Zorro"]:
obs_mode = ObservationMode.IMAGING
Expand All @@ -568,7 +574,7 @@ def determine_mode(inst: str) -> ObservationMode:
elif inst == 'Flamingos2':
if search_list('LONGSLIT', fpus):
obs_mode = ObservationMode.LONGSLIT
if search_list('FPU_NONE', fpu) and search_list('IMAGING', dispersers):
elif search_list('IMAGING', dispersers):
obs_mode = ObservationMode.IMAGING
elif inst == 'NIRI':
if search_list('NONE', dispersers) and search_list('MASK_IMAGING', fpus):
Expand Down Expand Up @@ -658,7 +664,7 @@ def autocorr_lag(x):
instrument_resources = frozenset([self._sources.origin.resource.lookup_resource(instrument)])
if 'GMOS' in instrument:
# Convert FPUs and dispersers to barcodes.
fpu_resources = frozenset([self._sources.origin.resource.fpu_to_barcode(site, fpu) for fpu in fpus])
fpu_resources = frozenset([self._sources.origin.resource.fpu_to_barcode(site, fpu, instrument) for fpu in fpus])
disperser_resources = frozenset([self._sources.origin.resource.lookup_resource(disperser.split('_')[0])
for disperser in dispersers])
resources = frozenset([r for r in fpu_resources | disperser_resources | instrument_resources])
Expand Down Expand Up @@ -771,7 +777,8 @@ def autocorr_lag(x):
qa_state=QAState.NONE,
guide_state=False,
resources=resources,
wavelengths=frozenset(wavelengths)))
wavelengths=frozenset(wavelengths),
obs_mode=mode))

if (step[OcsProgramProvider._AtomKeys.OBSERVE_TYPE].upper() not in OcsProgramProvider._OBSERVE_TYPES and
n_pattern == 0):
Expand Down Expand Up @@ -870,7 +877,7 @@ def parse_observation(self,
atoms = self.parse_atoms(site, data[OcsProgramProvider._ObsKeys.SEQUENCE], qa_states, split=split)
# exec_time = sum([atom.exec_time for atom in atoms], ZeroTime) + acq_overhead
# for atom in atoms:
# print(f'\t\t\t {atom.id} {atom.exec_time}')
# print(f'\t\t\t {atom.id} {atom.exec_time} {atom.obs_mode}')

# TODO: Should this be a list of all targets for the observation?
targets = []
Expand Down
24 changes: 21 additions & 3 deletions scheduler/services/resource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Dict, List, Set, Tuple, Union, Final
from io import BytesIO, StringIO

from lucupy.minimodel import Site, ALL_SITES
from lucupy.minimodel import Site, ALL_SITES, Resource
from lucupy.helpers import str_to_bool
import gelidum
import requests
Expand Down Expand Up @@ -102,6 +102,17 @@ def __init__(self, sites: FrozenSet[Site] = ALL_SITES):
# The final output from this class: the configuration per night.
self._night_configurations: Dict[Site, Dict[date, NightConfiguration]] = {site: {} for site in self._sites}

@staticmethod
def _mdf_to_barcode(mdfname: str, inst: str) -> Resource:
"""Legacy MOS mask barcode convention"""
barcode = None
instd = {'GMOS': '1', 'GMOS-N': '1', 'GMOS-S': '1', 'Flamingos2': '3'}
semd = {'A': '0', 'B': '1'}
progd = {'Q': '0', 'C': '1', 'L': '2', 'F': '3', 'S': '8', 'D': '9'}
if inst in instd.keys():
barcode = instd[inst] + semd[mdfname[6]] + progd[mdfname[7]] + mdfname[-6:-3] + mdfname[-2:]
return Resource(id=barcode)

def _itcd_fpu_to_barcode_parser(self, r: List[str], site: Site) -> Set[str]:
return {self._itcd_fpu_to_barcode[site][r[0].strip()].id} | {i.strip() for i in r[1:]}

Expand Down Expand Up @@ -171,12 +182,19 @@ def get_resources(self, site: Site, night_date: date) -> FrozenSet[Resource]:

return frozenset(self._resources[site][night_date])

def fpu_to_barcode(self, site: Site, fpu_name: str) -> Optional[Resource]:
def fpu_to_barcode(self, site: Site, fpu_name: str, instrument: str) -> Optional[Resource]:
"""
Convert a long FPU name into the barcode, if it exists.
"""
barcode = None
itcd_fpu_name = self._convert_fpu_to_itcd_name(site, fpu_name)
return self._itcd_fpu_to_barcode[site].get(itcd_fpu_name)
# print(f'fpu_to_barcode {fpu_name} {instrument} {itcd_fpu_name}')
if itcd_fpu_name:
barcode = self._itcd_fpu_to_barcode[site].get(itcd_fpu_name)
elif fpu_name.startswith('G'):
barcode = self._mdf_to_barcode(fpu_name, inst=instrument)
# print(f'\t barcode {barcode}')
return barcode


class FileBasedResourceService(ResourceService):
Expand Down

0 comments on commit 50814cc

Please sign in to comment.