modelflowib 2.79__tar.gz → 2.81__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {modelflowib-2.79 → modelflowib-2.81}/PKG-INFO +14 -10
- {modelflowib-2.79 → modelflowib-2.81}/modelclass.py +171 -65
- {modelflowib-2.79 → modelflowib-2.81}/modelflowib.egg-info/PKG-INFO +14 -10
- {modelflowib-2.79 → modelflowib-2.81}/modelflowib.egg-info/requires.txt +12 -6
- {modelflowib-2.79 → modelflowib-2.81}/pyproject.toml +23 -11
- {modelflowib-2.79 → modelflowib-2.81}/README.md +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/license.md +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelBLfunk.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_Excel.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_cvx.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_dynare.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_financial_stability.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_latex.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_latex_class.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/model_parquet_mixin.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelconstruct.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelconstruct_estimation.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeldash.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeldashboot.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeldashsidebar.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeldekom.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeldiff.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeldisplay.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelestimation.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelestimator_new.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelflowib.egg-info/SOURCES.txt +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelflowib.egg-info/dependency_links.txt +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelflowib.egg-info/top_level.txt +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelgrab.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelgrabgdx.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelgrabwf2.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelhelp.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelhtml.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelinvert.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeljupyter.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeljupytermagic.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelmacrograb.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelmanipulation.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelmf.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelnet.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelnewton.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelnormalize.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelpattern.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelreport.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelsolver_ng.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modeluserfunk.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelvis.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelwidget.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/modelwidget_input.py +0 -0
- {modelflowib-2.79 → modelflowib-2.81}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelflowib
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.81
|
|
4
4
|
Summary: A tool to solve and manage dynamic economic and financial models
|
|
5
5
|
Author-email: Ib Hansen <Ib.Hansen.Iv@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,22 +20,26 @@ Requires-Dist: numpy
|
|
|
20
20
|
Requires-Dist: networkx
|
|
21
21
|
Requires-Dist: tqdm
|
|
22
22
|
Requires-Dist: scipy
|
|
23
|
-
Requires-Dist: numexpr
|
|
24
|
-
Requires-Dist: bottleneck
|
|
25
23
|
Requires-Dist: XlsxWriter
|
|
26
24
|
Requires-Dist: pyarrow
|
|
27
25
|
Requires-Dist: tabulate
|
|
28
26
|
Requires-Dist: openpyxl
|
|
29
27
|
Requires-Dist: xarray
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: dash
|
|
33
|
-
Requires-Dist: dash-bootstrap-components
|
|
34
|
-
Requires-Dist: dash-interactive-graphviz
|
|
35
|
-
Requires-Dist: lmfit
|
|
36
|
-
Requires-Dist: jupyter
|
|
28
|
+
Requires-Dist: jinja2
|
|
29
|
+
Requires-Dist: ipython
|
|
37
30
|
Requires-Dist: ipywidgets
|
|
38
31
|
Requires-Dist: ipydatagrid
|
|
32
|
+
Requires-Dist: lmfit
|
|
33
|
+
Requires-Dist: statsmodels
|
|
34
|
+
Requires-Dist: numba; sys_platform != "emscripten"
|
|
35
|
+
Requires-Dist: cvxopt; sys_platform != "emscripten"
|
|
36
|
+
Requires-Dist: numexpr; sys_platform != "emscripten"
|
|
37
|
+
Requires-Dist: bottleneck; sys_platform != "emscripten"
|
|
38
|
+
Requires-Dist: dash; sys_platform != "emscripten"
|
|
39
|
+
Requires-Dist: dash-bootstrap-components; sys_platform != "emscripten"
|
|
40
|
+
Requires-Dist: dash-interactive-graphviz; sys_platform != "emscripten"
|
|
41
|
+
Requires-Dist: plotly; sys_platform != "emscripten"
|
|
42
|
+
Requires-Dist: jupyter; sys_platform != "emscripten"
|
|
39
43
|
Provides-Extra: shiny
|
|
40
44
|
Requires-Dist: shiny; extra == "shiny"
|
|
41
45
|
Requires-Dist: shinywidgets; extra == "shiny"
|
|
@@ -73,6 +73,11 @@ from typing import Iterable
|
|
|
73
73
|
import zipfile
|
|
74
74
|
from functools import partial,cached_property,lru_cache
|
|
75
75
|
from tqdm.auto import tqdm
|
|
76
|
+
if sys.platform == 'emscripten':
|
|
77
|
+
# a browser has no threads, so tqdm can not start its monitor thread. Set on the
|
|
78
|
+
# base class, which tqdm.auto and tqdm.notebook inherit it from
|
|
79
|
+
import tqdm as tqdm_module
|
|
80
|
+
tqdm_module.tqdm.monitor_interval = 0
|
|
76
81
|
import operator
|
|
77
82
|
from urllib.request import urlopen
|
|
78
83
|
from io import BytesIO,StringIO
|
|
@@ -3907,20 +3912,20 @@ class Graph_Draw_Mixin():
|
|
|
3907
3912
|
|
|
3908
3913
|
def drawendo(self, **kwargs):
|
|
3909
3914
|
'''draws a graph of of the whole model'''
|
|
3910
|
-
alllinks =
|
|
3911
|
-
return self.
|
|
3915
|
+
alllinks = [node(0, n[1], n[0]) for n in self.endograph.edges()]
|
|
3916
|
+
return self.draw_links(alllinks, **kwargs)
|
|
3912
3917
|
|
|
3913
3918
|
def drawendo_lag_lead(self, **kwargs):
|
|
3914
3919
|
'''draws a graph of of the whole model'''
|
|
3915
|
-
alllinks =
|
|
3916
|
-
for n in self.endograph_lag_lead.edges()
|
|
3917
|
-
return self.
|
|
3920
|
+
alllinks = [node(0, n[1], n[0])
|
|
3921
|
+
for n in self.endograph_lag_lead.edges()]
|
|
3922
|
+
return self.draw_links(alllinks, **kwargs)
|
|
3918
3923
|
|
|
3919
3924
|
def drawmodel(self, lag=True, **kwargs):
|
|
3920
3925
|
'''draws a graph of of the whole model'''
|
|
3921
3926
|
graph = self.totgraph if lag else self.totgraph_nolag
|
|
3922
|
-
alllinks =
|
|
3923
|
-
return self.
|
|
3927
|
+
alllinks = [node(0, n[1], n[0]) for n in graph.edges()]
|
|
3928
|
+
return self.draw_links(alllinks, **kwargs)
|
|
3924
3929
|
|
|
3925
3930
|
def plotadjacency(self, size=(5, 5), title='Structure', nolag=False):
|
|
3926
3931
|
'''
|
|
@@ -3970,14 +3975,26 @@ class Graph_Draw_Mixin():
|
|
|
3970
3975
|
self.upwalk(graph, navn.upper(), maxlevel=down, lpre=False,filter=filter))
|
|
3971
3976
|
return list(chain(uplinks, downlinks))
|
|
3972
3977
|
|
|
3973
|
-
|
|
3978
|
+
# in a browser (jupyterlite) there is no graphviz program, and the svg drawing
|
|
3979
|
+
# is the one which can be zoomed and has tooltips
|
|
3980
|
+
if sys.platform == 'emscripten':
|
|
3981
|
+
#: the engine of draw: dot for graphviz, else an engine of draw_nx
|
|
3982
|
+
draw_engine = 'svg'
|
|
3983
|
+
#: the engine of draw_nx: mpl for matplotlib or svg
|
|
3984
|
+
nx_engine = 'svg'
|
|
3985
|
+
else:
|
|
3986
|
+
draw_engine = 'dot'
|
|
3987
|
+
nx_engine = 'mpl'
|
|
3988
|
+
|
|
3989
|
+
def draw(self, navn, down=1, up=1, lag=False, endo=False, filter=0, engine='', **kwargs):
|
|
3974
3990
|
'''draws a graph of dependensies of navn up to maxlevel
|
|
3975
3991
|
|
|
3976
3992
|
:lag: show the complete graph including lagged variables else only variables.
|
|
3977
3993
|
:endo: Show only the graph for current endogenous variables
|
|
3978
3994
|
:down: level downstream
|
|
3979
3995
|
:up: level upstream
|
|
3980
|
-
:engine: dot draws with graphviz, mpl and svg are the engines of draw_nx
|
|
3996
|
+
:engine: dot draws with graphviz, mpl and svg are the engines of draw_nx,
|
|
3997
|
+
default self.draw_engine which is svg in a browser else dot
|
|
3981
3998
|
|
|
3982
3999
|
If graphviz fails - the dot program is for instance not there when running
|
|
3983
4000
|
in a browser - or if self.no_graphviz is True, draw_nx draws the graph
|
|
@@ -3985,19 +4002,40 @@ class Graph_Draw_Mixin():
|
|
|
3985
4002
|
'''
|
|
3986
4003
|
alllinks = self.get_alllinks(navn, down=down, up=up, lag=lag, endo=endo,
|
|
3987
4004
|
filter=filter)
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
4005
|
+
return self.draw_links(alllinks, navn=navn.upper(), engine=engine,
|
|
4006
|
+
down=down, up=up, filter=filter, **kwargs)
|
|
4007
|
+
|
|
4008
|
+
def draw_links(self, alllinks, navn='', engine='', **kwargs):
|
|
4009
|
+
'''Draws the links from get_alllinks, drawmodel, drawendo ... with the engine
|
|
4010
|
+
|
|
4011
|
+
:engine: dot draws with graphviz, mpl and svg are the engines of draw_nx,
|
|
4012
|
+
default self.draw_engine which is svg in a browser else dot
|
|
4013
|
+
|
|
4014
|
+
If graphviz fails - the dot program is for instance not there when running
|
|
4015
|
+
in a browser - or if self.no_graphviz is True, networkx draws the graph.
|
|
4016
|
+
'''
|
|
4017
|
+
if kwargs.get('dot', False):
|
|
4018
|
+
# the caller wants the dot source itself, for instance the dash apps.
|
|
4019
|
+
# The dot program is not needed for that, and networkx can not make it
|
|
4020
|
+
return self.todot2(alllinks, navn=navn, **kwargs)
|
|
4021
|
+
|
|
4022
|
+
engine = engine or self.draw_engine
|
|
4023
|
+
if engine == 'dot' and not self.no_graphviz:
|
|
3991
4024
|
try:
|
|
3992
|
-
return self.todot2(alllinks, navn=navn
|
|
4025
|
+
return self.todot2(alllinks, navn=navn, **kwargs)
|
|
3993
4026
|
except Exception as e:
|
|
3994
4027
|
print(f'Graphviz did not draw the graph: {e}\nDrawing with networkx')
|
|
3995
|
-
engine =
|
|
4028
|
+
engine = self.nx_engine
|
|
3996
4029
|
elif engine == 'dot':
|
|
3997
|
-
engine =
|
|
4030
|
+
engine = self.nx_engine # no_graphviz is set, then networkx draws it
|
|
3998
4031
|
|
|
3999
|
-
|
|
4000
|
-
|
|
4032
|
+
if not len(alllinks):
|
|
4033
|
+
print(f'No graph {navn}')
|
|
4034
|
+
if kwargs.get('filter', 0):
|
|
4035
|
+
print('Perhaps filter prunes to much')
|
|
4036
|
+
return
|
|
4037
|
+
G = self.alllinks_to_nx(alllinks, navn=navn, **kwargs)
|
|
4038
|
+
return self.display_nx(G, navn=navn, engine=engine, **kwargs)
|
|
4001
4039
|
|
|
4002
4040
|
#: Set to True on a model instance to make draw use draw_nx, so the networkx
|
|
4003
4041
|
#: drawing can be tested on a machine where graphviz works
|
|
@@ -4085,18 +4123,26 @@ class Graph_Draw_Mixin():
|
|
|
4085
4123
|
except Exception:
|
|
4086
4124
|
G.nodes[v]['values'] = None
|
|
4087
4125
|
|
|
4088
|
-
# the layer
|
|
4126
|
+
# the layer places the node in a column, so the drawing is layered like rankdir=LR
|
|
4089
4127
|
if navn in G:
|
|
4128
|
+
# the layer is the distance to navn, upstream to the left of it
|
|
4090
4129
|
upstream = nx.single_source_shortest_path_length(G.reverse(copy=False), navn)
|
|
4091
4130
|
downstream = nx.single_source_shortest_path_length(G, navn)
|
|
4131
|
+
for v in G.nodes:
|
|
4132
|
+
up_len, down_len = upstream.get(v), downstream.get(v)
|
|
4133
|
+
if up_len is not None and (down_len is None or up_len <= down_len):
|
|
4134
|
+
G.nodes[v]['layer'] = -up_len
|
|
4135
|
+
else:
|
|
4136
|
+
G.nodes[v]['layer'] = 0 if down_len is None else down_len
|
|
4092
4137
|
else:
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4138
|
+
# no variable in the center, like drawmodel, then the layer is the logical
|
|
4139
|
+
# order. The simultaneous blocks are condensed to one node, else there is
|
|
4140
|
+
# no order, and a node of such a block gets the layer of its block
|
|
4141
|
+
condensed = nx.condensation(G)
|
|
4142
|
+
for layer, blocks in enumerate(nx.topological_generations(condensed)):
|
|
4143
|
+
for block in blocks:
|
|
4144
|
+
for v in condensed.nodes[block]['members']:
|
|
4145
|
+
G.nodes[v]['layer'] = layer
|
|
4100
4146
|
|
|
4101
4147
|
for child, parent in G.edges:
|
|
4102
4148
|
try:
|
|
@@ -4166,23 +4212,21 @@ class Graph_Draw_Mixin():
|
|
|
4166
4212
|
if alllinks is None:
|
|
4167
4213
|
alllinks = self.get_alllinks(navn, down=down, up=up, lag=lag, endo=endo,
|
|
4168
4214
|
filter=filter)
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
print('Perhaps filter prunes to much')
|
|
4173
|
-
return
|
|
4174
|
-
G = self.alllinks_to_nx(alllinks, navn=navn.upper(), **kwargs)
|
|
4175
|
-
return self.display_nx(G, navn=navn.upper(), **kwargs)
|
|
4215
|
+
engine = kwargs.pop('engine', '') or self.nx_engine
|
|
4216
|
+
return self.draw_links(alllinks, navn=navn.upper(), engine=engine,
|
|
4217
|
+
down=down, up=up, filter=filter, **kwargs)
|
|
4176
4218
|
|
|
4177
|
-
def display_nx(self, G, navn='', engine='
|
|
4219
|
+
def display_nx(self, G, navn='', engine='', **kwargs):
|
|
4178
4220
|
'''Draws a graph made by alllinks_to_nx
|
|
4179
4221
|
|
|
4180
|
-
:engine: mpl draws with matplotlib, svg makes a svg drawing
|
|
4222
|
+
:engine: mpl draws with matplotlib, svg makes a svg drawing,
|
|
4223
|
+
default self.nx_engine which is svg in a browser else mpl
|
|
4181
4224
|
|
|
4182
4225
|
Each engine is the method display_nx_<engine>, so a new engine is made by
|
|
4183
4226
|
writing a new method. They all take the same graph and the positions from
|
|
4184
4227
|
nx_layout, and only do the drawing itself.
|
|
4185
4228
|
'''
|
|
4229
|
+
engine = engine or self.nx_engine
|
|
4186
4230
|
try:
|
|
4187
4231
|
displayer = getattr(self, f'display_nx_{engine}')
|
|
4188
4232
|
except AttributeError:
|
|
@@ -4330,7 +4374,12 @@ class Graph_Draw_Mixin():
|
|
|
4330
4374
|
svgname.write_text(svg, encoding='utf-8')
|
|
4331
4375
|
if browser:
|
|
4332
4376
|
# the same as display_graph, a separate window where the svg can be zoomed
|
|
4333
|
-
|
|
4377
|
+
try:
|
|
4378
|
+
wb.open(f'file://{svgname.resolve()}', new=2)
|
|
4379
|
+
except Exception as e:
|
|
4380
|
+
# in a browser (jupyterlite) there is no window to open from
|
|
4381
|
+
print(f'No separate window here: {e}')
|
|
4382
|
+
print(f'The drawing is saved as {svgname} and is shown below')
|
|
4334
4383
|
|
|
4335
4384
|
display(HTML(svg))
|
|
4336
4385
|
self.last_svg = svg
|
|
@@ -6273,36 +6322,41 @@ class Display_Mixin():
|
|
|
6273
6322
|
from IPython.display import display, Markdown, HTML
|
|
6274
6323
|
from pathlib import Path
|
|
6275
6324
|
display(Markdown(text))
|
|
6325
|
+
rows = []
|
|
6276
6326
|
for dir in sorted(Path(folder).glob('**')):
|
|
6277
6327
|
# print(f'{dir=} {nocwd=}')
|
|
6278
6328
|
if len(dir.parts) and str(dir.parts[-1]).startswith('.'):
|
|
6279
6329
|
continue
|
|
6280
|
-
|
|
6330
|
+
|
|
6281
6331
|
if dir == Path('.') and nocwd :
|
|
6282
6332
|
continue
|
|
6283
|
-
|
|
6284
|
-
filelist = (list(dir.glob('*readme.ipynb'))
|
|
6285
|
-
+ [f for f in sorted(dir.glob('*.ipynb'))
|
|
6333
|
+
|
|
6334
|
+
filelist = (list(dir.glob('*readme.ipynb'))
|
|
6335
|
+
+ [f for f in sorted(dir.glob('*.ipynb'))
|
|
6286
6336
|
if not f.stem.endswith('readme')])
|
|
6287
|
-
|
|
6288
|
-
for i, notebook in enumerate(filelist):
|
|
6289
|
-
# print(notebook)
|
|
6290
|
-
if (not all) and (notebook.name.startswith('test') or notebook.name.startswith('Overview')):
|
|
6291
|
-
continue
|
|
6292
|
-
if i == 0:
|
|
6293
|
-
blanks = ''.join(
|
|
6294
|
-
[' ']*len(dir.parts))
|
|
6295
|
-
if len(dir.parts):
|
|
6296
|
-
display(HTML(f'{blanks}<b>{str(dir)}</b>'))
|
|
6297
|
-
else:
|
|
6298
|
-
display(
|
|
6299
|
-
HTML(f'{blanks}<b>{str(Path.cwd().parts[-1])} (.)</b>'))
|
|
6300
6337
|
|
|
6301
|
-
|
|
6338
|
+
if not all:
|
|
6339
|
+
filelist = [f for f in filelist
|
|
6340
|
+
if not (f.name.startswith('test') or f.name.startswith('Overview'))]
|
|
6341
|
+
|
|
6342
|
+
if not filelist:
|
|
6343
|
+
continue
|
|
6344
|
+
|
|
6345
|
+
indent = 2 * len(dir.parts) # indentation of this folder in em
|
|
6346
|
+
folder_name = str(dir) if len(dir.parts) else f'{str(Path.cwd().parts[-1])} (.)'
|
|
6347
|
+
rows.append(
|
|
6348
|
+
f'<tr><td colspan="2" style="text-align:left;padding:6px 12px 2px {indent}em">'
|
|
6349
|
+
f'<b>{folder_name}</b></td></tr>')
|
|
6350
|
+
|
|
6351
|
+
for notebook in filelist:
|
|
6302
6352
|
# print(notebook)
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6353
|
+
name = notebook.name.split('.')[0]
|
|
6354
|
+
title = Display_Mixin._notebook_title(notebook)
|
|
6355
|
+
rows.append(
|
|
6356
|
+
f'<tr><td style="text-align:left;padding:2px 24px 2px {indent+2}em;white-space:nowrap">'
|
|
6357
|
+
f'<a href="{notebook}" target="_blank">{name}</a></td>'
|
|
6358
|
+
f'<td style="text-align:left;padding:2px 12px">{title}</td></tr>')
|
|
6359
|
+
|
|
6306
6360
|
# try:
|
|
6307
6361
|
# # Replace with your method of opening a notebook
|
|
6308
6362
|
# # Example: Using jupyter command-line to open the notebook
|
|
@@ -6310,12 +6364,43 @@ class Display_Mixin():
|
|
|
6310
6364
|
# subprocess.Popen(["jupyter", "notebook", str(notebook)])
|
|
6311
6365
|
# except Exception as e:
|
|
6312
6366
|
# print(f"Error opening notebook {notebook}: {e}")
|
|
6367
|
+
if rows:
|
|
6368
|
+
display(HTML(
|
|
6369
|
+
'<table style="border-collapse:collapse;border:none">'
|
|
6370
|
+
+ ''.join(rows) + '</table>'))
|
|
6313
6371
|
|
|
6314
6372
|
|
|
6373
|
+
@staticmethod
|
|
6374
|
+
def _notebook_title(fname):
|
|
6375
|
+
'''Returns the first line starting with one or more # in the first cell of a jupyter notebook.
|
|
6376
|
+
|
|
6377
|
+
Returns an empty string if the notebook can not be read or no such line is found'''
|
|
6378
|
+
|
|
6379
|
+
import json
|
|
6380
|
+
from html import escape
|
|
6381
|
+
|
|
6382
|
+
try:
|
|
6383
|
+
with open(fname, 'rt', encoding='utf-8') as f:
|
|
6384
|
+
nb = json.load(f)
|
|
6385
|
+
cells = nb.get('cells', [])
|
|
6386
|
+
if not cells:
|
|
6387
|
+
return ''
|
|
6388
|
+
source = cells[0].get('source', '')
|
|
6389
|
+
lines = source.splitlines() if isinstance(source, str) else source
|
|
6390
|
+
for line in lines:
|
|
6391
|
+
stripped = line.strip()
|
|
6392
|
+
if stripped.startswith('#'):
|
|
6393
|
+
return escape(stripped.lstrip('#').strip())
|
|
6394
|
+
except Exception:
|
|
6395
|
+
...
|
|
6396
|
+
return ''
|
|
6397
|
+
|
|
6315
6398
|
@staticmethod
|
|
6316
6399
|
def display_toc_this(pat='*',text='**Jupyter notebooks**',path='.',ext='ipynb',showext=False):
|
|
6317
|
-
|
|
6318
|
-
'''In a jupyter notebook this function displays a clickable table of content in the folder pat with name in path
|
|
6400
|
+
|
|
6401
|
+
'''In a jupyter notebook this function displays a clickable table of content in the folder pat with name in path
|
|
6402
|
+
|
|
6403
|
+
For notebooks the first markdown header in the first cell is shown beside the name'''
|
|
6319
6404
|
|
|
6320
6405
|
from IPython.display import display, Markdown, HTML
|
|
6321
6406
|
from pathlib import Path
|
|
@@ -6323,10 +6408,18 @@ class Display_Mixin():
|
|
|
6323
6408
|
display(Markdown(text))
|
|
6324
6409
|
dir = Path(path)
|
|
6325
6410
|
# print(dir,':')
|
|
6411
|
+
rows = []
|
|
6326
6412
|
for fname in sorted(dir.glob(pat+'.'+ext)):
|
|
6327
6413
|
name = fname.name if showext else fname.name.split('.')[0]
|
|
6414
|
+
title = Display_Mixin._notebook_title(fname) if ext == 'ipynb' else ''
|
|
6415
|
+
rows.append(
|
|
6416
|
+
f'<tr><td style="text-align:left;padding:2px 24px 2px 12px;white-space:nowrap">'
|
|
6417
|
+
f'<a href="{fname}" target="_blank">{name}</a></td>'
|
|
6418
|
+
f'<td style="text-align:left;padding:2px 12px">{title}</td></tr>')
|
|
6419
|
+
if rows:
|
|
6328
6420
|
display(HTML(
|
|
6329
|
-
|
|
6421
|
+
'<table style="border-collapse:collapse;border:none">'
|
|
6422
|
+
+ ''.join(rows) + '</table>'))
|
|
6330
6423
|
|
|
6331
6424
|
|
|
6332
6425
|
@staticmethod
|
|
@@ -6379,13 +6472,25 @@ class Display_Mixin():
|
|
|
6379
6472
|
} catch (e) { /* ignore */ }
|
|
6380
6473
|
"""))
|
|
6381
6474
|
|
|
6382
|
-
# Notebook 7 / JupyterLab:
|
|
6383
|
-
#
|
|
6475
|
+
# Notebook 7 / JupyterLab: the height is set on the output area of the
|
|
6476
|
+
# cell: .jp-mod-outputsScrolled .jp-Cell-outputArea {max-height: 24em}
|
|
6477
|
+
# height:auto also undoes a height the user has dragged in place, as an
|
|
6478
|
+
# important declaration wins over an inline style
|
|
6384
6479
|
display(HTML("""
|
|
6385
6480
|
<style id="mf-scroll-off">
|
|
6481
|
+
.jp-mod-outputsScrolled .jp-Cell-outputArea {
|
|
6482
|
+
max-height: none !important;
|
|
6483
|
+
height: auto !important;
|
|
6484
|
+
overflow-y: visible !important;
|
|
6485
|
+
resize: none !important;
|
|
6486
|
+
}
|
|
6386
6487
|
.jp-OutputArea-output.jp-OutputArea-output { max-height: none !important; }
|
|
6387
|
-
|
|
6488
|
+
/* Classic Notebook (<=6) sets height, not max-height, on output_scroll */
|
|
6489
|
+
.output_scroll {
|
|
6490
|
+
height: auto !important;
|
|
6388
6491
|
max-height: none !important;
|
|
6492
|
+
overflow: visible !important;
|
|
6493
|
+
box-shadow: none !important;
|
|
6389
6494
|
}
|
|
6390
6495
|
</style>
|
|
6391
6496
|
"""))
|
|
@@ -6410,11 +6515,12 @@ class Display_Mixin():
|
|
|
6410
6515
|
} catch (e) { /* ignore */ }
|
|
6411
6516
|
"""))
|
|
6412
6517
|
|
|
6413
|
-
# Remove the override
|
|
6518
|
+
# Remove the override stylesheets we injected above, there is one for
|
|
6519
|
+
# each cell where scroll_off has been run
|
|
6414
6520
|
display(Javascript("""
|
|
6415
6521
|
try {
|
|
6416
|
-
|
|
6417
|
-
|
|
6522
|
+
document.querySelectorAll('#mf-scroll-off').forEach(
|
|
6523
|
+
function (s) { s.parentNode.removeChild(s); });
|
|
6418
6524
|
} catch (e) { /* ignore */ }
|
|
6419
6525
|
"""))
|
|
6420
6526
|
except Exception as e:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelflowib
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.81
|
|
4
4
|
Summary: A tool to solve and manage dynamic economic and financial models
|
|
5
5
|
Author-email: Ib Hansen <Ib.Hansen.Iv@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,22 +20,26 @@ Requires-Dist: numpy
|
|
|
20
20
|
Requires-Dist: networkx
|
|
21
21
|
Requires-Dist: tqdm
|
|
22
22
|
Requires-Dist: scipy
|
|
23
|
-
Requires-Dist: numexpr
|
|
24
|
-
Requires-Dist: bottleneck
|
|
25
23
|
Requires-Dist: XlsxWriter
|
|
26
24
|
Requires-Dist: pyarrow
|
|
27
25
|
Requires-Dist: tabulate
|
|
28
26
|
Requires-Dist: openpyxl
|
|
29
27
|
Requires-Dist: xarray
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: dash
|
|
33
|
-
Requires-Dist: dash-bootstrap-components
|
|
34
|
-
Requires-Dist: dash-interactive-graphviz
|
|
35
|
-
Requires-Dist: lmfit
|
|
36
|
-
Requires-Dist: jupyter
|
|
28
|
+
Requires-Dist: jinja2
|
|
29
|
+
Requires-Dist: ipython
|
|
37
30
|
Requires-Dist: ipywidgets
|
|
38
31
|
Requires-Dist: ipydatagrid
|
|
32
|
+
Requires-Dist: lmfit
|
|
33
|
+
Requires-Dist: statsmodels
|
|
34
|
+
Requires-Dist: numba; sys_platform != "emscripten"
|
|
35
|
+
Requires-Dist: cvxopt; sys_platform != "emscripten"
|
|
36
|
+
Requires-Dist: numexpr; sys_platform != "emscripten"
|
|
37
|
+
Requires-Dist: bottleneck; sys_platform != "emscripten"
|
|
38
|
+
Requires-Dist: dash; sys_platform != "emscripten"
|
|
39
|
+
Requires-Dist: dash-bootstrap-components; sys_platform != "emscripten"
|
|
40
|
+
Requires-Dist: dash-interactive-graphviz; sys_platform != "emscripten"
|
|
41
|
+
Requires-Dist: plotly; sys_platform != "emscripten"
|
|
42
|
+
Requires-Dist: jupyter; sys_platform != "emscripten"
|
|
39
43
|
Provides-Extra: shiny
|
|
40
44
|
Requires-Dist: shiny; extra == "shiny"
|
|
41
45
|
Requires-Dist: shinywidgets; extra == "shiny"
|
|
@@ -6,22 +6,28 @@ numpy
|
|
|
6
6
|
networkx
|
|
7
7
|
tqdm
|
|
8
8
|
scipy
|
|
9
|
-
numexpr
|
|
10
|
-
bottleneck
|
|
11
9
|
XlsxWriter
|
|
12
10
|
pyarrow
|
|
13
11
|
tabulate
|
|
14
12
|
openpyxl
|
|
15
13
|
xarray
|
|
16
|
-
|
|
14
|
+
jinja2
|
|
15
|
+
ipython
|
|
16
|
+
ipywidgets
|
|
17
|
+
ipydatagrid
|
|
18
|
+
lmfit
|
|
19
|
+
statsmodels
|
|
20
|
+
|
|
21
|
+
[:sys_platform != "emscripten"]
|
|
17
22
|
numba
|
|
23
|
+
cvxopt
|
|
24
|
+
numexpr
|
|
25
|
+
bottleneck
|
|
18
26
|
dash
|
|
19
27
|
dash-bootstrap-components
|
|
20
28
|
dash-interactive-graphviz
|
|
21
|
-
|
|
29
|
+
plotly
|
|
22
30
|
jupyter
|
|
23
|
-
ipywidgets
|
|
24
|
-
ipydatagrid
|
|
25
31
|
|
|
26
32
|
[shiny]
|
|
27
33
|
shiny
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "modelflowib" # PyPI distribution name
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.81" # OVERWRITTEN at build time from MF_VERSION
|
|
8
8
|
# (set_pyproject_version.py / make_pip.py -v)
|
|
9
9
|
description = "A tool to solve and manage dynamic economic and financial models"
|
|
10
10
|
readme = "README.md"
|
|
@@ -18,8 +18,15 @@ classifiers = [
|
|
|
18
18
|
"Operating System :: OS Independent",
|
|
19
19
|
]
|
|
20
20
|
|
|
21
|
-
# PyPI dependencies (pip names).
|
|
21
|
+
# PyPI dependencies (pip names).
|
|
22
|
+
#
|
|
23
|
+
# The ones marked `sys_platform != "emscripten"` have no wasm build, or need a web
|
|
24
|
+
# server, so they can not be installed in a browser (JupyterLite/Pyodide). pip on a
|
|
25
|
+
# desktop installs them as before; micropip in the browser skips them. That makes
|
|
26
|
+
# `piplite.install("modelflowib")` work *with* its dependencies, so a notebook in
|
|
27
|
+
# JupyterLite needs no list of packages of its own.
|
|
22
28
|
dependencies = [
|
|
29
|
+
# --- everywhere ---
|
|
23
30
|
"pandas",
|
|
24
31
|
"matplotlib",
|
|
25
32
|
"seaborn",
|
|
@@ -28,22 +35,27 @@ dependencies = [
|
|
|
28
35
|
"networkx",
|
|
29
36
|
"tqdm",
|
|
30
37
|
"scipy",
|
|
31
|
-
"numexpr",
|
|
32
|
-
"bottleneck",
|
|
33
38
|
"XlsxWriter",
|
|
34
39
|
"pyarrow",
|
|
35
40
|
"tabulate",
|
|
36
41
|
"openpyxl",
|
|
37
42
|
"xarray",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"dash",
|
|
41
|
-
"dash-bootstrap-components",
|
|
42
|
-
"dash-interactive-graphviz",
|
|
43
|
-
"lmfit",
|
|
44
|
-
"jupyter",
|
|
43
|
+
"jinja2", # pandas .style, used by the report and vis tables
|
|
44
|
+
"ipython", # IPython.display, imported by most modules
|
|
45
45
|
"ipywidgets",
|
|
46
46
|
"ipydatagrid",
|
|
47
|
+
"lmfit", # modelestimation, modelestimator_new
|
|
48
|
+
"statsmodels", # modelestimation, modelestimator_new
|
|
49
|
+
# --- not in a browser ---
|
|
50
|
+
"numba; sys_platform != 'emscripten'",
|
|
51
|
+
"cvxopt; sys_platform != 'emscripten'",
|
|
52
|
+
"numexpr; sys_platform != 'emscripten'", # pandas accelerators
|
|
53
|
+
"bottleneck; sys_platform != 'emscripten'",
|
|
54
|
+
"dash; sys_platform != 'emscripten'", # needs a web server
|
|
55
|
+
"dash-bootstrap-components; sys_platform != 'emscripten'",
|
|
56
|
+
"dash-interactive-graphviz; sys_platform != 'emscripten'",
|
|
57
|
+
"plotly; sys_platform != 'emscripten'", # modeldashsidebar
|
|
58
|
+
"jupyter; sys_platform != 'emscripten'", # JupyterLite is the notebook there
|
|
47
59
|
]
|
|
48
60
|
|
|
49
61
|
[project.optional-dependencies]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|