modelflowib 2.73__py3-none-any.whl

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.
modeljupyter.py ADDED
@@ -0,0 +1,824 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Sat Jun 22 21:26:13 2019
4
+
5
+ @author: hanseni
6
+ """
7
+
8
+ import pandas as pd
9
+ import ipywidgets as widgets
10
+ from IPython.display import display, clear_output,Latex, Markdown
11
+ import matplotlib.pylab as plt
12
+ import seaborn as sns
13
+ import os
14
+ import webbrowser as wb
15
+ import sys
16
+ import re
17
+ import fnmatch
18
+ import matplotlib.ticker as ticker
19
+
20
+
21
+
22
+ #import qgrid
23
+
24
+
25
+
26
+ from modelhelp import insertModelVar, finddec
27
+ import modelpattern as pt
28
+
29
+
30
+ def vis_alt3(dfs,model,title='Show variables',basename='Baseline',altname='Alternative',trans={},legend=True):
31
+ ''' display tabbed widget with results from different dataframes, usuallly 2 but more can be shown
32
+
33
+ dfs is a list of dataframes. They should be of same dimensionalities
34
+
35
+ '''
36
+ avar = dfs[0].columns
37
+ outlist = [widgets.Output() for var in avar]
38
+ outdiflist = [widgets.Output() for var in avar]
39
+ deplist = [widgets.Output() for var in avar]
40
+ reslist = [widgets.Output() for var in avar]
41
+ attlist = [widgets.Output() for var in avar]
42
+ varouttablist = [widgets.Tab(children = [out,outdif,att,dep,res])
43
+ for out,outdif,att,dep,res in zip(outlist,outdiflist,attlist,deplist,reslist)]
44
+ for var,varouttab in zip(avar,varouttablist):
45
+ for i,tabtext in enumerate(['Level','Impact','Attribution','Dependencies','Results']):
46
+ varouttab.set_title(i,tabtext)
47
+
48
+ controllist = [widgets.VBox([varouttab]) for varouttab in varouttablist]
49
+ tab = widgets.Tab(children = controllist)
50
+ for i,(var,out) in enumerate(zip(avar,controllist)):
51
+ tab.set_title(i, var)
52
+
53
+ def showvar(b):
54
+ sel = b['new']
55
+ out = outlist[sel]
56
+ outdif = outdiflist[sel]
57
+ dep = deplist[sel]
58
+ res = reslist[sel]
59
+ att = attlist[sel]
60
+ var = avar[sel]
61
+ with out:
62
+ clear_output()
63
+ fig,ax = plt.subplots(figsize=(10,6))
64
+ ax.set_title(trans.get(var,var),fontsize=14)
65
+ ax.spines['right'].set_visible(False)
66
+ # ax.spines['top'].set_visible(False)
67
+ for i,df in enumerate(dfs):
68
+ alt=i if len(dfs) >= 3 else ''
69
+ data = df.loc[:,var]
70
+ data.name = f'{basename}' if i ==0 else f'{altname}{alt}'
71
+ data.plot(ax=ax,legend=legend,fontsize=14)
72
+ x_pos = data.index[-1]
73
+ if not legend:
74
+ if i == 0:
75
+ basevalue = data.values[-1]
76
+ else:
77
+ if (abs(data.values[-1]-basevalue) < 0.01 or
78
+ (abs(basevalue) > 100. and (1.-abs(data.values[-1]/basevalue) < 0.008))):
79
+ if i == 1:
80
+ ax.text(x_pos, data.values[-1] ,f' {basename} and {altname}{alt}',fontsize=14)
81
+ else:
82
+ ax.text(x_pos, data.values[-1] ,f' {altname}{alt}',fontsize=14)
83
+ ax.text(x_pos, basevalue ,f' {basename}',fontsize=14)
84
+ plt.show(fig)
85
+ with outdif:
86
+ clear_output()
87
+ fig,ax = plt.subplots(figsize=(10,6))
88
+ ax.set_title(trans.get(var,var),fontsize=14)
89
+ ax.spines['right'].set_visible(False)
90
+ for i,df in enumerate(dfs):
91
+ if i == 0:
92
+ basedata = df.loc[:,var]
93
+ x_pos = data.index[-1]
94
+ else:
95
+ data = df.loc[:,var]-basedata
96
+ data.plot(ax=ax,legend=False,fontsize=14)
97
+ x_pos = data.index[-1]
98
+ alt=i if len(dfs) >= 3 else ''
99
+ ax.text(x_pos, data.values[-1] ,f' Impact of {altname}{alt}',fontsize=14)
100
+ plt.show(fig)
101
+ with dep:
102
+ clear_output()
103
+ model.draw(var,up=2,down=2,svg=1)
104
+ with res:
105
+ clear_output()
106
+ out = model.get_values(var).T.rename(columns={'Base':basename,'Last':altname})
107
+ out.style.set_caption(trans.get(var,var))
108
+ print(trans.get(var,var))
109
+ print(out)
110
+ with att:
111
+ clear_output()
112
+ #model.smpl(N-20,N)
113
+ if var in model.endogene:
114
+ print(f'What explains the difference between the {basename} and the {altname} run ')
115
+ print(model.allvar[var]['frml'])
116
+ model.explain(var,up=0,dec=1,size=(9,12),svg=1,HR=0)
117
+ else:
118
+ print(f'{var} is exogeneous and attribution can not be performed')
119
+
120
+ display(tab)
121
+
122
+ showvar({'new':0})
123
+ tab.observe(showvar,'selected_index')
124
+ return tab
125
+
126
+ def vis_alt4(dfs,model,title='Show variables',trans={},legend=True):
127
+ ''' display tabbed widget with results from different dataframes, usuallly 2 but more can be shown
128
+
129
+ dfs is a list of dataframes. They should be of same dimensionalities
130
+
131
+ '''
132
+ avar = dfs[list(dfs.keys())[0]].columns
133
+ outlist = [widgets.Output() for var in avar]
134
+ outdiflist = [widgets.Output() for var in avar]
135
+ deplist = [widgets.Output() for var in avar]
136
+ reslist = [widgets.Output() for var in avar]
137
+ attlist = [widgets.Output() for var in avar]
138
+ varouttablist = [widgets.Tab(children = [out,outdif,att,dep,res])
139
+ for out,outdif,att,dep,res in zip(outlist,outdiflist,attlist,deplist,reslist)]
140
+ for var,varouttab in zip(avar,varouttablist):
141
+ for i,tabtext in enumerate(['Level','Impact','Attribution','Dependencies','Results']):
142
+ varouttab.set_title(i,tabtext)
143
+
144
+ controllist = [widgets.VBox([varouttab]) for varouttab in varouttablist]
145
+ tab = widgets.Tab(children = controllist)
146
+ for i,(var,out) in enumerate(zip(avar,controllist)):
147
+ tab.set_title(i, var)
148
+
149
+ def showvar(b):
150
+ sel = b['new']
151
+ out = outlist[sel]
152
+ outdif = outdiflist[sel]
153
+ dep = deplist[sel]
154
+ res = reslist[sel]
155
+ att = attlist[sel]
156
+ var = avar[sel]
157
+ with out:
158
+ clear_output()
159
+ fig,ax = plt.subplots(figsize=(10,6))
160
+ ax.set_title(trans.get(var,var),fontsize=14)
161
+ ax.spines['right'].set_visible(False)
162
+ # ax.spines['top'].set_visible(False)
163
+ for i,(k,df) in enumerate(dfs.items()):
164
+ data = df.loc[:,var]
165
+ data.name = k
166
+ data.plot(ax=ax,legend=legend,fontsize=14)
167
+ x_pos = data.index[-1]
168
+ if not legend:
169
+ if i == 0:
170
+ basevalue = data.values[-1]
171
+ else:
172
+ if (abs(data.values[-1]-basevalue) < 0.01 or
173
+ (abs(basevalue) > 100. and (1.-abs(data.values[-1]/basevalue) < 0.008))):
174
+ if i == 1:
175
+ ax.text(x_pos, data.values[-1] ,f' {basename} and {altname}{alt}',fontsize=14)
176
+ else:
177
+ ax.text(x_pos, data.values[-1] ,f' {altname}{alt}',fontsize=14)
178
+ ax.text(x_pos, basevalue ,f' {basename}',fontsize=14)
179
+ plt.show(fig)
180
+ with outdif:
181
+ clear_output()
182
+ fig,ax = plt.subplots(figsize=(10,6))
183
+ ax.set_title(trans.get(var,var),fontsize=14)
184
+ ax.spines['right'].set_visible(False)
185
+ for i,(k,df) in enumerate(dfs.items()):
186
+ if i == 0:
187
+ basedata = df.loc[:,var]
188
+ x_pos = data.index[-1]
189
+ else:
190
+ data = df.loc[:,var]-basedata
191
+ data.name = f' Impact of: {k}'
192
+ data.plot(ax=ax,legend=legend,fontsize=14)
193
+ x_pos = data.index[-1]
194
+ if not legend:
195
+ ax.text(x_pos, data.values[-1] ,f' Impact of: {k}',fontsize=14)
196
+ plt.show(fig)
197
+ with dep:
198
+ clear_output()
199
+ model.draw(var,up=2,down=2,svg=1)
200
+ with res:
201
+ clear_output()
202
+ out = pd.concat([df.loc[:,var] for k,df in dfs.items()],axis=1)
203
+ out.columns = [k for k in dfs.keys()]
204
+ out.style.set_caption(trans.get(var,var))
205
+ print(trans.get(var,var))
206
+ print(out.to_string())
207
+ with att:
208
+ clear_output()
209
+ #model.smpl(N-20,N)
210
+ if var in model.endogene:
211
+ print(f'What explains the difference between the {basename} and the {altname} run ')
212
+ print(model.allvar[var]['frml'])
213
+ model.explain(var,up=0,dec=1,size=(9,12),svg=1,HR=0)
214
+ else:
215
+ print(f'{var} is exogeneous and attribution can not be performed')
216
+
217
+ display(tab)
218
+
219
+ showvar({'new':0})
220
+ tab.observe(showvar,'selected_index')
221
+
222
+ class jup_keepviz() :
223
+ ''' Class to vizualize a number of runs, primary in Jupyter
224
+ :dfs: A dict with runs {name :{'result' : df}}
225
+ :title: A title
226
+ :trans: a translation of variable names to more redable names
227
+ :legend: if legends has to be shown
228
+
229
+ '''
230
+
231
+
232
+
233
+ def __init__(self,dfs,title='Show variables',trans={},legend=True,showfig=False):
234
+ self.dfs = dfs
235
+ self.title = title
236
+ self.trans = trans
237
+ self.legend = legend
238
+ self.showfig = showfig
239
+
240
+ return
241
+
242
+ def plot_level(self,var):
243
+ fig,ax = plt.subplots(figsize=(10,6))
244
+ ax.set_title(f'Level: {self.trans.get(var,var)}',fontsize=14)
245
+ if self.legend :
246
+ ax.spines['right'].set_visible(True)
247
+ else:
248
+ ax.spines['right'].set_visible(False)
249
+ ax.spines['top'].set_visible(False)
250
+
251
+ # ax.spines['top'].set_visible(False)
252
+ for i,(k,df) in enumerate(self.dfs.items()):
253
+ data = df.loc[:,var]
254
+ data.name = k
255
+ data.plot(ax=ax,legend=self.legend,fontsize=14)
256
+ dec=finddec(df)
257
+ ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda value,number: f'{value:,.{dec}f}'))
258
+
259
+ x_pos = data.index[-1]
260
+ if not self.legend:
261
+ if i == 0:
262
+ basename = k
263
+ basevalue = data.values[-1]
264
+ ax.text(x_pos, basevalue ,f' {basename}',fontsize=14)
265
+ else:
266
+ if (abs(data.values[-1]-basevalue) < 0.01 or
267
+ (abs(basevalue) > 100. and (1.-abs(data.values[-1]/basevalue) < 0.008))):
268
+ if i == 1:
269
+ ax.text(x_pos, data.values[-1] ,f' {basename} and {k}',fontsize=14)
270
+ else:
271
+ ax.text(x_pos, data.values[-1] ,f' {k}',fontsize=14)
272
+
273
+ else:
274
+ ax.text(x_pos, data.values[-1] ,f' {k}',fontsize=14)
275
+ return fig
276
+
277
+ def plot_dif(self,var):
278
+ fig,ax = plt.subplots(figsize=(10,6))
279
+ ax.set_title(f'{self.trans.get(var,var)}',fontsize=14)
280
+ if self.legend :
281
+ ax.spines['right'].set_visible(True)
282
+ else:
283
+ ax.spines['right'].set_visible(False)
284
+ for i,(k,df) in enumerate(self.dfs.items()):
285
+ if i == 0:
286
+ basedata = df.loc[:,var]
287
+ else:
288
+ data = df.loc[:,var]-basedata
289
+ data.name = f' Impact of: {k}'
290
+ dec=finddec(data)
291
+
292
+ data.plot(ax=ax,legend=self.legend,fontsize=14)
293
+ ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda value,number: f'{value:,.{dec}f}'))
294
+
295
+ x_pos = basedata.index[-1]
296
+ if not self.legend:
297
+ ax.text(x_pos, data.values[-1] ,f' Impact of: {k}',fontsize=14)
298
+ return fig
299
+
300
+ def formatnumber(self,var,out):
301
+ if out.abs().max(axis=1).max() >= 30.0:
302
+ return lambda number : f'{number:,.0f}'
303
+ else:
304
+ return lambda number : f'{number:,.6f}'
305
+
306
+
307
+ class jupviz(jup_keepviz) :
308
+ '''
309
+ Class to vizualize a number of experiments in an tabbed ipywidget in a jupyter notebook
310
+ '''
311
+
312
+ def __call__(self):
313
+ self.vis()
314
+
315
+ def vis(self):
316
+ ''' display tabbed widget with results from different dataframes, usuallly 2 but more can be shown
317
+
318
+ dfs is a list of dataframes. They should be of same dimensionalities
319
+
320
+ '''
321
+ self.basekey = [key for key in self.dfs.keys()][0]
322
+
323
+ wexperiment_name = widgets.Text(value=self.basekey,placeholder='Type something',description='Name of these experiments:',
324
+ layout={'width':'55%'},style={'description_width':'45%'})
325
+
326
+ wsavefig = widgets.Button(description="Save figure")
327
+ wbut = widgets.HBox([wsavefig,wexperiment_name])
328
+
329
+ wfile_folder = widgets.Text(value = 'test2',placeholder='Type something',description='Figure saved in:',
330
+ layout={'width':'65%'},style={'description_width':'25%'},visible=False,disabled=True)
331
+ wfile_folder.layout.visibility = 'hidden'
332
+
333
+ wopen = widgets.Button(description="Open the saved figures")
334
+ wopen.layout.visibility = 'hidden'
335
+
336
+ winputstring = widgets.VBox([wfile_folder,wopen])
337
+
338
+
339
+ avar = self.dfs[list(self.dfs.keys())[0]].columns
340
+ outlist = [widgets.Output() for var in avar]
341
+ outdiflist = [widgets.Output() for var in avar]
342
+ reslist = [widgets.Output() for var in avar]
343
+ resdiflist = [widgets.Output() for var in avar]
344
+ varouttablist = [widgets.Tab(children = [out,outdif,res,resdif])
345
+ for out,outdif,res,resdif in zip(outlist,outdiflist,reslist,resdiflist)]
346
+ for var,varouttab in zip(avar,varouttablist):
347
+ for i,tabtext in enumerate(['Level','Impact','Level data','Impact data']):
348
+ varouttab.set_title(i,tabtext)
349
+
350
+ controllist = [widgets.VBox([varouttab]) for varouttab in varouttablist]
351
+ tab = widgets.Tab(children = controllist)
352
+
353
+ for i,(var,out) in enumerate(zip(avar,controllist)):
354
+ tab.set_title(i, var)
355
+
356
+ def showvar(b):
357
+ wfile_folder.layout.visibility = 'hidden'
358
+ wopen.layout.visibility = 'hidden'
359
+
360
+ sel = b['new']
361
+ out = outlist[sel]
362
+ outdif = outdiflist[sel]
363
+ res = reslist[sel]
364
+ resdif = resdiflist[sel]
365
+ var = avar[sel]
366
+ self.selected = sel
367
+ self.selected_var = var
368
+ with out:
369
+ clear_output()
370
+ self.fig_level = self.plot_level(var)
371
+ plt.show(self.fig_level)
372
+ with outdif:
373
+ clear_output()
374
+ self.fig_dif = self.plot_dif(var)
375
+ plt.show(self.fig_dif)
376
+ with res:
377
+ clear_output()
378
+ out = pd.concat([df.loc[:,var] for k,df in self.dfs.items()],axis=1)
379
+ out.columns = [k for k in self.dfs.keys()]
380
+ print(self.trans.get(var,var))
381
+ print(out.to_string(float_format= self.formatnumber(var,out)))
382
+ with resdif:
383
+ clear_output()
384
+ try:
385
+ baseline = self.dfs[[k for i,k in enumerate(self.dfs.keys()) if i == 0][0]].loc[:,[var]]
386
+ out = pd.concat([df.loc[:,[var]]-baseline for i,(k,df) in enumerate(self.dfs.items()) if i >= 1],axis=1)
387
+ out.columns = [k for i,k in enumerate(self.dfs.keys()) if i >= 1]
388
+ # out.style.set_caption(self.trans.get(var,var))
389
+ print(self.trans.get(var,var))
390
+ print(out.to_string(float_format= self.formatnumber(var,out)))
391
+ except:
392
+ print('No Data')
393
+
394
+ outtab = widgets.VBox([tab,wbut,winputstring])
395
+ def savefig(s):
396
+ self.graph_folde=os.path.join(os.getcwd(),'experiments',wexperiment_name.value,'graph')
397
+ self.figlocation = os.path.join(self.graph_folde,f'{self.selected_var}')
398
+ self.figlocation_impact = os.path.join(self.graph_folde,f'{self.selected_var}-impact')
399
+ wfile_folder.layout.visibility = 'visible'
400
+ if self.showfig:
401
+ wopen.layout.visibility = 'visible'
402
+ else:
403
+ wopen.layout.visibility = 'hidden'
404
+
405
+ try:
406
+ if not os.path.exists(self.graph_folde):
407
+ os.makedirs(self.graph_folde)
408
+ except:
409
+ wfile_folder.value = f"Can't create {self.graph_folde}"
410
+ return
411
+
412
+ try:
413
+ self.fig_level.savefig(self.figlocation+'.svg')
414
+ self.fig_dif.savefig(self.figlocation_impact+'.svg')
415
+ self.fig_level.savefig(self.figlocation+'.pdf')
416
+ self.fig_dif.savefig(self.figlocation_impact+'.pdf')
417
+ wfile_folder.value = self.graph_folde
418
+ except:
419
+ wfile_folder.value = f"Can't write to {self.graph_folde}, remember to close"
420
+
421
+ def openfig_svg(s):
422
+ try:
423
+ wb.open(self.figlocation_impact+'.svg',new=2)
424
+ wb.open(self.figlocation+'.svg',new=2)
425
+ # os.system(self.figlocation)
426
+ # os.system(self.figlocation_impact)
427
+ except:
428
+ wfile_folder.layout.visibility = 'visible'
429
+ wfile_folder.value = f"Can't open to {self.figlocation}.svg Try to download the file"
430
+
431
+ def openfig_pdf(s):
432
+ try:
433
+ wb.open(self.figlocation_impact+'.pdf')
434
+ wb.open(self.figlocation+'.pdf')
435
+ except:
436
+ wfile_folder.layout.visibility = 'visible'
437
+ wfile_folder.value = f"Can't open to {self.figlocation}.svg Try to download the file"
438
+
439
+
440
+
441
+ if self.showfig : wopen.on_click(openfig_svg)
442
+
443
+ wsavefig.on_click(savefig)
444
+
445
+ display(outtab)
446
+
447
+ showvar({'new':0})
448
+ tab.observe(showvar,'selected_index')
449
+
450
+
451
+
452
+ # Define data extraction
453
+
454
+
455
+ def get_alt(mmodel,pat,onlyendo=False):
456
+ ''' Retrieves variables matching pat from a model '''
457
+ varnames = mmodel.vlist(pat)
458
+ modelvar = mmodel.endogene if onlyendo else mmodel.exogene | mmodel.endogene
459
+ modelvarnames = list(dict.fromkeys([v for v in varnames if v in modelvar])) # to awoid dublicate names
460
+ per = mmodel.current_per
461
+ return [mmodel.basedf.loc[per,modelvarnames],mmodel.lastdf.loc[per,modelvarnames]]
462
+
463
+ def get_alt_dic(mmodel,pat,dfs,onlyendo=False):
464
+ ''' Retrieves variables matching pat from a model '''
465
+ varnames = mmodel.vlist(pat)
466
+ modelvar = mmodel.endogene if onlyendo else mmodel.exogene | mmodel.endogene
467
+ modelvarnames = list(dict.fromkeys([v for v in varnames if v in modelvar])) # to awoid dublicate names
468
+ per = mmodel.current_per
469
+ return {k: df_dic['results'].loc[per,modelvarnames] for k,df_dic in dfs.items()}
470
+
471
+
472
+
473
+
474
+
475
+
476
+ def inputwidget(model,basedf,slidedef={},radiodef=[],checkdef=[],modelopt={},varpat='RFF XGDPN RFFMIN GFSRPN DMPTRSH XXIBDUMMY'
477
+ ,showout=1,trans={},base1name='',alt1name='',go_now=True,showvar=False):
478
+ '''Creates an input widgets for updating variables
479
+
480
+ :df: Baseline dataframe
481
+ :slidedef: dict with definition of variables to be updated by slider
482
+ :radiodef: dict of lists. each at first level defines a collection of radiobuttoms
483
+ second level defines the text for each leved and the variable to set or reset to 0
484
+ :varpat: the variables to show in the output widget
485
+ :showout: 1 if the output widget is to be called '''
486
+
487
+ lradiodef= len(radiodef)
488
+ lslidedef = len(slidedef)
489
+ lcheckdef = len(checkdef)
490
+ basename = base1name if base1name else 'Baseline'
491
+ altname = alt1name if alt1name else 'Alternative'
492
+
493
+ if lradiodef:
494
+ wradiolist = [widgets.RadioButtons(options=[i for i,j in cont],description=des,layout={'width':'70%'},
495
+ style={'description_width':'37%'}) for des,cont in radiodef.items()]
496
+ if len(wradiolist) <=2:
497
+ wradio = widgets.HBox(wradiolist)
498
+ else:
499
+ wradio = widgets.VBox(wradiolist)
500
+
501
+
502
+
503
+ # define slidesets
504
+ if lslidedef:
505
+ wexp = widgets.Label(value="Input new parameter ",layout={'width':'52%'})
506
+ walt = widgets.Label(value=f'{altname}',layout={'width':'10%'})
507
+ wbas = widgets.Label(value=f'{basename}',layout={'width':'20%'})
508
+ whead = widgets.HBox([wexp,walt,wbas])
509
+
510
+ wset = [widgets.FloatSlider(description=des,
511
+ min=cont['min'],max=cont['max'],value=cont['value'],step=cont.get('step',0.01),
512
+ layout={'width':'60%'},style={'description_width':'40%'},readout_format = f":<,.{cont.get('dec',2)}f")
513
+ for des,cont in slidedef.items()]
514
+ formattest = ':>.2f'
515
+ waltval= [widgets.Label(value=f"{cont['value']:<,.{cont.get('dec',2)}f}",layout={'width':'10%'})
516
+ for des,cont in slidedef.items()]
517
+ wslide = [widgets.HBox([s,v]) for s,v in zip(wset,waltval)]
518
+
519
+ # cheklist
520
+ if lcheckdef:
521
+ wchecklist = [widgets.Checkbox(description=des,value=val) for des,var,val in checkdef]
522
+ wcheck = widgets.HBox(wchecklist)
523
+
524
+ # some buttons and text
525
+ wname = widgets.Text(value=basename,placeholder='Type something',description='Scenario name:',
526
+ layout={'width':'30%'},style={'description_width':'50%'})
527
+ wpat = widgets.Text(value=varpat,placeholder='Type something',description='Output variables:',
528
+ layout={'width':'65%'},style={'description_width':'30%'})
529
+ if showvar:
530
+ wpat.layout.visibility = 'visible'
531
+ else:
532
+ wpat.layout.visibility = 'hidden'
533
+
534
+
535
+ winputstring = widgets.HBox([wname,wpat])
536
+
537
+ wgo = widgets.Button(description="Run scenario")
538
+ wreset = widgets.Button(description="Reset to start")
539
+ wzero = widgets.Button(description="Set all to 0")
540
+ wsetbas = widgets.Button(description="Use as baseline")
541
+ wbut = widgets.HBox([wgo,wreset,wzero,wsetbas])
542
+
543
+ wvar = [whead]+wslide if lslidedef else []
544
+ if lradiodef: wvar = wvar + [wradio]
545
+ if lcheckdef: wvar = wvar + [wcheck]
546
+
547
+ w = widgets.VBox(wvar+[winputstring] +[wbut])
548
+
549
+ # This function is run when the button is clecked
550
+ firstrun = True
551
+ model.rundic = {}
552
+
553
+ def run(b):
554
+ nonlocal firstrun
555
+ nonlocal altname
556
+ # mulstart = model.basedf.copy()
557
+ mulstart = insertModelVar(basedf.copy(deep=True),model)
558
+ # model.smpl(df=mulstart)
559
+
560
+ # First update from the sliders
561
+ if lslidedef:
562
+ for i,(des,cont) in enumerate(slidedef.items()):
563
+ op = cont.get('op','=')
564
+ var = cont['var']
565
+ for var in cont['var'].split():
566
+ if op == '+':
567
+ mulstart.loc[model.current_per,var] = mulstart.loc[model.current_per,var] + wset[i].value
568
+ elif op == '%':
569
+ mulstart.loc[model.current_per,var] = mulstart.loc[model.current_per,var] * (1+wset[i].value/100)
570
+ elif op == '+impulse':
571
+ mulstart.loc[model.current_per[0],var] = mulstart.loc[model.current_per[0],var] + wset[i].value
572
+ elif op == '=start-':
573
+ startindex = mulstart.index.get_loc(model.current_per[0])
574
+ varloc = mulstart.columns.get_loc(var)
575
+ mulstart.iloc[:startindex,varloc] = wset[i].value
576
+ elif op == '=':
577
+ mulstart.loc[model.current_per,var] = wset[i].value
578
+ elif op == '=impulse':
579
+ mulstart.loc[model.current_per[0],var] = wset[i].value
580
+ else:
581
+ print(f'Wrong operator in {cont}.\nNot updated')
582
+ assert 1==3,'wRONG OPERATOR'
583
+
584
+ # now update from the radio buttons
585
+ if lradiodef:
586
+ for wradio,(des,cont) in zip(wradiolist,radiodef.items()):
587
+ # print(des,wradio.value,wradio.index,cont[wradio.index])
588
+ for v in cont:
589
+ mulstart.loc[model.current_per,v[1]] = 0.0
590
+ mulstart.loc[model.current_per,cont[wradio.index][1]] = 1.0
591
+
592
+ if lcheckdef:
593
+ for box,(des,var,_) in zip(wchecklist,checkdef):
594
+ mulstart.loc[model.current_per,var] = 1.0 * box.value
595
+
596
+ #with out:
597
+ clear_output()
598
+ mul = model(mulstart,**modelopt)
599
+ # model.mulstart=mulstart
600
+
601
+
602
+ clear_output()
603
+ display(w)
604
+ #_ = mfrbus['XGDPN RFF RFFMIN GFSRPN'].dif.rename(trans).plot(colrow=1,sharey=0)
605
+
606
+
607
+ if firstrun:
608
+ model.experiment_results = {}
609
+ model.experiment_results[basename] = {'results':model.lastdf.copy()}
610
+ firstrun = False
611
+ wname.value = f'{altname}'
612
+ else:
613
+ altname = wname.value
614
+ walt.value = f'{altname}'
615
+ model.experiment_results[altname] = {'results':model.lastdf.copy()}
616
+
617
+
618
+ if showout:
619
+ varpat_this = wpat.value
620
+ resdic = get_alt_dic(model,varpat_this,model.experiment_results)
621
+ a = jupviz(resdic,trans=trans)()
622
+ else:
623
+ a = vis_alt4(get_alt_dic(model,wpat.value,model.experiment_results),model,trans=trans)
624
+
625
+ def reset(b):
626
+
627
+ if lslidedef:
628
+ for i,(des,cont) in enumerate(slidedef.items()):
629
+ wset[i].value = cont['value']
630
+
631
+ if lradiodef:
632
+ for wradio in wradiolist:
633
+ wradio.index = 0
634
+
635
+ if lcheckdef:
636
+ for box,(des,var,defvalue) in zip(wchecklist,checkdef):
637
+ box.value = defvalue
638
+
639
+ def zeroset(b):
640
+ basename = base1name if base1name else 'Baseline'
641
+ walt.value = f'{altname}'
642
+ wbas.value = f'{basename}'
643
+
644
+ if lslidedef:
645
+ for i,(des,cont) in enumerate(slidedef.items()):
646
+ wset[i].value = type(cont['value'])(0.0)
647
+
648
+ if lradiodef:
649
+ for wradio in wradiolist:
650
+ wradio.index = 0
651
+
652
+ if lcheckdef:
653
+ for box,(des,var,defvalue) in zip(wchecklist,checkdef):
654
+ box.value = defvalue
655
+
656
+
657
+
658
+
659
+ def setbas(b):
660
+ nonlocal basename
661
+ nonlocal firstrun
662
+ model.basedf = model.lastdf.copy(deep=True)
663
+ basename = wname.value
664
+ walt.value = f'{altname}'
665
+ wbas.value = f'{basename}'
666
+ wname.value = f'{basename}'
667
+ model.rundic = {}
668
+ firstrun = True
669
+
670
+ if lslidedef:
671
+ for i,(des,cont) in enumerate(slidedef.items()):
672
+ waltval[i].value= f"{cont['value']:<,.{cont.get('dec',2)}f}"
673
+
674
+ if lradiodef:
675
+ for wradio in wradiolist:
676
+ wradio.index = 0
677
+
678
+ if lcheckdef:
679
+ for box,(des,var,defvalue) in zip(wchecklist,checkdef):
680
+ box.value = defvalue
681
+
682
+
683
+ # Assign the function to the button
684
+ wgo.on_click(run)
685
+ wreset.on_click(reset)
686
+ wzero.on_click(zeroset)
687
+ wsetbas.on_click(setbas)
688
+ # out = widgets.Output()
689
+
690
+
691
+ if go_now:
692
+ run(None)
693
+ return w
694
+
695
+
696
+
697
+
698
+
699
+ def get_att_gui(totdif,var='FY',spat = '*',desdic={},use='level',kind='bar',perselect='per',ysize=10):
700
+ '''Creates a jupyter ipywidget to display model level
701
+ attributions '''
702
+ xvar=var
703
+ # print(f'{var=} {xvar}')
704
+ def show_all2(Variable,Periode,Save,Use):
705
+ global fig1,fig2
706
+ fig1 = totdif.totexplain(pat=Variable,top=0.87,use=Use,axvline=Periode,kind=kind)
707
+ display(fig1)
708
+ fig2 = totdif.totexplain(pat=Variable,vtype='per',per = Periode,top=0.85,use=Use,ysize=ysize)
709
+ display(fig2)
710
+ if Save:
711
+ fig1.savefig(f'Attribution-{Variable}-{use}.pdf')
712
+ fig2.savefig(f'Attribution-{Variable}-{Periode}-{use}.pdf')
713
+ print(f'Attribution-{Variable}-{use}.pdf and Attribution-{Variable}-{Periode}-{use}.pdf aare saved' )
714
+ plt.close('all')
715
+ show = widgets.interactive(show_all2,
716
+ Variable = widgets.Dropdown(options = sorted(totdif.model.endogene),value=xvar),
717
+ Periode = widgets.Dropdown(options = totdif.model.current_per) if perselect=='per'
718
+ else [f'{t.year}-{t.month}-{t.day}' for t in totdif.model.current_per],
719
+ Use = widgets.RadioButtons(options= ['level', 'growth'],description='Use'),
720
+ Save = widgets.Checkbox(description='Save the charts',value=False)
721
+ )
722
+ return show
723
+
724
+ def get_att_gui2(totdif,var='RP',spat = '*',desdic={},use='level',kind='bar'):
725
+ '''Creates a jupyter ipywidget to display model level
726
+ attributions for datily dates '''
727
+ def show_all2(Variable,Periode,Save,Use):
728
+ global fig1,fig2
729
+ fig1 = totdif.explain_all(pat=Variable,top=0.87,use=Use,kind='line',stacked=False,axvline=Periode,threshold=0.01,resample='m')
730
+ fig2 = totdif.totexplain(pat=Variable,vtype='per',per = Periode,top=0.85,use=Use,threshold=0.01)
731
+ if Save:
732
+ fig1.savefig(f'Attribution-{Variable}-{use}.pdf')
733
+ fig2.savefig(f'Attribution-{Variable}-{Periode}-{use}.pdf')
734
+ print(f'Attribution-{Variable}-{use}.pdf and Attribution-{Variable}-{Periode}-{use}.pdf aare saved' )
735
+
736
+ show = widgets.interactive(show_all2,
737
+ Variable = widgets.Dropdown(options = sorted(totdif.model.endogene),value=var),
738
+ Periode = widgets.Dropdown(options = [f'{t.year}-{t.month}-{t.day}' for t in mddm.totdekomp.model.current_per]),
739
+ Use = widgets.RadioButtons(options= ['level', 'growth'],description='Use'),
740
+ Save = widgets.Checkbox(description='Save the charts',value=False)
741
+ )
742
+ return show
743
+
744
+ def vtol(var):
745
+ ''' replaces special characters in variable name to latex'''
746
+ return var.replace(r'_',r'\_').replace('{',r'\{').replace('}',r'\}')
747
+
748
+
749
+ def an_expression_to_latex(exp,funks=[]):
750
+ ''' Returns a latex string from a list of terms (defined in the modelpattern module)
751
+
752
+ funks is a list of localy defines functions
753
+ '''
754
+ def t_to_latex(t):
755
+ if t.var:
756
+ var =vtol(t.var)
757
+ if t.lag:
758
+ return f'{var}_{{t{t.lag}}}'
759
+ else:
760
+ return f'{var}_t'
761
+ elif t.number:
762
+ return t.number
763
+ else:
764
+ if t.op == '*':
765
+ op=r'\times'
766
+ elif t.op == '$':
767
+ op=''
768
+ else:
769
+ op = t.op
770
+ return op
771
+
772
+ return ' '.join([t_to_latex(t) for t in pt.udtryk_parse(exp,funks=funks)])
773
+
774
+ def expressions_to_latex(expressions,funks=[],allign = True, disp = False):
775
+ ''' Returns a latex string from a list of a list of terms
776
+
777
+ :funks: a list of local functions in the model
778
+ :allign: the first = is enclosed in & for alligning several equations in latex
779
+ :disp: the result is displayed
780
+ '''
781
+
782
+ texp = expressions if type(expressions) == list else [expressions ]
783
+ latex_list = [an_expression_to_latex(exp,funks=funks) for exp in texp]
784
+ if allign:
785
+ latex_list = [l.replace('=',' & = & ',1) for l in latex_list]
786
+ latex_out = r'\\'.join(latex_list)
787
+ latex_out = r'\begin{eqnarray*}'+latex_out+r'\end{eqnarray*}'
788
+
789
+ if disp:
790
+ display(Latex('$'+latex_out+'$'))
791
+ else:
792
+ return latex_out
793
+
794
+ def frml_as_latex(frml_in,funks=[],allign= True, name=True,disp=True,linespace = False):
795
+ ''' Display formula
796
+
797
+ :funks: local functions
798
+ :allign: allign =
799
+ :name: also display the frml name
800
+ '''
801
+ frmls = frml_in if type(frml_in) == list else [frml_in ]
802
+ out = []
803
+ for i,frml in enumerate(frmls):
804
+ a,fr,n,udtryk= pt.split_frml(frml)
805
+ out_udtryk = an_expression_to_latex(udtryk,funks = funks)
806
+ out_frmlname = vtol(n) if name and n != '<>' else ''
807
+ if allign:
808
+ out_udtryk = out_udtryk.replace('=',' & = & ',1)+(r'\\[1em]' if linespace else '')
809
+ out.append(f'{out_frmlname} {out_udtryk}')
810
+ latex_out = r'\\'.join(out)
811
+ if allign:
812
+ latex_out = r'\begin{eqnarray*}'+latex_out+r'\end{eqnarray*}'
813
+
814
+ if disp:
815
+ display(Latex('$'+latex_out+'$'))
816
+ else:
817
+ return latex_out
818
+
819
+ def get_frml_latex(model,pat='*',name=True):
820
+
821
+ variabler = [var for p in pat.split() for var in fnmatch.filter(model.nrorder,p)]
822
+ frmls = [model.allvar[var]['frml'] for var in variabler if not model.allvar[var]['dropfrml']]
823
+ _=frml_as_latex(frmls,funks=model.funks,name=name)
824
+