class SkyRegion(pexConfig.Config): """Configuration for a proposal's sky region of interest. """ selections = pexConfig.ConfigDictField( 'A list of type selections for sky region determination.', int, Selection) combiners = pexConfig.ListField( 'A list of logical operations [and, or] that combine the region ' 'selections. Must be one less than the number of selections. If ' 'only one region, the list is left empty.', str) time_ranges = pexConfig.ConfigDictField( 'A collection of time ranges for sky region selection.', int, TimeRange, optional=True) selection_mapping = pexConfig.ConfigDictField( 'A collection of selection mapping arrays.', int, SelectionList, optional=True) def setDefaults(self): """Default specification for a sky region. """ self.combiners = []
class ReferenceSourceSelectorConfig(pexConfig.Config): doMagLimit = pexConfig.Field(dtype=bool, default=False, doc="Apply magnitude limit?") doFlags = pexConfig.Field(dtype=bool, default=False, doc="Apply flag limitation?") doUnresolved = pexConfig.Field(dtype=bool, default=False, doc="Apply unresolved limitation?") doSignalToNoise = pexConfig.Field(dtype=bool, default=False, doc="Apply signal-to-noise limit?") doMagError = pexConfig.Field(dtype=bool, default=False, doc="Apply magnitude error limit?") magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc="Magnitude limit to apply") flags = pexConfig.ConfigField(dtype=RequireFlags, doc="Flags to require") unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc="Star/galaxy separation to apply") signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc="Signal-to-noise limit to apply") magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc="Magnitude error limit to apply") colorLimits = pexConfig.ConfigDictField( keytype=str, itemtype=ColorLimit, default={}, doc="Color limits to apply; key is used as a label only")
class TransformMapConfig(pexConfig.Config): transforms = pexConfig.ConfigDictField( doc="Dict of coordinate system name: TransformConfig", keytype=str, itemtype=TransformConfig, ) nativeSys = pexConfig.Field( doc="Name of native coordinate system", dtype=str, optional=False, )
class MasterSubSequence(BaseSequence): """Configuration for master sub-sequences. """ name = pexConfig.Field('The identifier for the master sub-sequence.', str) sub_sequences = pexConfig.ConfigDictField('The set of nested sub-sequences for this master sub-sequence.', int, SubSequence) def setDefaults(self): """Default specification for MasterSubSequence information. """ BaseSequence.setDefaults(self)
class CameraConfig(pexConfig.Config): """!A configuration that represents (and can be used to construct) a Camera """ detectorList = pexConfig.ConfigDictField( "List of detector configs", keytype=int, itemtype=DetectorConfig) transformDict = pexConfig.ConfigField( "Dictionary of camera transforms keyed on the transform type.", TransformMapConfig) name = pexConfig.Field("Name of this camera", str) plateScale = pexConfig.Field( "Plate scale of the camera in arcsec/mm", float) # Note that the radial transform will also apply a scaling, so all coefficients should be # scaled by the plate scale in appropriate units radialCoeffs = pexConfig.ListField( "Coefficients for radial distortion", float)
class SkyExclusion(pexConfig.Config): """Configuration for a proposal's sky exclusions. """ dec_window = pexConfig.Field( 'Angle (units=degrees) around the observing site\'s latitude for which to ' 'create a Declination window for field selection.', float) selections = pexConfig.ConfigDictField( 'A list of type selections for sky exclusion ' 'determination. Currently, only GP is supported.', int, Selection) def setDefaults(self): """Default specification for a sky exclusions. """ self.dec_window = 90.0 self.selections = {}
class General(pexConfig.Config): """Configuration for a general proposal. This includes area distribution, time-domain and hybrid proposals. """ name = pexConfig.Field('Name for the proposal.', str) sky_region = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyRegion) sky_exclusion = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyExclusion) sky_nightly_bounds = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyNightlyBounds) sky_constraints = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyConstraints) filters = pexConfig.ConfigDictField( 'Filter configuration for the proposal.', str, GeneralBandFilter) scheduling = pexConfig.ConfigField( 'Scheduling configuration for the proposal.', GeneralScheduling) def proposal_fields(self, fd, fs): """Return the field Ids for this proposal. Parameters ---------- fd : lsst.sims.survey.fields.FieldsDatabase An instance of the fields database. fs : lsst.sims.survey.fields.FieldSelection An instance of the field selector. Returns ------- list[int] """ query_list = [] combine_list = [] region_cuts = [] # Handle any time dependent cuts try: num_selections = len(self.sky_region.selection_mapping) for i, mapping in self.sky_region.selection_mapping.items(): for index in mapping.indexes: region_cuts.append(self.sky_region.selections[index]) try: combine_list.append(self.sky_region.combiners[i]) except IndexError: # Don't have combiners, must be single selection per time range pass if i < num_selections - 1: combine_list.append("or") except TypeError: region_cuts = list(self.sky_region.selections.values()) combine_list.extend(self.sky_region.combiners) # Handle the sky region selections for cut in region_cuts: cut_type = cut.limit_type if cut_type != "GP": query_list.append( fs.select_region(cut_type, cut.minimum_limit, cut.maximum_limit)) else: query_list.append( fs.galactic_region(cut.maximum_limit, cut.minimum_limit, cut.bounds_limit)) # Handle the sky exclusion selections exclusion_query = None for cut in self.sky_exclusion.selections.values(): cut_type = cut.limit_type if cut_type == "GP": # Need the field Ids, so don't mark it as an exclusion exclusion_query = fs.galactic_region(cut.maximum_limit, cut.minimum_limit, cut.bounds_limit) query = fs.combine_queries(*query_list, combiners=combine_list) fields = fd.get_field_set(query) ids = set([x[0] for x in fields]) if exclusion_query is not None: equery = fs.combine_queries(exclusion_query) efields = fd.get_field_set(equery) eids = set([x[0] for x in efields]) ids.difference_update(eids) return sorted(list(ids)) def set_topic(self, topic): """Set the information on a DDS topic instance. Parameters ---------- topic : SALPY_scheduler.scheduler_generalPropConfigC The instance of the DDS topic to set information on. Returns ------- SALPY_scheduler.scheduler_generalPropConfigC The topic with current information set. """ topic.name = self.name if self.name is not None else "None" topic.twilightBoundary = self.sky_nightly_bounds.twilight_boundary topic.deltaLst = self.sky_nightly_bounds.delta_lst topic.decWindow = self.sky_exclusion.dec_window topic.maxAirmass = self.sky_constraints.max_airmass topic.maxCloud = self.sky_constraints.max_cloud topic.minDistanceMoon = self.sky_constraints.min_distance_moon topic.excludePlanets = self.sky_constraints.exclude_planets num_region_selections = len(self.sky_region.selections) \ if self.sky_region.selections is not None else 0 topic.numRegionSelections = num_region_selections if num_region_selections: limit_types = [] for i, v in enumerate(self.sky_region.selections.values()): limit_types.append(v.limit_type) topic.regionMinimums[i] = v.minimum_limit topic.regionMaximums[i] = v.maximum_limit topic.regionBounds[i] = v.bounds_limit topic.regionTypes = ','.join(limit_types) topic.regionCombiners = ','.join(self.sky_region.combiners) num_time_ranges = len( self.sky_region.time_ranges ) if self.sky_region.time_ranges is not None else 0 topic.numTimeRanges = num_time_ranges if num_time_ranges: for i, v in enumerate(self.sky_region.time_ranges.values()): topic.timeRangeStarts[i] = v.start topic.timeRangeEnds[i] = v.end num_selection_mappings = len(self.sky_region.selection_mapping) \ if self.sky_region.selection_mapping is not None else 0 if num_selection_mappings: selection_index = 0 for i, v in enumerate(self.sky_region.selection_mapping.values()): topic.numSelectionMappings[i] = len(v.indexes) for index in v.indexes: topic.selectionMappings[selection_index] = index selection_index += 1 num_exclusion_selections = len(self.sky_exclusion.selections) \ if self.sky_exclusion.selections is not None else 0 topic.numExclusionSelections = num_exclusion_selections if num_exclusion_selections: limit_types = [] for i, v in enumerate(self.sky_exclusion.selections.values()): limit_types.append(v.limit_type) topic.exclusionMinimums[i] = v.minimum_limit topic.exclusionMaximums[i] = v.maximum_limit topic.exclusionBounds[i] = v.bounds_limit topic.exclusionTypes = ','.join(limit_types) topic.numFilters = len(self.filters) if self.filters is not None else 0 if topic.numFilters: filter_names = [] exp_index = 0 for i, v in enumerate(self.filters.values()): filter_names.append(v.name) topic.numVisits[i] = v.num_visits topic.numGroupedVisits[i] = v.num_grouped_visits topic.maxGroupedVisits[i] = v.max_grouped_visits topic.brightLimit[i] = v.bright_limit topic.darkLimit[i] = v.dark_limit topic.maxSeeing[i] = v.max_seeing topic.numFilterExposures[i] = len(v.exposures) for exposure in v.exposures: topic.exposures[exp_index] = exposure exp_index += 1 topic.filterNames = ','.join(filter_names) topic.maxNumTargets = self.scheduling.max_num_targets topic.acceptSerendipity = self.scheduling.accept_serendipity topic.acceptConsecutiveVisits = self.scheduling.accept_consecutive_visits topic.airmassBonus = self.scheduling.airmass_bonus topic.hourAngleBonus = self.scheduling.hour_angle_bonus topic.hourAngleMax = self.scheduling.hour_angle_max topic.restrictGroupedVisits = self.scheduling.restrict_grouped_visits topic.timeInterval = self.scheduling.time_interval topic.timeWindowStart = self.scheduling.time_window_start topic.timeWindowMax = self.scheduling.time_window_max topic.timeWindowEnd = self.scheduling.time_window_end topic.timeWeight = self.scheduling.time_weight topic.fieldRevisitLimit = self.scheduling.field_revisit_limit return topic
class DiffMatchedTractCatalogConfig( pipeBase.PipelineTaskConfig, pipelineConnections=DiffMatchedTractCatalogConnections, ): column_matched_prefix_ref = pexConfig.Field( dtype=str, default='refcat_', doc='The prefix for matched columns copied from the reference catalog', ) column_ref_extended = pexConfig.Field( dtype=str, default='is_pointsource', doc='The boolean reference table column specifying if the target is extended', ) column_ref_extended_inverted = pexConfig.Field( dtype=bool, default=True, doc='Whether column_ref_extended specifies if the object is compact, not extended', ) column_target_extended = pexConfig.Field( dtype=str, default='refExtendedness', doc='The target table column estimating the extendedness of the object (0 <= x <= 1)', ) @property def columns_in_ref(self) -> Set[str]: columns_all = [self.coord_format.column_ref_coord1, self.coord_format.column_ref_coord2, self.column_ref_extended] for column_lists in ( ( self.columns_ref_copy, ), (x.columns_in_ref for x in self.columns_flux.values()), ): for column_list in column_lists: columns_all.extend(column_list) return set(columns_all) @property def columns_in_target(self) -> Set[str]: columns_all = [self.coord_format.column_target_coord1, self.coord_format.column_target_coord2, self.column_target_extended] if self.coord_format.coords_ref_to_convert is not None: columns_all.extend(self.coord_format.coords_ref_to_convert.values()) for column_lists in ( ( self.columns_target_coord_err, self.columns_target_select_false, self.columns_target_select_true, self.columns_target_copy, ), (x.columns_in_target for x in self.columns_flux.values()), ): for column_list in column_lists: columns_all.extend(column_list) return set(columns_all) columns_flux = pexConfig.ConfigDictField( keytype=str, itemtype=MatchedCatalogFluxesConfig, doc="Configs for flux columns for each band", ) columns_ref_copy = pexConfig.ListField( dtype=str, default=set(), doc='Reference table columns to copy to copy into cat_matched', ) columns_target_coord_err = pexConfig.ListField( dtype=str, listCheck=lambda x: (len(x) == 2) and (x[0] != x[1]), doc='Target table coordinate columns with standard errors (sigma)', ) columns_target_copy = pexConfig.ListField( dtype=str, default=('patch',), doc='Target table columns to copy to copy into cat_matched', ) columns_target_select_true = pexConfig.ListField( dtype=str, default=('detect_isPrimary',), doc='Target table columns to require to be True for selecting sources', ) columns_target_select_false = pexConfig.ListField( dtype=str, default=('merge_peak_sky',), doc='Target table columns to require to be False for selecting sources', ) coord_format = pexConfig.ConfigField( dtype=ConvertCatalogCoordinatesConfig, doc="Configuration for coordinate conversion", ) extendedness_cut = pexConfig.Field( dtype=float, default=0.5, doc='Minimum extendedness for a measured source to be considered extended', ) mag_num_bins = pexConfig.Field( doc='Number of magnitude bins', default=15, dtype=int, ) mag_brightest_ref = pexConfig.Field( dtype=float, default=15, doc='Brightest magnitude cutoff for binning', ) mag_ceiling_target = pexConfig.Field( dtype=float, default=None, optional=True, doc='Ceiling (maximum/faint) magnitude for target sources', ) mag_faintest_ref = pexConfig.Field( dtype=float, default=30, doc='Faintest magnitude cutoff for binning', ) mag_zeropoint_ref = pexConfig.Field( dtype=float, default=31.4, doc='Magnitude zeropoint for reference sources', ) mag_zeropoint_target = pexConfig.Field( dtype=float, default=31.4, doc='Magnitude zeropoint for target sources', ) percentiles = pexConfig.ListField( dtype=str, # -2, -1, +1, +2 sigma percentiles for normal distribution default=('2.275', '15.866', '84.134', '97.725'), doc='Percentiles to compute for diff/chi values', itemCheck=is_percentile, listCheck=is_sequence_set, )
class BadItemCheck(pexConfig.Config): d = pexConfig.ConfigDictField("...", keytype=str, itemtype=Config1, itemCheck=4)
class BadItemtype(pexConfig.Config): d = pexConfig.ConfigDictField("...", keytype=int, itemtype=dict)
class BadKeytype(pexConfig.Config): d = pexConfig.ConfigDictField("...", keytype=list, itemtype=Config1)
class Config3(pexConfig.Config): field1 = pexConfig.ConfigDictField(keytype=str, itemtype=pexConfig.Config, default={}, doc='doc')
class Config2(pexConfig.Config): d1 = pexConfig.ConfigDictField("d1", keytype=str, itemtype=Config1, itemCheck=lambda x: x.f > 0)
class Sequence(pexConfig.Config): """Configuration for a sequence proposal. This includes sequence, sub-sequence and nested sub-sequence proposals. """ name = pexConfig.Field('Name for the proposal.', str) sky_user_regions = pexConfig.ListField( 'Sky user regions for the proposal as a list of field Ids.', int) sky_exclusion = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyExclusion) sky_nightly_bounds = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyNightlyBounds) sky_constraints = pexConfig.ConfigField( 'Sky region selection for the proposal.', SkyConstraints) sub_sequences = pexConfig.ConfigDictField('Set of sub-sequences.', int, SubSequence) master_sub_sequences = pexConfig.ConfigDictField( 'Set of master sub-sequences.', int, MasterSubSequence) filters = pexConfig.ConfigDictField( 'Filter configuration for the proposal.', str, BandFilter) scheduling = pexConfig.ConfigField( 'Scheduling configuration for the proposal.', SequenceScheduling) def setDefaults(self): """Default specification for a sequence proposal. """ self.sky_user_regions = [] self.sub_sequences = {} self.master_sub_sequences = {} def proposal_fields(self): """Return the list of field Ids for this proposal. Returns ------- list[int] """ return sorted(self.sky_user_regions) def set_topic(self, topic): """Set the information on a DDS topic instance. Parameters ---------- topic : SALPY_scheduler.scheduler_sequencePropConfigC The instance of the DDS topic to set information on. Returns ------- SALPY_scheduler.scheduler_sequencePropConfigC The topic with current information set. """ topic.name = self.name if self.name is not None else "None" topic.twilight_boundary = self.sky_nightly_bounds.twilight_boundary topic.delta_lst = self.sky_nightly_bounds.delta_lst topic.dec_window = self.sky_exclusion.dec_window topic.max_airmass = self.sky_constraints.max_airmass topic.max_cloud = self.sky_constraints.max_cloud topic.min_distance_moon = self.sky_constraints.min_distance_moon topic.exclude_planets = self.sky_constraints.exclude_planets num_sky_user_regions = len(self.sky_user_regions) topic.num_user_regions = num_sky_user_regions for i, sky_user_region in enumerate(self.sky_user_regions): topic.user_region_ids[i] = sky_user_region num_sub_sequences = len( self.sub_sequences) if self.sub_sequences is not None else 0 topic.num_sub_sequences = num_sub_sequences if topic.num_sub_sequences: sub_sequence_names = [] sub_sequence_filters = [] filter_visit_index = 0 for i, sub_sequence in self.sub_sequences.items(): sub_sequence_names.append(sub_sequence.name) sub_sequence_filters.append(sub_sequence.get_filter_string()) topic.num_sub_sequence_filters[i] = len(sub_sequence.filters) for filter_visit in sub_sequence.visits_per_filter: topic.num_sub_sequence_filter_visits[ filter_visit_index] = filter_visit filter_visit_index += 1 topic.num_sub_sequence_events[i] = sub_sequence.num_events topic.num_sub_sequence_max_missed[ i] = sub_sequence.num_max_missed topic.sub_sequence_time_intervals[ i] = sub_sequence.time_interval topic.sub_sequence_time_window_starts[ i] = sub_sequence.time_window_start topic.sub_sequence_time_window_maximums[ i] = sub_sequence.time_window_max topic.sub_sequence_time_window_ends[ i] = sub_sequence.time_window_end topic.sub_sequence_time_weights[i] = sub_sequence.time_weight topic.sub_sequence_names = ",".join(sub_sequence_names) topic.sub_sequence_filters = ",".join(sub_sequence_filters) num_master_sub_sequences = len(self.master_sub_sequences) \ if self.master_sub_sequences is not None else 0 topic.num_master_sub_sequences = num_master_sub_sequences if topic.num_master_sub_sequences: master_sub_sequence_names = [] nested_sub_sequence_names = [] nested_sub_sequence_filters = [] nss_index = 0 filter_visit_index = 0 for i, master_sub_sequence in self.master_sub_sequences.items(): master_sub_sequence_names.append(master_sub_sequence.name) topic.num_nested_sub_sequences[i] = len( master_sub_sequence.sub_sequences) topic.num_master_sub_sequence_events[ i] = master_sub_sequence.num_events topic.num_master_sub_sequence_max_missed[ i] = master_sub_sequence.num_max_missed topic.master_sub_sequence_time_intervals[ i] = master_sub_sequence.time_interval topic.master_sub_sequence_time_window_starts[ i] = master_sub_sequence.time_window_start topic.master_sub_sequence_time_window_maximums[ i] = master_sub_sequence.time_window_max topic.master_sub_sequence_time_window_ends[ i] = master_sub_sequence.time_window_end topic.master_sub_sequence_time_weights[ i] = master_sub_sequence.time_weight for sub_sequence in master_sub_sequence.sub_sequences.values(): nested_sub_sequence_names.append(sub_sequence.name) nested_sub_sequence_filters.append( sub_sequence.get_filter_string()) topic.num_nested_sub_sequence_filters[nss_index] = len( sub_sequence.filters) for filter_visit in sub_sequence.visits_per_filter: topic.num_nested_sub_sequence_filter_visits[ filter_visit_index] = filter_visit filter_visit_index += 1 topic.num_nested_sub_sequence_events[ nss_index] = sub_sequence.num_events topic.num_nested_sub_sequence_max_missed[ nss_index] = sub_sequence.num_max_missed topic.nested_sub_sequence_time_intervals[ nss_index] = sub_sequence.time_interval topic.nested_sub_sequence_time_window_starts[ nss_index] = sub_sequence.time_window_start topic.nested_sub_sequence_time_window_maximums[ nss_index] = sub_sequence.time_window_max topic.nested_sub_sequence_time_window_ends[ nss_index] = sub_sequence.time_window_end topic.nested_sub_sequence_time_weights[ nss_index] = sub_sequence.time_weight nss_index += 1 topic.master_sub_sequence_names = ",".join( master_sub_sequence_names) topic.nested_sub_sequence_names = ",".join( nested_sub_sequence_names) topic.nested_sub_sequence_filters = ",".join( nested_sub_sequence_filters) topic.num_filters = len( self.filters) if self.filters is not None else 0 if topic.num_filters: filter_names = [] exp_index = 0 for i, v in enumerate(self.filters.values()): filter_names.append(v.name) topic.bright_limit[i] = v.bright_limit topic.dark_limit[i] = v.dark_limit topic.max_seeing[i] = v.max_seeing topic.num_filter_exposures[i] = len(v.exposures) for exposure in v.exposures: topic.exposures[exp_index] = exposure exp_index += 1 topic.filter_names = ','.join(filter_names) topic.max_num_targets = self.scheduling.max_num_targets topic.accept_serendipity = self.scheduling.accept_serendipity topic.accept_consecutive_visits = self.scheduling.accept_consecutive_visits topic.airmass_bonus = self.scheduling.airmass_bonus topic.hour_angle_bonus = self.scheduling.hour_angle_bonus topic.hour_angle_max = self.scheduling.hour_angle_max topic.restart_lost_sequences = self.scheduling.restart_lost_sequences topic.restart_complete_sequences = self.scheduling.restart_complete_sequences topic.max_visits_goal = self.scheduling.max_visits_goal return topic