modelflowib 2.79__tar.gz → 2.80__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.
Files changed (50) hide show
  1. {modelflowib-2.79 → modelflowib-2.80}/PKG-INFO +1 -1
  2. {modelflowib-2.79 → modelflowib-2.80}/modelclass.py +79 -35
  3. {modelflowib-2.79 → modelflowib-2.80}/modelflowib.egg-info/PKG-INFO +1 -1
  4. {modelflowib-2.79 → modelflowib-2.80}/pyproject.toml +1 -1
  5. {modelflowib-2.79 → modelflowib-2.80}/README.md +0 -0
  6. {modelflowib-2.79 → modelflowib-2.80}/license.md +0 -0
  7. {modelflowib-2.79 → modelflowib-2.80}/modelBLfunk.py +0 -0
  8. {modelflowib-2.79 → modelflowib-2.80}/model_Excel.py +0 -0
  9. {modelflowib-2.79 → modelflowib-2.80}/model_cvx.py +0 -0
  10. {modelflowib-2.79 → modelflowib-2.80}/model_dynare.py +0 -0
  11. {modelflowib-2.79 → modelflowib-2.80}/model_financial_stability.py +0 -0
  12. {modelflowib-2.79 → modelflowib-2.80}/model_latex.py +0 -0
  13. {modelflowib-2.79 → modelflowib-2.80}/model_latex_class.py +0 -0
  14. {modelflowib-2.79 → modelflowib-2.80}/model_parquet_mixin.py +0 -0
  15. {modelflowib-2.79 → modelflowib-2.80}/modelconstruct.py +0 -0
  16. {modelflowib-2.79 → modelflowib-2.80}/modelconstruct_estimation.py +0 -0
  17. {modelflowib-2.79 → modelflowib-2.80}/modeldash.py +0 -0
  18. {modelflowib-2.79 → modelflowib-2.80}/modeldashboot.py +0 -0
  19. {modelflowib-2.79 → modelflowib-2.80}/modeldashsidebar.py +0 -0
  20. {modelflowib-2.79 → modelflowib-2.80}/modeldekom.py +0 -0
  21. {modelflowib-2.79 → modelflowib-2.80}/modeldiff.py +0 -0
  22. {modelflowib-2.79 → modelflowib-2.80}/modeldisplay.py +0 -0
  23. {modelflowib-2.79 → modelflowib-2.80}/modelestimation.py +0 -0
  24. {modelflowib-2.79 → modelflowib-2.80}/modelestimator_new.py +0 -0
  25. {modelflowib-2.79 → modelflowib-2.80}/modelflowib.egg-info/SOURCES.txt +0 -0
  26. {modelflowib-2.79 → modelflowib-2.80}/modelflowib.egg-info/dependency_links.txt +0 -0
  27. {modelflowib-2.79 → modelflowib-2.80}/modelflowib.egg-info/requires.txt +0 -0
  28. {modelflowib-2.79 → modelflowib-2.80}/modelflowib.egg-info/top_level.txt +0 -0
  29. {modelflowib-2.79 → modelflowib-2.80}/modelgrab.py +0 -0
  30. {modelflowib-2.79 → modelflowib-2.80}/modelgrabgdx.py +0 -0
  31. {modelflowib-2.79 → modelflowib-2.80}/modelgrabwf2.py +0 -0
  32. {modelflowib-2.79 → modelflowib-2.80}/modelhelp.py +0 -0
  33. {modelflowib-2.79 → modelflowib-2.80}/modelhtml.py +0 -0
  34. {modelflowib-2.79 → modelflowib-2.80}/modelinvert.py +0 -0
  35. {modelflowib-2.79 → modelflowib-2.80}/modeljupyter.py +0 -0
  36. {modelflowib-2.79 → modelflowib-2.80}/modeljupytermagic.py +0 -0
  37. {modelflowib-2.79 → modelflowib-2.80}/modelmacrograb.py +0 -0
  38. {modelflowib-2.79 → modelflowib-2.80}/modelmanipulation.py +0 -0
  39. {modelflowib-2.79 → modelflowib-2.80}/modelmf.py +0 -0
  40. {modelflowib-2.79 → modelflowib-2.80}/modelnet.py +0 -0
  41. {modelflowib-2.79 → modelflowib-2.80}/modelnewton.py +0 -0
  42. {modelflowib-2.79 → modelflowib-2.80}/modelnormalize.py +0 -0
  43. {modelflowib-2.79 → modelflowib-2.80}/modelpattern.py +0 -0
  44. {modelflowib-2.79 → modelflowib-2.80}/modelreport.py +0 -0
  45. {modelflowib-2.79 → modelflowib-2.80}/modelsolver_ng.py +0 -0
  46. {modelflowib-2.79 → modelflowib-2.80}/modeluserfunk.py +0 -0
  47. {modelflowib-2.79 → modelflowib-2.80}/modelvis.py +0 -0
  48. {modelflowib-2.79 → modelflowib-2.80}/modelwidget.py +0 -0
  49. {modelflowib-2.79 → modelflowib-2.80}/modelwidget_input.py +0 -0
  50. {modelflowib-2.79 → modelflowib-2.80}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelflowib
