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
read_curated_calibs.py
Go to the documentation of this file.
1 from lsst.meas.algorithms import Defects
2 from lsst.meas.algorithms.simple_curve import Curve
3 
4 import os
5 import glob
6 import dateutil.parser
7 
8 
9 def read_one_chip(root, chip_name, chip_id):
10  """Read data for a particular sensor from the standard format at a particular root.
11 
12  Parameters
13  ----------
14  root : `str`
15  Path to the top level of the data tree. This is expected to hold directories
16  named after the sensor names. They are expected to be lower case.
17  chip_name : `str`
18  The name of the sensor for which to read data.
19  chip_id : `int`
20  The identifier for the sensor in question.
21 
22  Returns
23  -------
24  `dict`
25  A dictionary of objects constructed from the appropriate factory class.
26  The key is the validity start time as a `datetime` object.
27  """
28  factory_map = {'qe_curves': Curve, 'defects': Defects}
29  files = glob.glob(os.path.join(root, chip_name, '*.ecsv'))
30  parts = os.path.split(root)
31  instrument = os.path.split(parts[0])[1] # convention is that these reside at <instrument>/<data_name>
32  data_name = parts[1]
33  if data_name not in factory_map:
34  raise ValueError(f"Unknown calibration data type, '{data_name}' found. "
35  f"Only understand {','.join(k for k in factory_map)}")
36  factory = factory_map[data_name]
37  data_dict = {}
38  for f in files:
39  date_str = os.path.splitext(os.path.basename(f))[0]
40  valid_start = dateutil.parser.parse(date_str)
41  data_dict[valid_start] = factory.readText(f)
42  check_metadata(data_dict[valid_start], valid_start, instrument, chip_id, f, data_name)
43  return data_dict, data_name
44 
45 
46 def check_metadata(obj, valid_start, instrument, chip_id, filepath, data_name):
47  """Check that the metadata is complete and self consistent
48 
49  Parameters
50  ----------
51  obj : object of same type as the factory
52  Object to retrieve metadata from in order to compare with
53  metadata inferred from the path.
54  valid_start : `datetime`
55  Start of the validity range for data
56  instrument : `str`
57  Name of the instrument in question
58  chip_id : `int`
59  Identifier of the sensor in question
60  filepath : `str`
61  Path of the file read to construct the data
62  data_name : `str`
63  Name of the type of data being read
64 
65  Returns
66  -------
67  None
68 
69  Raises
70  ------
71  ValueError
72  If the metadata from the path and the metadata encoded
73  in the path do not match for any reason.
74  """
75  md = obj.getMetadata()
76  finst = md['INSTRUME']
77  fchip_id = md['DETECTOR']
78  fcalib_date = md['CALIBDATE']
79  fdata_name = md['OBSTYPE']
80  if not ((finst.lower(), int(fchip_id), fcalib_date, fdata_name) ==
81  (instrument.lower(), chip_id, valid_start.isoformat(), data_name)):
82  st_time = valid_start.isoformat()
83  raise ValueError(f"Path and file metadata do not agree:\n"
84  f"Path metadata: {instrument} {chip_id} {st_time} {data_name}\n"
85  f"File metadata: {finst} {fchip_id} {fcalib_date} {fdata_name}\n"
86  f"File read from : %s\n"%(filepath)
87  )
88 
89 
90 def read_all(root, camera):
91  """Read all data from the standard format at a particular root.
92 
93  Parameters
94  ----------
95  root : `str`
96  Path to the top level of the data tree. This is expected to hold directories
97  named after the sensor names. They are expected to be lower case.
98  camera : `lsst.afw.cameraGeom.Camera`
99  The camera that goes with the data being read.
100 
101  Returns
102  -------
103  dict
104  A dictionary of dictionaries of objects constructed with the appropriate factory class.
105  The first key is the sensor name lowered, and the second is the validity
106  start time as a `datetime` object.
107 
108  Notes
109  -----
110  Each leaf object in the constructed dictionary has metadata associated with it.
111  The detector ID may be retrieved from the DETECTOR entry of that metadata.
112  """
113  root = os.path.normpath(root)
114  dirs = os.listdir(root) # assumes all directories contain data
115  dirs = [d for d in dirs if os.path.isdir(os.path.join(root, d))]
116  data_by_chip = {}
117  name_map = {det.getName().lower(): det.getName() for
118  det in camera} # we assume the directories have been lowered
119  calib_type_old = None
120  for d in dirs:
121  chip_name = os.path.basename(d)
122  chip_id = camera[name_map[chip_name]].getId()
123  data_by_chip[chip_name], calib_type = read_one_chip(root, chip_name, chip_id)
124  if calib_type_old is not None:
125  if calib_type_old != calib_type:
126  raise ValueError(f'Calibration types do not agree: {calib_type_old} != {calib_type}')
127  return data_by_chip, calib_type
def check_metadata(obj, valid_start, instrument, chip_id, filepath, data_name)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
def read_one_chip(root, chip_name, chip_id)