# From the validation errors printed above you'll see that none of the # units we need are built-in. The good news is that we can create the ones # we need from the set of built-in units, we just need to define the # relationship. NB: Even though units are used by Variables, which sit # 'inside' Components, Units sit inside the Model itself. This helps you to # reuse Units when you have more than one component (more on that in # Tutorial 5) # 3.a # Define the relationship between our custom units and the built-in # units. There is a list of built-in units and their definitions # available in section 19.2 of the CellML2 specification. # First we create the "month" units, which will be equivalent to # 60*60*24*30 = 2,592,000 seconds. month = Units("month") month.addUnit("second", 1, 2592000) # Setting a month to be 2592000 seconds. model.addUnits(month) # "second" is a built-in unit, used with a multiplier of 2592000. # Note that this could have been written: # month.addUnit("second", "mega", 1, 2.592) # month.addUnit("second", 5, 25.92) # 3.b # Create units which represent "per_month", which # is simply the inverse of the "month" unit above. per_month = Units() per_month.setName("per_month") per_month.addUnit("month", -1)
def test_set_units(self): from libcellml import Issue, Units # void setUnits(const UnitsPtr &units) e = Issue() e.setUnits(Units())
def test_replace_units(self): from libcellml import Model, Units # bool replaceUnits(size_t index, const UnitsPtr &units) m = Model() u1 = Units() u1.setName('a') m.addUnits(u1) u2 = Units() u2.setName('b') self.assertTrue(m.replaceUnits(0, u2)) self.assertFalse(m.replaceUnits(1, u1)) self.assertFalse(m.replaceUnits(-1, u1)) self.assertEqual(m.units(0).name(), 'b') del [m, u1, u2] # bool replaceUnits(const std::string &name, const UnitsPtr &units) m = Model() a = Units() a.setName('a') m.addUnits(a) b = Units() b.setName('b') self.assertFalse(m.replaceUnits('b', a)) self.assertTrue(m.replaceUnits('a', b)) self.assertTrue(m.replaceUnits('b', a)) self.assertFalse(m.replaceUnits('b', a)) del [m, a, b] # bool replaceUnits(const UnitsPtr &oldUnits, const UnitsPtr &newUnits) m = Model() a = Units() m.addUnits(a) b = Units() self.assertFalse(m.replaceUnits(b, a)) self.assertFalse(m.replaceUnits(a, b)) self.assertFalse(m.replaceUnits(b, a)) del [m, a, b]
def test_set_units(self): from libcellml import Error, Units # void setUnits(const UnitsPtr &units) e = Error() e.setUnits(Units())
# The messages below indicate that we're missing a Units item named 'mS_per_cm2'. # Issue 1: Variable 'Na_conductance' in component 'sodiumChannelEquations' has a units reference 'mS_per_cm2' which is neither standard nor defined in the parent model. # reference: 2.8.1.2 # see: https://cellml-specification.readthedocs.io/en/latest/reference/formal_and_informative/specB08.html?issue=2.8.1.2 # Issue 2: Variable 'g_Na' in component 'sodiumChannelEquations' has a units reference 'mS_per_cm2' which is neither standard nor defined in the parent model. # reference: 2.8.1.2 # see: https://cellml-specification.readthedocs.io/en/latest/reference/formal_and_informative/specB08.html?issue=2.8.1.2 # Issue 3: Variable 'g_Na' in component 'sodiumChannelParameters' has a units reference 'mS_per_cm2' which is neither standard nor defined in the parent model. # reference: 2.8.1.2 # see: https://cellml-specification.readthedocs.io/en/latest/reference/formal_and_informative/specB08.html?issue=2.8.1.2 # 3.b # Create an appropriate Units item (note that S stands for 'siemens'), and add it to your model. mS_per_cm2 = Units('mS_per_cm2') mS_per_cm2.addUnit('siemens', 'milli') mS_per_cm2.addUnit('metre', 'centi', -2) model.addUnits(mS_per_cm2) # end 3.b # As with 3.a, here we have more than one issue generated from the same cause: in this case, # we haven't specified units for a variable. # Issue 4: Variable 'V' in component 'sodiumChannel' does not have a valid units attribute. The attribute given is ''. # reference: 2.8.1.2 # see: https://cellml-specification.readthedocs.io/en/latest/reference/formal_and_informative/specB08.html?issue=2.8.1.2 # Issue 8: Variable 'V' in component 'sodiumChannel' has units of '' and an equivalent variable 'V' in component 'sodiumChannelEquations' with non-matching units of 'mV'. The mismatch is: # reference: # see:
# end 4 print('----------------------------------------------------------') print(' STEP 5: Add the units ') print('----------------------------------------------------------') # The validator has reported that the four variables are missing units attributes. # In this example none of the units exist yet, so we need to create all of them. # The variables' units should be: # - t, time has units of *milliseconds* # - X, gate status has units of *dimensionless* # - alpha_X and beta_X, rates, have units of *per millisecond*. # 5.a # Create the units which will be needed by your variables and add them to the model. ms = Units('ms') per_ms = Units('per_ms') # 5.b # Add Unit items to the units you created to define them. ms.addUnit('second', 'milli') per_ms.addUnit('second', 'milli', -1) # 5.c # Add the Units to the model (not the component) so that other components can make # use of them too. model.addUnits(ms) model.addUnits(per_ms) # 5.d # Use the setUnits function to associate them with the appropriate variables.
def test_standard_unit(self): from libcellml import Units u = Units() u.addUnit(Units.StandardUnit.AMPERE) u.addUnit(Units.StandardUnit.BECQUEREL) u.addUnit(Units.StandardUnit.CANDELA) u.addUnit(Units.StandardUnit.COULOMB) u.addUnit(Units.StandardUnit.DIMENSIONLESS) u.addUnit(Units.StandardUnit.FARAD) u.addUnit(Units.StandardUnit.GRAM) u.addUnit(Units.StandardUnit.GRAY) u.addUnit(Units.StandardUnit.HENRY) u.addUnit(Units.StandardUnit.HERTZ) u.addUnit(Units.StandardUnit.JOULE) u.addUnit(Units.StandardUnit.KATAL) u.addUnit(Units.StandardUnit.KELVIN) u.addUnit(Units.StandardUnit.KILOGRAM) u.addUnit(Units.StandardUnit.LITRE) u.addUnit(Units.StandardUnit.LUMEN) u.addUnit(Units.StandardUnit.LUX) u.addUnit(Units.StandardUnit.METRE) u.addUnit(Units.StandardUnit.MOLE) u.addUnit(Units.StandardUnit.NEWTON) u.addUnit(Units.StandardUnit.OHM) u.addUnit(Units.StandardUnit.PASCAL) u.addUnit(Units.StandardUnit.RADIAN) u.addUnit(Units.StandardUnit.SECOND) u.addUnit(Units.StandardUnit.SIEMENS) u.addUnit(Units.StandardUnit.SIEVERT) u.addUnit(Units.StandardUnit.STERADIAN) u.addUnit(Units.StandardUnit.TESLA) u.addUnit(Units.StandardUnit.VOLT) u.addUnit(Units.StandardUnit.WATT) u.addUnit(Units.StandardUnit.WEBER) self.assertRaises(RuntimeError, u.addUnit, Units.StandardUnit.AMPERE - 1) self.assertRaises(RuntimeError, u.addUnit, Units.StandardUnit.WEBER + 1)
def test_inheritance(self): import libcellml from libcellml import Units x = Units() self.assertIsInstance(x, libcellml.ImportedEntity) self.assertIsInstance(x, libcellml.NamedEntity) self.assertIsInstance(x, libcellml.Entity) # Test access to inherited methods x = Units() idx = 'test' self.assertEqual(x.getId(), '') x.setId(idx) self.assertEqual(x.getId(), idx) y = Units(x) self.assertEqual(y.getId(), idx)
def test_remove_all_units(self): from libcellml import Units # void removeAllUnits() u = Units() self.assertEqual(u.unitCount(), 0) u.addUnit('') self.assertEqual(u.unitCount(), 1) u.addUnit('') self.assertEqual(u.unitCount(), 2) u.removeAllUnits() self.assertEqual(u.unitCount(), 0)
def test_requires_imports(self): from libcellml import Units u = Units("Volt") self.assertFalse(u.requiresImports())
def test_remove_unit(self): from libcellml import Units # bool removeUnit(size_t index) u = Units() self.assertFalse(u.removeUnit(0)) self.assertFalse(u.removeUnit(1)) self.assertFalse(u.removeUnit(-1)) u.addUnit('hello') self.assertFalse(u.removeUnit(1)) self.assertFalse(u.removeUnit(-1)) self.assertTrue(u.removeUnit(0)) self.assertFalse(u.removeUnit(0)) del [u] # bool removeUnit(const std::string &reference) u = Units() self.assertFalse(u.removeUnit('hello')) u.addUnit('hello') self.assertFalse(u.removeUnit('hi')) self.assertTrue(u.removeUnit('hello')) self.assertFalse(u.removeUnit('hello')) del [u]
def test_unit_attributes(self): from libcellml import Units # void unitAttributes(size_t index, std::string &reference, # std::string &prefix, double &exponent, double &multiplier, std::string &id) u = Units() x = u.unitAttributes(0) self.assertIsInstance(x, list) self.assertEqual(x, ['', '', 1.0, 1.0, '']) u.addUnit('blabla', 'hello', 1.2, 3.4, 'unitid') x = u.unitAttributes(0) self.assertIsInstance(x, list) self.assertEqual(x, ['blabla', 'hello', 1.2, 3.4, 'unitid']) x = u.unitAttributes(1) self.assertIsInstance(x, list) self.assertEqual(x, ['', '', 1.0, 1.0, '']) del [u, x] # void unitAttributes(const std::string &reference, # std::string &prefix, double &exponent, double &multiplier) const; u = Units() x = u.unitAttributes('newton') self.assertIsInstance(x, list) self.assertEqual(x, ['newton', '', 1.0, 1.0, '']) u.addUnit('few', 'bars', 4.3, 2.1, 'job') x = u.unitAttributes('newton') self.assertIsInstance(x, list) self.assertEqual(x, ['newton', '', 1.0, 1.0, '']) x = u.unitAttributes('few') self.assertIsInstance(x, list) self.assertEqual(x, ['few', 'bars', 4.3, 2.1, 'job']) del [u, x]
def test_prefix(self): from libcellml import Units u = Units() u.addUnit('test', Units.Prefix.YOTTA) u.addUnit('test', Units.Prefix.ZETTA) u.addUnit('test', Units.Prefix.EXA) u.addUnit('test', Units.Prefix.PETA) u.addUnit('test', Units.Prefix.TERA) u.addUnit('test', Units.Prefix.GIGA) u.addUnit('test', Units.Prefix.MEGA) u.addUnit('test', Units.Prefix.KILO) u.addUnit('test', Units.Prefix.HECTO) u.addUnit('test', Units.Prefix.DECA) u.addUnit('test', Units.Prefix.DECI) u.addUnit('test', Units.Prefix.CENTI) u.addUnit('test', Units.Prefix.MILLI) u.addUnit('test', Units.Prefix.MICRO) u.addUnit('test', Units.Prefix.NANO) u.addUnit('test', Units.Prefix.PICO) u.addUnit('test', Units.Prefix.FEMTO) u.addUnit('test', Units.Prefix.ATTO) u.addUnit('test', Units.Prefix.ZEPTO) u.addUnit('test', Units.Prefix.YOCTO) self.assertRaises(RuntimeError, u.addUnit, 'test', Units.Prefix.YOTTA - 1) self.assertRaises(RuntimeError, u.addUnit, 'test', Units.Prefix.YOCTO + 1)
def test_item(self): from libcellml import Component, Issue, ImportSource, Model, Unit from libcellml import Reset, Units, Variable, CellmlElementType, VariablePair i = Issue() item = i.item() self.assertEqual(CellmlElementType.UNDEFINED, item[0]) self.assertIsNone(item[1]) i.setItem(CellmlElementType.VARIABLE, Variable("v")) vItem = i.item() self.assertEqual(CellmlElementType.VARIABLE, vItem[0]) self.assertEqual("v", vItem[1].name()) i.setItem(CellmlElementType.UNITS, Units("u")) uItem = i.item() self.assertEqual(CellmlElementType.UNITS, uItem[0]) self.assertEqual("u", uItem[1].name()) u = Units("ui") u.addUnit("volt") u.addUnit("second") u.addUnit("metre") i.setItem(CellmlElementType.UNIT, Unit(u, 2)) uiItem = i.item() self.assertEqual(CellmlElementType.UNIT, uiItem[0]) self.assertEqual("ui", uiItem[1].units().name()) self.assertEqual(2, uiItem[1].index()) v1 = Variable("v1") v2 = Variable("v2") i.setItem(CellmlElementType.CONNECTION, VariablePair(v1, v2)) vpItem = i.item() self.assertEqual(CellmlElementType.CONNECTION, vpItem[0]) self.assertEqual("v1", vpItem[1].variable1().name()) self.assertEqual("v2", vpItem[1].variable2().name()) v3 = Variable("v3") v4 = Variable("v4") i.setItem(CellmlElementType.MAP_VARIABLES, VariablePair(v3, v4)) vpItem = i.item() self.assertEqual(CellmlElementType.MAP_VARIABLES, vpItem[0]) self.assertEqual("v3", vpItem[1].variable1().name()) self.assertEqual("v4", vpItem[1].variable2().name()) r = Reset() r.setId("r") i.setItem(CellmlElementType.RESET, r) rItem = i.item() self.assertEqual(CellmlElementType.RESET, rItem[0]) self.assertEqual("r", rItem[1].id()) r.setId("r1") i.setItem(CellmlElementType.RESET_VALUE, r) rItem = i.item() self.assertEqual(CellmlElementType.RESET_VALUE, rItem[0]) self.assertEqual("r1", rItem[1].id()) r.setId("r2") i.setItem(CellmlElementType.TEST_VALUE, r) rItem = i.item() self.assertEqual(CellmlElementType.TEST_VALUE, rItem[0]) self.assertEqual("r2", rItem[1].id()) i.setItem(CellmlElementType.MODEL, Model("m")) mItem = i.item() self.assertEqual(CellmlElementType.MODEL, mItem[0]) self.assertEqual("m", mItem[1].name()) i.setItem(CellmlElementType.ENCAPSULATION, Model("e")) mItem = i.item() self.assertEqual(CellmlElementType.ENCAPSULATION, mItem[0]) self.assertEqual("e", mItem[1].name()) iS = ImportSource() iS.setId("is") i.setItem(CellmlElementType.IMPORT, iS) isItem = i.item() self.assertEqual(CellmlElementType.IMPORT, isItem[0]) self.assertEqual("is", isItem[1].id()) i.setItem(CellmlElementType.COMPONENT, Component("c")) cItem = i.item() self.assertEqual(CellmlElementType.COMPONENT, cItem[0]) self.assertEqual("c", cItem[1].name()) i.setItem(CellmlElementType.COMPONENT_REF, Component("c1")) cItem = i.item() self.assertEqual(CellmlElementType.COMPONENT_REF, cItem[0]) self.assertEqual("c1", cItem[1].name())
def test_add_unit(self): from libcellml import Units # void addUnit(const std::string &reference, const std::string &prefix, # double exponent=1.0, double multiplier=1.0) u = Units() u.addUnit('a', 'b') u.addUnit('a', 'b', 2.0) u.addUnit('a', 'b', -1) u.addUnit('a', 'b', 0) u.addUnit('a', 'b', 3, 3) u.addUnit('a', 'b', 0.1, -1.2) del u # void addUnit(const std::string &reference, int prefix, # double exponent, double multiplier=1.0) u = Units() u.addUnit('a', 1, -1) u.addUnit('a', 1, 2.3) u.addUnit('a', 1, -1, 3) u.addUnit('a', 1, -1, 2.3) u.addUnit('a', 1, 1.2, 3.4) u.addUnit('a', -1, -1) u.addUnit('a', -1, 2.3) u.addUnit('a', -1, -1, 3) u.addUnit('a', -1, -1, 2.3) u.addUnit('a', -1, 1.2, 3.4) del u # void addUnit(const std::string &reference, double exponent) u = Units() u.addUnit('a', 1.0) # TODO Ints get converted to Prefix enum, not to double! # u.addUnit('a', -1) del u # void addUnit(const std::string &reference) u = Units() u.addUnit('') u.addUnit('a') del u # void addUnit(StandardUnit standardRef, const std::string &prefix, # double exponent=1.0, double multiplier=1.0) u = Units() u.addUnit(Units.StandardUnit.KATAL, 'pico') u.addUnit(Units.StandardUnit.KATAL, 'pico', 1.0) u.addUnit(Units.StandardUnit.KATAL, 'pico', -1) u.addUnit(Units.StandardUnit.KATAL, 'pico', 1.0, 2.0) u.addUnit(Units.StandardUnit.KATAL, 'pico', 1, 2.0) u.addUnit(Units.StandardUnit.KATAL, 'pico', -1, 2) del u # void addUnit(StandardUnit standardRef, int prefix, # double exponent, double multiplier=1.0) u = Units() u.addUnit(Units.StandardUnit.KATAL, 1, 1.0) u.addUnit(Units.StandardUnit.KATAL, -1, -1.0) u.addUnit(Units.StandardUnit.KATAL, 1, 1.0, 1.0) u.addUnit(Units.StandardUnit.KATAL, -1, -1.0, 1.0, 'id') del u # void addUnit(StandardUnit standardRef, double exponent) # Hidden to avoid confusion with addUnit(StandardUnit, Prefix, double, # double) # void addUnit(StandardUnit standardRef) u = Units() u.addUnit(Units.StandardUnit.KATAL) del u
def test_unit_item_coverage(self): from libcellml import Units, Unit u = Units("bob") ui = Unit(u, 0) self.assertFalse(ui.isValid())
# 3.d Call the validator and print the messages to the terminal. # Expected errors refer to units referred to by these variables, but # which don't (yet) exist in the model. validator.validateModel(model) print_errors_to_terminal(validator) print("-----------------------------------------------") print(" STEP 4: Define the units and add to the model") print("-----------------------------------------------") # 4.a Defining the units of millisecond, millivolt, per_millisecond, # microA_per_cm2, and milliS_per_cm2. Note that the dimensionless # units are part of those built-in already, so do not need to be # defined here. ms = Units() ms.setName("millisecond") ms.addUnit("second", "milli") mV = Units() mV.setName("millivolt") mV.addUnit("volt", "milli") per_ms = Units() per_ms.setName("per_millisecond") per_ms.addUnit("millisecond", -1.0) microA_per_cm2 = Units() microA_per_cm2.setName("microA_per_cm2") microA_per_cm2.addUnit("ampere", "micro") microA_per_cm2.addUnit("metre", "centi", -2.0)