27 from lsst.daf.butler.formatters.fileFormatter
import FileFormatter
32 """Class to support bright object masks 34 N.b. I/O is done by providing a readFits method which fools the butler. 38 schema = afwTable.SimpleTable.makeMinimalSchema()
39 schema.addField(
"type", str,
"type of region (e.g. box, circle)", size=10)
40 schema.addField(
"radius",
"Angle",
"radius of mask (if type == circle")
41 schema.addField(
"height",
"Angle",
"height of mask (if type == box)")
42 schema.addField(
"width",
"Angle",
"width of mask (if type == box)")
43 schema.addField(
"angle",
"Angle",
"rotation of mask (if type == box)")
44 schema.addField(
"mag", float,
"object's magnitude")
66 """FitsCatalogStorage facade for `read`. 68 This method is intended for use by the Gen2 Butler only. 73 Name of the file to read. 75 Provided for compatibility with the "FitsCatalogStorage" read API 76 defined in `lsst.daf.persistence`, and ignored here. 78 Provided for compatibility with the "FitsCatalogStorage" read API 79 defined in `lsst.daf.persistence`, and ignored here. 83 Having a `readFits` method makes the `ObjectCatalogMask` class 84 duck-type compatible with `lsst.afw.table` catalogs, to the extent 85 needed to support reading by the Gen2 Butler with no specialized code 86 in `lsst.daf.persistence`. The on-disk type should actually be an 87 ASCII ds9 region file, typically with a ".reg" suffix. 89 return cls.
read(fileName)
93 """Read a ds9 region file, returning a ObjectMaskCatalog object 95 The files should be structured as follows: 97 # Description of catalogue as a comment 98 # CATALOG: catalog-id-string 105 circle(RA, DEC, RADIUS) # ID: 1, mag: 12.34 106 box(RA, DEC, XSIZE, YSIZE, THETA) # ID: 2, mag: 23.45 109 The ", mag: XX.YY" is optional 111 The commented lines must be present, with the relevant fields such as 112 tract patch and filter filled in. The coordinate system must be listed 113 as above. Each patch is specified as a box or circle, with RA, DEC, 114 and dimensions specified in decimal degrees (with or without an 117 Only (axis-aligned) boxes and circles are currently supported as 121 log = Log.getLogger(
"ObjectMaskCatalog")
124 checkedWcsIsFk5 =
False 125 NaN =
float(
"NaN")*afwGeom.degrees
128 with open(fileName)
as fd:
129 for lineNo, line
in enumerate(fd.readlines(), 1):
132 if re.search(
r"^\s*#", line):
141 mat = re.search(
r"^\s*#\s*([a-zA-Z][a-zA-Z0-9_]+)\s*:\s*(.*)", line)
143 key, value = mat.group(1).lower(), mat.group(2)
147 brightObjects.table.getMetadata().
set(key, value)
149 line = re.sub(
r"^\s*#.*",
"", line)
153 if re.search(
r"^\s*wcs\s*;\s*fk5\s*$", line, re.IGNORECASE):
154 checkedWcsIsFk5 =
True 159 mat = re.search(
r"^\s*(box|circle)" 161 r"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)([d]*)" 163 r"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)([d]*)" 165 r"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)([d]*)" 168 r"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)([d]*)" 171 r"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)([d]*)" 175 r"#\s*ID:[\w\s]*(\d+)" 176 r"(?:\s*,?\s*mag:\s*([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?))?" 179 _type, ra, raUnit, dec, decUnit, \
180 param1, param1Unit, param2, param2Unit, param3, param3Unit, \
181 _id, mag = mat.groups()
195 angle = 0.0*afwGeom.degrees
198 width =
convertToAngle(param1, param1Unit,
"width", fileName, lineNo)
199 height =
convertToAngle(param2, param2Unit,
"height", fileName, lineNo)
200 if param3
is not None:
201 angle =
convertToAngle(param3, param3Unit,
"angle", fileName, lineNo)
204 log.warn(
"Rotated boxes are not supported: \"%s\" at %s:%d" % (
205 line, fileName, lineNo))
207 elif _type ==
"circle":
208 radius =
convertToAngle(param1, param1Unit,
"radius", fileName, lineNo)
210 if not (param2
is None and param3
is None):
211 log.warn(
"Extra parameters for circle: \"%s\" at %s:%d" % (
212 line, fileName, lineNo))
215 rec = brightObjects.addNew()
223 rec[
"height"] = height
225 rec[
"radius"] = radius
227 log.warn(
"Unexpected line \"%s\" at %s:%d" % (line, fileName, lineNo))
231 raise RuntimeError(
"Saw %d formatting errors in %s" % (nFormatError, fileName))
233 if not checkedWcsIsFk5:
234 raise RuntimeError(
"Expected to see a line specifying an fk5 wcs in %s" % fileName)
237 brightObjects._catalog = brightObjects._catalog.copy(
True)
243 """Given a variable and its units, return an afwGeom.Angle 245 what, fileName, and lineNo are used to generate helpful error messages 249 if varUnit
in (
"d",
"",
None):
256 raise RuntimeError(
"unsupported unit \"%s\" for %s at %s:%d" %
257 (varUnit, what, fileName, lineNo))
259 return var*afwGeom.degrees
263 """Plugin for reading DS9 region file catalogs with Gen3 Butler. 267 def _readFile(self, path, pytype):
269 if not os.path.exists(path):
272 return pytype.read(path)
274 def _writeFile(self, inMemoryDataset, fileDescriptor):
276 raise NotImplementedError(
"Write not implemented.")
Class for storing ordered metadata with comments.
def convertToAngle(var, varUnit, what, fileName, lineNo)
daf::base::PropertySet * set
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
def __setitem__(self, i, v)
Point in an unspecified spherical coordinate system.
def readFits(cls, fileName, hdu=0, flags=0)