3
- Version: 2.79
3
+ Version: 2.80
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
@@ -3907,20 +3907,20 @@ class Graph_Draw_Mixin():
3907
3907
 
3908
3908
  def drawendo(self, **kwargs):
3909
3909
  '''draws a graph of of the whole model'''
3910
- alllinks = (node(0, n[1], n[0]) for n in self.endograph.edges())
3911
- return self.todot2(alllinks, **kwargs)
3910
+ alllinks = [node(0, n[1], n[0]) for n in self.endograph.edges()]
3911
+ return self.draw_links(alllinks, **kwargs)
3912
3912
 
3913
3913
  def drawendo_lag_lead(self, **kwargs):
3914
3914
  '''draws a graph of of the whole model'''
3915
- alllinks = (node(0, n[1], n[0])
3916
- for n in self.endograph_lag_lead.edges())
3917
- return self.todot2(alllinks, **kwargs)
3915
+ alllinks = [node(0, n[1], n[0])
3916
+ for n in self.endograph_lag_lead.edges()]
3917
+ return self.draw_links(alllinks, **kwargs)
3918
3918
 
3919
3919
  def drawmodel(self, lag=True, **kwargs):
3920
3920
  '''draws a graph of of the whole model'''
3921
3921
  graph = self.totgraph if lag else self.totgraph_nolag
3922
- alllinks = (node(0, n[1], n[0]) for n in graph.edges())
3923
- return self.todot2(alllinks, **kwargs)
3922
+ alllinks = [node(0, n[1], n[0]) for n in graph.edges()]
3923
+ return self.draw_links(alllinks, **kwargs)
3924
3924
 
3925
3925
  def plotadjacency(self, size=(5, 5), title='Structure', nolag=False):
3926
3926
  '''
@@ -3970,14 +3970,26 @@ class Graph_Draw_Mixin():
3970
3970
  self.upwalk(graph, navn.upper(), maxlevel=down, lpre=False,filter=filter))
3971
3971
  return list(chain(uplinks, downlinks))
3972
3972
 
3973
- def draw(self, navn, down=1, up=1, lag=False, endo=False, filter=0, engine='dot', **kwargs):
3973
+ # in a browser (jupyterlite) there is no graphviz program, and the svg drawing
3974
+ # is the one which can be zoomed and has tooltips
3975
+ if sys.platform == 'emscripten':
3976
+ #: the engine of draw: dot for graphviz, else an engine of draw_nx
3977
+ draw_engine = 'svg'
3978
+ #: the engine of draw_nx: mpl for matplotlib or svg
3979
+ nx_engine = 'svg'
3980
+ else:
3981
+ draw_engine = 'dot'
3982
+ nx_engine = 'mpl'
3983
+
3984
+ def draw(self, navn, down=1, up=1, lag=False, endo=False, filter=0, engine='', **kwargs):
3974
3985
  '''draws a graph of dependensies of navn up to maxlevel
3975
3986
 
