Skip to content

Commit b8a6585

Browse files
Merge pull request #279 from rogersamso/building_split_model_merge
Split Vensim views in separate Python files
2 parents 86b109f + ce3f359 commit b8a6585

20 files changed

+3666
-1917
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
include requirements.txt
22
include README.md
3+
include LICENSE
34
include pysd/py_backend/xmile/smile.grammar

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ PySD
22
====
33
[![Build Status](https://travis-ci.com/JamesPHoughton/pysd.svg?branch=master)](https://travis-ci.com/JamesPHoughton/pysd)
44
[![Coverage Status](https://coveralls.io/repos/github/JamesPHoughton/pysd/badge.svg?branch=master)](https://coveralls.io/github/JamesPHoughton/pysd?branch=master)
5+
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pysd/badges/version.svg)](https://anaconda.org/conda-forge/pysd)
56
[![PyPI version](https://badge.fury.io/py/pysd.svg)](https://badge.fury.io/py/pysd)
67
[![PyPI status](https://img.shields.io/pypi/status/pysd.svg)](https://pypi.python.org/pypi/pysd/)
78
[![Py version](https://img.shields.io/pypi/pyversions/pysd.svg)](https://pypi.python.org/pypi/pysd/)

docs/advanced_usage.rst

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,32 @@ We can substitute this function directly for the heat_loss_to_room model compone
4141

4242
If you want to replace a subscripted variable, you need to ensure that the output from the new function is the same as the previous one. You can check the current coordinates and dimensions of a component by using :py:data:`.get_coords(variable_name)` as it is explained in :doc:`basic usage <../basic_usage>`.
4343

44+
45+
Splitting Vensim views in different files
46+
-----------------------------------------
47+
In order to replicate the Vensim views in translated models, the user can set the `split_modules` argument to True in the :py:func:`read_vensim` function::
48+
49+
read_vensim("many_views_model.mdl", split_modules=True)
50+
51+
52+
The option to split the model in views is particularly interesting for large models with tens of views. Translating those models into a single file may make the resulting Python model difficult to read and maintain.
53+
54+
In a Vensim model with three separate views (e.g. `view_1`, `view_2` and `view_3`), setting `split_modules` to True would create the following tree inside the directory where the `.mdl` model is located:
55+
56+
| main-folder
57+
| ├── modules_many_views_model
58+
| │ ├── _modules.json
59+
| │ ├── view_1.py
60+
| │ ├── view_2.py
61+
| │ └── view_3.py
62+
| ├── _namespace_many_views_model.json
63+
| ├── _subscripts_dict_many_views_model.json
64+
| ├── many_views_model.py
65+
|
66+
|
67+
If macros are present, they will be self-contained in files named as the macro itself. The macro inner variables will be placed inside the module that corresponds with the view in which they were defined.
68+
69+
4470
Starting simulations from an end-state of another simulation
4571
------------------------------------------------------------
4672
The current state of a model can be saved in a pickle file using the :py:data:`.export()`method::
@@ -68,5 +94,5 @@ the new simulation will have initial time equal to 50 with the saved values from
6894
The changes done with *params* arguments are not ported to the new model (*model2*) object that you initialize with *final_state.pic*. If you want to keep them, you need to call run with the same *params* values as in the original model (*model1*).
6995

7096
.. warning::
71-
Exported data is saved and loaded using `pickle <https://docs.python.org/3/library/pickle.html>`_, this data can be not compatible with future versions of
97+
Exported data is saved and loaded using `pickle <https://docs.python.org/3/library/pickle.html>`_, this data can be incompatible with future versions of
7298
*PySD* or *xarray*. In order to prevent data losses save always the source code.

docs/command_line_usage.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ The progress bar can be activated using *-p/--progress* command:
4141
4242
python -m pysd --progress Teacup.mdl
4343
44+
Translation options
45+
-------------------
46+
4447
Only translate model file
4548
^^^^^^^^^^^^^^^^^^^^^^^^^
4649
To only translate the model file, it does not run the model, *-t/--trasnlate* command is provided:
@@ -49,6 +52,14 @@ To only translate the model file, it does not run the model, *-t/--trasnlate* co
4952
5053
python -m pysd --translate Teacup.mdl
5154
55+
Splitting Vensim views in different files
56+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
57+
In order to split the Vensim model views in different files as explained in :doc:`advanced usage <../advanced_usage>`:
58+
59+
.. code-block:: text
60+
61+
python -m pysd --split-modules many_views_model.mdl
62+
5263
Outputting various run information
5364
----------------------------------
5465
The output number of variables can be modified bu passing them as arguments separated by commas, using *-r/return_columns* argument:

docs/installation.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ Python environment, use the pip command:
1010
1111
pip install pysd
1212
13+
Installing with conda
14+
---------------------
15+
To install PySD with conda, using the conda-forge channel, into a conda environment, use the following command:
16+
17+
.. code-block:: bash
18+
19+
conda install -c conda-forge pysd
1320
1421
Installing from source
1522
----------------------

pysd/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.7.0"
1+
__version__ = "1.8.0"

pysd/cli/main.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ def main(args):
2525
"""
2626
options = parser.parse_args(args)
2727

28-
model = load(options.model_file, options.missing_values)
28+
model = load(options.model_file, options.missing_values,
29+
options.split_modules)
2930

3031
if not options.run:
3132
print("\nFinished!")
@@ -43,7 +44,7 @@ def main(args):
4344
sys.exit()
4445

4546

46-
def load(model_file, missing_values):
47+
def load(model_file, missing_values, split_modules):
4748
"""
4849
Translate and load model file.
4950
@@ -60,7 +61,8 @@ def load(model_file, missing_values):
6061
if model_file.lower().endswith('.mdl'):
6162
print("\nTranslating model file...\n")
6263
return pysd.read_vensim(model_file, initialize=False,
63-
missing_values=missing_values)
64+
missing_values=missing_values,
65+
split_modules=split_modules)
6466
elif model_file.lower().endswith('.xmile'):
6567
print("\nTranslating model file...\n")
6668
return pysd.read_xmile(model_file, initialize=False,

pysd/cli/parser.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,6 @@ def __call__(self, parser, namespace, values, option_string=None):
152152
'-v', '--version',
153153
action='version', version=f'PySD {__version__}')
154154

155-
parser.add_argument(
156-
'-t', '--translate', dest='run',
157-
action='store_false', default=True,
158-
help='only translate the model_file, '
159-
'it does not run it after translation')
160-
161155
parser.add_argument(
162156
'-o', '--output-file', dest='output_file',
163157
type=check_output, metavar='FILE',
@@ -187,6 +181,7 @@ def __call__(self, parser, namespace, values, option_string=None):
187181
help='import stateful objects states from a pickle file,'
188182
'if given initial conditions from var:value will be ignored')
189183

184+
190185
###################
191186
# Model arguments #
192187
###################
@@ -223,6 +218,26 @@ def __call__(self, parser, namespace, values, option_string=None):
223218
'--saveper will be ignored')
224219

225220

221+
###################
222+
# Model arguments #
223+
###################
224+
225+
trans_arguments = parser.add_argument_group(
226+
'translation arguments',
227+
'Configure the translation of the original model.')
228+
229+
trans_arguments.add_argument(
230+
'--translate', dest='run',
231+
action='store_false', default=True,
232+
help='only translate the model_file, '
233+
'it does not run it after translation')
234+
235+
trans_arguments.add_argument(
236+
'--split-modules', dest='split_modules',
237+
action='store_true', default=False,
238+
help='parse the sketch to detect model elements in each model view,'
239+
' and then translate each view in a separate python file')
240+
226241
#######################
227242
# Warnings and errors #
228243
#######################
@@ -232,7 +247,7 @@ def __call__(self, parser, namespace, values, option_string=None):
232247
'Modify warning and errors management.')
233248

234249
warn_err_arguments.add_argument(
235-
'-m', '--missing-values', dest='missing_values', default="warning",
250+
'--missing-values', dest='missing_values', default="warning",
236251
action='store', type=str, choices=['warning', 'raise', 'ignore', 'keep'],
237252
help='exception with missing values, \'warning\' (default) shows a '
238253
'warning message and interpolates the values, \'raise\' raises '

0 commit comments

Comments
 (0)