lsst.fgcmcal g34bb90edf1+3320ede73f
dataIds.py
Go to the documentation of this file.
1# See COPYRIGHT file at the top of the source tree.
2#
3# This file is part of fgcmcal.
4#
5# Developed for the LSST Data Management System.
6# This product includes software developed by the LSST Project
7# (https://www.lsst.org).
8# See the COPYRIGHT file at the top-level directory of this distribution
9# for details of code ownership.
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation, either version 3 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program. If not, see <https://www.gnu.org/licenses/>.
23"""Class for checking sourceTable_visit dataIds
24"""
25
26import lsst.pipe.base as pipeBase
27import lsst.log as lsstLog
28
29
30class TractCheckDataIdContainer(pipeBase.DataIdContainer):
31 """A version of lsst.pipe.base.DataIdContainer that ensures that tract
32 is additionally set with sourceTable_visit catalogs.
33 """
34 # TODO: Move to pipe_tasks with DM-25778
35
36 def castDataIds(self, butler):
37 """Validate data IDs and cast them to the correct type
38 (modify self.idList in place).
39
40 This code casts the values in the data IDs dicts in `self.idList`
41 to the type required by the butler. Data IDs are read from the
42 command line as `str`, but the butler requires some values to be
43 other types. For example "visit" values should be `int` (which
44 is defined by the templates).
45
46 This is taken from lsst.pipe.base.ArgumentParser.castDataIds(),
47 adding in a check that the tract is an int, which must be done
48 explicitly because it is not in the template.
49
50 Parameters
51 ----------
52 butler : `lsst.daf.persistence.Butler`
53 Data butler.
54 """
55 datasetType = 'sourceTable_visit'
56 try:
57 idKeyTypeDict = butler.getKeys(datasetType=datasetType, level=self.level)
58 except KeyError as e:
59 msg = f"Cannot get keys for datasetType {datasetType} at level {self.level}"
60 raise KeyError(msg) from e
61
62 idKeyTypeDict = idKeyTypeDict.copy()
63 idKeyTypeDict['tract'] = int
64
65 log = None
66
67 for dataDict in self.idList:
68 for key, strVal in dataDict.items():
69 try:
70 keyType = idKeyTypeDict[key]
71 except KeyError:
72 # OK, assume that it's a valid key and guess that it's a string
73 keyType = str
74
75 if log is None:
76 log = lsstLog.Log.getDefaultLogger()
77 log.warning("Unexpected ID %s; guessing type is \"%s\"",
78 key, 'str' if keyType == str else keyType)
79 idKeyTypeDict[key] = keyType
80
81 if keyType != str:
82 try:
83 castVal = keyType(strVal)
84 except Exception:
85 raise TypeError(f"Cannot cast value {strVal!r} to {keyType} for ID key {key}")
86 dataDict[key] = castVal
87
88 def makeDataRefList(self, namespace):
89 if self.datasetType is None:
90 raise RuntimeError("Must call setDatasetType first")
91
92 tracts = set()
93 for dataId in self.idList:
94 if "tract" not in dataId:
95 raise RuntimeError("Must set tract for dataId")
96 tracts.add(dataId['tract'])
97
98 self.refList.append(namespace.butler.dataRef(datasetType=self.datasetType,
99 dataId=dataId))
100
101 if len(tracts) > 1:
102 raise RuntimeError("Can only run a single tract")