3976
3987
  :lag: show the complete graph including lagged variables else only variables.
3977
3988
  :endo: Show only the graph for current endogenous variables
3978
3989
  :down: level downstream
3979
3990
  :up: level upstream
3980
- :engine: dot draws with graphviz, mpl and svg are the engines of draw_nx
3991
+ :engine: dot draws with graphviz, mpl and svg are the engines of draw_nx,
3992
+ default self.draw_engine which is svg in a browser else dot
3981
3993
 
3982
3994
  If graphviz fails - the dot program is for instance not there when running
3983
3995
  in a browser - or if self.no_graphviz is True, draw_nx draws the graph
@@ -3985,19 +3997,40 @@ class Graph_Draw_Mixin():
3985
3997
  '''
3986
3998
  alllinks = self.get_alllinks(navn, down=down, up=up, lag=lag, endo=endo,
3987
3999
  filter=filter)
3988
- # dot=True means the caller wants the dot source, for instance the dash apps,
3989
- # then no_graphviz is not respected, as networkx can not make a dot file
3990
- if engine == 'dot' and (not self.no_graphviz or kwargs.get('dot', False)):
4000
+ return self.draw_links(alllinks, navn=navn.upper(), engine=engine,
4001
+ down=down, up=up, filter=filter, **kwargs)
4002
+
4003
+ def draw_links(self, alllinks, navn='', engine='', **kwargs):
4004
+ '''Draws the links from get_alllinks, drawmodel, drawendo ... with the engine
4005
+
4006
+ :engine: dot draws with graphviz, mpl and svg are the engines of draw_nx,
4007
+ default self.draw_engine which is svg in a browser else dot
4008
+
4009
+ If graphviz fails - the dot program is for instance not there when running
4010
+ in a browser - or if self.no_graphviz is True, networkx draws the graph.
4011
+ '''
4012
+ if kwargs.get('dot', False):
4013
+ # the caller wants the dot source itself, for instance the dash apps.
4014
+ # The dot program is not needed for that, and networkx can not make it
4015
+ return self.todot2(alllinks, navn=navn, **kwargs)
4016
+
4017
+ engine = engine or self.draw_engine
4018
+ if engine == 'dot' and not self.no_graphviz:
3991
4019
  try:
3992
- return self.todot2(alllinks, navn=navn.upper(), down=down, up=up, filter = filter, **kwargs)
4020
+ return self.todot2(alllinks, navn=navn, **kwargs)
3993
4021
  except Exception as e:
3994
4022
  print(f'Graphviz did not draw the graph: {e}\nDrawing with networkx')
3995
- engine = 'mpl'
4023
+ engine = self.nx_engine
3996
4024
  elif engine == 'dot':
3997
- engine = 'mpl' # no_graphviz is set, then networkx draws the graph
4025
+ engine = self.nx_engine # no_graphviz is set, then networkx draws it
3998
4026
 
3999
- return self.draw_nx(navn, down=down, up=up, lag=lag, endo=endo, filter=filter,
4000
- alllinks=alllinks, engine=engine, **kwargs)
4027
+ if not len(alllinks):
4028
+ print(f'No graph {navn}')
4029
+ if kwargs.get('filter', 0):
4030
+ print('Perhaps filter prunes to much')
4031
+ return
4032
+ G = self.alllinks_to_nx(alllinks, navn=navn, **kwargs)
4033
+ return self.display_nx(G, navn=navn, engine=engine, **kwargs)
4001
4034
 
4002
4035
  #: Set to True on a model instance to make draw use draw_nx, so the networkx
4003
4036
  #: drawing can be tested on a machine where graphviz works
@@ -4085,18 +4118,26 @@ class Graph_Draw_Mixin():
4085
4118
  except Exception:
4086
4119
  G.nodes[v]['values'] = None
4087
4120
 
4088
- # the layer is the distance to navn, so the drawing can be layered like rankdir=LR
4121
+ # the layer places the node in a column, so the drawing is layered like rankdir=LR
4089
4122
  if navn in G:
4123
+ # the layer is the distance to navn, upstream to the left of it
4090
4124
  upstream = nx.single_source_shortest_path_length(G.reverse(copy=False), navn)
4091
4125
  downstream = nx.single_source_shortest_path_length(G, navn)
4126
+ for v in G.nodes:
4127
+ up_len, down_len = upstream.get(v), downstream.get(v)
4128
+ if up_len is not None and (down_len is None or up_len <= down_len):
4129
+ G.nodes[v]['layer'] = -up_len
4130
+ else:
4131
+ G.nodes[v]['layer'] = 0 if down_len is None else down_len
4092
4132
  else:
4093
- upstream, downstream = {}, {}
4094
- for v in G.nodes:
4095
- up_len, down_len = upstream.get(v), downstream.get(v)
4096
- if up_len is not None and (down_len is None or up_len <= down_len):
4097
- G.nodes[v]['layer'] = -up_len
4098
- else:
4099
- G.nodes[v]['layer'] = 0 if down_len is None else down_len
4133
+ # no variable in the center, like drawmodel, then the layer is the logical
4134
+ # order. The simultaneous blocks are condensed to one node, else there is
4135
+ # no order, and a node of such a block gets the layer of its block
4136
+ condensed = nx.condensation(G)
4137
+ for layer, blocks in enumerate(nx.topological_generations(condensed)):
4138
+ for block in blocks:
4139
+ for v in condensed.nodes[block]['members']:
4140
+ G.nodes[v]['layer'] = layer
4100
4141
 
4101
4142
  for child, parent in G.edges:
4102
4143
  try:
@@ -4166,23 +4207,21 @@ class Graph_Draw_Mixin():
4166
4207
  if alllinks is None:
4167
4208
  alllinks = self.get_alllinks(navn, down=down, up=up, lag=lag, endo=endo,
4168
4209
  filter=filter)
4169
- if not len(alllinks):
4170
- print(f'No graph {navn}')
4171
- if filter:
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)
4210
+ engine = kwargs.pop('engine', '') or self.nx_engine
4211
+ return self.draw_links(alllinks, navn=navn.upper(), engine=engine,
4212
+ down=down, up=up, filter=filter, **kwargs)
4176
4213
 
4177
- def display_nx(self, G, navn='', engine='mpl', **kwargs):
4214
+ def display_nx(self, G, navn='', engine='', **kwargs):
4178
4215
  '''Draws a graph made by alllinks_to_nx
