""" License, Header
Use pkglts
Problems:
- name of a model unit?
"""
from __future__ import print_function
from __future__ import absolute_import
from path import Path
# The package used to generate Notebook
import nbformat as nbf
from . import render_python as rp
import six
[docs]class Model2Nb(rp.Model2Package):
""" Generate a Jupyter Notebook from a set of models.
"""
def __init__(self, models, dir=None):
"""TODO.
"""
super(Model2Nb, self).__init__(models, dir=dir)
self.with_import = False
[docs] def run(self):
"""TODO.
"""
self.generate_notebook()
[docs] def generate_notebook(self):
"""Generate a Python package equivalent to the xml definition.
Args:
- models : a list of model
- dir: the directory where the code is generated.
Returns:
- None or status
"""
# Create a directory (mymodel)
cwd = Path(self.dir)
directory=cwd/'python_notebook'
if (directory).isdir() :
_dir = directory
else:
_dir = directory.mkdir()
count = 0
files=[]
for model in self.models:
self.generate_component(model)
# In the directory notebook/model.py
# TODO: The code need to be generated locally in different methods.
nb = nbf.v4.new_notebook()
text = """\
# Automatic generation of Notebook using PyCropML
This notebook implements a crop model."""
_cells = nb['cells'] = [nbf.v4.new_markdown_cell(text),
nbf.v4.new_code_cell(self.code)]
# Generate the tests
text_test = """\
## Run the model with a set of parameters.
Each run will be defined in its own cell."""
_cells.append(nbf.v4.new_markdown_cell(text_test))
#for model in self.models:
code_tests = self.generate_test(model)
for code in code_tests:
_cells.append(nbf.v4.new_code_cell(code))
ext = '' if count == 0 else str(count)
fname =_dir/"test%s.ipynb"%ext
#fname = _dir/'test.ipynb'
with open(fname, "w") as f:
nbf.write(nb, f)
files.append(fname)
count +=1
return files
[docs] def generate_test(self, model_unit):
tab = ' '*4
m = model_unit
#name = m.description.Title
name = m.name
name.strip()
name = name.replace(' ', '_').lower()
model_name = name
psets = m.parametersets
code_test=[]
for v_tests in m.testsets:
test_name = v_tests.name # name of tests
test_runs = v_tests.test # different run in the thest
test_paramsets = v_tests.parameterset # name of paramsets
# map the paramsets
params = {}
if test_paramsets not in list(psets.keys()):
print('Unknow parameter %s'%test_paramsets)
else:
params.update(psets[test_paramsets].params)
for each_run in test_runs :
test_codes = []
# make a function that transforms a title into a function name
tname = list(each_run.keys())[0].replace(' ', '_')
tname = tname.replace('-', '_')
(run, inouts) = list(each_run.items())[0]
ins = inouts['inputs']
outs = inouts['outputs']
code = "params= %s("%model_name
test_codes.append(code)
run_param = params.copy()
run_param.update(ins)
for k, v in six.iteritems(run_param):
code = " %s = %s,"%(k,v)
test_codes.append(code)
code = " )"
test_codes.append(code)
for j, k in enumerate(m.outputs):
if k.datatype in ("STRINGLIST", "DATELIST", "STRINGARRAY", "DATEARRAY") :
code = "print('%s_estimated =')"%k.name
test_codes.append(code)
code = "print(params[%s])"%(j) if len(m.outputs)>1 else "print(params)"%k.name
test_codes.append(code)
code = "# %s_computed = %s"%(k.name,outs[k.name][0])
test_codes.append(code)
if k.datatype in ("STRING", "BOOL", "INT", "DATE"):
code = "print('%s_estimated =')"%k.name
test_codes.append(code)
code = "print(params[%s])"%(j) if len(m.outputs)>1 else "print(params)"
test_codes.append(code)
code = "# %s_computed = %s"%(k.name,outs[k.name][0])
test_codes.append(code)
if k.datatype in ("DOUBLELIST", "DOUBLEARRAY"):
code = "print('%s_estimated =')"%k.name
test_codes.append(code)
code = "print(np.around(params[%s], %s))"%(j,outs[k.name][1]) if len(m.outputs)>1 else "print(np.around(params, %s))"%outs[k.name][1]
test_codes.append(code)
code = "# %s_computed = %s"%(k.name,outs[k.name][0])
test_codes.append(code)
if k.datatype in ("INTLIST", "INTARRAY"):
code = "print('%s_estimated =')"%k.name
test_codes.append(code)
code = "print(params[%s])"%(j) if len(m.outputs)>1 else "print(params)"
test_codes.append(code)
code = "# %s_computed = %s"%(k.name,outs[k.name][0])
test_codes.append(code)
if k.datatype == "DOUBLE":
code = "print('%s_estimated =')"%k.name
test_codes.append(code)
code = "print(round(params[%s], %s))"%(j,outs[k.name][1]) if len(m.outputs)>1 else "print(round(params, %s))"%outs[k.name][1]
test_codes.append(code)
code = "# %s_computed = %s"%(k.name,outs[k.name][0])
test_codes.append(code)
code = '\n'.join(test_codes)
code_test.append(code)
return code_test