1 from __future__
import absolute_import, division, print_function
2 from builtins
import object
4 import lsst.daf.base
as dafBase
5 import lsst.afw.coord
as afwCoord
6 import lsst.afw.geom
as afwGeom
7 import lsst.afw.table
as afwTable
8 from lsst.log
import Log
12 """Class to support bright object masks 14 N.b. I/O is done by providing a readFits method which fools the butler. 18 schema = afwTable.SimpleTable.makeMinimalSchema()
19 schema.addField(
"type", str,
"type of region (e.g. box, circle)", size=10)
20 schema.addField(
"radius",
"Angle",
"radius of mask (if type == circle")
21 schema.addField(
"height",
"Angle",
"height of mask (if type == box)")
22 schema.addField(
"width",
"Angle",
"width of mask (if type == box)")
23 schema.addField(
"angle",
"Angle",
"rotation of mask (if type == box)")
24 schema.addField(
"mag", float,
"object's magnitude")
26 self.
_catalog = afwTable.SimpleCatalog(schema)
27 self.
_catalog.table.setMetadata(dafBase.PropertyList())
46 """Read a ds9 region file, returning a ObjectMaskCatalog object 48 This method is called "readFits" to fool the butler. The corresponding mapper entry looks like 50 template: "deepCoadd/BrightObjectMasks/%(tract)d/BrightObjectMask-%(tract)d-%(patch)s-%(filter)s.reg" 51 python: "lsst.obs.subaru.objectMasks.ObjectMaskCatalog" 52 persistable: "PurePythonClass" 53 storage: "FitsCatalogStorage" 55 and this is the only way I know to get it to read a random file type, in this case a ds9 region file. 57 This method expects to find files named as BrightObjectMask-%(tract)d-%(patch)s-%(filter)s.reg 58 The files should be structured as follows: 60 # Description of catalogue as a comment 61 # CATALOG: catalog-id-string 68 circle(RA, DEC, RADIUS) # ID: 1, mag: 12.34 69 box(RA, DEC, XSIZE, YSIZE, THETA) # ID: 2, mag: 23.45 72 The ", mag: XX.YY" is optional 74 The commented lines must be present, with the relevant fields such as tract patch and filter filled 75 in. The coordinate system must be listed as above. Each patch is specified as a box or circle, with 76 RA, DEC, and dimensions specified in decimal degrees (with or without an explicit "d"). 78 Only (axis-aligned) boxes and circles are currently supported as region definitions. 81 log = Log.getLogger(
"ObjectMaskCatalog")
84 checkedWcsIsFk5 =
False 85 NaN = float(
"NaN")*afwGeom.degrees
88 with open(fileName)
as fd:
89 for lineNo, line
in enumerate(fd.readlines(), 1):
92 if re.search(
r"^\s*#", line):
101 mat = re.search(
r"^\s*#\s*([a-zA-Z][a-zA-Z0-9_]+)\s*:\s*(.*)", line)
103 key, value = mat.group(1).lower(), mat.group(2)
107 brightObjects.table.getMetadata().set(key, value)
109 line = re.sub(
r"^\s*#.*",
"", line)
113 if re.search(
r"^\s*wcs\s*;\s*fk5\s*$", line, re.IGNORECASE):
114 checkedWcsIsFk5 =
True 119 mat = re.search(
r"^\s*(box|circle)" 121 "(\d+(?:\.\d*)?([d]*))" "(?:\s+|\s*,\s*)" 122 "([+-]?\d+(?:\.\d*)?)([d]*)" "(?:\s+|\s*,\s*)" 123 "([+-]?\d+(?:\.\d*)?)([d]*)" "(?:\s+|\s*,\s*)?" 124 "(?:([+-]?\d+(?:\.\d*)?)([d]*)" 126 "([+-]?\d+(?:\.\d*)?)([d]*)" 130 "(?:\s*,\s*mag:\s*(\d+\.\d*))?" 133 _type, ra, raUnit, dec, decUnit, \
134 param1, param1Unit, param2, param2Unit, param3, param3Unit, \
135 _id, mag = mat.groups()
152 width =
convertToAngle(param1, param1Unit,
"width", fileName, lineNo)
153 height =
convertToAngle(param2, param2Unit,
"height", fileName, lineNo)
154 angle =
convertToAngle(param3, param3Unit,
"angle", fileName, lineNo)
157 log.warn(
"Rotated boxes are not supported: \"%s\" at %s:%d" % (
158 line, fileName, lineNo))
160 elif _type ==
"circle":
161 radius =
convertToAngle(param1, param1Unit,
"radius", fileName, lineNo)
163 if not (param2
is None and param3
is None):
164 log.warn(
"Extra parameters for circle: \"%s\" at %s:%d" % (
165 line, fileName, lineNo))
168 rec = brightObjects.addNew()
173 rec.setCoord(afwCoord.Fk5Coord(ra, dec))
176 rec[
"height"] = height
178 rec[
"radius"] = radius
180 log.warn(
"Unexpected line \"%s\" at %s:%d" % (line, fileName, lineNo))
184 raise RuntimeError(
"Saw %d formatting errors in %s" % (nFormatError, fileName))
186 if not checkedWcsIsFk5:
187 raise RuntimeError(
"Expected to see a line specifying an fk5 wcs in %s" % fileName)
190 brightObjects._catalog = brightObjects._catalog.copy(
True)
196 """Given a variable and its units, return an afwGeom.Angle 198 what, fileName, and lineNo are used to generate helpful error messages 202 if varUnit
in (
"d",
"",
None):
209 raise RuntimeError(
"unsupported unit \"%s\" for %s at %s:%d" %
210 (varUnit, what, fileName, lineNo))
212 return var*afwGeom.degrees
def convertToAngle(var, varUnit, what, fileName, lineNo)
def readFits(fileName, hdu=0, flags=0)
def __setitem__(self, i, v)