LSST Applications  21.0.0+75b29a8a7f,21.0.0+e70536a077,21.0.0-1-ga51b5d4+62c747d40b,21.0.0-10-gbfb87ad6+3307648ee3,21.0.0-15-gedb9d5423+47cba9fc36,21.0.0-2-g103fe59+fdf0863a2a,21.0.0-2-g1367e85+d38a93257c,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g5242d73+d38a93257c,21.0.0-2-g7f82c8f+e682ffb718,21.0.0-2-g8dde007+d179fbfa6a,21.0.0-2-g8f08a60+9402881886,21.0.0-2-ga326454+e682ffb718,21.0.0-2-ga63a54e+08647d4b1b,21.0.0-2-gde069b7+26c92b3210,21.0.0-2-gecfae73+0445ed2f95,21.0.0-2-gfc62afb+d38a93257c,21.0.0-27-gbbd0d29+ae871e0f33,21.0.0-28-g5fc5e037+feb0e9397b,21.0.0-3-g21c7a62+f4b9c0ff5c,21.0.0-3-g357aad2+57b0bddf0b,21.0.0-3-g4be5c26+d38a93257c,21.0.0-3-g65f322c+3f454acf5d,21.0.0-3-g7d9da8d+75b29a8a7f,21.0.0-3-gaa929c8+9e4ef6332c,21.0.0-3-ge02ed75+4b120a55c4,21.0.0-4-g3300ddd+e70536a077,21.0.0-4-g591bb35+4b120a55c4,21.0.0-4-gc004bbf+4911b9cd27,21.0.0-4-gccdca77+f94adcd104,21.0.0-4-ge8fba5a+2b3a696ff9,21.0.0-5-gb155db7+2c5429117a,21.0.0-5-gdf36809+637e4641ee,21.0.0-6-g00874e7+c9fd7f7160,21.0.0-6-g4e60332+4b120a55c4,21.0.0-7-gc8ca178+40eb9cf840,21.0.0-8-gfbe0b4b+9e4ef6332c,21.0.0-9-g2fd488a+d83b7cd606,w.2021.05
LSST Data Management Base Package
standardRepoConverter.py
Go to the documentation of this file.
1 # This file is part of obs_base.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 from __future__ import annotations
22 
23 __all__ = ["StandardRepoConverter"]
24 
25 from dataclasses import dataclass
26 from typing import TYPE_CHECKING, Dict, Iterator, List, Mapping, Optional, Tuple
27 
28 from lsst.log import Log
29 from lsst.log.utils import temporaryLogLevel
30 from lsst.daf.persistence import Butler as Butler2
31 from lsst.daf.butler import DatasetType, DatasetRef, DataCoordinate, FileDataset
32 from lsst.skymap import BaseSkyMap
33 from .repoConverter import RepoConverter
34 from .repoWalker import RepoWalker
35 
36 SKYMAP_DATASET_TYPES = {
37  coaddName: f"{coaddName}Coadd_skyMap" for coaddName in ("deep", "goodSeeing", "dcr")
38 }
39 
40 if TYPE_CHECKING:
41  from lsst.daf.butler import StorageClass, FormatterParameter
42  from .cameraMapper import CameraMapper
43  from .repoWalker.scanner import PathElementHandler
44  from ..mapping import Mapping as CameraMapperMapping # disambiguate from collections.abc.Mapping
45 
46 
47 @dataclass
49  """Struct containing information about a SkyMap found in a Gen2 repository.
50  """
51 
52  name: str
53  """Name of the skymap used in Gen3 data IDs.
54  """
55 
56  instance: BaseSkyMap
57  """An instance of the actual skymap class.
58  """
59 
60  coaddName: str
61  """The coadd name used as a prefix for the dataset type this skymap was
62  found in.
63  """
64 
65  ref: DatasetRef
66  """A `DatasetRef` that can be used to ingest the skymap dataset into a
67  Gen3 repository.
68  """
69 
70  filename: str
71  """Name of the file containing the skymap dataset, relative to the
72  repository root.
73  """
74 
75 
77  """A specialization of `RepoConverter` for non-calibration repositories.
78 
79  Parameters
80  ----------
81  kwds
82  Keyword arguments are forwarded to (and required by) `RepoConverter`.
83  """
84 
85  def __init__(self, **kwds):
86  super().__init__(**kwds)
87  # Shush noisy log messages from Gen2 Mapper classes.
88  with temporaryLogLevel("CameraMapper", Log.ERROR):
89  with temporaryLogLevel("HscMapper", Log.ERROR):
90  self.butler2butler2 = Butler2(self.rootroot)
91  self.mappermapper = self.butler2butler2.getMapperClass(self.rootroot)(root=self.rootroot)
92  self._foundSkyMapsByCoaddName_foundSkyMapsByCoaddName = {}
93  self._chain_chain = []
94 
95  def isDatasetTypeSpecial(self, datasetTypeName: str) -> bool:
96  # Docstring inherited from RepoConverter.
97  return datasetTypeName in SKYMAP_DATASET_TYPES.values()
98 
99  def prep(self):
100  # Docstring inherited from RepoConverter.
101  self.tasktask.log.info(f"Looking for skymaps in root {self.root}.")
102  for coaddName, datasetTypeName in SKYMAP_DATASET_TYPES.items():
103  if not self.tasktask.isDatasetTypeIncluded(datasetTypeName):
104  continue
105  try:
106  exists = self.butler2butler2.datasetExists(datasetTypeName)
107  except AttributeError:
108  # This mapper doesn't even define this dataset type.
109  continue
110  if not exists:
111  continue
112  instance = self.butler2butler2.get(datasetTypeName)
113  name = self.tasktask.useSkyMap(instance, datasetTypeName)
114  datasetType = DatasetType(datasetTypeName, dimensions=["skymap"],
115  storageClass="SkyMap", universe=self.tasktask.universe)
116  dataId = DataCoordinate.standardize(skymap=name, universe=self.tasktask.universe)
117  struct = FoundSkyMap(name=name, instance=instance, coaddName=coaddName,
118  ref=DatasetRef(datasetType, dataId),
119  filename=self.butler2butler2.getUri(datasetTypeName))
120  self._foundSkyMapsByCoaddName_foundSkyMapsByCoaddName[coaddName] = struct
121  self.tasktask.log.info("Found skymap %s in %s in %s.", name, datasetTypeName, self.rootroot)
122  super().prep()
123 
124  def iterMappings(self) -> Iterator[Tuple[str, CameraMapperMapping]]:
125  # Docstring inherited from RepoConverter.
126  for datasetTypeName, mapping in self.mappermapper.mappings.items():
127  if datasetTypeName not in self.mappermapper.calibrations:
128  yield datasetTypeName, mapping
129 
130  def findMatchingSkyMap(self, datasetTypeName: str) -> Tuple[Optional[BaseSkyMap], Optional[str]]:
131  """Return the appropriate SkyMap for the given dataset type.
132 
133  Parameters
134  ----------
135  datasetTypeName : `str`
136  Name of the dataset type for which a skymap is sought.
137 
138  Returns
139  -------
140  skyMap : `BaseSkyMap` or `None`
141  The `BaseSkyMap` instance, or `None` if there was no match.
142  skyMapName : `str` or `None`
143  The Gen3 name for the SkyMap, or `None` if there was no match.
144  """
145  # Use deepCoadd_skyMap by default; there are some dataset types
146  # that use it but don't have "deep" anywhere in their name.
147  struct = self._foundSkyMapsByCoaddName_foundSkyMapsByCoaddName.get("deep")
148  for coaddName in SKYMAP_DATASET_TYPES.keys():
149  if coaddName in datasetTypeName:
150  try:
151  struct = self._foundSkyMapsByCoaddName_foundSkyMapsByCoaddName[coaddName]
152  break
153  except KeyError:
154  # Don't use the default, since we did find a specific
155  # coaddName.
156  struct = None
157  self.tasktask.log.debug(
158  ("Dataset %s looks like it might need a skymap, but no %sCoadd_skyMap "
159  "found in repo %s."),
160  datasetTypeName, coaddName, self.rootroot
161  )
162  if struct is not None:
163  return struct.instance, struct.name
164  else:
165  return None, None
166 
167  def makeRepoWalkerTarget(self, datasetTypeName: str, template: str, keys: Dict[str, type],
168  storageClass: StorageClass,
169  formatter: FormatterParameter = None,
170  targetHandler: Optional[PathElementHandler] = None,
171  ) -> RepoWalker.Target:
172  # Docstring inherited from RepoConverter.
173  skyMap, skyMapName = self.findMatchingSkyMapfindMatchingSkyMap(datasetTypeName)
174  return RepoWalker.Target(
175  datasetTypeName=datasetTypeName,
176  storageClass=storageClass,
177  template=template,
178  keys=keys,
179  universe=self.tasktask.registry.dimensions,
180  instrument=self.tasktask.instrument.getName(),
181  skyMap=skyMap,
182  skyMapName=skyMapName,
183  formatter=formatter,
184  targetHandler=targetHandler,
185  translatorFactory=self.tasktask.translatorFactory,
186  )
187 
188  def iterDatasets(self) -> Iterator[FileDataset]:
189  # Docstring inherited from RepoConverter.
190  yield from super().iterDatasets()
191 
192  def getRun(self, datasetTypeName: str, calibDate: Optional[str] = None) -> str:
193  # Docstring inherited from RepoConverter.
194  run = self.tasktask.config.runsForced.get(datasetTypeName)
195  if run is None:
196  if self._run_run is not None:
197  run = self._run_run
198  else:
199  run = self.tasktask.config.runs.get(datasetTypeName)
200  if run is None:
201  raise ValueError(f"No default run for repo at {self.root}, and no "
202  f"override for dataset {datasetTypeName}.")
203  if run not in self._chain_chain:
204  self._chain_chain.append(run)
205  return run
206 
207  def getCollectionChain(self) -> List[str]:
208  """Return run names that can be used to construct a chained collection
209  that refers to the converted repository (`list` [ `str` ]).
210  """
211  return self._chain_chain
212 
213  def _finish(self, datasets: Mapping[DatasetType, Mapping[Optional[str], List[FileDataset]]]):
214  # Docstring inherited from RepoConverter.
215  super()._finish(datasets)
216  if self._foundSkyMapsByCoaddName_foundSkyMapsByCoaddName:
217  self._chain_chain.append(BaseSkyMap.SKYMAP_RUN_COLLECTION_NAME)
218 
219  # Class attributes that will be shadowed by public instance attributes;
220  # defined here only for documentation purposes.
221 
222  butler2: Butler2
223  """Gen2 butler associated with this repository.
224  """
225 
226  mapper: CameraMapper
227  """Gen2 mapper associated with this repository.
228  """
Tuple[Optional[BaseSkyMap], Optional[str]] findMatchingSkyMap(self, str datasetTypeName)
Iterator[Tuple[str, CameraMapperMapping]] iterMappings(self)
str getRun(self, str datasetTypeName, Optional[str] calibDate=None)
RepoWalker.Target makeRepoWalkerTarget(self, str datasetTypeName, str template, Dict[str, type] keys, StorageClass storageClass, FormatterParameter formatter=None, Optional[PathElementHandler] targetHandler=None)
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
Definition: functional.cc:33
def temporaryLogLevel(name, level)
Definition: utils.py:49
Definition: Log.h:706