def _location_available(location_info, location_constraints): for constraint in [ 'telescope_class', 'site', 'enclosure', 'telescope' ]: if (constraint in location_constraints and not case_insensitive_equals( location_info[constraint], location_constraints[constraint])): return False return True
def get_specific_instrument(self, instrument_type_code, site, enclosure, telescope): """Get the specific instrument name. Parameters: instrument_type: Instrument type site: 3-letter site code enclosure: 4-letter enclosure code telescope: 4-letter telescope code Returns: The matching specific instrument name Raises: ConfigDBError: If the specific instrument name is not found """ fallback_instrument = '' for instrument in self.active_instruments: if instrument['state'] != ['DISABLED']: temp_instrument_type = instrument['instrument_type']['code'] if case_insensitive_equals(instrument_type_code, temp_instrument_type): split_string = instrument['__str__'].lower().split('.') temp_site, temp_observatory, temp_telescope, _ = split_string if (case_insensitive_equals(site, temp_site) and case_insensitive_equals( enclosure, temp_observatory) and case_insensitive_equals( telescope, temp_telescope)): if instrument['state'] == 'SCHEDULABLE': return instrument['code'] else: fallback_instrument = instrument['code'] if fallback_instrument: return fallback_instrument raise ConfigDBError( 'get_specific_instrument failed: unable to find instrument type {} at location {}' .format(instrument_type_code, '.'.join([site, enclosure, telescope])))
def _elements_available(elements_by_type, available_element_groups): # Assume that the elements_by_type have only valid element types. for element_type in elements_by_type: available_element_group_types = [ eg['type'].lower() for eg in available_element_groups ] if element_type.lower() not in available_element_group_types: return False lowercase_elements_of_type = set( [e.lower() for e in elements_by_type[element_type]]) for element_group in available_element_groups: if case_insensitive_equals(element_type, element_group['type']): codes = { oe['code'].lower() for oe in element_group['optical_elements'] if oe['schedulable'] } if not lowercase_elements_of_type.issubset(codes): return False break return True
def get_autoguider_for_instrument(self, instrument_name, self_guide): """Get the autoguider instrument name. Parameters: instrument_name: Science camera instrument name self_guide: Boolean indicating whether to self-guide Returns: Instrument name to be used for autoguiding Raises: ConfigDBError: If unable to determine a suitable autoguider """ fallback_instrument = '' for instrument in self.active_instruments: if instrument['state'] != ['DISABLED']: if case_insensitive_equals(instrument_name, instrument['code']): if instrument['state'] == 'SCHEDULABLE': if not self_guide: return instrument['autoguider_camera']['code'] elif instrument['instrument_type'][ 'allow_self_guiding']: return instrument['code'] else: if not self_guide: fallback_instrument = instrument[ 'autoguider_camera']['code'] elif instrument['instrument_type'][ 'allow_self_guiding']: fallback_instrument = instrument['code'] if fallback_instrument: return fallback_instrument raise ConfigDBError( 'get_autoguider_for_instrument failed: unable to find autoguider for instrument {} where self_guide={}' .format(instrument_name, self_guide))
def get_telescopes_for_instruments(self, instrument_types_to_requirements, location, is_staff=False): """Get the set of telescopes on which a request can be observed. The main dictionary passed in contains instrument requirements by instrument type. The requirements include the science and guide camera optical elements needed, and whether the observation is planning to self-guide. The optical elements sub-structures can contain any number of lists of different elements, keyed by element type Parameters: instrument_types_to_requirements: dict of Instrument type to corresponding sets of science_optical_elements, guiding_optical_elements, and self_guide fields location: Dictionary with any location restrictions Returns: Set of available telescopes """ loc_is_set = self._location_fully_set(location) telescope_sets = defaultdict(set) for instrument in self.active_instruments: if instrument['state'] == 'SCHEDULABLE' or ( instrument['state'] != 'DISABLED' and is_staff and loc_is_set): instrument_location = self._parse_instrument_string( instrument['__str__']) for instrument_type, instrument_requirements in instrument_types_to_requirements.items( ): if (case_insensitive_equals( instrument_type, instrument['instrument_type']['code']) and self._location_available( instrument_location, location)): # This instrument is a candidate, now the optical elements just need to match self_guide = instrument_requirements['self_guide'] these_imager_element_groups = [] for science_camera in instrument['science_cameras']: these_imager_element_groups.extend( science_camera['optical_element_groups']) if self_guide and instrument['instrument_type'][ 'allow_self_guiding']: these_guider_element_groups = these_imager_element_groups elif not self_guide: these_guider_element_groups = instrument[ 'autoguider_camera']['optical_element_groups'] else: # There is no available guider on this telescope continue if (self._elements_available( instrument_requirements[ 'science_optical_elements'], these_imager_element_groups) and self._elements_available( instrument_requirements[ 'guiding_optical_elements'], these_guider_element_groups)): telescope_sets[instrument_type].add( instrument_location['telescope_location']) telescope_sets = list(telescope_sets.values()) if len(telescope_sets) > 1: return telescope_sets[0].intersection(*telescope_sets[1:]) else: return telescope_sets[0] if telescope_sets else set()