From f1d090ba1ef40357fddcd4114a26c66b9b3601b6 Mon Sep 17 00:00:00 2001 From: Andreagiovanni Reina Date: Fri, 27 Sep 2019 12:23:41 +0100 Subject: [PATCH 1/6] Fixed exceptions for stochastic analysis methods --- mumot/models.py | 2 +- mumot/utils.py | 20 ++++---------------- mumot/views.py | 11 ++++------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/mumot/models.py b/mumot/models.py index 0271865..469043c 100644 --- a/mumot/models.py +++ b/mumot/models.py @@ -1782,7 +1782,7 @@ def _getSingleAgentRules(self): if reactant in allConstantReactants: warningMsg = 'WARNING! Constant reactants appearing on the right-handside are ignored. Every constant reactant on the left-handside (implicitly) corresponds to the same constant reactant on the right-handside.\n'\ f'E.g., in rule ' + str(rule.lhsReactants) + ' -> ' + str(rule.rhsReactants) + ' constant reactants should not appear on the right-handside.' - print(warningMsg) + raise exceptions.MuMoTWarning(warningMsg) break # print maximum one warning # Add to the target of the first non-empty item the new born coming from empty-set or constant reactants diff --git a/mumot/utils.py b/mumot/utils.py index b4d77ab..6ca8197 100644 --- a/mumot/utils.py +++ b/mumot/utils.py @@ -143,7 +143,6 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= if reactant not in allReactants: error_msg = (f"Reactant '{reactant}' does not exist in this model.\n" f"Valid reactants are {allReactants}. Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) pop = initialState[reactant] @@ -161,7 +160,7 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= new_val = max(0, pop[0] + (1 - sumValues)) if not _almostEqual(pop[0], new_val): wrn_msg = f"WARNING! the initial value of reactant {reactant} has been changed to {new_val}\n" - print(wrn_msg) + raise exceptions.MuMoTWarning(wrn_msg) sumValues -= pop[0] sumValues += new_val initialState[reactant][0] = new_val @@ -180,7 +179,7 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= for reactant in allReactants if reactant != idleReactant]) wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" - print(wrn_msg) + raise exceptions.MuMoTWarning(wrn_msg) initialState[idleReactant][0] = new_val return [initialState, fixedBool] # print("Initial State is " + str(initialState)) @@ -228,7 +227,6 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= if decodedNetType is None: # terminating the process if the input argument is wrong error_msg = (f"The specified value for netType ={inputValue} is not valid. \n" "Accepted values are: 'full', 'erdos-renyi', 'barabasi-albert', and 'dynamic'.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) return [inputValue, True] @@ -246,7 +244,6 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= if (not netType[-1]) and inputValue is not None: error_msg = ("If netType is not fixed, netParam cannot be fixed. " "Either leave free to widget the 'netParam' or fix the 'netType'.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) # check if netParam range is valid or set the correct default range (systemSize is necessary) if utils._decodeNetworkTypeFromString(netType[0]) == consts.NetworkType.FULLY_CONNECTED: @@ -317,7 +314,6 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= if inputValue not in validVisualisationTypes: # terminating the process if the input argument is wrong errorMsg = (f"The specified value for visualisationType = {inputValue} is not valid.\n" f"Valid values are: {validVisualisationTypes}. Please correct it and retry.") - print(errorMsg) raise exceptions.MuMoTValueError(errorMsg) return [inputValue, True] else: @@ -333,7 +329,6 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= if inputValue not in reactants_str: error_msg = (f"The specified value for {optionName} = {inputValue} is not valid.\n" f"Valid values are the reactants: {reactants_str}. Please correct it and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) else: return [inputValue, True] @@ -429,18 +424,15 @@ def _parse_input_keyword_for_numeric_widgets( if initValueRangeStep is not None and getattr(initValueRangeStep, "__getitem__", None) is None: error_msg = (f"initValueRangeStep value '{initValueRangeStep}' must be specified in the format [val,min,max,step].\n" "Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) if inputValue is not None: if not isinstance(inputValue, numbers.Number): error_msg = (f"Input value '{inputValue}' is not a numeric vaule and must be a number.\n" "Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) elif validRange and (inputValue < validRange[0] or inputValue > validRange[1]): error_msg = (f"Input value '{inputValue}' has raised out-of-range exception. Valid range is {validRange}\n" "Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) else: if onlyValue: @@ -456,7 +448,6 @@ def _parse_input_keyword_for_numeric_widgets( if validRange and (initValueRangeStep < validRange[0] or initValueRangeStep > validRange[1]): error_msg = (f"Invalid init value={initValueRangeStep} has raised out-of-range exception. Valid range is {validRange}\n" "Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) else: outputValues = [initValueRangeStep] @@ -464,12 +455,10 @@ def _parse_input_keyword_for_numeric_widgets( if initValueRangeStep[1] > initValueRangeStep[2] or initValueRangeStep[0] < initValueRangeStep[1] or initValueRangeStep[0] > initValueRangeStep[2]: error_msg = (f"Invalid init range [val,min,max,step]={initValueRangeStep}. Value must be within min and max values.\n" "Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) elif validRange and (initValueRangeStep[1] < validRange[0] or initValueRangeStep[2] > validRange[1]): error_msg = (f"Invalid init range [val,min,max,step]={initValueRangeStep} has raised out-of-range exception. Valid range is {validRange}\n" "Please, correct the value and retry.") - print(error_msg) raise exceptions.MuMoTValueError(error_msg) else: outputValues = initValueRangeStep @@ -502,7 +491,6 @@ def _parse_input_keyword_for_boolean_widgets(inputValue, defaultValue, initValue paramNameForErrorMsg = f"for {paramNameForErrorMsg} = " if paramNameForErrorMsg else "" errorMsg = (f"The specified value {paramNameForErrorMsg}'{inputValue}' is not valid. \n" "The value must be a boolean True/False.") - print(errorMsg) raise exceptions.MuMoTValueError(errorMsg) return [inputValue, True] else: @@ -540,7 +528,7 @@ def _decodeNetworkTypeFromString(netTypeStr: str) -> Optional[consts.NetworkType 'dynamic': consts.NetworkType.DYNAMIC} if netTypeStr not in admissibleNetTypes: - print(f"ERROR! Invalid network type argument! Valid strings are: {admissibleNetTypes}") + raise exceptions.MuMoTValueError(f"ERROR! Invalid network type argument! Valid strings are: {admissibleNetTypes}") return admissibleNetTypes.get(netTypeStr, None) @@ -552,7 +540,7 @@ def _encodeNetworkTypeToString(netType: consts.NetworkType) -> Optional[str]: consts.NetworkType.DYNAMIC: 'dynamic'} if netType not in netTypeEncoding: - print(f"ERROR! Invalid netTypeEncoding table! Tried to encode network type: {netType}") + raise exceptions.MuMoTValueError(f"ERROR! Invalid netTypeEncoding table! Tried to encode network type: {netType}") return netTypeEncoding.get(netType, 'none') diff --git a/mumot/views.py b/mumot/views.py index 3656023..ed1fc07 100644 --- a/mumot/views.py +++ b/mumot/views.py @@ -3911,7 +3911,7 @@ def _constructorSpecificParams(self, MAParams): # if (not self._controller) and (not self._netType == consts.NetworkType.DYNAMIC): # if the user has specified the network type, we notify him/her through error-message # self._errorMessage.value = "Only Moving-Particle netType is available when rules contain the emptyset." if not self._netType == consts.NetworkType.DYNAMIC: - print("Only Moving-Particle netType is available when rules contain the emptyset or constant reactants.") + raise exceptions.MuMoTWarning("Only Moving-Particle netType is available when rules contain the emptyset or constant reactants.") self._netType = consts.NetworkType.DYNAMIC if self._controller: # updating value and disabling widget if self._controller._widgetsExtraParams.get('netType') is not None: @@ -3926,7 +3926,7 @@ def _constructorSpecificParams(self, MAParams): wrnMsg = "WARNING! net-param value " + str(self._netParam) + " is invalid for Moving-Particles. Valid range is [0,1] indicating the particles' communication range. \n" self._netParam = 0.1 wrnMsg += "New default values is '_netParam'=" + str(self._netParam) - print(wrnMsg) + raise exceptions.MuMoTWarning(wrnMsg) def _build_bookmark(self, includeParams=True) -> str: log_str = "bookmark = " if not self._silent else "" @@ -4224,7 +4224,6 @@ def _initGraph(self): else: errorMsg = ("ERROR! Invalid network parameter (link probability) for E-R networks. " f"It must be between 0 and 1; input is {self._netParam}") - print(errorMsg) raise exceptions.MuMoTValueError(errorMsg) elif (self._netType == consts.NetworkType.BARABASI_ALBERT): # print("Generating Barabasi-Albert graph") @@ -4234,12 +4233,10 @@ def _initGraph(self): else: errorMsg = ("ERROR! Invalid network parameter (number of edges per new node) for B-A networks." f"It must be an integer between 1 and {numNodes}; input is {self._netParam}") - print(errorMsg) raise exceptions.MuMoTValueError(errorMsg) elif (self._netType == consts.NetworkType.SPACE): # @todo: implement network generate by placing points (with local communication range) randomly in 2D space errorMsg = "ERROR: Graphs of type SPACE are not implemented yet." - print(errorMsg) raise exceptions.MuMoTValueError(errorMsg) elif (self._netType == consts.NetworkType.DYNAMIC): self._positions = [] @@ -4697,7 +4694,7 @@ def _simulationStep(self) -> Tuple[float, object]: bottom += prob if reaction_id == -1: - print("ERROR! Transition not found. Error in the algorithm execution.") + raise exceptions.MuMoTError("ERROR! Transition not found. Error in the algorithm execution.") sys.exit() # print("current state: " + str(self._currentState)) # print("triggered change: " + str(self._mumotModel._stoichiometry[reaction_id])) @@ -4708,7 +4705,7 @@ def _simulationStep(self) -> Tuple[float, object]: continue self._currentState[reactant] += re_stoch[1] - re_stoch[0] if self._currentState[reactant] < 0: - print(f"ERROR! Population size became negative: {self._currentState}; Error in the algorithm execution.") + raise exceptions.MuMoTError(f"ERROR! Population size became negative: {self._currentState}; Error in the algorithm execution.") sys.exit() # print(self._currentState) From 7c6a86990c998549e9721eb6fdb1d1a03058dfb6 Mon Sep 17 00:00:00 2001 From: Andreagiovanni Reina Date: Fri, 27 Sep 2019 15:11:11 +0100 Subject: [PATCH 2/6] Added possibility to have initial state >1 for integrate() and bifurcation(). For multiagent() and SSA() the widgets are still limited to the sum of 1. This fixes #318 #317 --- mumot/controllers.py | 1 + mumot/models.py | 31 +++++++++---- mumot/utils.py | 106 +++++++++++++++++++++++-------------------- 3 files changed, 80 insertions(+), 58 deletions(-) diff --git a/mumot/controllers.py b/mumot/controllers.py index 2b73903..d1f05af 100644 --- a/mumot/controllers.py +++ b/mumot/controllers.py @@ -1031,6 +1031,7 @@ def __init__(self, controllers, params=None, initWidgets=None, **kwargs): controller._view._chooseXrange = kwargs.get('choose_xrange') if key == 'initialState': ep1 = views_[0]._mumotModel._getAllReactants() + ep2 = [react for react in views_[0]._mumotModel._getAllReactants()[0] if react not in views_[0]._mumotModel._reactants][0] if views_[0]._mumotModel._systemSize is not None else None # @todo assuming same model for all views. # This operation is NOT correct when multicotroller views have different models. if key == 'visualisationType': diff --git a/mumot/models.py b/mumot/models.py index 469043c..5e46d3d 100644 --- a/mumot/models.py +++ b/mumot/models.py @@ -804,11 +804,13 @@ def integrate(self, showStateVars=None, initWidgets=None, **kwargs): IntParams = {} # read input parameters + IntParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] IntParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), - extraParam=self._getAllReactants()) + extraParam=self._getAllReactants(), + extraParam2 = IntParams['substitutedReactant'][0] ) IntParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), @@ -818,7 +820,6 @@ def integrate(self, showStateVars=None, initWidgets=None, **kwargs): inputValue=kwargs.get('plotProportions'), initValues=initWidgets.get('plotProportions')) IntParams['conserved'] = [kwargs.get('conserved', False), True] - IntParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] # construct controller viewController = controllers.MuMoTtimeEvolutionController( @@ -919,17 +920,18 @@ def noiseCorrelations(self, initWidgets=None, **kwargs): NCParams = {} # read input parameters + NCParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] NCParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), - extraParam=self._getAllReactants()) + extraParam=self._getAllReactants(), + extraParam2=NCParams['substitutedReactant'][0]) NCParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), initValues=initWidgets.get('maxTime')) NCParams['conserved'] = [kwargs.get('conserved', False), True] - NCParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] EQsys1stOrdMom, EOM_1stOrderMom, NoiseSubs1stOrder, EQsys2ndOrdMom, EOM_2ndOrderMom, NoiseSubs2ndOrder = \ _getNoiseEOM(_getFokkerPlanckEquation, _get_orderedLists_vKE, self._stoichiometry) @@ -1370,14 +1372,15 @@ def bifurcation(self, bifurcationParameter, stateVariable1, optionName='initBifParam', inputValue=kwargs.get('initBifParam'), initValues=initWidgets.get('initBifParam')) + BfcParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] BfcParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), - extraParam=self._getAllReactants()) + extraParam=self._getAllReactants(), + extraParam2=BfcParams['substitutedReactant'][0]) BfcParams['bifurcationParameter'] = [bifPar, True] BfcParams['conserved'] = [conserved, True] - BfcParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] # construct controller viewController = controllers.MuMoTbifurcationController( @@ -1464,12 +1467,16 @@ def multiagent(self, initWidgets=None, **kwargs): MAParams = {} # Read input parameters + MAParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + # next line forces the multiagent() view to have the sum of the initial states to 1. If this wants to be changed, remember to change also the callback function of the widgets _updateInitialStateWidgets in controllers.py + if MAParams['substitutedReactant'][0] is None: + MAParams['substitutedReactant'][0] = sorted(self._getAllReactants()[0], key=str)[0] MAParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), - extraParam=self._getAllReactants()) - MAParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + extraParam=self._getAllReactants(), + extraParam2=MAParams['substitutedReactant'][0]) MAParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), @@ -1622,12 +1629,16 @@ def SSA(self, initWidgets=None, **kwargs): ssaParams = {} # Read input parameters + ssaParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + # next line forces the SSA() view to have the sum of the initial states to 1. If this wants to be changed, remember to change also the callback function of the widgets _updateInitialStateWidgets in controllers.py + if ssaParams['substitutedReactant'][0] is None: + ssaParams['substitutedReactant'][0] = sorted(self._getAllReactants()[0], key=str)[0] ssaParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), - extraParam=self._getAllReactants()) - ssaParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + extraParam=self._getAllReactants(), + extraParam2=ssaParams['substitutedReactant'][0]) ssaParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), diff --git a/mumot/utils.py b/mumot/utils.py index 6ca8197..28f1c91 100644 --- a/mumot/utils.py +++ b/mumot/utils.py @@ -101,10 +101,12 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= """ if optionName == 'initialState': (allReactants, _) = extraParam + fixSumTo1 = extraParam2 is not None + idleReactant = extraParam2 #if extraParam2 is not None else sorted(allReactants, key=str)[0] initialState = {} # handle initialState dictionary (either convert or generate a default one) if inputValue is not None: - for i, reactant in enumerate(sorted(inputValue.keys(), key=str)): + for reactant in sorted(inputValue.keys(), key=str): pop = inputValue[reactant] initPop = initValues.get(reactant) if initValues is not None else None @@ -116,14 +118,14 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= defaults.MuMoTdefault._agentsLimits[1], defaults.MuMoTdefault._agentsStep], initValueRangeStep=initPop, - validRange=(0.0, 1.0)) + validRange=(0.0, 1.0) if fixSumTo1 else (0, float("inf"))) fixedBool = True else: first = True initValuesSympy = ({parse_latex(reactant): pop for reactant, pop in initValues.items()} if initValues is not None else {}) - for i, reactant in enumerate(sorted(allReactants, key=str)): + for reactant in sorted(allReactants, key=str): defaultV = defaults.MuMoTdefault._agents if first else 0 first = False initialState[reactant] = _parse_input_keyword_for_numeric_widgets( @@ -133,54 +135,62 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= defaults.MuMoTdefault._agentsLimits[1], defaults.MuMoTdefault._agentsStep], initValueRangeStep=initValuesSympy.get(reactant), - validRange=(0.0, 1.0)) + validRange=(0.0, 1.0) if fixSumTo1 else (0, float("inf"))) fixedBool = False # Check if the initialState values are valid - sumValues = sum([initialState[reactant][0] for reactant in allReactants]) - minStep = min([initialState[reactant][3] for reactant in allReactants]) - for i, reactant in enumerate(sorted(allReactants, key=str)): - if reactant not in allReactants: - error_msg = (f"Reactant '{reactant}' does not exist in this model.\n" - f"Valid reactants are {allReactants}. Please, correct the value and retry.") - raise exceptions.MuMoTValueError(error_msg) - - pop = initialState[reactant] - # check if the proportions sum to 1 - if i == 0: - idleReactant = reactant - idleValue = pop[0] - # the idleValue have range min-max reset to [0,1] - initialState[reactant][1] = 0 - initialState[reactant][2] = 1 - initialState[reactant][3] = minStep - else: - # modify (if necessary) the initial value - if sumValues > 1: - new_val = max(0, pop[0] + (1 - sumValues)) - if not _almostEqual(pop[0], new_val): - wrn_msg = f"WARNING! the initial value of reactant {reactant} has been changed to {new_val}\n" - raise exceptions.MuMoTWarning(wrn_msg) - sumValues -= pop[0] - sumValues += new_val - initialState[reactant][0] = new_val - # modify (if necessary) min-max - pop = initialState[reactant] - sumNorm = sumValues if sumValues <= 1 else 1 - if pop[2] > (1 - sumNorm + pop[0] + idleValue): # max - if pop[1] > (1 - sumNorm + pop[0] + idleValue): # min - initialState[reactant][1] = (1 - sumNorm + pop[0] + idleValue) - initialState[reactant][2] = (1 - sumNorm + pop[0] + idleValue) - if pop[1] > (1 - sumNorm + pop[0]): # min - initialState[reactant][1] = (1 - sumNorm + pop[0]) - # initialState[reactant][3] = minStep - if not _almostEqual(sumValues, 1): - new_val = 1 - sum([initialState[reactant][0] - for reactant in allReactants - if reactant != idleReactant]) - wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" - raise exceptions.MuMoTWarning(wrn_msg) - initialState[idleReactant][0] = new_val + if fixSumTo1: + sumValues = sum([initialState[reactant][0] for reactant in allReactants]) + minStep = min([initialState[reactant][3] for reactant in allReactants]) + + # first thing setting the values of the idleReactant + idleValue = initialState[idleReactant][0] + if idleValue > 1: + wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" + print(wrn_msg) + #raise exceptions.MuMoTWarning(wrn_msg) + initialState[idleReactant][0] = new_val + # the idleValue have range min-max reset to [0,1] + initialState[idleReactant][1] = 0 + initialState[idleReactant][2] = 1 + initialState[idleReactant][3] = minStep + for reactant in sorted(allReactants, key=str): + if reactant not in allReactants: + error_msg = (f"Reactant '{reactant}' does not exist in this model.\n" + f"Valid reactants are {allReactants}. Please, correct the value and retry.") + raise exceptions.MuMoTValueError(error_msg) + + # check if the proportions sum to 1 + if reactant != idleReactant: + pop = initialState[reactant] + # modify (if necessary) the initial value + if sumValues > 1: + new_val = max(0, pop[0] + (1 - sumValues)) + if not _almostEqual(pop[0], new_val): + wrn_msg = f"WARNING! the initial value of reactant {reactant} has been changed to {new_val}\n" + print(wrn_msg) + #raise exceptions.MuMoTWarning(wrn_msg) + sumValues -= pop[0] + sumValues += new_val + initialState[reactant][0] = new_val + # modify (if necessary) min-max + pop = initialState[reactant] + sumNorm = sumValues if sumValues <= 1 else 1 + if pop[2] > (1 - sumNorm + pop[0] + idleValue): # max + if pop[1] > (1 - sumNorm + pop[0] + idleValue): # min + initialState[reactant][1] = (1 - sumNorm + pop[0] + idleValue) + initialState[reactant][2] = (1 - sumNorm + pop[0] + idleValue) + if pop[1] > (1 - sumNorm + pop[0]): # min + initialState[reactant][1] = (1 - sumNorm + pop[0]) + # initialState[reactant][3] = minStep + if not _almostEqual(sumValues, 1): + new_val = 1 - sum([initialState[reactant][0] + for reactant in allReactants + if reactant != idleReactant]) + wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" + print(wrn_msg) + #raise exceptions.MuMoTWarning(wrn_msg) + initialState[idleReactant][0] = new_val return [initialState, fixedBool] # print("Initial State is " + str(initialState)) if optionName == 'maxTime': From 890f53fdea86cce59ab5528e92b5b661527e5ac6 Mon Sep 17 00:00:00 2001 From: Andreagiovanni Reina Date: Fri, 27 Sep 2019 16:02:29 +0100 Subject: [PATCH 3/6] Forcing sum to 1 for all views #317 #318 --- mumot/models.py | 31 +++++++++++++++++++++---------- mumot/utils.py | 48 ++++++++++++++++++++++++++---------------------- mumot/views.py | 7 +++++-- 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/mumot/models.py b/mumot/models.py index 5e46d3d..0294c8b 100644 --- a/mumot/models.py +++ b/mumot/models.py @@ -805,12 +805,14 @@ def integrate(self, showStateVars=None, initWidgets=None, **kwargs): IntParams = {} # read input parameters IntParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + # the first item of extraParam2 for intial state is fixSumTo1, the second is the idle reactant + extraParam2initS = [True, IntParams['substitutedReactant'][0]] IntParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), extraParam=self._getAllReactants(), - extraParam2 = IntParams['substitutedReactant'][0] ) + extraParam2 = extraParam2initS ) IntParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), @@ -921,12 +923,14 @@ def noiseCorrelations(self, initWidgets=None, **kwargs): NCParams = {} # read input parameters NCParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + # the first item of extraParam2 for intial state is fixSumTo1, the second is the idle reactant + extraParam2initS = [True, NCParams['substitutedReactant'][0]] NCParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), extraParam=self._getAllReactants(), - extraParam2=NCParams['substitutedReactant'][0]) + extraParam2=extraParam2initS) NCParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), @@ -1373,12 +1377,14 @@ def bifurcation(self, bifurcationParameter, stateVariable1, inputValue=kwargs.get('initBifParam'), initValues=initWidgets.get('initBifParam')) BfcParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] + # the first item of extraParam2 for intial state is fixSumTo1, the second is the idle reactant + extraParam2initS = [True, BfcParams['substitutedReactant'][0]] BfcParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), extraParam=self._getAllReactants(), - extraParam2=BfcParams['substitutedReactant'][0]) + extraParam2=extraParam2initS) BfcParams['bifurcationParameter'] = [bifPar, True] BfcParams['conserved'] = [conserved, True] @@ -1468,15 +1474,17 @@ def multiagent(self, initWidgets=None, **kwargs): MAParams = {} # Read input parameters MAParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] - # next line forces the multiagent() view to have the sum of the initial states to 1. If this wants to be changed, remember to change also the callback function of the widgets _updateInitialStateWidgets in controllers.py - if MAParams['substitutedReactant'][0] is None: + # the first item of extraParam2 for intial state is fixSumTo1, the second is the idle reactant + # in the multiagent() view, the sum of the initial states is fixed to 1. If this wants to be changed, remember to change also the callback function of the widgets _updateInitialStateWidgets in controllers.py + if MAParams['substitutedReactant'][0] is None and len(self._getAllReactants()[0]) > 1: MAParams['substitutedReactant'][0] = sorted(self._getAllReactants()[0], key=str)[0] + extraParam2initS = [True, MAParams['substitutedReactant'][0]] MAParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), extraParam=self._getAllReactants(), - extraParam2=MAParams['substitutedReactant'][0]) + extraParam2=extraParam2initS) MAParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), @@ -1630,15 +1638,17 @@ def SSA(self, initWidgets=None, **kwargs): ssaParams = {} # Read input parameters ssaParams['substitutedReactant'] = [[react for react in self._getAllReactants()[0] if react not in self._reactants][0] if self._systemSize is not None else None, True] - # next line forces the SSA() view to have the sum of the initial states to 1. If this wants to be changed, remember to change also the callback function of the widgets _updateInitialStateWidgets in controllers.py - if ssaParams['substitutedReactant'][0] is None: + # the first item of extraParam2 for intial state is fixSumTo1, the second is the idle reactant + # in the SSA() view, the sum of the initial states is fixed to 1. If this wants to be changed, remember to change also the callback function of the widgets _updateInitialStateWidgets in controllers.py + if ssaParams['substitutedReactant'][0] is None and len(self._getAllReactants()[0]) > 1: ssaParams['substitutedReactant'][0] = sorted(self._getAllReactants()[0], key=str)[0] + extraParam2initS = [True, ssaParams['substitutedReactant'][0]] ssaParams['initialState'] = utils._format_advanced_option( optionName='initialState', inputValue=kwargs.get('initialState'), initValues=initWidgets.get('initialState'), extraParam=self._getAllReactants(), - extraParam2=ssaParams['substitutedReactant'][0]) + extraParam2=extraParam2initS) ssaParams['maxTime'] = utils._format_advanced_option( optionName='maxTime', inputValue=kwargs.get('maxTime'), @@ -1793,7 +1803,8 @@ def _getSingleAgentRules(self): if reactant in allConstantReactants: warningMsg = 'WARNING! Constant reactants appearing on the right-handside are ignored. Every constant reactant on the left-handside (implicitly) corresponds to the same constant reactant on the right-handside.\n'\ f'E.g., in rule ' + str(rule.lhsReactants) + ' -> ' + str(rule.rhsReactants) + ' constant reactants should not appear on the right-handside.' - raise exceptions.MuMoTWarning(warningMsg) + print(warningMsg) + #raise exceptions.MuMoTWarning(warningMsg) break # print maximum one warning # Add to the target of the first non-empty item the new born coming from empty-set or constant reactants diff --git a/mumot/utils.py b/mumot/utils.py index 28f1c91..0e33640 100644 --- a/mumot/utils.py +++ b/mumot/utils.py @@ -101,8 +101,8 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= """ if optionName == 'initialState': (allReactants, _) = extraParam - fixSumTo1 = extraParam2 is not None - idleReactant = extraParam2 #if extraParam2 is not None else sorted(allReactants, key=str)[0] + fixSumTo1 = extraParam2[0] + idleReactant = extraParam2[1] initialState = {} # handle initialState dictionary (either convert or generate a default one) if inputValue is not None: @@ -143,17 +143,20 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= sumValues = sum([initialState[reactant][0] for reactant in allReactants]) minStep = min([initialState[reactant][3] for reactant in allReactants]) - # first thing setting the values of the idleReactant - idleValue = initialState[idleReactant][0] - if idleValue > 1: - wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" - print(wrn_msg) - #raise exceptions.MuMoTWarning(wrn_msg) - initialState[idleReactant][0] = new_val - # the idleValue have range min-max reset to [0,1] - initialState[idleReactant][1] = 0 - initialState[idleReactant][2] = 1 - initialState[idleReactant][3] = minStep + # first thing setting the values of the idleReactant + if idleReactant is not None: + idleValue = initialState[idleReactant][0] + if idleValue > 1: + wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" + print(wrn_msg) + #raise exceptions.MuMoTWarning(wrn_msg) + initialState[idleReactant][0] = new_val + # the idleValue have range min-max reset to [0,1] + initialState[idleReactant][1] = 0 + initialState[idleReactant][2] = 1 + initialState[idleReactant][3] = minStep + else: + idleValue = 0 for reactant in sorted(allReactants, key=str): if reactant not in allReactants: error_msg = (f"Reactant '{reactant}' does not exist in this model.\n" @@ -174,15 +177,16 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= sumValues += new_val initialState[reactant][0] = new_val # modify (if necessary) min-max - pop = initialState[reactant] - sumNorm = sumValues if sumValues <= 1 else 1 - if pop[2] > (1 - sumNorm + pop[0] + idleValue): # max - if pop[1] > (1 - sumNorm + pop[0] + idleValue): # min - initialState[reactant][1] = (1 - sumNorm + pop[0] + idleValue) - initialState[reactant][2] = (1 - sumNorm + pop[0] + idleValue) - if pop[1] > (1 - sumNorm + pop[0]): # min - initialState[reactant][1] = (1 - sumNorm + pop[0]) - # initialState[reactant][3] = minStep + if idleReactant is not None: + pop = initialState[reactant] + sumNorm = sumValues if sumValues <= 1 else 1 + if pop[2] > (1 - sumNorm + pop[0] + idleValue): # max + if pop[1] > (1 - sumNorm + pop[0] + idleValue): # min + initialState[reactant][1] = (1 - sumNorm + pop[0] + idleValue) + initialState[reactant][2] = (1 - sumNorm + pop[0] + idleValue) + if pop[1] > (1 - sumNorm + pop[0]): # min + initialState[reactant][1] = (1 - sumNorm + pop[0]) + # initialState[reactant][3] = minStep if not _almostEqual(sumValues, 1): new_val = 1 - sum([initialState[reactant][0] for reactant in allReactants diff --git a/mumot/views.py b/mumot/views.py index ed1fc07..a964133 100644 --- a/mumot/views.py +++ b/mumot/views.py @@ -3911,7 +3911,9 @@ def _constructorSpecificParams(self, MAParams): # if (not self._controller) and (not self._netType == consts.NetworkType.DYNAMIC): # if the user has specified the network type, we notify him/her through error-message # self._errorMessage.value = "Only Moving-Particle netType is available when rules contain the emptyset." if not self._netType == consts.NetworkType.DYNAMIC: - raise exceptions.MuMoTWarning("Only Moving-Particle netType is available when rules contain the emptyset or constant reactants.") + wrnMsg = "Only Moving-Particle netType is available when rules contain the emptyset or constant reactants." + print(wrnMsg) + #raise exceptions.MuMoTWarning() self._netType = consts.NetworkType.DYNAMIC if self._controller: # updating value and disabling widget if self._controller._widgetsExtraParams.get('netType') is not None: @@ -3926,7 +3928,8 @@ def _constructorSpecificParams(self, MAParams): wrnMsg = "WARNING! net-param value " + str(self._netParam) + " is invalid for Moving-Particles. Valid range is [0,1] indicating the particles' communication range. \n" self._netParam = 0.1 wrnMsg += "New default values is '_netParam'=" + str(self._netParam) - raise exceptions.MuMoTWarning(wrnMsg) + print(wrnMsg) + #raise exceptions.MuMoTWarning(wrnMsg) def _build_bookmark(self, includeParams=True) -> str: log_str = "bookmark = " if not self._silent else "" From 1c08906506417adace688be039595080ac0357ff Mon Sep 17 00:00:00 2001 From: Andreagiovanni Reina Date: Fri, 27 Sep 2019 17:40:46 +0100 Subject: [PATCH 4/6] Patched issue with multiController --- mumot/controllers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mumot/controllers.py b/mumot/controllers.py index d1f05af..1f77ea0 100644 --- a/mumot/controllers.py +++ b/mumot/controllers.py @@ -1031,7 +1031,7 @@ def __init__(self, controllers, params=None, initWidgets=None, **kwargs): controller._view._chooseXrange = kwargs.get('choose_xrange') if key == 'initialState': ep1 = views_[0]._mumotModel._getAllReactants() - ep2 = [react for react in views_[0]._mumotModel._getAllReactants()[0] if react not in views_[0]._mumotModel._reactants][0] if views_[0]._mumotModel._systemSize is not None else None + ep2 = [True, [react for react in views_[0]._mumotModel._getAllReactants()[0] if react not in views_[0]._mumotModel._reactants][0] if views_[0]._mumotModel._systemSize is not None else None] # @todo assuming same model for all views. # This operation is NOT correct when multicotroller views have different models. if key == 'visualisationType': From ab14ba2cb7610ba980b5b7c6059cd78c75f9dec3 Mon Sep 17 00:00:00 2001 From: Andreagiovanni Reina Date: Fri, 27 Sep 2019 19:01:31 +0100 Subject: [PATCH 5/6] Patched issue for 1D models --- mumot/utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mumot/utils.py b/mumot/utils.py index 0e33640..5339a50 100644 --- a/mumot/utils.py +++ b/mumot/utils.py @@ -188,13 +188,14 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= initialState[reactant][1] = (1 - sumNorm + pop[0]) # initialState[reactant][3] = minStep if not _almostEqual(sumValues, 1): + reactantToFix = sorted(allReactants, key=str)[0] if idleReactant is None else idleReactant new_val = 1 - sum([initialState[reactant][0] for reactant in allReactants - if reactant != idleReactant]) - wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" + if reactant != reactantToFix]) + wrn_msg = f"WARNING! the initial value of reactant {reactantToFix} has been changed to {new_val}\n" print(wrn_msg) #raise exceptions.MuMoTWarning(wrn_msg) - initialState[idleReactant][0] = new_val + initialState[reactantToFix][0] = new_val return [initialState, fixedBool] # print("Initial State is " + str(initialState)) if optionName == 'maxTime': From e94b5566caafc30781fe719baac4d5c9aaf2cc43 Mon Sep 17 00:00:00 2001 From: James Marshall Date: Mon, 30 Sep 2019 12:18:36 +0100 Subject: [PATCH 6/6] Sum to 1 for all views; implement warnings correctly --- mumot/exceptions.py | 1 - mumot/models.py | 4 ++-- mumot/utils.py | 13 ++++++------- mumot/views.py | 7 +++---- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/mumot/exceptions.py b/mumot/exceptions.py index 6880d65..ef96c9b 100644 --- a/mumot/exceptions.py +++ b/mumot/exceptions.py @@ -1,6 +1,5 @@ """MuMoT warning, exception and error classes.""" - class MuMoTWarning(Warning): """Class to report MuMoT-specific warnings. """ diff --git a/mumot/models.py b/mumot/models.py index 0294c8b..71d4a0d 100644 --- a/mumot/models.py +++ b/mumot/models.py @@ -25,6 +25,7 @@ Function ) from sympy.parsing.latex import parse_latex +from warnings import warn from . import ( controllers, @@ -1803,8 +1804,7 @@ def _getSingleAgentRules(self): if reactant in allConstantReactants: warningMsg = 'WARNING! Constant reactants appearing on the right-handside are ignored. Every constant reactant on the left-handside (implicitly) corresponds to the same constant reactant on the right-handside.\n'\ f'E.g., in rule ' + str(rule.lhsReactants) + ' -> ' + str(rule.rhsReactants) + ' constant reactants should not appear on the right-handside.' - print(warningMsg) - #raise exceptions.MuMoTWarning(warningMsg) + warn(warningMsg, exceptions.MuMoTWarning) break # print maximum one warning # Add to the target of the first non-empty item the new born coming from empty-set or constant reactants diff --git a/mumot/utils.py b/mumot/utils.py index 5339a50..2e5f45a 100644 --- a/mumot/utils.py +++ b/mumot/utils.py @@ -4,6 +4,7 @@ import numpy as np from sympy.parsing.latex import parse_latex +from warnings import warn from . import ( consts, @@ -101,7 +102,8 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= """ if optionName == 'initialState': (allReactants, _) = extraParam - fixSumTo1 = extraParam2[0] + #fixSumTo1 = extraParam2[0] # until we have better information, all views should sum to 1, then use system size to scale + fixSumTo1 = True idleReactant = extraParam2[1] initialState = {} # handle initialState dictionary (either convert or generate a default one) @@ -148,8 +150,7 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= idleValue = initialState[idleReactant][0] if idleValue > 1: wrn_msg = f"WARNING! the initial value of reactant {idleReactant} has been changed to {new_val}\n" - print(wrn_msg) - #raise exceptions.MuMoTWarning(wrn_msg) + warn(wrn_msg, exceptions.MuMoTWarning) initialState[idleReactant][0] = new_val # the idleValue have range min-max reset to [0,1] initialState[idleReactant][1] = 0 @@ -171,8 +172,7 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= new_val = max(0, pop[0] + (1 - sumValues)) if not _almostEqual(pop[0], new_val): wrn_msg = f"WARNING! the initial value of reactant {reactant} has been changed to {new_val}\n" - print(wrn_msg) - #raise exceptions.MuMoTWarning(wrn_msg) + warn(wrn_msg, exceptions.MuMoTWarning) sumValues -= pop[0] sumValues += new_val initialState[reactant][0] = new_val @@ -193,8 +193,7 @@ def _format_advanced_option(optionName: str, inputValue, initValues, extraParam= for reactant in allReactants if reactant != reactantToFix]) wrn_msg = f"WARNING! the initial value of reactant {reactantToFix} has been changed to {new_val}\n" - print(wrn_msg) - #raise exceptions.MuMoTWarning(wrn_msg) + warn(wrn_msg, exceptions.MuMoTWarning) initialState[reactantToFix][0] = new_val return [initialState, fixedBool] # print("Initial State is " + str(initialState)) diff --git a/mumot/views.py b/mumot/views.py index a964133..6639419 100644 --- a/mumot/views.py +++ b/mumot/views.py @@ -32,6 +32,7 @@ symbols, ) from sympy.parsing.latex import parse_latex +from warnings import warn from . import ( consts, @@ -3912,8 +3913,7 @@ def _constructorSpecificParams(self, MAParams): # self._errorMessage.value = "Only Moving-Particle netType is available when rules contain the emptyset." if not self._netType == consts.NetworkType.DYNAMIC: wrnMsg = "Only Moving-Particle netType is available when rules contain the emptyset or constant reactants." - print(wrnMsg) - #raise exceptions.MuMoTWarning() + warn(wrnMsg, exceptions.MuMoTWarning) self._netType = consts.NetworkType.DYNAMIC if self._controller: # updating value and disabling widget if self._controller._widgetsExtraParams.get('netType') is not None: @@ -3928,8 +3928,7 @@ def _constructorSpecificParams(self, MAParams): wrnMsg = "WARNING! net-param value " + str(self._netParam) + " is invalid for Moving-Particles. Valid range is [0,1] indicating the particles' communication range. \n" self._netParam = 0.1 wrnMsg += "New default values is '_netParam'=" + str(self._netParam) - print(wrnMsg) - #raise exceptions.MuMoTWarning(wrnMsg) + warn(wrnMsg, exceptions.MuMoTWarning) def _build_bookmark(self, includeParams=True) -> str: log_str = "bookmark = " if not self._silent else ""