diff --git a/mira/metamodel/io.py b/mira/metamodel/io.py index 84c83a3e7..b268bd557 100644 --- a/mira/metamodel/io.py +++ b/mira/metamodel/io.py @@ -2,7 +2,7 @@ import json import sympy -from .template_model import TemplateModel +from .template_model import TemplateModel, SympyExprStr def model_from_json_file(fname) -> TemplateModel: @@ -42,6 +42,8 @@ def expression_to_mathml(expression: sympy.Expr, *args, **kwargs) -> str: Here we pay attention to not style underscores and numeric suffixes in special ways. """ + if isinstance(expression, SympyExprStr): + expression = expression.args[0] mappings = {} for sym in expression.atoms(sympy.Symbol): name = '|' + str(sym).replace('_', 'QQQ') + '|' diff --git a/mira/metamodel/schema.json b/mira/metamodel/schema.json index 6621ec5ad..e32b2c46f 100644 --- a/mira/metamodel/schema.json +++ b/mira/metamodel/schema.json @@ -30,6 +30,11 @@ "description": "The name of the concept.", "type": "string" }, + "display_name": { + "title": "Display Name", + "description": "An optional display name for the concept. If not provided, the name can be used for display purposes.", + "type": "string" + }, "description": { "title": "Description", "description": "An optional description of the concept.", @@ -470,6 +475,11 @@ "description": "The name of the concept.", "type": "string" }, + "display_name": { + "title": "Display Name", + "description": "An optional display name for the concept. If not provided, the name can be used for display purposes.", + "type": "string" + }, "description": { "title": "Description", "description": "An optional description of the concept.", @@ -516,8 +526,7 @@ } }, "required": [ - "name", - "value" + "name" ] }, "Initial": { @@ -548,6 +557,11 @@ "description": "The name of the concept.", "type": "string" }, + "display_name": { + "title": "Display Name", + "description": "An optional display name for the concept. If not provided, the name can be used for display purposes.", + "type": "string" + }, "description": { "title": "Description", "description": "An optional description of the concept.", diff --git a/mira/metamodel/template_model.py b/mira/metamodel/template_model.py index fef99bea4..05a00cd2f 100644 --- a/mira/metamodel/template_model.py +++ b/mira/metamodel/template_model.py @@ -31,7 +31,7 @@ class Distribution(BaseModel): class Parameter(Concept): """A Parameter is a special type of Concept that carries a value.""" - value: float = Field( + value: Optional[float] = Field( default_factory=None, description="Value of the parameter.") distribution: Optional[Distribution] = Field( diff --git a/mira/metamodel/templates.py b/mira/metamodel/templates.py index cb80e3cf4..c2961e571 100644 --- a/mira/metamodel/templates.py +++ b/mira/metamodel/templates.py @@ -124,6 +124,10 @@ class Concept(BaseModel): """ name: str = Field(..., description="The name of the concept.") + display_name: str = \ + Field(None, description="An optional display name for the concept. " + "If not provided, the name can be used for " + "display purposes.") description: Optional[str] = \ Field(None, description="An optional description of the concept.") identifiers: Mapping[str, str] = Field( diff --git a/mira/modeling/__init__.py b/mira/modeling/__init__.py index 647ccf24b..65551790c 100644 --- a/mira/modeling/__init__.py +++ b/mira/modeling/__init__.py @@ -108,8 +108,8 @@ def assemble_variable( return var def assemble_parameter(self, template: Template, tkey) -> ModelParameter: - rate_parameters = self.template_model.get_parameters_from_rate_law( - template.rate_law) + rate_parameters = sorted( + self.template_model.get_parameters_from_rate_law(template.rate_law)) if rate_parameters: model_parameters = [] @@ -133,8 +133,8 @@ def assemble_parameter(self, template: Template, tkey) -> ModelParameter: def make_model(self): for name, observable in self.template_model.observables.items(): - params = observable.get_parameter_names( - self.template_model.parameters) + params = sorted( + observable.get_parameter_names(self.template_model.parameters)) self.observables[observable.name] = \ ModelObservable(observable, params) for key in params: diff --git a/mira/modeling/askenet/petrinet.py b/mira/modeling/askenet/petrinet.py index 469413cc1..dc93a35ba 100644 --- a/mira/modeling/askenet/petrinet.py +++ b/mira/modeling/askenet/petrinet.py @@ -55,6 +55,7 @@ def __init__(self, model: Model): # Use the variable's concept name if possible but fall back # on the key otherwise vmap[key] = name = var.concept.name or str(key) + display_name = var.concept.display_name or name # State structure # { # 'id': str, @@ -63,7 +64,7 @@ def __init__(self, model: Model): # } states_dict = { 'id': name, - 'name': name, + 'name': display_name, 'grounding': { 'identifiers': {k: v for k, v in var.concept.identifiers.items() @@ -258,10 +259,11 @@ def to_json_file(self, fname, name=None, description=None, kwargs : Additional keyword arguments to pass to :func:`json.dump`. """ + indent = kwargs.pop('indent', 1) js = self.to_json(name=name, description=description, model_version=model_version) with open(fname, 'w') as fh: - json.dump(js, fh, **kwargs) + json.dump(js, fh, indent=indent, **kwargs) class Initial(BaseModel): diff --git a/mira/sources/askenet/petrinet.py b/mira/sources/askenet/petrinet.py index 67e812851..7cb71ed6f 100644 --- a/mira/sources/askenet/petrinet.py +++ b/mira/sources/askenet/petrinet.py @@ -226,7 +226,11 @@ def state_to_concept(state): # } # } # } - name = state.get('name') or state['id'] + # Note that in the shared representation we have id and name + # whereas for Concepts in MIRA we have names and display + # names + name = state['id'] + display_name = state.get('name') grounding = state.get('grounding', {}) identifiers = grounding.get('identifiers', {}) context = grounding.get('modifiers', {}) @@ -239,6 +243,7 @@ def state_to_concept(state): units_expr = sympy.parse_expr(expr, local_dict=UNIT_SYMBOLS) units_obj = Unit(expression=units_expr) return Concept(name=name, + display_name=display_name, identifiers=identifiers, context=context, units=units_obj) diff --git a/mira/sources/sbml/processor.py b/mira/sources/sbml/processor.py index 153c3129c..5171ba047 100644 --- a/mira/sources/sbml/processor.py +++ b/mira/sources/sbml/processor.py @@ -190,6 +190,14 @@ def _lookup_concepts_filtered(species_ids) -> List[Concept]: product_species = [species.species for species in reaction.products] rate_law = reaction.getKineticLaw() + # Some rate laws define parameters locally and so we need to + # extract them and add them to the global parameter list + for parameter in rate_law.parameters: + all_parameters[parameter.id] = {'value': parameter.value, + 'description': parameter.name if parameter.name else None, + 'units': self.get_object_units(parameter)} + parameter_symbols[clean_formula(parameter.id)] = \ + sympy.Symbol(clean_formula(parameter.id)) rate_expr = sympy.parse_expr(clean_formula(rate_law.formula), local_dict=all_locals) diff --git a/notebooks/hackathon_2023.07/scenario1.ipynb b/notebooks/hackathon_2023.07/scenario1.ipynb new file mode 100644 index 000000000..99a5e4bdf --- /dev/null +++ b/notebooks/hackathon_2023.07/scenario1.ipynb @@ -0,0 +1,244 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c947d97c", + "metadata": {}, + "source": [ + "### Step a-b: create the base model\n", + "Questions: You want to implement a masking intervention in a simple compartmental model and simulate epidemic trajectories under different compliance scenarios. You found an existing model that incorporates masking as a time-dependent modification to the β parameter (https://doi.org/10.3390/ijerph18179027 plus accompanying code), and you want to ensure that the model is working as expected by reproducing plots in the publication. \n", + "\n", + "Replicate an analysis from the paper.\n", + "- (TA1 Model Extraction Workflow, TA2 Model Representation) Extract the SEIRD model (equations 1-5, with time-varying β as defined in equations 8-9) and load into the workbench. In equation 8, let kappa = γR0, R0 = 5. In equation 9, let k = 5.\n", + "\n", + "- (TA3 Simulation Workflow, Unit Test): Replicate Figure 3 from the paper, which maps to the first scenario in the paper- implementing a masking intervention at several different timepoints (delays of 0 days, 50 days, 100 days, and control case, from the date of first infection) in the pandemic, with 100% compliance. Recreate the Fig. 3 curves (including peak infection times and levels), up to some reasonable margin of error. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "11406f4a", + "metadata": {}, + "outputs": [], + "source": [ + "import sympy\n", + "from mira.metamodel import *\n", + "from mira.modeling import Model\n", + "from mira.modeling.askenet.petrinet import AskeNetPetriNetModel" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b2351930", + "metadata": {}, + "outputs": [], + "source": [ + "person_units = Unit(expression=sympy.Symbol('person'))\n", + "day_units = Unit(expression=sympy.Symbol('day'))\n", + "per_day_units = Unit(expression=1/sympy.Symbol('day'))\n", + "dimensionless_units = Unit(expression=sympy.Integer('1'))\n", + "\n", + "c = {\n", + " 'S': Concept(name='S', units=person_units),\n", + " 'E': Concept(name='E', units=person_units),\n", + " 'I': Concept(name='I', units=person_units),\n", + " 'R': Concept(name='R', units=person_units),\n", + " 'D': Concept(name='D', units=person_units)\n", + "}\n", + "\n", + "\n", + "parameters = {\n", + " 'gamma': Parameter(name='gamma', value=1/11, units=per_day_units),\n", + " 'delta': Parameter(name='delta', value=1/5, units=per_day_units),\n", + " 'alpha': Parameter(name='alpha', value=0.000064, units=dimensionless_units),\n", + " 'rho': Parameter(name='rho', value=1/9, units=per_day_units),\n", + " 'N': Parameter(name='N', value=5_600_000, units=person_units),\n", + " 'beta_s': Parameter(name='beta_s', value=1),\n", + " 'beta_c': Parameter(name='beta_c', value=0.4),\n", + " 't_0': Parameter(name='t_0', value=89, unts=day_units),\n", + " # D=11, gamma = 1/D, R_0 = 5 and\n", + " # beta = R_0 * gamma * mask(t) so kappa = 5/11\n", + " 'kappa': Parameter(name='kappa', value=5/11),\n", + "}\n", + "\n", + "initials = {\n", + " 'S': Initial(concept=Concept(name='S'), value=5_600_000-1),\n", + " 'E': Initial(concept=Concept(name='E'), value=1),\n", + " 'I': Initial(concept=Concept(name='I'), value=0),\n", + " 'R': Initial(concept=Concept(name='R'), value=0),\n", + " 'D': Initial(concept=Concept(name='D'), value=0),\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "28178230", + "metadata": {}, + "outputs": [], + "source": [ + "S, E, I, R, D, N, kappa, beta_s, beta_c, k, t_0, t, alpha, delta, rho, gamma = \\\n", + " sympy.symbols('S E I R D N kappa beta_s beta_c k t_0 t alpha delta rho gamma')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f2645cae", + "metadata": {}, + "outputs": [], + "source": [ + "m_1 = (beta_s - beta_c) / (1 + sympy.exp(-k*(t_0-t))) + beta_c\n", + "beta = kappa*m_1\n", + "\n", + "t1 = ControlledConversion(subject=c['S'],\n", + " outcome=c['E'],\n", + " controller=c['E'],\n", + " rate_law=S*I*beta / N)\n", + "t2 = NaturalConversion(subject=c['E'],\n", + " outcome=c['I'],\n", + " rate_law=delta*E)\n", + "t3 = NaturalConversion(subject=c['I'],\n", + " outcome=c['R'],\n", + " rate_law=(1-alpha)*gamma*I)\n", + "t4 = NaturalConversion(subject=c['I'],\n", + " outcome=c['D'],\n", + " rate_law=alpha*rho*I)\n", + "templates = [t1, t2, t3, t4]\n", + "tm = TemplateModel(\n", + " templates=templates,\n", + " parameters=parameters,\n", + " initials=initials,\n", + " time=Time(name='t', units=day_units)\n", + ")\n", + "AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_a.json')" + ] + }, + { + "cell_type": "markdown", + "id": "48e4ed6a", + "metadata": {}, + "source": [ + "### Step c: update beta\n", + "\n", + "(TA2 Model Modification Workflow, TA3 Simulation Workflow): Update the β(t) function to be defined as equations 8 and 10, with k1 = 5, and k2 = 1. This reflects the paper’s second scenario, gradual noncompliance with the masking policy over time. Rerun the simulation with several different delays in enforcing a mask policy (ranging from 0 to 140 days), and replicate Fig. 5, up to some reasonable margin of error." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "85e41bc9", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "k_1, k_2, t_1, beta_nc = sympy.symbols('k_1 k_2 t_1 beta_nc')\n", + "parameters['k_1'] = Parameter(name='k_1')\n", + "parameters['k_2'] = Parameter(name='k_2')\n", + "parameters['t_1'] = Parameter(name='t_1', value=154, units=day_units)\n", + "parameters['beta_nc'] = Parameter(name='beta_nc', value=0.5)\n", + "m_2 = (beta_s - beta_c) / (1 + sympy.exp(-k_1*(t_0-t))) + (beta_c - beta_nc) / (1 + sympy.exp(-k_2*(t_1-t))) + beta_nc" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5fa367b5", + "metadata": {}, + "outputs": [], + "source": [ + "t1.rate_law = SympyExprStr(kappa*m_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c073ca18", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\kappa \\left(\\beta_{nc} + \\frac{\\beta_{c} - \\beta_{nc}}{1 + e^{- k_{2} \\left(- t + t_{1}\\right)}} + \\frac{- \\beta_{c} + \\beta_{s}}{1 + e^{- k_{1} \\left(- t + t_{0}\\right)}}\\right)$" + ], + "text/plain": [ + "kappa*(beta_nc + (beta_c - beta_nc)/(1 + exp(-k_2*(-t + t_1))) + (-beta_c + beta_s)/(1 + exp(-k_1*(-t + t_0))))" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t1.rate_law.args[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b1c1abab", + "metadata": {}, + "outputs": [], + "source": [ + "AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_c.json')" + ] + }, + { + "cell_type": "markdown", + "id": "6e3374f9", + "metadata": {}, + "source": [ + "### Step d: update for reinfection\n", + "(TA2 Model Modification Workflow, TA3 Simulation Workflow): Update the system of equations to include equations 6 and 7. This adds the potential for reinfection. Compare with the outcomes from 1c. What impact does immunity loss and potential for reinfection have?" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6fab9358", + "metadata": {}, + "outputs": [], + "source": [ + "epsilon = sympy.Symbol('epsilon')\n", + "parameters['epsilon'] = Parameter(name='epsilon', value=1/90)\n", + "t5 = NaturalConversion(subject=c['R'],\n", + " outcome=c['S'],\n", + " rate_law=epsilon*R)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "00c70176", + "metadata": {}, + "outputs": [], + "source": [ + "AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_d.json')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/hackathon_2023.07/scenario1_a.json b/notebooks/hackathon_2023.07/scenario1_a.json new file mode 100644 index 000000000..2ce954672 --- /dev/null +++ b/notebooks/hackathon_2023.07/scenario1_a.json @@ -0,0 +1,258 @@ +{ + "name": "Model", + "schema": "https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json", + "schema_name": "petrinet", + "description": "Model", + "model_version": "0.1", + "properties": {}, + "model": { + "states": [ + { + "id": "S", + "name": "S", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "E", + "name": "E", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "I", + "name": "I", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "R", + "name": "R", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "D", + "name": "D", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + } + ], + "transitions": [ + { + "id": "t1", + "input": [ + "E", + "S" + ], + "output": [ + "E", + "E" + ], + "properties": { + "name": "t1" + } + }, + { + "id": "t2", + "input": [ + "E" + ], + "output": [ + "I" + ], + "properties": { + "name": "t2" + } + }, + { + "id": "t3", + "input": [ + "I" + ], + "output": [ + "R" + ], + "properties": { + "name": "t3" + } + }, + { + "id": "t4", + "input": [ + "I" + ], + "output": [ + "D" + ], + "properties": { + "name": "t4" + } + } + ] + }, + "semantics": { + "ode": { + "rates": [ + { + "target": "t1", + "expression": "I*S*kappa*(beta_c + (-beta_c + beta_s)/(1 + exp(-k*(-t + t_0))))/N", + "expression_mathml": "ISkappabeta_cbeta_cbeta_s1kt_0tN" + }, + { + "target": "t2", + "expression": "E*delta", + "expression_mathml": "Edelta" + }, + { + "target": "t3", + "expression": "I*gamma*(1 - alpha)", + "expression_mathml": "Igamma1alpha" + }, + { + "target": "t4", + "expression": "I*alpha*rho", + "expression_mathml": "Ialpharho" + } + ], + "initials": [ + { + "target": "S", + "expression": "5599999.00000000", + "expression_mathml": "5599999.0" + }, + { + "target": "E", + "expression": "1.00000000000000", + "expression_mathml": "1.0" + }, + { + "target": "I", + "expression": "0.0", + "expression_mathml": "0.0" + }, + { + "target": "R", + "expression": "0.0", + "expression_mathml": "0.0" + }, + { + "target": "D", + "expression": "0.0", + "expression_mathml": "0.0" + } + ], + "parameters": [ + { + "id": "N", + "value": 5600000.0, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "beta_c", + "value": 0.4 + }, + { + "id": "beta_s", + "value": 1.0 + }, + { + "id": "kappa", + "value": 0.45454545454545453 + }, + { + "id": "t_0", + "value": 89.0 + }, + { + "id": "delta", + "value": 0.2, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, + { + "id": "alpha", + "value": 6.4e-05, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "gamma", + "value": 0.09090909090909091, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, + { + "id": "rho", + "value": 0.1111111111111111, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + } + ], + "observables": [], + "time": { + "id": "t", + "units": { + "expression": "day", + "expression_mathml": "day" + } + } + } + }, + "metadata": { + "annotations": { + "license": null, + "authors": [], + "references": [], + "time_scale": null, + "time_start": null, + "time_end": null, + "locations": [], + "pathogens": [], + "diseases": [], + "hosts": [], + "model_types": [] + } + } +} \ No newline at end of file diff --git a/notebooks/hackathon_2023.07/scenario1_c.json b/notebooks/hackathon_2023.07/scenario1_c.json new file mode 100644 index 000000000..0511f2622 --- /dev/null +++ b/notebooks/hackathon_2023.07/scenario1_c.json @@ -0,0 +1,250 @@ +{ + "name": "Model", + "schema": "https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json", + "schema_name": "petrinet", + "description": "Model", + "model_version": "0.1", + "properties": {}, + "model": { + "states": [ + { + "id": "S", + "name": "S", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "E", + "name": "E", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "I", + "name": "I", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "R", + "name": "R", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "D", + "name": "D", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + } + ], + "transitions": [ + { + "id": "t1", + "input": [ + "E", + "S" + ], + "output": [ + "E", + "E" + ], + "properties": { + "name": "t1" + } + }, + { + "id": "t2", + "input": [ + "E" + ], + "output": [ + "I" + ], + "properties": { + "name": "t2" + } + }, + { + "id": "t3", + "input": [ + "I" + ], + "output": [ + "R" + ], + "properties": { + "name": "t3" + } + }, + { + "id": "t4", + "input": [ + "I" + ], + "output": [ + "D" + ], + "properties": { + "name": "t4" + } + } + ] + }, + "semantics": { + "ode": { + "rates": [ + { + "target": "t1", + "expression": "kappa*(beta_nc + (beta_c - beta_nc)/(1 + exp(-k_2*(-t + t_1))) + (-beta_c + beta_s)/(1 + exp(-k_1*(-t + t_0))))", + "expression_mathml": "kappabeta_ncbeta_cbeta_nc1k_2t_1tbeta_cbeta_s1k_1t_0t" + }, + { + "target": "t2", + "expression": "E*delta", + "expression_mathml": "Edelta" + }, + { + "target": "t3", + "expression": "I*gamma*(1 - alpha)", + "expression_mathml": "Igamma1alpha" + }, + { + "target": "t4", + "expression": "I*alpha*rho", + "expression_mathml": "Ialpharho" + } + ], + "initials": [ + { + "target": "S", + "expression": "5599999.00000000", + "expression_mathml": "5599999.0" + }, + { + "target": "E", + "expression": "1.00000000000000", + "expression_mathml": "1.0" + }, + { + "target": "I", + "expression": "0.0", + "expression_mathml": "0.0" + }, + { + "target": "R", + "expression": "0.0", + "expression_mathml": "0.0" + }, + { + "target": "D", + "expression": "0.0", + "expression_mathml": "0.0" + } + ], + "parameters": [ + { + "id": "beta_c", + "value": 0.4 + }, + { + "id": "beta_s", + "value": 1.0 + }, + { + "id": "kappa", + "value": 0.45454545454545453 + }, + { + "id": "t_0", + "value": 89.0 + }, + { + "id": "delta", + "value": 0.2, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, + { + "id": "alpha", + "value": 6.4e-05, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "gamma", + "value": 0.09090909090909091, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, + { + "id": "rho", + "value": 0.1111111111111111, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + } + ], + "observables": [], + "time": { + "id": "t", + "units": { + "expression": "day", + "expression_mathml": "day" + } + } + } + }, + "metadata": { + "annotations": { + "license": null, + "authors": [], + "references": [], + "time_scale": null, + "time_start": null, + "time_end": null, + "locations": [], + "pathogens": [], + "diseases": [], + "hosts": [], + "model_types": [] + } + } +} \ No newline at end of file diff --git a/notebooks/hackathon_2023.07/scenario1_d.json b/notebooks/hackathon_2023.07/scenario1_d.json new file mode 100644 index 000000000..0511f2622 --- /dev/null +++ b/notebooks/hackathon_2023.07/scenario1_d.json @@ -0,0 +1,250 @@ +{ + "name": "Model", + "schema": "https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json", + "schema_name": "petrinet", + "description": "Model", + "model_version": "0.1", + "properties": {}, + "model": { + "states": [ + { + "id": "S", + "name": "S", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "E", + "name": "E", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "I", + "name": "I", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "R", + "name": "R", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "D", + "name": "D", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "person", + "expression_mathml": "person" + } + } + ], + "transitions": [ + { + "id": "t1", + "input": [ + "E", + "S" + ], + "output": [ + "E", + "E" + ], + "properties": { + "name": "t1" + } + }, + { + "id": "t2", + "input": [ + "E" + ], + "output": [ + "I" + ], + "properties": { + "name": "t2" + } + }, + { + "id": "t3", + "input": [ + "I" + ], + "output": [ + "R" + ], + "properties": { + "name": "t3" + } + }, + { + "id": "t4", + "input": [ + "I" + ], + "output": [ + "D" + ], + "properties": { + "name": "t4" + } + } + ] + }, + "semantics": { + "ode": { + "rates": [ + { + "target": "t1", + "expression": "kappa*(beta_nc + (beta_c - beta_nc)/(1 + exp(-k_2*(-t + t_1))) + (-beta_c + beta_s)/(1 + exp(-k_1*(-t + t_0))))", + "expression_mathml": "kappabeta_ncbeta_cbeta_nc1k_2t_1tbeta_cbeta_s1k_1t_0t" + }, + { + "target": "t2", + "expression": "E*delta", + "expression_mathml": "Edelta" + }, + { + "target": "t3", + "expression": "I*gamma*(1 - alpha)", + "expression_mathml": "Igamma1alpha" + }, + { + "target": "t4", + "expression": "I*alpha*rho", + "expression_mathml": "Ialpharho" + } + ], + "initials": [ + { + "target": "S", + "expression": "5599999.00000000", + "expression_mathml": "5599999.0" + }, + { + "target": "E", + "expression": "1.00000000000000", + "expression_mathml": "1.0" + }, + { + "target": "I", + "expression": "0.0", + "expression_mathml": "0.0" + }, + { + "target": "R", + "expression": "0.0", + "expression_mathml": "0.0" + }, + { + "target": "D", + "expression": "0.0", + "expression_mathml": "0.0" + } + ], + "parameters": [ + { + "id": "beta_c", + "value": 0.4 + }, + { + "id": "beta_s", + "value": 1.0 + }, + { + "id": "kappa", + "value": 0.45454545454545453 + }, + { + "id": "t_0", + "value": 89.0 + }, + { + "id": "delta", + "value": 0.2, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, + { + "id": "alpha", + "value": 6.4e-05, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "gamma", + "value": 0.09090909090909091, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, + { + "id": "rho", + "value": 0.1111111111111111, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + } + ], + "observables": [], + "time": { + "id": "t", + "units": { + "expression": "day", + "expression_mathml": "day" + } + } + } + }, + "metadata": { + "annotations": { + "license": null, + "authors": [], + "references": [], + "time_scale": null, + "time_start": null, + "time_end": null, + "locations": [], + "pathogens": [], + "diseases": [], + "hosts": [], + "model_types": [] + } + } +} \ No newline at end of file diff --git a/tests/test_askenet_source.py b/tests/test_askenet_source.py index e24ed28a5..dda00ee82 100644 --- a/tests/test_askenet_source.py +++ b/tests/test_askenet_source.py @@ -14,11 +14,12 @@ def test_petrinet_model_from_url(): assert len(template_model.templates) == 2 assert isinstance(template_model.templates[0], ControlledConversion) assert isinstance(template_model.templates[1], NaturalConversion) - assert template_model.templates[0].controller.name == 'Infected' - assert template_model.templates[0].subject.name == 'Susceptible' - assert template_model.templates[0].outcome.name == 'Infected' - assert template_model.templates[1].subject.name == 'Infected' - assert template_model.templates[1].outcome.name == 'Recovered' + assert template_model.templates[0].controller.display_name == 'Infected' + assert template_model.templates[0].controller.name == 'I' + assert template_model.templates[0].subject.display_name == 'Susceptible' + assert template_model.templates[0].outcome.display_name == 'Infected' + assert template_model.templates[1].subject.display_name == 'Infected' + assert template_model.templates[1].outcome.display_name == 'Recovered' def test_regnet_model_from_url():