25from lsst.ip.isr import (Linearizer, CrosstalkCalib, Defects, BrighterFatterKernel, PhotodiodeCalib)
30from deprecated.sphinx
import deprecated
34 """Read data for a particular sensor from the standard format at a particular root.
39 Path to the top level of the data tree. This is expected to hold directories
40 named after the sensor names. They are expected to be lower case.
42 The name of the sensor
for which to read data.
44 The identifier
for the sensor
in question.
49 A dictionary of objects constructed
from the appropriate factory
class.
50 The key
is the validity start time
as a `datetime` object.
52 factory_map = {'qe_curve': Curve,
'defects': Defects,
'linearizer': Linearizer,
53 'crosstalk': CrosstalkCalib,
'bfk': BrighterFatterKernel,
54 'photodiode': PhotodiodeCalib, }
56 extensions = (
".ecsv",
".yaml")
57 for ext
in extensions:
58 files.extend(glob.glob(os.path.join(root, chip_name, f
"*{ext}")))
59 parts = os.path.split(root)
60 instrument = os.path.split(parts[0])[1]
62 if data_name
not in factory_map:
63 raise ValueError(f
"Unknown calibration data type, '{data_name}' found. "
64 f
"Only understand {','.join(k for k in factory_map)}")
65 factory = factory_map[data_name]
68 date_str = os.path.splitext(os.path.basename(f))[0]
69 valid_start = dateutil.parser.parse(date_str)
70 data_dict[valid_start] = factory.readText(f)
71 check_metadata(data_dict[valid_start], valid_start, instrument, chip_id, f, data_name)
72 return data_dict, data_name
75def check_metadata(obj, valid_start, instrument, chip_id, filepath, data_name):
76 """Check that the metadata is complete and self consistent
80 obj : object of same type as the factory
81 Object to retrieve metadata
from in order to compare
with
82 metadata inferred
from the path.
83 valid_start : `datetime`
84 Start of the validity range
for data
86 Name of the instrument
in question
88 Identifier of the sensor
in question
90 Path of the file read to construct the data
92 Name of the type of data being read
101 If the metadata
from the path
and the metadata encoded
102 in the path do
not match
for any reason.
104 md = obj.getMetadata()
105 finst = md['INSTRUME']
106 fchip_id = md[
'DETECTOR']
107 fdata_name = md[
'OBSTYPE']
108 if not ((finst.lower(), int(fchip_id), fdata_name.lower())
109 == (instrument.lower(), chip_id, data_name.lower())):
110 raise ValueError(f
"Path and file metadata do not agree:\n"
111 f
"Path metadata: {instrument} {chip_id} {data_name}\n"
112 f
"File metadata: {finst} {fchip_id} {fdata_name}\n"
113 f
"File read from : %s\n"%(filepath)
117@deprecated(reason=
"Curated calibration ingest now handled by obs_base Instrument classes."
118 " Will be removed after v25.0.",
119 version=
"v25.0", category=FutureWarning)
121 """Read all data from the standard format at a particular root.
126 Path to the top level of the data tree. This is expected to hold directories
127 named after the sensor names. They are expected to be lower case.
129 The camera that goes
with the data being read.
134 A dictionary of dictionaries of objects constructed
with the appropriate factory
class.
135 The first key
is the sensor name lowered,
and the second
is the validity
136 start time
as a `datetime` object.
140 Each leaf object
in the constructed dictionary has metadata associated
with it.
141 The detector ID may be retrieved
from the DETECTOR entry of that metadata.
143 root = os.path.normpath(root)
144 dirs = os.listdir(root)
145 dirs = [d
for d
in dirs
if os.path.isdir(os.path.join(root, d))]
147 name_map = {det.getName().lower(): det.getName()
for
151 raise RuntimeError(f
"No data found on path {root}")
155 chip_name = os.path.basename(d)
158 if chip_name
not in name_map:
159 detectors = [det
for det
in camera.getNameIter()]
162 if len(detectors) > max_detectors:
164 note_str =
"examples"
165 detectors = detectors[:max_detectors]
166 raise RuntimeError(f
"Detector {chip_name} not known to supplied camera "
167 f
"{camera.getName()} ({note_str}: {','.join(detectors)})")
168 chip_id = camera[name_map[chip_name]].getId()
169 data_by_chip[chip_name], calib_type =
read_one_chip(root, chip_name, chip_id)
170 calib_types.add(calib_type)
171 if len(calib_types) != 1:
172 raise ValueError(f
'Error mixing calib types: {calib_types}')
174 no_data = all([v == {}
for v
in data_by_chip.values()])
176 raise RuntimeError(
"No data to ingest")
178 return data_by_chip, calib_type
An immutable representation of a camera.
daf::base::PropertySet * set
def check_metadata(obj, valid_start, instrument, chip_id, filepath, data_name)
def read_all(root, camera)
def read_one_chip(root, chip_name, chip_id)