From 9dd006678e34275a0090dbcb7931cb2654ce9088 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Fri, 30 Jun 2023 17:07:01 -0400 Subject: [PATCH 1/9] Add scenario 1 implementation --- notebooks/hackathon_2023.07/scenario1.ipynb | 244 ++++++++++++++++++ notebooks/hackathon_2023.07/scenario1_a.json | 258 +++++++++++++++++++ notebooks/hackathon_2023.07/scenario1_c.json | 250 ++++++++++++++++++ notebooks/hackathon_2023.07/scenario1_d.json | 250 ++++++++++++++++++ 4 files changed, 1002 insertions(+) create mode 100644 notebooks/hackathon_2023.07/scenario1.ipynb create mode 100644 notebooks/hackathon_2023.07/scenario1_a.json create mode 100644 notebooks/hackathon_2023.07/scenario1_c.json create mode 100644 notebooks/hackathon_2023.07/scenario1_d.json diff --git a/notebooks/hackathon_2023.07/scenario1.ipynb b/notebooks/hackathon_2023.07/scenario1.ipynb new file mode 100644 index 000000000..584db70f4 --- /dev/null +++ b/notebooks/hackathon_2023.07/scenario1.ipynb @@ -0,0 +1,244 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7a646367", + "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": "56172b31", + "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": "f07383fb", + "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=dimensionless_units),\n", + " 'E': Concept(name='E', units=dimensionless_units),\n", + " 'I': Concept(name='I', units=dimensionless_units),\n", + " 'R': Concept(name='R', units=dimensionless_units),\n", + " 'D': Concept(name='D', units=dimensionless_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),\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": "bdf70b6a", + "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": "d1b732b3", + "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": "4c29d51a", + "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": "3413db92", + "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)\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": "f487b47f", + "metadata": {}, + "outputs": [], + "source": [ + "t1.rate_law = SympyExprStr(kappa*m_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "30a47395", + "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": "0791ae2d", + "metadata": {}, + "outputs": [], + "source": [ + "AskeNetPetriNetModel(Model(tm)).to_json_file('scenario1_c.json')" + ] + }, + { + "cell_type": "markdown", + "id": "5f67f2e9", + "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": "38b6002e", + "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": "3aed70ad", + "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..194f8473d --- /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": "1", + "expression_mathml": "1" + } + }, + { + "id": "E", + "name": "E", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "I", + "name": "I", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "R", + "name": "R", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "D", + "name": "D", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + } + ], + "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": "beta_s", + "value": 1.0 + }, + { + "id": "N", + "value": 5600000.0, + "units": { + "expression": "person", + "expression_mathml": "person" + } + }, + { + "id": "t_0", + "value": 89.0 + }, + { + "id": "kappa", + "value": 0.45454545454545453 + }, + { + "id": "beta_c", + "value": 0.4 + }, + { + "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..a65c907d7 --- /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": "1", + "expression_mathml": "1" + } + }, + { + "id": "E", + "name": "E", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "I", + "name": "I", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "R", + "name": "R", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "D", + "name": "D", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + } + ], + "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": "kappa", + "value": 0.45454545454545453 + }, + { + "id": "t_0", + "value": 89.0 + }, + { + "id": "beta_s", + "value": 1.0 + }, + { + "id": "beta_c", + "value": 0.4 + }, + { + "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..a65c907d7 --- /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": "1", + "expression_mathml": "1" + } + }, + { + "id": "E", + "name": "E", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "I", + "name": "I", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "R", + "name": "R", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, + { + "id": "D", + "name": "D", + "grounding": { + "identifiers": {}, + "modifiers": {} + }, + "units": { + "expression": "1", + "expression_mathml": "1" + } + } + ], + "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": "kappa", + "value": 0.45454545454545453 + }, + { + "id": "t_0", + "value": 89.0 + }, + { + "id": "beta_s", + "value": 1.0 + }, + { + "id": "beta_c", + "value": 0.4 + }, + { + "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 From b5499b6e3edbd6810c3c8192a9d58f485e422793 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Wed, 5 Jul 2023 09:29:29 -0400 Subject: [PATCH 2/9] Improvements to representation and processing --- mira/metamodel/io.py | 4 +++- mira/metamodel/template_model.py | 2 +- mira/modeling/askenet/petrinet.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) 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/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/modeling/askenet/petrinet.py b/mira/modeling/askenet/petrinet.py index 469413cc1..1a3674817 100644 --- a/mira/modeling/askenet/petrinet.py +++ b/mira/modeling/askenet/petrinet.py @@ -258,10 +258,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): From bba8c44e176a4297f3cedea8b048138f7b0b580b Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Wed, 5 Jul 2023 09:29:43 -0400 Subject: [PATCH 3/9] Update scenario 1 --- notebooks/hackathon_2023.07/scenario1.ipynb | 40 +++++++++--------- notebooks/hackathon_2023.07/scenario1_a.json | 36 ++++++++-------- notebooks/hackathon_2023.07/scenario1_c.json | 44 ++++++++++---------- notebooks/hackathon_2023.07/scenario1_d.json | 44 ++++++++++---------- 4 files changed, 82 insertions(+), 82 deletions(-) diff --git a/notebooks/hackathon_2023.07/scenario1.ipynb b/notebooks/hackathon_2023.07/scenario1.ipynb index 584db70f4..99a5e4bdf 100644 --- a/notebooks/hackathon_2023.07/scenario1.ipynb +++ b/notebooks/hackathon_2023.07/scenario1.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "7a646367", + "id": "c947d97c", "metadata": {}, "source": [ "### Step a-b: create the base model\n", @@ -17,7 +17,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "56172b31", + "id": "11406f4a", "metadata": {}, "outputs": [], "source": [ @@ -30,7 +30,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "f07383fb", + "id": "b2351930", "metadata": {}, "outputs": [], "source": [ @@ -40,11 +40,11 @@ "dimensionless_units = Unit(expression=sympy.Integer('1'))\n", "\n", "c = {\n", - " 'S': Concept(name='S', units=dimensionless_units),\n", - " 'E': Concept(name='E', units=dimensionless_units),\n", - " 'I': Concept(name='I', units=dimensionless_units),\n", - " 'R': Concept(name='R', units=dimensionless_units),\n", - " 'D': Concept(name='D', units=dimensionless_units)\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", @@ -56,7 +56,7 @@ " '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),\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", @@ -74,7 +74,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "bdf70b6a", + "id": "28178230", "metadata": {}, "outputs": [], "source": [ @@ -85,7 +85,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "d1b732b3", + "id": "f2645cae", "metadata": {}, "outputs": [], "source": [ @@ -117,7 +117,7 @@ }, { "cell_type": "markdown", - "id": "4c29d51a", + "id": "48e4ed6a", "metadata": {}, "source": [ "### Step c: update beta\n", @@ -128,7 +128,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "3413db92", + "id": "85e41bc9", "metadata": { "scrolled": true }, @@ -137,7 +137,7 @@ "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)\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" ] @@ -145,7 +145,7 @@ { "cell_type": "code", "execution_count": 6, - "id": "f487b47f", + "id": "5fa367b5", "metadata": {}, "outputs": [], "source": [ @@ -155,7 +155,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "30a47395", + "id": "c073ca18", "metadata": {}, "outputs": [ { @@ -179,7 +179,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "0791ae2d", + "id": "b1c1abab", "metadata": {}, "outputs": [], "source": [ @@ -188,7 +188,7 @@ }, { "cell_type": "markdown", - "id": "5f67f2e9", + "id": "6e3374f9", "metadata": {}, "source": [ "### Step d: update for reinfection\n", @@ -198,7 +198,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "38b6002e", + "id": "6fab9358", "metadata": {}, "outputs": [], "source": [ @@ -212,7 +212,7 @@ { "cell_type": "code", "execution_count": 10, - "id": "3aed70ad", + "id": "00c70176", "metadata": {}, "outputs": [], "source": [ diff --git a/notebooks/hackathon_2023.07/scenario1_a.json b/notebooks/hackathon_2023.07/scenario1_a.json index 194f8473d..517cc7d18 100644 --- a/notebooks/hackathon_2023.07/scenario1_a.json +++ b/notebooks/hackathon_2023.07/scenario1_a.json @@ -15,8 +15,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -27,8 +27,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -39,8 +39,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -51,8 +51,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -63,8 +63,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } } ], @@ -205,14 +205,6 @@ "expression_mathml": "day-1" } }, - { - "id": "alpha", - "value": 6.4e-05, - "units": { - "expression": "1", - "expression_mathml": "1" - } - }, { "id": "gamma", "value": 0.09090909090909091, @@ -221,6 +213,14 @@ "expression_mathml": "day-1" } }, + { + "id": "alpha", + "value": 6.4e-05, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, { "id": "rho", "value": 0.1111111111111111, diff --git a/notebooks/hackathon_2023.07/scenario1_c.json b/notebooks/hackathon_2023.07/scenario1_c.json index a65c907d7..1da50e5f0 100644 --- a/notebooks/hackathon_2023.07/scenario1_c.json +++ b/notebooks/hackathon_2023.07/scenario1_c.json @@ -15,8 +15,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -27,8 +27,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -39,8 +39,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -51,8 +51,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -63,8 +63,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } } ], @@ -174,16 +174,16 @@ ], "parameters": [ { - "id": "kappa", - "value": 0.45454545454545453 + "id": "beta_s", + "value": 1.0 }, { "id": "t_0", "value": 89.0 }, { - "id": "beta_s", - "value": 1.0 + "id": "kappa", + "value": 0.45454545454545453 }, { "id": "beta_c", @@ -197,14 +197,6 @@ "expression_mathml": "day-1" } }, - { - "id": "alpha", - "value": 6.4e-05, - "units": { - "expression": "1", - "expression_mathml": "1" - } - }, { "id": "gamma", "value": 0.09090909090909091, @@ -213,6 +205,14 @@ "expression_mathml": "day-1" } }, + { + "id": "alpha", + "value": 6.4e-05, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, { "id": "rho", "value": 0.1111111111111111, diff --git a/notebooks/hackathon_2023.07/scenario1_d.json b/notebooks/hackathon_2023.07/scenario1_d.json index a65c907d7..1da50e5f0 100644 --- a/notebooks/hackathon_2023.07/scenario1_d.json +++ b/notebooks/hackathon_2023.07/scenario1_d.json @@ -15,8 +15,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -27,8 +27,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -39,8 +39,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -51,8 +51,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } }, { @@ -63,8 +63,8 @@ "modifiers": {} }, "units": { - "expression": "1", - "expression_mathml": "1" + "expression": "person", + "expression_mathml": "person" } } ], @@ -174,16 +174,16 @@ ], "parameters": [ { - "id": "kappa", - "value": 0.45454545454545453 + "id": "beta_s", + "value": 1.0 }, { "id": "t_0", "value": 89.0 }, { - "id": "beta_s", - "value": 1.0 + "id": "kappa", + "value": 0.45454545454545453 }, { "id": "beta_c", @@ -197,14 +197,6 @@ "expression_mathml": "day-1" } }, - { - "id": "alpha", - "value": 6.4e-05, - "units": { - "expression": "1", - "expression_mathml": "1" - } - }, { "id": "gamma", "value": 0.09090909090909091, @@ -213,6 +205,14 @@ "expression_mathml": "day-1" } }, + { + "id": "alpha", + "value": 6.4e-05, + "units": { + "expression": "1", + "expression_mathml": "1" + } + }, { "id": "rho", "value": 0.1111111111111111, From 1a45e2909fc2c7e6497cff6f5aa22246fd52eba6 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Thu, 6 Jul 2023 11:11:24 -0400 Subject: [PATCH 4/9] Handle local parameter definition --- mira/sources/sbml/processor.py | 8 ++++++++ 1 file changed, 8 insertions(+) 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) From baf557c266cc92c967433c275648225b0e2155b2 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Thu, 6 Jul 2023 11:11:34 -0400 Subject: [PATCH 5/9] Stabilize parameter order --- mira/modeling/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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: From 84cd710ccd71cd56d17d7369e412b301dfef1c77 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Thu, 6 Jul 2023 11:18:53 -0400 Subject: [PATCH 6/9] Update schema --- mira/metamodel/schema.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mira/metamodel/schema.json b/mira/metamodel/schema.json index 6621ec5ad..62ac00c5d 100644 --- a/mira/metamodel/schema.json +++ b/mira/metamodel/schema.json @@ -516,8 +516,7 @@ } }, "required": [ - "name", - "value" + "name" ] }, "Initial": { From 21d1911e93460913bcadfc3454b4245652457b3b Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Thu, 6 Jul 2023 11:26:03 -0400 Subject: [PATCH 7/9] Implement display name and update scenario --- mira/metamodel/templates.py | 4 +++ mira/modeling/askenet/petrinet.py | 3 +- mira/sources/askenet/petrinet.py | 7 ++++- notebooks/hackathon_2023.07/scenario1_a.json | 32 ++++++++++---------- notebooks/hackathon_2023.07/scenario1_c.json | 28 ++++++++--------- notebooks/hackathon_2023.07/scenario1_d.json | 28 ++++++++--------- 6 files changed, 56 insertions(+), 46 deletions(-) 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/askenet/petrinet.py b/mira/modeling/askenet/petrinet.py index 1a3674817..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() 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/notebooks/hackathon_2023.07/scenario1_a.json b/notebooks/hackathon_2023.07/scenario1_a.json index 517cc7d18..2ce954672 100644 --- a/notebooks/hackathon_2023.07/scenario1_a.json +++ b/notebooks/hackathon_2023.07/scenario1_a.json @@ -173,10 +173,6 @@ } ], "parameters": [ - { - "id": "beta_s", - "value": 1.0 - }, { "id": "N", "value": 5600000.0, @@ -186,16 +182,20 @@ } }, { - "id": "t_0", - "value": 89.0 + "id": "beta_c", + "value": 0.4 + }, + { + "id": "beta_s", + "value": 1.0 }, { "id": "kappa", "value": 0.45454545454545453 }, { - "id": "beta_c", - "value": 0.4 + "id": "t_0", + "value": 89.0 }, { "id": "delta", @@ -205,14 +205,6 @@ "expression_mathml": "day-1" } }, - { - "id": "gamma", - "value": 0.09090909090909091, - "units": { - "expression": "1/day", - "expression_mathml": "day-1" - } - }, { "id": "alpha", "value": 6.4e-05, @@ -221,6 +213,14 @@ "expression_mathml": "1" } }, + { + "id": "gamma", + "value": 0.09090909090909091, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, { "id": "rho", "value": 0.1111111111111111, diff --git a/notebooks/hackathon_2023.07/scenario1_c.json b/notebooks/hackathon_2023.07/scenario1_c.json index 1da50e5f0..0511f2622 100644 --- a/notebooks/hackathon_2023.07/scenario1_c.json +++ b/notebooks/hackathon_2023.07/scenario1_c.json @@ -174,20 +174,20 @@ ], "parameters": [ { - "id": "beta_s", - "value": 1.0 + "id": "beta_c", + "value": 0.4 }, { - "id": "t_0", - "value": 89.0 + "id": "beta_s", + "value": 1.0 }, { "id": "kappa", "value": 0.45454545454545453 }, { - "id": "beta_c", - "value": 0.4 + "id": "t_0", + "value": 89.0 }, { "id": "delta", @@ -197,14 +197,6 @@ "expression_mathml": "day-1" } }, - { - "id": "gamma", - "value": 0.09090909090909091, - "units": { - "expression": "1/day", - "expression_mathml": "day-1" - } - }, { "id": "alpha", "value": 6.4e-05, @@ -213,6 +205,14 @@ "expression_mathml": "1" } }, + { + "id": "gamma", + "value": 0.09090909090909091, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, { "id": "rho", "value": 0.1111111111111111, diff --git a/notebooks/hackathon_2023.07/scenario1_d.json b/notebooks/hackathon_2023.07/scenario1_d.json index 1da50e5f0..0511f2622 100644 --- a/notebooks/hackathon_2023.07/scenario1_d.json +++ b/notebooks/hackathon_2023.07/scenario1_d.json @@ -174,20 +174,20 @@ ], "parameters": [ { - "id": "beta_s", - "value": 1.0 + "id": "beta_c", + "value": 0.4 }, { - "id": "t_0", - "value": 89.0 + "id": "beta_s", + "value": 1.0 }, { "id": "kappa", "value": 0.45454545454545453 }, { - "id": "beta_c", - "value": 0.4 + "id": "t_0", + "value": 89.0 }, { "id": "delta", @@ -197,14 +197,6 @@ "expression_mathml": "day-1" } }, - { - "id": "gamma", - "value": 0.09090909090909091, - "units": { - "expression": "1/day", - "expression_mathml": "day-1" - } - }, { "id": "alpha", "value": 6.4e-05, @@ -213,6 +205,14 @@ "expression_mathml": "1" } }, + { + "id": "gamma", + "value": 0.09090909090909091, + "units": { + "expression": "1/day", + "expression_mathml": "day-1" + } + }, { "id": "rho", "value": 0.1111111111111111, From 28a93034db1ebbf422d0bd7f52421e965fdd3905 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Thu, 6 Jul 2023 11:33:19 -0400 Subject: [PATCH 8/9] Update schema --- mira/metamodel/schema.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mira/metamodel/schema.json b/mira/metamodel/schema.json index 62ac00c5d..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.", @@ -547,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.", From 6b089453c4b178f87faa6c11f8e86d5b0dac94c5 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Thu, 6 Jul 2023 11:54:06 -0400 Subject: [PATCH 9/9] Update test to match new id/name scheme --- tests/test_askenet_source.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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():