LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
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, Iterator, 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 .filePathParser import FilePathParser
35 from .dataIdExtractor import DataIdExtractor
36 
37 SKYMAP_DATASET_TYPES = {
38  coaddName: f"{coaddName}Coadd_skyMap" for coaddName in ("deep", "goodSeeing", "dcr")
39 }
40 
41 if TYPE_CHECKING:
42  from lsst.skymap import BaseSkyMap
43  from lsst.daf.butler import StorageClass
44  from .cameraMapper import CameraMapper
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 isDirectorySpecial(self, subdirectory: str) -> bool:
100  # Docstring inherited from RepoConverter.
101  return False
102 
103  def prep(self):
104  # Docstring inherited from RepoConverter.
105  self.task.log.info(f"Looking for skymaps in root {self.root}.")
106  for coaddName, datasetTypeName in SKYMAP_DATASET_TYPES.items():
107  if not self.task.isDatasetTypeIncluded(datasetTypeName):
108  continue
109  try:
110  exists = self.butler2.datasetExists(datasetTypeName)
111  except AttributeError:
112  # This mapper doesn't even define this dataset type.
113  continue
114  if not exists:
115  continue
116  instance = self.butler2.get(datasetTypeName)
117  name = self.task.useSkyMap(instance)
118  datasetType = DatasetType(datasetTypeName, dimensions=["skymap"],
119  storageClass="SkyMap", universe=self.task.universe)
120  dataId = DataCoordinate.standardize(skymap=name, universe=self.task.universe)
121  struct = FoundSkyMap(name=name, instance=instance, coaddName=coaddName,
122  ref=DatasetRef(datasetType, dataId),
123  filename=self.butler2.getUri(datasetTypeName))
124  self._foundSkyMapsByCoaddName[coaddName] = struct
125  self.task.log.info("Found skymap %s in %s in %s.", name, datasetTypeName, self.root)
126  super().prep()
127 
128  def iterMappings(self) -> Iterator[Tuple[str, CameraMapperMapping]]:
129  # Docstring inherited from RepoConverter.
130  for datasetTypeName, mapping in self.mapper.mappings.items():
131  if datasetTypeName not in self.mapper.calibrations:
132  yield datasetTypeName, mapping
133 
134  def makeDataIdExtractor(self, datasetTypeName: str, parser: FilePathParser,
135  storageClass: StorageClass) -> DataIdExtractor:
136  # Docstring inherited from RepoConverter.
137  # Use deepCoadd_skyMap by default; there are some dataset types
138  # that use it but don't have "deep" anywhere in their name.
139  struct = self._foundSkyMapsByCoaddName.get("deep")
140  for coaddName in SKYMAP_DATASET_TYPES.keys():
141  if coaddName in datasetTypeName:
142  try:
143  struct = self._foundSkyMapsByCoaddName[coaddName]
144  break
145  except KeyError:
146  # Don't use the default, since we did find a specific
147  # coaddName.
148  struct = None
149  self.task.log.debug(
150  ("Dataset %s looks like it might need a skymap, but no %sCoadd_skyMap "
151  "found in repo %s."),
152  datasetTypeName, coaddName, self.root
153  )
154  return DataIdExtractor(
155  datasetTypeName,
156  storageClass,
157  filePathParser=parser,
158  universe=self.task.universe,
159  instrument=self.task.instrument.getName(),
160  skyMap=struct.instance if struct is not None else None,
161  skyMapName=struct.name if struct is not None else None,
162  )
163 
164  def iterDatasets(self) -> Iterator[FileDataset]:
165  # Docstring inherited from RepoConverter.
166  for struct in self._foundSkyMapsByCoaddName.values():
167  if self.task.isDatasetTypeIncluded(struct.ref.datasetType.name):
168  yield FileDataset(path=os.path.join(self.root, struct.filename), ref=struct.ref)
169  yield from super().iterDatasets()
170 
171  # Class attributes that will be shadowed by public instance attributes;
172  # defined here only for documentation purposes.
173 
174  butler2: Butler2
175  """Gen2 butler associated with this repository.
176  """
177 
178  mapper: CameraMapper
179  """Gen2 mapper associated with this repository.
180  """
def temporaryLogLevel(name, level)
Definition: utils.py:45
Definition: Log.h:706