#!/usr/bin/env python
# coding: utf-8
'''
This module defines several magic jupyter functions\:
:graphviz: Draw Graphviz graph
:dataframe: Create Pandas Dataframe
:latexflow: Create a modelflow modelinstance from latex script
he doc strings can only be displayed when the module is used from Jupyter. So they are not shown in the Sphinx documentation To display the doc strings use the functions in jupyter.
'''
from IPython.display import display, Math, Latex, Markdown , Image, SVG, display_svg,IFrame
from IPython.lib.latextools import latex_to_png
from io import StringIO
import pandas as pd
from IPython.core.magic import register_line_magic, register_cell_magic
from subprocess import run
import re
from model_latex import latextotxt
from modelclass import model
from modelmanipulation import explode
from model_latex_class import a_latex_model
[docs]
def get_options(line,defaultname = 'test'):
'''
Retrives options from the first line
Args:
line (TYPE): DESCRIPTION.
defaultname (TYPE, optional): DESCRIPTION. Defaults to 'test'.
Returns:
name (string): name .
opt (dict): options.
'''
if line:
arglistfull = line.split()
name= arglistfull[0]
arglist=arglistfull[1:] if len(arglistfull)>= 1 else []
else:
name = defaultname
arglist=[]
opt = {o.split('=')[0] : o.split('=')[1] if len(o.split('='))==2 else True for o in arglist}
opt = {o : False if ( v== '0' or v=='False') else v for o,v in opt.items()}
return name,opt
try:
# this is to
@register_cell_magic
def graphviz(line, cell):
'''Creates a ModelFlow model from a Latex document'''
name,options = get_options(line,'Testgraph')
gv = cell
# print(options)
model.display_graph(gv,name,**options)
return
# In[29]:
@register_cell_magic
def latexflow(line, cell):
'''Creates a ModelFlow model from a Latex document'''
name,options = get_options(line)
lmodel = cell
# display(Markdown(f'## Now creating the model **{name}**'))
fmodel = latextotxt(cell)
if options.get('debug',False):
display(Markdown('## Creating this Template model'))
print(fmodel)
mmodel = model.from_eq(fmodel)
mmodel.equations_latex = cell
globals()[f'{name}'] = mmodel
ia = get_ipython()
ia.push(f'{name}',interactive=True)
if options.get('render',True):
display(Markdown(cell))
# display(Markdown('## The model'))
if options.get('display',False):
display(Markdown(cell))
display(Markdown('## Creating this Template model'))
print(mmodel.equations_original)
display(Markdown('## And this Business Logic Language model'))
print(mmodel.equations)
return
@register_cell_magic
def latexmodelgrab(line, cell):
'''Creates a ModelFlow model from a Latex document'''
name,options = get_options(line)
ia = get_ipython()
# print(f'{options=}')
if options.get('segment',False):
if f'{name}_dict' not in globals():
globals()[f'{name}_dict'] = {}
ia.push(f'{name}_dict',interactive=True)
modelsegment= options.get('segment','rest')
globals()[f'{name}_dict'][modelsegment]=cell
if modelsegment.startswith('list'):
display(Markdown(cell))
return
if modelsegment.startswith('text'):
display(Markdown(cell))
return
# we want this cell plus all list cells to make this small model
if options.get('all',False):
model_text = '\n'.join([text for name,text in globals()[f'{name}_dict'].items()] )
else:
model_text = '\n'.join([text for name,text in globals()[f'{name}_dict'].items()
if name.startswith('list')])+cell
else:
if f'{name}_dict' in globals():
temp='\n'
model_text = '\n'.join([text for name,text in globals()[f'{name}_dict'].items()] )
else:
model_text = cell
model_text = r'''
\documentclass{article}
% Add necessary packages
\usepackage{amsmath} % For mathematical equations
\begin{document}
''' + model_text + r'''
\end{document}'''
replace = [('##','title'),('###','section')]
for pat,rep in replace:
pattern = fr'^{pat} (.*?)\s*$'
replacement = fr'\\{rep}{{\1}}'+'\n'
model_text = re.sub(pattern, replacement, model_text, flags=re.MULTILINE)
latex_model = a_latex_model(model_text,modelname=name)
mmodel = latex_model.mmodel
mmodel.equations_latex = model_text
globals()[f'{name}'] = mmodel
globals()[f'{name}_latex_model_instance'] = latex_model
ia.push(f'{name}',interactive=True)
ia.push(f'{name}_latex_model_instance',interactive=True)
if options.get('render',True) and not options.get('display',False):
display(Markdown(cell))
# display(Markdown('## The model'))
if options.get('display',False):
display(Markdown(cell))
try:
print(f'Model:{name} is created from these segments:\n'+
f"{temp.join([s for s in globals()[f'{name}_dict'].keys()])} \n")
except:
...
display(Markdown('## Creating this Template model'))
print(mmodel.equations_original)
display(Markdown('## And this Business Logic Language model'))
print(mmodel.equations)
return
def ibmelt(df,prefix='',per=3):
# breakpoint()
temp= df.reset_index().rename(columns={'index':'row'}).melt(id_vars='row',var_name='column').assign(var_name=lambda x: prefix+x.row+'_'+x.column) .loc[:,['value','var_name']].set_index('var_name')
newdf = pd.concat([temp]*per,axis=1).T
newdf.index = range(per)
newdf.index.name = 'Year'
return newdf
# @register_cell_magic
# def dataframe(line, cell):
# '''Converts this cell to a dataframe. and create a melted dataframe
# options can be added to the inpput line\:
# - t transposes the dataframe
# - periods=<number> repeats the melted datframe
# - repeat = <number> repeats the original dataframe - for parameters
# - melt will create a melted dataframe
# - prefix=<a string> prefix columns in the melted dataframe
# - show will show the resulting dataframes
# - start=index will set the index (default 2021)
# '''
# name,options = get_options(line,'Testgraph')
# trans = options.get('t',False )
# if (options.get('help',False )):
# print(__doc__)
# prefix = options.get('prefix','')
# periods = int(options.get('periods','1'))
# melt = options.get('melt',False)
# start = int(options.get('start','2021'))
# silent = options.get('silent',True)
# ia = get_ipython()
# xtrans = (lambda xx:xx.T) if trans else (lambda xx:xx)
# xcell= cell.replace('%','').replace(',','.')
# mul = 0.01 if '%' in cell else 1.
# sio = StringIO(xcell)
# df = pd.read_csv(sio,sep=r"\s+|\t+|\s+\t+|\t+\s+",engine='python')\
# .pipe(xtrans)\
# .pipe(lambda xx:xx.rename(index = {i:i.upper() if type(i) == str else i for i in xx.index}
# ,columns={c:c.upper() for c in xx.columns})) *mul
# # breakpoint()
# if not melt:
# df= pd.concat([df]*periods,axis=0)
# df.index = pd.period_range(start=start,freq = 'Y',periods=len(df))
# df.index.name = 'index'
# globals()[f'{name}'] = df
# ia.push(f'{name}',interactive=True)
# if melt:
# df_melted = ibmelt(df,prefix=prefix.upper(),per=periods)
# df_melted.index = pd.period_range(start=start,freq = 'Y',periods=len(df_melted))
# df_melted.index.name = 'index'
# globals()[f'{name}_melted'] = df_melted
# ia.push(f'{name}_melted',interactive=True)
# if not silent:
# melttext = f' and {name}_melted' if melt else ''
# display(Markdown(f'## Created the dataframes: {name}{melttext}'))
# if options.get('show',False):
# display(df)
# if melt: display(df_melted)
# return
@register_cell_magic
def modeleviews(line, cell):
'''Creates a ModelFlow model from a Latex document
In developement
'''
try:
import pyeviews as evp
except:
print('no pyeviews')
raise Exception('No pyeviews ')
from pathlib import Path, PureWindowsPath
name,options = get_options(line)
display(Markdown(f'# Now creating the model **{name}**'))
commands = cell.split('\n')
print(commands)
if options.get('debug',False):
display(Markdown('# executing these eviews commands'))
print(cell)
eviewsapp = evp.GetEViewsApp(instance='new',showwindow=True)
for c in commands:
print(c)
evp.Run(c,eviewsapp)
evp.Cleanup()
return
def ibmelt(df,prefix='',per=3):
# breakpoint()
temp= df.reset_index().rename(columns={'index':'row'}).melt(id_vars='row',var_name='column').assign(var_name=lambda x: prefix+x.row+'_'+x.column) .loc[:,['value','var_name']].set_index('var_name')
newdf = pd.concat([temp]*per,axis=1).T
newdf.index = range(per)
newdf.index.name = 'Year'
return newdf
@register_cell_magic
def dataframe(line, cell):
'''Converts this cell to a dataframe. and create a melted dataframe
Works for yearly data.
Options can be added to the input line
- t transposes the dataframe
- periods=<number> repeats the melted datframe
- melt will create a melted dataframe
- prefix=<a string> prefix columns in the melted dataframe
- show will show the resulting dataframes
- start will set the start index (default to 2021) '''
name,options = get_options(line,'Testgraph')
trans = options.get('t',False )
prefix = options.get('prefix','')
periods = int(options.get('periods','1'))
melt = options.get('melt',False)
start = int(options.get('start','2021'))
silent = options.get('silent',True)
ia = get_ipython()
xtrans = (lambda xx:xx.T) if trans else (lambda xx:xx)
xcell= cell.replace('%','').replace(',','.')
mul = 0.01 if '%' in cell else 1.
sio = StringIO(xcell)
df = pd.read_csv(sio,sep=r"\s+|\t+|\s+\t+|\t+\s+",engine='python')\
.pipe(xtrans)\
.pipe(lambda xx:xx.rename(index = {i:i.upper() if type(i) == str else i for i in xx.index}
,columns={c:c.upper() for c in xx.columns})) *mul
# breakpoint()
if not melt:
df= pd.concat([df]*periods,axis=0)
df.index = pd.period_range(start=start,freq = 'Y',periods=len(df))
df.index.name = 'index'
globals()[f'{name}'] = df
ia.push(f'{name}',interactive=True)
if melt:
df_melted = ibmelt(df,prefix=prefix.upper(),per=periods)
df_melted.index = pd.period_range(start=start,freq = 'Y',periods=len(df_melted))
df_melted.index.name = 'index'
globals()[f'{name}_melted'] = df_melted
ia.push(f'{name}_melted',interactive=True)
if not silent:
melttext = f' and {name}_melted' if melt else ''
display(Markdown(f'## Created the dataframes: {name}{melttext}'))
if options.get('show',False):
display(df)
if melt: display(df_melted)
return
except:
print('no magic')