def test_unit_system_units_call(self): """ test call to a unit_system's 'units' method """ kgs = unit_manager.lookup_system("KGS") # do some funny stuff to get 'almost_equal' testing # first test 'value' self.assertAlmostEqual(kgs.units("rhog").value, unit_parser.parse_unit("1000*kg/m**3").value) self.assertAlmostEqual(kgs.units("pvelocity").value, unit_parser.parse_unit("1000*m/s").value) # now make sure derivations match self.assertEqual(kgs.units("rhog").derivation, unit_parser.parse_unit("1000*kg/m**3").derivation) self.assertEqual(kgs.units("pvelocity").derivation, unit_parser.parse_unit("1000*m/s").derivation)
def test_unit_parser_derivation_valid(self): # Make sure every derivation of the SI core units can be parsed. for i, label in enumerate(unit._labels): derivation = [0] * len(unit._labels) derivation[i] = 1 base_unit = unit(1.0, tuple(derivation)) base_unit.label = label self.assertEqual( unit_parser.parse_unit(label, suppress_unknown=False), base_unit, ) self.assertEqual( unit_parser.parse_unit('S', suppress_unknown=False), SI.siemens, )
def DrawBackground(self, grid, attr, dc, rect, row, col, isSelected): """ Erases whatever is already in the cell by drawing over it. """ # We have to set the clipping region on the grid's DC, # otherwise the text will spill over to the next cell dc.SetClippingRegion(rect) # overwrite anything currently in the cell ... dc.SetBackgroundMode(wx.SOLID) dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID)) text = grid.model.GetValue(row, col) if unit_parser: this_unit = unit_parser.parse_unit(text, self.suppress_warnings) else: this_unit = None # Todo - clean up this hardcoded logic/column position mess family = grid.model.GetValue(row, 6) # AI units of 'impedance ((kg/s)*(g/cc))' creates list of 3, not 2! try: family, other_text = family[:-1].split("(") except: family, other_text = family[:-1].split(" ") if unit_parser: other_unit = unit_parser.parse_unit( other_text, self.suppress_warnings ) dimensionally_equivalent = this_unit.can_convert(other_unit) else: other_unit = None dimensionally_equivalent = False if isSelected: dc.SetBrush(DefaultRenderer.selected_cells) elif not this_unit or not this_unit.is_valid(): dc.SetBrush(DefaultRenderer.error_cells) elif not dimensionally_equivalent: dc.SetBrush(DefaultRenderer.warn_cells) else: dc.SetBrush(DefaultRenderer.normal_cells) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) return
def setattr(self, info, object, name, value): """ Handles setting a specified object trait's value. Parameters ---------- object : object The object whose attribute is being set name : string The name of the attribute being set value The value to which the attribute is being set """ if not info.initialized: return if name == 'units': # Convert units label to units object. if not unit_manager.is_compatible(value, object.family_name): raise TraitError() value = unit_parser.parse_unit(value, suppress_warnings=False) super(QuantityViewHandler, self).setattr(info, object, name, value) return
def from_string(cls, string): """ Create a Variable object from a colon (':') delimited string. The first field is the name. The 2nd is the description. After that, are xyz=abc fields. Currently, only units is handled. fixme: this is woefully simple... We should report/log more failure information... """ name = '' desc = '' units = None fields = string.split(':') # Get the name variable. if len(fields) > 0: name = fields[0].strip() else: # fixme: We should probably log an error here... pass # Now the description if len(fields) > 1: desc = fields[1].strip() # Finally handle any 'keyword' attributes. for extra_attributes in fields[2:]: var, value = [x.strip() for x in extra_attributes.split('=')] if var.lower() == 'units': units = unit_parser.parse_unit(value) else: # fixme: raise some sort of error here? pass return cls(name=name, desc=desc, units=units)
def add_family(self, family_name, fam_unit, description=None, inverse=None): """ Add to families dictionary parameters ---------- family_name: name of family--also sets preferred_name system_units: either an scimath.units.unit type or a string that may be coerced into a unit type. """ # convert string to unit if type(fam_unit)== type(''): fam_unit = unit_parser.parse_unit(fam_unit) self.families[family_name] = fam_unit # if this system has a unit manager and the description or inverse # arguments are provided, populate this system's um.unit_families # as well. if self.unit_manager and (description or inverse): self.unit_manager.add_family(family_name, description, inverse)
def add_family(self, family_name, fam_unit, description=None, inverse=None): """ Add to families dictionary parameters ---------- family_name: name of family--also sets preferred_name system_units: either an scimath.units.unit type or a string that may be coerced into a unit type. """ # convert string to unit if isinstance(fam_unit, type('')): fam_unit = unit_parser.parse_unit(fam_unit) self.families[family_name] = fam_unit # if this system has a unit manager and the description or inverse # arguments are provided, populate this system's um.unit_families # as well. if self.unit_manager and (description or inverse): self.unit_manager.add_family(family_name, description, inverse)
def test_unit_parser_offsets(self): parse = lambda s: unit_parser.parse_unit(s, suppress_unknown=False) offset_units = [ temperature.degC, temperature.degF, ] for u in offset_units: self.assertEqual(parse(repr(u)), u)
def DrawBackground(self, grid, attr, dc, rect, row, col, isSelected): """ Erases whatever is already in the cell by drawing over it. """ # We have to set the clipping region on the grid's DC, # otherwise the text will spill over to the next cell dc.SetClippingRect(rect) # overwrite anything currently in the cell ... dc.SetBackgroundMode(wx.SOLID) dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID)) text = grid.model.GetValue(row, col) if unit_parser: this_unit = unit_parser.parse_unit(text, self.suppress_warnings) else: this_unit = None # Todo - clean up this hardcoded logic/column position mess family = grid.model.GetValue(row, 6) # AI units of 'impedance ((kg/s)*(g/cc))' creates list of 3, not 2! try: family, other_text = family[:-1].split('(') except: family, other_text = family[:-1].split(' ') if unit_parser: other_unit = unit_parser.parse_unit(other_text, self.suppress_warnings) dimensionally_equivalent = this_unit.can_convert(other_unit) else: other_unit = None dimensionally_equivalent = False if isSelected: dc.SetBrush(DefaultRenderer.selected_cells) elif not this_unit or not this_unit.is_valid(): dc.SetBrush(DefaultRenderer.error_cells) elif not dimensionally_equivalent: dc.SetBrush(DefaultRenderer.warn_cells) else: dc.SetBrush(DefaultRenderer.normal_cells) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) return
def test_unit_system_units_call(self): """ test call to a unit_system's 'units' method """ kgs = unit_manager.lookup_system('KGS') # do some funny stuff to get 'almost_equal' testing # first test 'value' self.assertAlmostEqual( kgs.units('rhog').value, unit_parser.parse_unit('1000*kg/m**3').value) self.assertAlmostEqual( kgs.units('pvelocity').value, unit_parser.parse_unit('1000*m/s').value) # now make sure derivations match self.assertEqual(kgs.units('rhog').derivation, unit_parser.parse_unit('1000*kg/m**3').derivation) self.assertEqual( kgs.units('pvelocity').derivation, unit_parser.parse_unit('1000*m/s').derivation)
def test_unit_parser_only_units(self): for bad_name in ['copy', 'math', '__id__', '__doc__', '__builtin__', 'Exception']: self.assertRaises( UnableToParseUnits, unit_parser.parse_unit, bad_name, suppress_unknown=False, ) # But plain numbers like the SI prefixes are kept. for good_name in ['hecto', 'yotta']: self.assertTrue(is_dimensionless( unit_parser.parse_unit(good_name, suppress_unknown=False)))
def test_unit_parser_non_python(self): parse = lambda s: unit_parser.parse_unit(s, suppress_unknown=False) odd_units = [ angle.circle, angle.grad, angle.minutes, acceleration.m_per_s2, electromagnetism.mf, volume.cm3, ] for u in odd_units: self.assertEqual(parse(u.label), u)
def test_wrapped_adds_outputs2(self): """ Are output specifications added correctly? """ @has_units(outputs="out: out desc:units=m/s") def func(v1, v2): return v1 + v2 self.assertTrue(len(func.outputs) == 1) # Does the output have its name and units assigned correctly? self.assertTrue(func.outputs[0].name == 'out') self.assertTrue(func.outputs[0].units == unit_parser.parse_unit('m/s'))
def test_wrapped_adds_outputs2(self): """ Are output specifications added correctly? """ @has_units(outputs="out: out desc:units=m/s") def func(v1, v2): return v1+v2 self.assertTrue(len(func.outputs)==1) # Does the output have its name and units assigned correctly? self.assertTrue(func.outputs[0].name=='out') self.assertTrue(func.outputs[0].units==unit_parser.parse_unit('m/s'))
def test_wrapped_adds_inputs(self): """ Are input specifications added correctly? """ @has_units(inputs="v1:a value:units=m/s") def func(v1, v2): return v1 + v2 self.assertTrue(len(func.inputs) == 2) # Does the 1st variable have its name and units assigned correctly? self.assertTrue(func.inputs[0].name == 'v1') self.assertTrue(func.inputs[0].units == unit_parser.parse_unit('m/s')) # Was the 2nd (unspecified) input given an input variable? self.assertTrue(func.inputs[1].name == 'v2') self.assertTrue(func.inputs[1].units == None)
def test_wrapped_adds_inputs(self): """ Are input specifications added correctly? """ @has_units(inputs="v1:a value:units=m/s") def func(v1, v2): return v1+v2 self.assertTrue(len(func.inputs)==2) # Does the 1st variable have its name and units assigned correctly? self.assertTrue(func.inputs[0].name=='v1') self.assertTrue(func.inputs[0].units==unit_parser.parse_unit('m/s')) # Was the 2nd (unspecified) input given an input variable? self.assertTrue(func.inputs[1].name=='v2') self.assertTrue(func.inputs[1].units==None)
def __new__(cls, data, dtype=None, copy=True, units=None): """ Called when a new object is created (before __init__). The default behavior of ndarray is overridden to add units and family_name to the class. For more details, see: http://docs.python.org/ref/customization.html """ ### Array Setup ######################################################## if isinstance(data, numpy.ndarray): # Handle the case where we are passed in a numpy array. if dtype is None: intype = data.dtype else: intype = numpy.dtype(dtype) new = data.view(cls) if intype != data.dtype: res = new.astype(intype) elif copy: res = new.copy() else: res = new else: # Handle other input types (lists, etc.) arr = numpy.array(data, dtype=dtype, copy=copy) res = numpy.ndarray.__new__(cls, arr.shape, arr.dtype, buffer=arr) ### Configure Other Attributes ######################################### if isinstance(units, basestring): units = unit_parser.parse_unit(units) res.units = units return res
def DrawBackground(self, grid, attr, dc, rect, row, col, isSelected): """ Erases whatever is already in the cell by drawing over it. """ # We have to set the clipping region on the grid's DC, # otherwise the text will spill over to the next cell dc.SetClippingRect(rect) # overwrite anything currently in the cell ... dc.SetBackgroundMode(wx.SOLID) dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID)) text = grid.model.GetValue(row, col) if isSelected: dc.SetBrush(DefaultRenderer.selected_cells) elif unit_parser and unit_parser.parse_unit(text).is_valid(): dc.SetBrush(DefaultRenderer.normal_cells) else: dc.SetBrush(DefaultRenderer.error_cells) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) return
def DrawBackground(self, grid, attr, dc, rect, row, col, isSelected): """ Erases whatever is already in the cell by drawing over it. """ # We have to set the clipping region on the grid's DC, # otherwise the text will spill over to the next cell dc.SetClippingRegion(rect) # overwrite anything currently in the cell ... dc.SetBackgroundMode(wx.SOLID) dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID)) text = grid.model.GetValue(row, col) if isSelected: dc.SetBrush(DefaultRenderer.selected_cells) elif unit_parser and unit_parser.parse_unit(text).is_valid(): dc.SetBrush(DefaultRenderer.normal_cells) else: dc.SetBrush(DefaultRenderer.error_cells) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) return
def __init__(self, data, units=None, name='', **traits): """ Constructor. """ # Base class constructors. super(Quantity, self).__init__(**traits) # Flag used to save a compare if units/family_name compatibility has # already been validated. compatibility_checked = None self.name = name # Determine what units to use and if they are family compatible. if units is None: units = unit_manager.default_units_for(self.family_name) # Allow for parsing a unit string as the units argument else: if isinstance(units, str): units = unit_parser.parse_unit(units, suppress_warnings=False) if 'family_name' not in traits: # If the family name wasn't passed in, we try to guess it. # TODO: Should lower() be called here--one can do an # 'obj.family_name='xxx'" that would not call a 'lower' method. try: um = unit_manager if self.family_name is None: family_name = '' else: family_name = self.family_name.lower() self.family_name = \ um.get_family_name(family_name) or \ em.get_family_name(name.lower()) # If units were passed in, but don't match the guessed family_name, # punt. if not unit_manager.is_compatible(units, self.family_name): self.family_name = "unknown" compatibility_checked = True except KeyError: logger.warn("Could not find family name: %s" % \ self.family_name or name) else: # fixme: This is subverting the FamilyNameTrait behavior, # but it gets around proava ticket:1715-comment14,item 2. self.family_name = traits['family_name'] # If we haven't checked compatibilty before, and units if (compatibility_checked != True and not unit_manager.is_compatible(units, self.family_name)): raise ValueError("units (%s) not compatible with family_name (%s)" \ % (units.label, self.family_name)) self.units = units # The following timing data is from using the code below the # timings that sets values for 'data' and 'units' using the # 'slow' method. if isinstance(data, Quantity): self.data = self._convert(data, units) else: self.data = data # The 'fast' method of just stuffing the __dict__ values yields a # performance improvement of 2x-- 0.0016 sec vs. 0.0035 sec per # unit change (which creates a new Quantity object). #self.__dict__['data'] = self._convert(data, units) #self.__dict__['units'] = units return
def test_unit_parser_dimensionless(self): for label in ['', 'None', 'none', 'unknown', 'unitless']: dless = unit_parser.parse_unit(label, suppress_unknown=False) self.assertTrue(is_dimensionless(dless)) self.assertEqual(dless.value, 1)
def cvt_unit(unit_label): """ Parse a unit description """ units = unit_parser.parse_unit(unit_label) return units
def __init__(self, data, units = None, name = '', **traits): """ Constructor. """ # Base class constructors. super(Quantity, self).__init__(**traits) # Flag used to save a compare if units/family_name compatibility has # already been validated. compatibility_checked = None self.name = name # Determine what units to use and if they are family compatible. if units is None: units = unit_manager.default_units_for( self.family_name ) # Allow for parsing a unit string as the units argument else: if isinstance(units, basestring): units = unit_parser.parse_unit(units, suppress_warnings=False) if not traits.has_key('family_name'): # If the family name wasn't passed in, we try to guess it. # TODO: Should lower() be called here--one can do an # 'obj.family_name='xxx'" that would not call a 'lower' method. try: um = unit_manager if self.family_name is None: family_name = '' else: family_name = self.family_name.lower() self.family_name = \ um.get_family_name(family_name) or \ em.get_family_name(name.lower()) # If units were passed in, but don't match the guessed family_name, # punt. if not unit_manager.is_compatible( units, self.family_name ): self.family_name = "unknown" compatibility_checked = True except KeyError: logger.warn("Could not find family name: %s" % \ self.family_name or name) else: # fixme: This is subverting the FamilyNameTrait behavior, # but it gets around proava ticket:1715-comment14,item 2. self.family_name = traits['family_name'] # If we haven't checked compatibilty before, and units if (compatibility_checked != True and not unit_manager.is_compatible( units, self.family_name )): raise ValueError, "units (%s) not compatible with family_name (%s)" \ % (units.label, self.family_name) self.units = units # The following timing data is from using the code below the # timings that sets values for 'data' and 'units' using the # 'slow' method. if isinstance(data, Quantity): self.data = self._convert(data, units) else: self.data = data # The 'fast' method of just stuffing the __dict__ values yields a # performance improvement of 2x-- 0.0016 sec vs. 0.0035 sec per # unit change (which creates a new Quantity object). #self.__dict__['data'] = self._convert(data, units) #self.__dict__['units'] = units return