21 from __future__
import annotations
23 __all__ = [
"RootRepoConverter"]
28 from typing
import TYPE_CHECKING, Iterator, Optional, Tuple, List, Set
30 from lsst.skymap
import BaseSkyMap
31 from lsst.daf.butler
import DatasetType, DatasetRef, FileDataset
32 from .standardRepoConverter
import StandardRepoConverter
34 SKYMAP_DATASET_TYPES = {
35 coaddName: f
"{coaddName}Coadd_skyMap" for coaddName
in (
"deep",
"goodSeeing",
"dcr")
39 from lsst.daf.butler
import SkyPixDimension
40 from ..ingest
import RawExposureData
44 """Strip HDU identifiers from paths and return a unique set of paths. 48 dataRefs : `lsst.daf.persistence.ButlerDataRef` 49 The gen2 datarefs to strip "[HDU]" values from. 54 The unique file paths without appended "[HDU]". 57 for dataRef
in dataRefs:
58 path = dataRef.getUri()
60 paths.add(path.split(
'[')[0])
65 """A specialization of `RepoConverter` for root data repositories. 67 `RootRepoConverter` adds support for raw images (mostly delegated to the 68 parent task's `RawIngestTask` subtask) and reference catalogs. 73 Keyword arguments are forwarded to (and required by) `RepoConverter`. 78 self._exposureData: List[RawExposureData] = []
79 self._refCats: List[Tuple[str, SkyPixDimension]] = []
80 if self.
task.config.rootSkyMapName
is not None:
90 or datasetTypeName
in (
"raw",
"ref_cat",
"ref_cat_config")
92 or datasetTypeName
in self.
task.config.curatedCalibrations
99 def findMatchingSkyMap(self, datasetTypeName: str) -> Tuple[Optional[BaseSkyMap], Optional[str]]:
102 if skyMap
is None and self.
task.config.rootSkyMapName
is not None:
104 (
"Assuming configured root skymap with name '%s' for dataset %s."),
105 self.
task.config.rootSkyMapName, datasetTypeName
108 name = self.
task.config.rootSkyMapName
114 if self.
task.raws
is not None:
115 self.
task.log.info(f
"Preparing raws from root {self.root}.")
116 if self.
subset is not None:
117 dataRefs = itertools.chain.from_iterable(
119 visit=visit)
for visit
in self.
subset.visits
124 self.
task.log.debug(
"Prepping files: %s", dataPaths)
125 self._exposureData.extend(self.
task.raws.prep(dataPaths))
127 if self.
task.isDatasetTypeIncluded(
"ref_cat")
and len(self.
task.config.refCats) != 0:
128 from lsst.meas.algorithms
import DatasetConfig
as RefCatDatasetConfig
129 for refCat
in os.listdir(os.path.join(self.
root,
"ref_cats")):
130 path = os.path.join(self.
root,
"ref_cats", refCat)
131 configFile = os.path.join(path,
"config.py")
132 if not os.path.exists(configFile):
134 if refCat
not in self.
task.config.refCats:
136 self.
task.log.info(f
"Preparing ref_cat {refCat} from root {self.root}.")
137 onDiskConfig = RefCatDatasetConfig()
138 onDiskConfig.load(configFile)
139 if onDiskConfig.indexer.name !=
"HTM":
140 raise ValueError(f
"Reference catalog '{refCat}' uses unsupported " 141 f
"pixelization '{onDiskConfig.indexer.name}'.")
142 level = onDiskConfig.indexer[
"HTM"].depth
144 dimension = self.
task.universe[f
"htm{level}"]
145 except KeyError
as err:
146 raise ValueError(f
"Reference catalog {refCat} uses HTM level {level}, but no htm{level} " 147 f
"skypix dimension is configured for this registry.")
from err
148 self.
task.useSkyPix(dimension)
149 self._refCats.append((refCat, dimension))
150 if self.
task.isDatasetTypeIncluded(
"brightObjectMask")
and self.
task.config.rootSkyMapName:
156 self.
task.log.info(f
"Inserting observation dimension records from {self.root}.")
157 records = {
"visit": [],
"exposure": [],
"visit_detector_region": []}
158 for exposure
in self._exposureData:
159 for dimension, recordsForDimension
in exposure.records.items():
160 records[dimension].extend(recordsForDimension)
161 self.
task.raws.insertDimensionData(records)
166 for refCat, dimension
in self._refCats:
167 datasetType = DatasetType(refCat, dimensions=[dimension], universe=self.
task.universe,
168 storageClass=
"SimpleCatalog")
170 regex = re.compile(
r"(\d+)\.fits")
171 for fileName
in os.listdir(os.path.join(self.
root,
"ref_cats", refCat)):
172 m = regex.match(fileName)
174 htmId = int(m.group(1))
175 dataId = self.
task.registry.expandDataId({dimension: htmId})
176 yield FileDataset(path=os.path.join(self.
root,
"ref_cats", refCat, fileName),
177 refs=DatasetRef(datasetType, dataId))
179 for begin, end
in self.
subset.skypix[dimension]:
180 for htmId
in range(begin, end):
181 dataId = self.
task.registry.expandDataId({dimension: htmId})
182 yield FileDataset(path=os.path.join(self.
root,
"ref_cats", refCat, f
"{htmId}.fits"),
183 refs=DatasetRef(datasetType, dataId))
189 if self.
task.raws
is not None:
190 self.
task.log.info(
"Ingesting raws from root %s into run %s.", self.
root,
191 self.
task.raws.butler.run)
192 self.
task.registry.registerDatasetType(self.
task.raws.datasetType)
193 self.
_chain.setdefault(self.
task.raws.butler.run, set()).add(self.
task.raws.datasetType.name)
198 for exposure
in self._exposureData:
199 self.
task.raws.ingestExposureDatasets(exposure)
202 def getRun(self, datasetTypeName: str) -> str:
204 run = self.
task.config.runs[datasetTypeName]
205 self.
_chain.setdefault(run, set()).add(datasetTypeName)
209 """Return tuples of run name and associated dataset type names that 210 can be used to construct a chained collection that refers to the 211 converted root repository (`list` [ `tuple` ]). 213 return list(self.
_chain.items())
def insertDimensionData(self)
def getCollectionChain(self)
def getDataPaths(dataRefs)
def getSpecialDirectories(self)