def __init__(self, model, lookup_params=DEFAULT_LOOKUP_PARAMETERS): """ Initialise a LookUpTables instance :param model: A :class:`cellmlmanip.Model` object. :param lookup_params: Optional collection of lists: [[<metadata tag>, mTableMins, mTableMaxs, mTableSteps]] """ self._lookup_parameters = tuple({ 'metadata_tag': param[0], 'mTableMins': param[1], 'mTableMaxs': param[2], 'mTableSteps': param[3], 'table_used_in_methods': set(), 'var': None, 'lookup_epxrs': [] } for param in lookup_params) self._model = model self._lookup_variables = set() self._lookup_table_expr = collections.OrderedDict() self._lookup_params_processed, self._lookup_params_printed = False, False self._method_printed = None for param in self._lookup_parameters: try: var = self._model.get_variable_by_ontology_term( (OXMETA, param['metadata_tag'])) self._lookup_variables.add(var) param['var'] = var except KeyError: LOGGER.warning('A lookup table was specified for ' + param['metadata_tag'] + ' but it is not tagged in the model, skipping!')
def _tag_ionic_vars(model): """ Get the ionic variables, defining the ionic derivatives""" # figure out the currents (by finding variables with the same units as the stimulus) # Only equations with the same (lhs) units as the STIMULUS_CURRENT are kept. # Also exclude membrane_stimulus_current variable itself, and default_stimulus equations (if model has those) # Manually recurse down the equation graph (bfs style) if no currents are found # If we don't have a stimulus_current we look for a set of default unit dimensions stimulus_unit_dims = [u.dimensionality for u in model.stimulus_units] if model.membrane_stimulus_current_orig is not None: stimulus_unit_dims = [ model.membrane_stimulus_current_orig.units.dimensionality ] + stimulus_unit_dims stimulus_params = set() for tag, _, _ in STIM_PARAM_TAGS: try: stimulus_params.add( model.get_variable_by_ontology_term((OXMETA, tag))) except KeyError: pass # doesn't need to have all params ionic_var_eqs = [] for dim in stimulus_unit_dims: if len(ionic_var_eqs) > 0: break equations, old_equations = list(filter(None, [model.dvdt])), None while len(ionic_var_eqs) == 0 and old_equations != equations: old_equations = equations equations = get_equations_for( model, equations, recurse=False, filter_modifiable_parameters_lhs=False, optimise=False) ionic_var_eqs = \ [eq for eq in equations for eq in equations if eq.lhs not in (model.membrane_stimulus_current_orig, stimulus_params) and model.units.evaluate_units(eq.lhs).dimensionality == dim and eq.lhs is not model.dvdt] equations = [eq.lhs for eq in equations] for eq in ionic_var_eqs: set_is_metadata(model, eq.lhs, 'ionic-current_chaste_codegen') assert len(model.dvdt_eq) <= 1, "Multiple dvdt equations found" if len(model.dvdt_eq) == 1: model.ionic_stimulus_sign = _stimulus_sign(model, model.dvdt_eq[0].rhs, [], stimulus_current=None) else: LOGGER.warning( model.name + ' has no ionic currents you may have trouble generating valid chaste code without.' ) model.ionic_stimulus_sign = 1
def _get_membrane_capacitance(model): """ Find membrane_capacitance if the model has it and convert it to uF / uF_per_cm2 if necessary Try to convert the capacitance and converts it to appropriate units. see: https://chaste.cs.ox.ac.uk/trac/ticket/1364 units converted to: Dimensions of current Dimensions of capacitance amps per unit area farads per unit area amps per unit capacitance We don't care amps farads """ try: capacitance = model.get_variable_by_ontology_term( (OXMETA, 'membrane_capacitance')) except KeyError: LOGGER.info('The model has no capacitance tagged.') return None try: capacitance = model.convert_variable( capacitance, model.conversion_units.get_unit('uF'), DataDirectionFlow.OUTPUT) except DimensionalityError: try: capacitance = model.convert_variable( capacitance, model.conversion_units.get_unit('uF_per_cm2'), DataDirectionFlow.OUTPUT) except DimensionalityError: pass # Check units match up with what is expected if model.membrane_stimulus_current_orig is not None: uA_dim = model.conversion_units.get_unit('uA').dimensionality uA_per_cm2_dim = model.conversion_units.get_unit( 'uA_per_cm2').dimensionality uF_dim = model.conversion_units.get_unit('uF').dimensionality uF_per_cm2_dim = model.conversion_units.get_unit( 'uF_per_cm2').dimensionality current_dim = model.membrane_stimulus_current_orig.units.dimensionality capac_dim = capacitance.units.dimensionality if (current_dim == uA_dim and not capac_dim == uF_dim) or \ (current_dim == uA_per_cm2_dim and not capac_dim == uF_per_cm2_dim): LOGGER.warning(model.name + ' The model has capacitance in incompatible units.') return capacitance