LSSTApplications  20.0.0
LSSTDataManagementBasePackage
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 import os.path
26 from dataclasses import dataclass
27 from typing import TYPE_CHECKING, Dict, Iterator, Optional, Tuple
28 
29 from lsst.log import Log
30 from lsst.log.utils import temporaryLogLevel
31 from lsst.daf.persistence import Butler as Butler2
32 from lsst.daf.butler import DatasetType, DatasetRef, DataCoordinate, FileDataset
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.skymap import BaseSkyMap
42  from lsst.daf.butler import StorageClass, FormatterParameter
43  from .cameraMapper import CameraMapper
44  from .repoWalker.scanner import PathElementHandler
45  from ..mapping import Mapping as CameraMapperMapping # disambiguate from collections.abc.Mapping
46 
47 
48 @dataclass
50  """Struct containing information about a SkyMap found in a Gen2 repository.
51  """
52 
53  name: str
54  """Name of the skymap used in Gen3 data IDs.
55  """
56 
57  instance: BaseSkyMap
58  """An instance of the actual skymap class.
59  """
60 
61  coaddName: str
62  """The coadd name used as a prefix for the dataset type this skymap was
63  found in.
64  """
65 
66  ref: DatasetRef
67  """A `DatasetRef` that can be used to ingest the skymap dataset into a
68  Gen3 repository.
69  """
70 
71  filename: str
72  """Name of the file containing the skymap dataset, relative to the
73  repository root.
74  """
75 
76 
78  """A specialization of `RepoConverter` for non-calibration repositories.
79 
80  Parameters
81  ----------
82  kwds
83  Keyword arguments are forwarded to (and required by) `RepoConverter`.
84  """
85 
86  def __init__(self, **kwds):
87  super().__init__(**kwds)
88  # Shush noisy log messages from Gen2 Mapper classes.
89  with temporaryLogLevel("CameraMapper", Log.ERROR):
90  with temporaryLogLevel("HscMapper", Log.ERROR):
91  self.butler2 = Butler2(self.root)
92  self.mapper = self.butler2.getMapperClass(self.root)(root=self.root)
93  self._foundSkyMapsByCoaddName = {}
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.task.log.info(f"Looking for skymaps in root {self.root}.")
102  for coaddName, datasetTypeName in SKYMAP_DATASET_TYPES.items():
103  if not self.task.isDatasetTypeIncluded(datasetTypeName):
104  continue
105  try:
106  exists = self.butler2.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.butler2.get(datasetTypeName)
113  name = self.task.useSkyMap(instance, datasetTypeName)
114  datasetType = DatasetType(datasetTypeName, dimensions=["skymap"],
115  storageClass="SkyMap", universe=self.task.universe)
116  dataId = DataCoordinate.standardize(skymap=name, universe=self.task.universe)
117  struct = FoundSkyMap(name=name, instance=instance, coaddName=coaddName,
118  ref=DatasetRef(datasetType, dataId),
119  filename=self.butler2.getUri(datasetTypeName))
120  self._foundSkyMapsByCoaddName[coaddName] = struct
121  self.task.log.info("Found skymap %s in %s in %s.", name, datasetTypeName, self.root)
122  super().prep()
123 
124  def iterMappings(self) -> Iterator[Tuple[str, CameraMapperMapping]]:
125  # Docstring inherited from RepoConverter.
126  for datasetTypeName, mapping in self.mapper.mappings.items():
127  if datasetTypeName not in self.mapper.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.get("deep")
148  for coaddName in SKYMAP_DATASET_TYPES.keys():
149  if coaddName in datasetTypeName:
150  try:
151  struct = self._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.task.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.root
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.findMatchingSkyMap(datasetTypeName)
174  return RepoWalker.Target(
175  datasetTypeName=datasetTypeName,
176  storageClass=storageClass,
177  template=template,
178  keys=keys,
179  universe=self.task.registry.dimensions,
180  instrument=self.task.instrument.getName(),
181  skyMap=skyMap,
182  skyMapName=skyMapName,
183  formatter=formatter,
184  targetHandler=targetHandler,
185  translatorFactory=self.task.translatorFactory,
186  )
187 
188  def iterDatasets(self) -> Iterator[FileDataset]:
189  # Docstring inherited from RepoConverter.
190  for struct in self._foundSkyMapsByCoaddName.values():
191  if self.task.isDatasetTypeIncluded(struct.ref.datasetType.name):
192  yield FileDataset(path=os.path.join(self.root, struct.filename), refs=struct.ref)
193  yield from super().iterDatasets()
194 
195  # Class attributes that will be shadowed by public instance attributes;
196  # defined here only for documentation purposes.
197 
198  butler2: Butler2
199  """Gen2 butler associated with this repository.
200  """
201 
202  mapper: CameraMapper
203  """Gen2 mapper associated with this repository.
204  """
lsst.obs.base.gen2to3.repoConverter.RepoConverter.root
root
Definition: repoConverter.py:207
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.__init__
def __init__(self, **kwds)
Definition: standardRepoConverter.py:86
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.iterDatasets
Iterator[FileDataset] iterDatasets(self)
Definition: standardRepoConverter.py:188
lsst.obs.base.gen2to3.standardRepoConverter.FoundSkyMap
Definition: standardRepoConverter.py:49
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter._foundSkyMapsByCoaddName
_foundSkyMapsByCoaddName
Definition: standardRepoConverter.py:93
lsst::log.utils
Definition: utils.py:1
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.iterMappings
Iterator[Tuple[str, CameraMapperMapping]] iterMappings(self)
Definition: standardRepoConverter.py:124
lsst.obs.base.gen2to3.repoConverter.RepoConverter.task
task
Definition: repoConverter.py:206
lsst::log
Definition: Log.h:706
lsst::log.utils.temporaryLogLevel
def temporaryLogLevel(name, level)
Definition: utils.py:49
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.findMatchingSkyMap
Tuple[Optional[BaseSkyMap], Optional[str]] findMatchingSkyMap(self, str datasetTypeName)
Definition: standardRepoConverter.py:130
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.isDatasetTypeSpecial
bool isDatasetTypeSpecial(self, str datasetTypeName)
Definition: standardRepoConverter.py:95
lsst.skymap
Definition: __init__.py:1
lsst::daf::persistence
Definition: Utils.h:50
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.makeRepoWalkerTarget
RepoWalker.Target makeRepoWalkerTarget(self, str datasetTypeName, str template, Dict[str, type] keys, StorageClass storageClass, FormatterParameter formatter=None, Optional[PathElementHandler] targetHandler=None)
Definition: standardRepoConverter.py:167
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter
Definition: standardRepoConverter.py:77
lsst.obs.base.gen2to3.repoConverter.RepoConverter
Definition: repoConverter.py:178
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.mapper
mapper
Definition: standardRepoConverter.py:92
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.prep
def prep(self)
Definition: standardRepoConverter.py:99
lsst.obs.base.gen2to3.standardRepoConverter.StandardRepoConverter.butler2
butler2
Definition: standardRepoConverter.py:91