22 __all__ = (
"Instrument",
"makeExposureRecordFromObsInfo",
"makeVisitRecordFromObsInfo",
23 "addUnboundedCalibrationLabel")
26 from datetime
import datetime
27 from abc
import ABCMeta, abstractmethod
31 """Base class for instrument-specific logic for the Gen3 Butler.
33 Concrete instrument subclasses should be directly constructable with no
38 """Paths to config files to read for specific Tasks.
40 The paths in this list should contain files of the form `task.py`, for
41 each of the Tasks that requires special configuration.
47 """`~lsst.obs.base.FilterDefinitionCollection`, defining the filters
59 raise NotImplementedError()
63 """Retrieve the cameraGeom representation of this instrument.
65 This is a temporary API that should go away once obs_ packages have
66 a standardized approach to writing versioned cameras to a Gen3 repo.
68 raise NotImplementedError()
72 """Insert instrument, physical_filter, and detector entries into a
75 raise NotImplementedError()
77 def _registerFilters(self, registry):
78 """Register the physical and abstract filter Dimension relationships.
79 This should be called in the ``register`` implementation.
83 registry : `lsst.daf.butler.core.Registry`
84 The registry to add dimensions to.
88 if filter.abstract_filter
is None:
89 abstract_filter = filter.physical_filter
91 abstract_filter = filter.abstract_filter
93 registry.insertDimensionData(
"physical_filter",
95 "name": filter.physical_filter,
96 "abstract_filter": abstract_filter
101 """Return the Formatter class that should be used to read a particular
106 dataId : `DataCoordinate`
107 Dimension-based ID for the raw file or files being ingested.
111 formatter : `Formatter` class
112 Class to be used that reads the file into an
113 `lsst.afw.image.Exposure` instance.
115 raise NotImplementedError()
119 """Write human-curated calibration Datasets to the given Butler with
120 the appropriate validity ranges.
122 This is a temporary API that should go away once obs_ packages have
123 a standardized approach to this problem.
125 raise NotImplementedError()
128 """Apply instrument-specific overrides for a task config.
133 Name of the object being configured; typically the _DefaultName
135 config : `lsst.pex.config.Config`
136 Config instance to which overrides should be applied.
139 path = os.path.join(root, f
"{name}.py")
140 if os.path.exists(path):
145 """Construct an exposure DimensionRecord from
146 `astro_metadata_translator.ObservationInfo`.
150 obsInfo : `astro_metadata_translator.ObservationInfo`
151 A `~astro_metadata_translator.ObservationInfo` object corresponding to
153 universe : `DimensionUniverse`
154 Set of all known dimensions.
158 record : `DimensionRecord`
159 A record containing exposure metadata, suitable for insertion into
162 dimension = universe[
"exposure"]
163 return dimension.RecordClass.fromDict({
164 "instrument": obsInfo.instrument,
165 "id": obsInfo.exposure_id,
166 "name": obsInfo.observation_id,
167 "datetime_begin": obsInfo.datetime_begin.to_datetime(),
168 "datetime_end": obsInfo.datetime_end.to_datetime(),
169 "exposure_time": obsInfo.exposure_time.to_value(
"s"),
170 "dark_time": obsInfo.dark_time.to_value(
"s"),
171 "observation_type": obsInfo.observation_type,
172 "physical_filter": obsInfo.physical_filter,
173 "visit": obsInfo.visit_id,
178 """Construct a visit `DimensionRecord` from
179 `astro_metadata_translator.ObservationInfo`.
183 obsInfo : `astro_metadata_translator.ObservationInfo`
184 A `~astro_metadata_translator.ObservationInfo` object corresponding to
186 universe : `DimensionUniverse`
187 Set of all known dimensions.
188 region : `lsst.sphgeom.Region`, optional
189 Spatial region for the visit.
193 record : `DimensionRecord`
194 A record containing visit metadata, suitable for insertion into a
197 dimension = universe[
"visit"]
198 return dimension.RecordClass.fromDict({
199 "instrument": obsInfo.instrument,
200 "id": obsInfo.visit_id,
201 "name": obsInfo.observation_id,
202 "datetime_begin": obsInfo.datetime_begin.to_datetime(),
203 "datetime_end": obsInfo.datetime_end.to_datetime(),
204 "exposure_time": obsInfo.exposure_time.to_value(
"s"),
205 "physical_filter": obsInfo.physical_filter,
211 """Add a special 'unbounded' calibration_label dimension entry for the
212 given camera that is valid for any exposure.
214 If such an entry already exists, this function just returns a `DataId`
215 for the existing entry.
219 registry : `Registry`
220 Registry object in which to insert the dimension entry.
221 instrumentName : `str`
222 Name of the instrument this calibration label is associated with.
227 New or existing data ID for the unbounded calibration.
229 d = dict(instrument=instrumentName, calibration_label=
"unbounded")
231 return registry.expandDataId(d)
235 entry[
"datetime_begin"] = datetime.min
236 entry[
"datetime_end"] = datetime.max
237 registry.insertDimensionData(
"calibration_label", entry)
238 return registry.expandDataId(d)