4179
4216
 
4180
- :engine: mpl draws with matplotlib, svg makes a svg drawing
4217
+ :engine: mpl draws with matplotlib, svg makes a svg drawing,
4218
+ default self.nx_engine which is svg in a browser else mpl
4181
4219
 
4182
4220
  Each engine is the method display_nx_<engine>, so a new engine is made by
4183
4221
  writing a new method. They all take the same graph and the positions from
4184
4222
  nx_layout, and only do the drawing itself.
4185
4223
  '''
4224
+ engine = engine or self.nx_engine
4186
4225
  try:
4187
4226
  displayer = getattr(self, f'display_nx_{engine}')
4188
4227
  except AttributeError:
@@ -4330,7 +4369,12 @@ class Graph_Draw_Mixin():
4330
4369
  svgname.write_text(svg, encoding='utf-8')
4331
4370
  if browser:
4332
4371
  # the same as display_graph, a separate window where the svg can be zoomed
4333
- wb.open(f'file://{svgname.resolve()}', new=2)
4372
+ try:
4373
+ wb.open(f'file://{svgname.resolve()}', new=2)
4374
+ except Exception as e:
4375
+ # in a browser (jupyterlite) there is no window to open from
4376
+ print(f'No separate window here: {e}')
4377
+ print(f'The drawing is saved as {svgname} and is shown below')
4334
4378
 
4335
4379
  display(HTML(svg))
4336
4380
  self.last_svg = svg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelflowib
3
- Version: 2.79
3
+ Version: 2.80
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "modelflowib" # PyPI distribution name
7
- version = "2.79" # OVERWRITTEN at build time from MF_VERSION
7
+ version = "2.80" # 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"
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