21 from __future__
import annotations
23 __all__ = [
"CalibRepoConverter"]
27 from datetime
import datetime, timedelta
28 from typing
import TYPE_CHECKING, Iterator, Tuple
30 from .repoConverter
import RepoConverter
31 from .dataIdExtractor
import DataIdExtractor
32 from .translators
import makeCalibrationLabel
35 from lsst.daf.butler
import StorageClass
36 from ..cameraMapper
import CameraMapper
37 from ..mapping
import Mapping
as CameraMapperMapping
38 from .filePathParser
import FilePathParser
40 CURATED_CALIBRATION_DATASET_TYPES = (
43 "transmission_sensor",
44 "transmission_filter",
45 "transmission_optics",
46 "transmission_atmosphere",
52 """A specialization of `RepoConverter` for calibration repositories. 56 mapper : `CameraMapper` 57 Gen2 mapper for the data repository. The root associated with the 58 mapper is ignored and need not match the root of the repository. 60 Additional keyword arguments are forwarded to (and required by) 64 def __init__(self, *, mapper: CameraMapper, **kwds):
71 return datasetTypeName
in CURATED_CALIBRATION_DATASET_TYPES
77 def iterMappings(self) -> Iterator[Tuple[str, CameraMapperMapping]]:
79 yield from self.
mapper.calibrations.items()
82 storageClass: StorageClass) -> DataIdExtractor:
87 filePathParser=parser,
88 universe=self.
task.universe,
89 instrument=self.
task.instrument.getName(),
99 db = sqlite3.connect(os.path.join(self.
root,
"calibRegistry.sqlite3"))
100 db.row_factory = sqlite3.Row
103 if "calibration_label" not in datasetType.dimensions:
105 fields = [
"validStart",
"validEnd",
"calibDate"]
106 if "detector" in datasetType.dimensions.names:
107 fields.append(self.
task.config.ccdKey)
109 fields.append(f
"NULL AS {self.task.config.ccdKey}")
110 if "physical_filter" in datasetType.dimensions.names:
111 fields.append(
"filter")
113 fields.append(
"NULL AS filter")
114 query = f
"SELECT DISTINCT {', '.join(fields)} FROM {datasetType.name};" 116 results = db.execute(query)
117 except sqlite3.OperationalError:
118 self.
task.log.warn(
"Could not extract calibration ranges for %s in %s.",
119 datasetType.name, self.
root)
123 ccd=row[self.
task.config.ccdKey], filter=row[
"filter"])
125 "instrument": self.
task.instrument.getName(),
127 "datetime_begin": datetime.strptime(row[
"validStart"],
"%Y-%m-%d"),
128 "datetime_end": datetime.strptime(row[
"validEnd"],
"%Y-%m-%d") + timedelta(days=1),
131 self.
task.registry.insertDimensionData(
"calibration_label", *records)
135 if self.
task.config.doWriteCuratedCalibrations:
136 for datasetTypeName
in CURATED_CALIBRATION_DATASET_TYPES:
137 if not self.
task.isDatasetTypeIncluded(datasetTypeName):
138 raise ValueError(f
"doWriteCuratedCalibrations is True but " 139 f
"{datasetTypeName} is configured to be ignored.")
141 butler3, collections = self.
getButler(
None)
142 except LookupError
as err:
143 raise ValueError(
"Cannot ingest curated calibration into a calibration repo with no " 144 "collections of its own; skipping.")
from err
147 assert not collections,
"Multiple collections for curated calibrations is not yet supported." 148 self.
task.instrument.writeCuratedCalibrations(butler3)
155 """Gen2 mapper associated with this repository.
def insertDimensionData(self)