Skip to content

Commit

Permalink
Enforce Astropy compliant unit string
Browse files Browse the repository at this point in the history
The Schema.addField method now first attempts to construct
an astropy.units.Unit object from the provided unit string.
This will raise a ValueError if the string is non-compliant.
The optional keyword argument parse_strict from
astropy.units.Unit is also added to addField.
It has three levels: 'raise' (default), 'warn' and 'silent'.
The latter causes any unit string to be accepted.
Also add Schema.checkUnits to allow a full Shema to be validated.
  • Loading branch information
Pim Schellart authored and Pim Schellart committed May 6, 2016
1 parent 85daa63 commit b6485ad
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
9 changes: 8 additions & 1 deletion python/lsst/afw/table/Base.i
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ template <> struct NumpyTraits<lsst::afw::geom::Angle> : public NumpyTraits<doub

%pythoncode %{
from . import _syntax
import astropy.units
%}

%include "lsst/afw/table/misc.h"
Expand Down Expand Up @@ -321,7 +322,13 @@ def find(self, k):
pass
raise KeyError("Field '%s' not found in Schema." % k)

def addField(self, field, type=None, doc="", units="", size=None, doReplace=False):
def checkUnits(self, parse_strict='raise'):
for schemaItem in self.asList():
astropy.units.Unit(schemaItem.getField().getUnits(), parse_strict=parse_strict)

def addField(self, field, type=None, doc="", units="", size=None, doReplace=False, parse_strict='raise'):
# Check for astropy compatible unit string
astropy.units.Unit(units, parse_strict=parse_strict)
if type is None:
try:
prefix, suffix = __builtins__['type'](field).__name__.split("_")
Expand Down
46 changes: 46 additions & 0 deletions tests/testSchema.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,52 @@ def testKey(name, key):
keys2 = map(lambda x: x.key, schema4.asList())
self.assertEqual(keys, keys2)

def testUnits(self):
schema = lsst.afw.table.Schema();
# first insert some valid units
try:
schema.addField("a", type="I", units="pixel")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.addField("b", type="I", units="m2")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.addField("c", type="I", units="electron / adu")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.addField("d", type="I", units="kg m s^(-2)")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.addField("e", type="I", units="GHz / Mpc")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.addField("f", type="Angle", units="deg")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.addField("g", type="Angle", units="rad")
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
try:
schema.checkUnits()
except ValueError:
self.fail("checkUnits raised ValueError unexpectedly!")
# now try inserting invalid units
self.assertRaises(ValueError, schema.addField, "a", type="I", units="camel")
self.assertRaises(ValueError, schema.addField, "b", type="I", units="pixels^2^2")
# add invalid units in silent mode, should work fine
try:
schema.addField("h", type="I", units="lala", parse_strict='silent')
except ValueError:
self.fail("addField raised ValueError unexpectedly!")
# Now this check should raise because there is an invalid unit
self.assertRaises(ValueError, schema.checkUnits)

def testInspection(self):
schema = lsst.afw.table.Schema()
keys = []
Expand Down

0 comments on commit b6485ad

Please sign in to comment.