Ejemplo n.º 1
0
 def try_to_recover_or_error(_lhs_type_symbol, _rhs_type_symbol,
                             _containing_expression):
     if _rhs_type_symbol.is_castable_to(_lhs_type_symbol):
         if isinstance(_lhs_type_symbol, UnitTypeSymbol) \
          and isinstance(_rhs_type_symbol, UnitTypeSymbol):
             conversion_factor = UnitTypeSymbol.get_conversion_factor(
                 _lhs_type_symbol.astropy_unit,
                 _rhs_type_symbol.astropy_unit)
             if not conversion_factor == 1.:
                 # the units are mutually convertible, but require a factor unequal to 1 (e.g. mV and A*Ohm)
                 TypeCaster.do_magnitude_conversion_rhs_to_lhs(
                     _rhs_type_symbol, _lhs_type_symbol,
                     _containing_expression)
         # the units are mutually convertible (e.g. V and A*Ohm)
         code, message = Messages.get_implicit_cast_rhs_to_lhs(
             _rhs_type_symbol.print_symbol(),
             _lhs_type_symbol.print_symbol())
         Logger.log_message(
             error_position=_containing_expression.get_source_position(),
             code=code,
             message=message,
             log_level=LoggingLevel.INFO)
     else:
         code, message = Messages.get_type_different_from_expected(
             _lhs_type_symbol, _rhs_type_symbol)
         Logger.log_message(
             error_position=_containing_expression.get_source_position(),
             code=code,
             message=message,
             log_level=LoggingLevel.ERROR)
Ejemplo n.º 2
0
def handle_unit(unit_type):
    """
    Handles a handed over unit by creating the corresponding unit-type, storing it in the list of predefined
    units, creating a type symbol and returning it.
    :param unit_type: a single sympy unit symbol
    :type unit_type: Symbol (sympy)
    :return: a new type symbol
    :rtype: type_symbol
    """
    # first ensure that it does not already exists, if not create it and register it in the set of predefined units
    # first clean up the unit of not required components, here it is the 1.0 in front of the unit
    # e.g., 1.0 * 1 / ms. This step is not mandatory for correctness, but makes  reporting easier
    if isinstance(unit_type, units.Quantity) and unit_type.value == 1.0:
        to_process = unit_type.unit
    else:
        to_process = unit_type
    if str(to_process) not in PredefinedUnits.get_units().keys():
        unit_type_t = UnitType(name=str(to_process), unit=to_process)
        PredefinedUnits.register_unit(unit_type_t)
    # now create the corresponding type symbol if it does not exists
    if PredefinedTypes.get_type(str(to_process)) is None:
        type_symbol = UnitTypeSymbol(
            unit=PredefinedUnits.get_unit(str(to_process)))
        PredefinedTypes.register_type(type_symbol)
    return PredefinedTypes.get_type(name=str(to_process))
Ejemplo n.º 3
0
 def __register_units(cls):
     """
     Adds all units as predefined type symbols to the list of available types.
     """
     from pynestml.symbols.predefined_units import PredefinedUnits
     from pynestml.symbols.unit_type_symbol import UnitTypeSymbol
     units = PredefinedUnits.get_units()
     for unitName in units.keys():
         type_symbol = UnitTypeSymbol(unit=units[unitName])
         cls.name2type[unitName] = type_symbol
     return
Ejemplo n.º 4
0
 def register_unit(cls, unit):
     """
     Registers a new astropy unit into the system
     :param unit: an astropy Unit object
     :type unit: astropy.units.core.Unit
     """
     unit_type = UnitType(str(unit), unit)
     PredefinedUnits.register_unit(unit_type)
     type_symbol = UnitTypeSymbol(unit=unit_type)
     cls.register_type(type_symbol)
     return
Ejemplo n.º 5
0
 def register_unit(cls, unit):
     """
     Registers a new sympy unit into the system
     :param unit: a sympy unit.
     :type unit: SympyUnit
     """
     unit_type = UnitType(str(unit), unit)
     PredefinedUnits.register_unit(unit_type)
     type_symbol = UnitTypeSymbol(unit=unit_type)
     cls.register_type(type_symbol)
     return
Ejemplo n.º 6
0
    def is_conductance_based(self) -> bool:
        """
        Indicates whether this element is conductance based, based on the physical units of the spike input port. If the unit can be cast to Siemens, the function returns True, otherwise it returns False.

        :return: True if conductance based, otherwise False.
        """
        is_cond_based = self.type_symbol.is_castable_to(
            UnitTypeSymbol(unit=PredefinedUnits.get_unit("S")))
        is_curr_based = self.type_symbol.is_castable_to(
            UnitTypeSymbol(unit=PredefinedUnits.get_unit("A")))
        if is_cond_based == is_curr_based:
            code, message = Messages.get_could_not_determine_cond_based(
                type_str=self.type_symbol.print_nestml_type(), name=self.name)
            Logger.log_message(
                node=None,
                code=code,
                message=message,
                log_level=LoggingLevel.WARNING,
                error_position=ASTSourceLocation.get_added_source_position())
            return False

        return is_cond_based
Ejemplo n.º 7
0
    def do_magnitude_conversion_rhs_to_lhs(_rhs_type_symbol, _lhs_type_symbol, _containing_expression):
        """
        determine conversion factor from rhs to lhs, register it with the relevant expression, drop warning
        """
        _containing_expression.set_implicit_conversion_factor(
            UnitTypeSymbol.get_conversion_factor(_lhs_type_symbol.astropy_unit,
                                                 _rhs_type_symbol.astropy_unit))
        _containing_expression.type = _lhs_type_symbol

        code, message = Messages.get_implicit_magnitude_conversion(_lhs_type_symbol, _rhs_type_symbol,
                                                                   _containing_expression.get_implicit_conversion_factor())
        Logger.log_message(code=code, message=message,
                           error_position=_containing_expression.get_source_position(),
                           log_level=LoggingLevel.WARNING)
 def visit_ode_equation(self, node):
     """
     Checks the coco.
     :param node: A single ode equation.
     :type node: ast_ode_equation
     """
     variable_name = node.get_lhs().get_name()
     variable_symbol = node.get_lhs().get_scope().resolve_to_symbol(variable_name, SymbolKind.VARIABLE)
     variable_type = variable_symbol.type_symbol
     from pynestml.utils.unit_type import UnitType
     from pynestml.symbols.unit_type_symbol import UnitTypeSymbol
     inv_diff_order_unit_type = UnitType(name="inv_diff_order_unit_type_" + variable_name + "'" * node.get_lhs().get_differential_order(), unit=1 / units.s**node.get_lhs().get_differential_order())
     inv_diff_order_unit_type_symbol = UnitTypeSymbol(inv_diff_order_unit_type)
     lhs_type = variable_type * inv_diff_order_unit_type_symbol
     rhs_type = node.get_rhs().type
     if not rhs_type.is_castable_to(lhs_type):
         code, message = Messages.get_ode_needs_consistent_units(variable_name, node.get_lhs().get_differential_order(), lhs_type, rhs_type)
         Logger.log_message(error_position=node.get_source_position(), code=code,
                            message=message, log_level=LoggingLevel.ERROR)
 def test_unit_type(self):
     ms_unit = UnitType(name=str(units.ms), unit=units.ms)
     uts = UnitTypeSymbol(unit=ms_unit)
     result = convert(uts)
     self.assertEqual(result, 'double')