pico-ml 2.0.0__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.
Files changed (52) hide show
  1. pico/__init__.py +3 -0
  2. pico/__main__.py +3 -0
  3. pico/cli/__init__.py +2 -0
  4. pico/cli/main.py +117 -0
  5. pico/conf/SupportedCV.py +17 -0
  6. pico/conf/SupportedModels.py +73 -0
  7. pico/conf/algo_sklearn.json +51 -0
  8. pico/conf/parameters.py +14 -0
  9. pico/domain/ClassificationDesign.py +107 -0
  10. pico/domain/Controller.py +397 -0
  11. pico/domain/DataMatrix.py +147 -0
  12. pico/domain/ExperimentDTO.py +17 -0
  13. pico/domain/MetaData.py +229 -0
  14. pico/domain/MetaboExperiment.py +696 -0
  15. pico/domain/MetaboModel.py +53 -0
  16. pico/domain/ModelFactory.py +45 -0
  17. pico/domain/Results.py +602 -0
  18. pico/domain/SplitGroup.py +202 -0
  19. pico/domain/__init__.py +9 -0
  20. pico/domain/dumps/metadata/.gitkeep +0 -0
  21. pico/domain/dumps/splits/.gitkeep +0 -0
  22. pico/service/DataFormat.py +180 -0
  23. pico/service/ExperimentDesign.py +30 -0
  24. pico/service/LoggerConfig.py +150 -0
  25. pico/service/Plots.py +472 -0
  26. pico/service/RunMLalgo.py +93 -0
  27. pico/service/SamplesPairing.py +390 -0
  28. pico/service/Utils.py +497 -0
  29. pico/service/__init__.py +7 -0
  30. pico/ui/__init__.py +1 -0
  31. pico/ui/app.py +145 -0
  32. pico/ui/assets/000_Stylesheet.css +464 -0
  33. pico/ui/assets/DecisionTree.png +0 -0
  34. pico/ui/assets/Figure_home_wider.png +0 -0
  35. pico/ui/assets/favicon.ico +0 -0
  36. pico/ui/assets/help_icon.png +0 -0
  37. pico/ui/assets/help_icon.svg +15 -0
  38. pico/ui/assets/update_figure_steps_MeDIC_4.svg +1 -0
  39. pico/ui/tabs/AggregatedResultsTab.py +394 -0
  40. pico/ui/tabs/InfoTab.py +440 -0
  41. pico/ui/tabs/InterpretTab.py +21 -0
  42. pico/ui/tabs/MLTab.py +487 -0
  43. pico/ui/tabs/MetaTab.py +23 -0
  44. pico/ui/tabs/ResultsTab.py +1062 -0
  45. pico/ui/tabs/SplitsTab.py +1227 -0
  46. pico/ui/tabs/__init__.py +6 -0
  47. pico/ui/tabs/utils.py +101 -0
  48. pico_ml-2.0.0.dist-info/METADATA +86 -0
  49. pico_ml-2.0.0.dist-info/RECORD +52 -0
  50. pico_ml-2.0.0.dist-info/WHEEL +4 -0
  51. pico_ml-2.0.0.dist-info/entry_points.txt +2 -0
  52. pico_ml-2.0.0.dist-info/licenses/LICENSE +437 -0
@@ -0,0 +1,1062 @@
1
+ import os
2
+ import time
3
+
4
+ import dash_bootstrap_components as dbc
5
+ import dash_interactive_graphviz as dg
6
+ import pandas as pd
7
+ from dash import html, dcc, Output, Input, State, dash, Dash
8
+ import dash_cytoscape as cyto
9
+ from matplotlib import pyplot as plt
10
+ from sklearn import tree
11
+
12
+ from ...conf import parameters as cfg
13
+ from . import utils
14
+ from .MetaTab import MetaTab
15
+ from ...domain import Controller
16
+ from ...service import Plots, Utils, init_logger, log_exceptions
17
+
18
+ PATH_TO_BIGRESULTS = os.path.abspath(
19
+ os.path.join(os.path.dirname(__file__), "..", "..", "..", "big_results.p")
20
+ )
21
+
22
+ CONFIG = {
23
+ "toImageButtonOptions": {
24
+ "format": "svg", # one of png, svg, jpeg, webp
25
+ "height": None,
26
+ "width": None,
27
+ "scale": 1, # Multiply title/legend/axis/canvas sizes by this factor
28
+ }
29
+ }
30
+
31
+
32
+ class ResultsTab(MetaTab):
33
+ def __init__(self, app: Dash, metabo_controller: Controller):
34
+ super().__init__(app, metabo_controller)
35
+ self._logger = init_logger()
36
+ # self.r = pkl.load(open(PATH_TO_BIGRESULTS, "rb"))
37
+ self.r = self.metabo_controller.get_all_results()
38
+ self._plots = Plots("blues")
39
+
40
+ def getLayout(self) -> dbc.Tab:
41
+ __resultsMenuDropdowns = dbc.Card(
42
+ className="results_menu_dropdowns",
43
+ children=[
44
+ dbc.CardBody(
45
+ [
46
+ html.Div(
47
+ className="dropdowns",
48
+ children=[
49
+ html.H6("Classification Design : "),
50
+ dbc.Select(
51
+ id="design_dropdown",
52
+ className="form_select",
53
+ options=[{"label": "None", "value": "None"}],
54
+ value="None",
55
+ ),
56
+ ],
57
+ ),
58
+ html.Div(
59
+ className="dropdowns",
60
+ children=[
61
+ html.H6("ML Algorithm : "),
62
+ dbc.Select(
63
+ id="ml_dropdown",
64
+ className="form_select",
65
+ options=[{"label": "None", "value": "None"}],
66
+ value="None",
67
+ ),
68
+ ],
69
+ ),
70
+ dbc.Button(
71
+ "Load",
72
+ color="primary",
73
+ id="load_ML_results_button",
74
+ className="custom_buttons",
75
+ n_clicks=0,
76
+ ),
77
+ html.Div(id="output_button_load_ML_results"),
78
+ ],
79
+ id="menu_results",
80
+ )
81
+ ],
82
+ )
83
+
84
+ __currentExperimentInfo = dbc.Card(
85
+ children=[
86
+ dbc.CardBody(
87
+ children=[
88
+ html.H6(
89
+ "Current experiment info"
90
+ ), # , style={"marginTop": 25},
91
+ # html.Div(id="view_info", children=[
92
+ dcc.Loading(
93
+ id="loading_expe_table",
94
+ children=html.Div(id="expe_table", children=""),
95
+ type="circle",
96
+ ),
97
+ # dcc.Loading(id="loading-1", children=[html.Div(id="loading-output-1")],
98
+ # type="dot", color="#13BD00")
99
+ ]
100
+ )
101
+ ],
102
+ className="w-25",
103
+ )
104
+
105
+ _resultsInfo = html.Div(
106
+ className="Results_info",
107
+ children=[
108
+ __resultsMenuDropdowns,
109
+ __currentExperimentInfo,
110
+ ],
111
+ )
112
+
113
+ ___pcaPlot = html.Div(
114
+ className="pca_plot_and_title",
115
+ children=[
116
+ html.Div(
117
+ className="title_and_help",
118
+ children=[
119
+ html.H6("PCA", id="PCA_title"),
120
+ dcc.RadioItems(
121
+ id='pca_dimensions',
122
+ options=[
123
+ {'label': ' 2D', 'value': '2d'},
124
+ {'label': ' 3D', 'value': '3d'},
125
+ ],
126
+ value='2d',
127
+ labelStyle={'margin': 'auto', 'padding': '5px'},
128
+ inline=True
129
+ ),
130
+ ],
131
+ style={"display": "flex", "justify-content": "space-between"},
132
+ ),
133
+ # Should we put the title on the plot?
134
+ dcc.Loading(
135
+ dcc.Graph(id="PCA", config=CONFIG), type="dot", color="#13BD00"
136
+ ),
137
+ dcc.Slider(
138
+ step=None,
139
+ value=1,
140
+ marks={**cfg.default_marks, **cfg.all_mark},
141
+ id="pca_slider",
142
+ ),
143
+ ],
144
+ )
145
+
146
+ ___umap = html.Div(
147
+ className="umap_plot_and_title",
148
+ children=[
149
+ html.Div(
150
+ className="title_and_help",
151
+ children=[
152
+ html.H6("Umap"),
153
+ dcc.RadioItems(
154
+ id='umap_dimensions',
155
+ options=[
156
+ {'label': ' 2D', 'value': '2d'},
157
+ {'label': ' 3D', 'value': '3d'},
158
+ ],
159
+ value='2d',
160
+ # add space between radio and label
161
+ labelStyle={'margin': 'auto', 'padding': '5px'},
162
+ inline=True
163
+
164
+ ),
165
+ ],
166
+ style={"display": "flex", "justify-content": "space-between"},
167
+ ),
168
+ dcc.Loading(
169
+ dcc.Graph(id="umap_overview", config=CONFIG),
170
+ type="dot",
171
+ color="#13BD00",
172
+ ),
173
+ dcc.Slider(
174
+ step=None,
175
+ value=1,
176
+ marks={**cfg.default_marks, **cfg.all_mark},
177
+ id="umap_slider",
178
+ )
179
+ ],
180
+ )
181
+
182
+ ___2dPlot = html.Div(
183
+ className="umap_plot_and_title",
184
+ children=[
185
+ html.Div(
186
+ className="title_and_help",
187
+ children=[
188
+ html.H6("2D"),
189
+ dbc.Button(
190
+ "[?]",
191
+ className="text-muted btn-secondary popover_btn",
192
+ id="help_2dPlot",
193
+ ),
194
+ dbc.Popover(
195
+ children=[dbc.PopoverBody("Blablabla wout wout")],
196
+ id="pop_help_2dPlot",
197
+ is_open=False,
198
+ target="help_2dPlot",
199
+ ),
200
+ ],
201
+ ),
202
+ dcc.Loading(
203
+ dcc.Graph(id="2d_overview", config=CONFIG),
204
+ type="dot",
205
+ color="#13BD00",
206
+ ),
207
+ ],
208
+ )
209
+
210
+ ___3dPlot = html.Div(
211
+ className="umap_plot_and_title",
212
+ children=[
213
+ html.Div(
214
+ className="title_and_help",
215
+ children=[
216
+ html.H6("3D"),
217
+ dbc.Button(
218
+ "[?]",
219
+ className="text-muted btn-secondary popover_btn",
220
+ id="help_3dPlot",
221
+ ),
222
+ dbc.Popover(
223
+ children=[dbc.PopoverBody("Blablabla wout wout")],
224
+ id="pop_help_3dPlot",
225
+ is_open=False,
226
+ target="help_3dPlot",
227
+ ),
228
+ ],
229
+ ),
230
+ dcc.Loading(
231
+ dcc.Graph(id="3d_overview", config=CONFIG),
232
+ type="dot",
233
+ color="#13BD00",
234
+ ),
235
+ ],
236
+ )
237
+
238
+ __dataResultTab = dbc.Tab(
239
+ className="sub_tab",
240
+ label="Data",
241
+ children=[
242
+ html.Div(className="fig_group", children=[___pcaPlot, ___umap]),
243
+ html.Div(className="fig_group", children=[___2dPlot, ___3dPlot]),
244
+ ],
245
+ )
246
+
247
+ ___accuracyPlot = html.Div(
248
+ className="acc_plot_and_title",
249
+ children=[
250
+ html.Div(
251
+ className="title_and_help",
252
+ children=[
253
+ html.H6("Balanced accuracy plot"),
254
+ dbc.Button(
255
+ "[?]",
256
+ className="text-muted btn-secondary popover_btn",
257
+ id="help_accPlot",
258
+ ),
259
+ dbc.Popover(
260
+ children=[
261
+ dbc.PopoverBody(
262
+ "Accuracies for each split on train and test set. Here you would want to check"
263
+ "the difference between each set, because a really good train performance and a mediocre"
264
+ "or bad test performance is a sign of over-fitting."
265
+ )
266
+ ],
267
+ id="pop_help_accPlot",
268
+ is_open=False,
269
+ target="help_accPlot",
270
+ ),
271
+ ],
272
+ ),
273
+ dcc.Loading(
274
+ dcc.Graph(id="accuracy_overview", config=CONFIG),
275
+ type="dot",
276
+ color="#13BD00",
277
+ ),
278
+ ],
279
+ )
280
+
281
+ ___globalMetric = html.Div(
282
+ className="w-25",
283
+ children=[
284
+ html.H6("Global confusion matrix"),
285
+ dcc.Loading(
286
+ dcc.Graph(id="conf_matrix", config=CONFIG),
287
+ type="dot",
288
+ color="#13BD00",
289
+ ),
290
+ ],
291
+ )
292
+ ___specificFilters = html.Div(
293
+ className="fig_group_col",
294
+ children=[
295
+ html.Div(
296
+ className="",
297
+ children=[
298
+ html.H6("Splits number"),
299
+ dbc.Select(
300
+ id="splits_dropdown",
301
+ className="form_select_large",
302
+ options=[{"label": "None", "value": "None"}],
303
+ value="None",
304
+ ),
305
+ dbc.Button(
306
+ "Update",
307
+ color="primary",
308
+ id="update_specific_results_button",
309
+ className="custom_buttons",
310
+ n_clicks=0,
311
+ ),
312
+ html.Div(id="output_button_update_specific_results"),
313
+ ],
314
+ ),
315
+ html.Div(
316
+ className="",
317
+ style={"display": "flex", "width": "100%"},
318
+ children=[
319
+ html.Div(
320
+ children=[
321
+ html.H6("Confusion matrix"),
322
+ dcc.Loading(
323
+ dcc.Graph(id="split_conf_matrix", config=CONFIG),
324
+ type="dot",
325
+ color="#13BD00",
326
+ ),
327
+ ],
328
+ ),
329
+ html.Div(
330
+ children=[
331
+ html.H6("Table of used hyperparameter"),
332
+ dcc.Loading(
333
+ html.Div(id="hyperparam_table", children="", style={"margin-top": "2em"}),
334
+ ),
335
+ ],
336
+ )
337
+ ],
338
+ ),
339
+ ],
340
+ )
341
+ ___metricsTable = html.Div(
342
+ className="table_features",
343
+ children=[
344
+ html.H6("Metrics table : mean(std)"),
345
+ dcc.Loading(
346
+ id="loading_metrics_table",
347
+ children=html.Div(id="metrics_score_table", children=""),
348
+ type="circle",
349
+ ),
350
+ ],
351
+ )
352
+
353
+ __algoResultsTab = dbc.Tab(
354
+ className="sub_tab",
355
+ label="Algorithm",
356
+ children=[
357
+ html.Div(
358
+ className="fig_group",
359
+ children=[
360
+ ___accuracyPlot,
361
+ # ___globalMetric,
362
+ ___metricsTable,
363
+ ],
364
+ ),
365
+ html.Div(className="fig_group", children=[___specificFilters]),
366
+ ],
367
+ )
368
+
369
+ __DTTreeTab = dbc.Tab(
370
+ id="DTTT", className="sub_tab", label="DT Tree", disabled=True,
371
+ children=[
372
+ html.Div(dg.DashInteractiveGraphviz(
373
+ id="DTTT_graph"
374
+ ),
375
+ style={"letter-spacing": "0"}),
376
+ ]
377
+ )
378
+
379
+ ___featuresTable = html.Div(
380
+ className="table_features",
381
+ children=[
382
+ html.H6("Top 10 features sorted by importance"),
383
+ dbc.Button(
384
+ "Export",
385
+ color="primary",
386
+ id="export_features",
387
+ className="custom_buttons",
388
+ n_clicks=0,
389
+ ),
390
+ dcc.Download(id="download_dataframe_csv"),
391
+ dcc.Loading(
392
+ id="loading_features_table",
393
+ children=html.Div(id="features_table", children=""),
394
+ type="circle",
395
+ ),
396
+ ],
397
+ )
398
+ ___stripChart = html.Div(
399
+ className="umap_plot_and_title",
400
+ children=[
401
+ html.Div(
402
+ className="title_and_help",
403
+ children=[
404
+ html.H6("StripChart of features"),
405
+ dbc.Button(
406
+ "[?]",
407
+ className="text-muted btn-secondary popover_btn",
408
+ id="help_stripChart",
409
+ ),
410
+ dbc.Popover(
411
+ children=[dbc.PopoverBody("Blablabla wout wout")],
412
+ id="pop_help_stripChart",
413
+ is_open=False,
414
+ target="help_stripChart",
415
+ ),
416
+ ],
417
+ ),
418
+ # dbc.Select(
419
+ # id="features_dropdown",
420
+ # className="form_select",
421
+ # options=[{"label": "None", "value": "None"}],
422
+ # value="None",
423
+ # style={"width": "35%"},
424
+ # ),
425
+ dcc.Loading(
426
+ dcc.Graph(id="features_stripChart", config=CONFIG),
427
+ type="dot",
428
+ color="#13BD00",
429
+ ),
430
+ dcc.Slider(
431
+ step=None,
432
+ value=1,
433
+ marks=cfg.default_marks,
434
+ id="strip_chart_slider",
435
+ )
436
+ ],
437
+ )
438
+
439
+ ___coocMatrix = html.Div(
440
+ id="cooc_matrix",
441
+ style={"width": "50%", "height": "5em"},
442
+ children=[
443
+ html.H6("Co-occurence graph of features"),
444
+ dcc.Loading(
445
+ children=[
446
+ cyto.Cytoscape(
447
+ id="cooc_matrix_graph",
448
+ layout={"name": "cose"},
449
+ style={"width": "100%", "height": "100%", "border": "1px solid black"},
450
+ stylesheet=self._plots.get_default_stylesheet_for_cooc_graph(),
451
+ elements=[],
452
+
453
+ ),
454
+ html.Div(
455
+ id="cooc_matrix_graph_error",
456
+ children="",
457
+ style={"color": "red", "height": "100%", "background-color": "lightgrey",
458
+ "text-align": "center", "vertical-align": "middle"},
459
+ ),
460
+ ],
461
+ type="dot",
462
+ color="#13BD00",
463
+ ),
464
+ ],
465
+ )
466
+
467
+ __featuresResultsTab = dbc.Tab(
468
+ className="sub_tab",
469
+ label="Features",
470
+ children=[
471
+ html.Div(
472
+ className="fig_group", children=[___featuresTable,
473
+ ___stripChart
474
+ ]
475
+ ),
476
+ ___coocMatrix
477
+ ],
478
+ )
479
+
480
+ _mainPlotContent = html.Div(
481
+ id="main_plots-content",
482
+ children=[ # className="six columns",
483
+ dbc.Tabs(
484
+ className="custom_sub_tabs",
485
+ id="sub_tabs",
486
+ children=[
487
+ __dataResultTab,
488
+ __algoResultsTab,
489
+ __featuresResultsTab,
490
+ __DTTreeTab,
491
+ ],
492
+ )
493
+ ],
494
+ )
495
+
496
+ return dbc.Tab(
497
+ className="global_tab",
498
+ id="results_tab",
499
+ label="Results",
500
+ children=[
501
+ dcc.Store(id='design_dropdown_store', storage_type='session'),
502
+ dcc.Store(id='ml_dropdown_store', storage_type='session'),
503
+ dcc.Store(id='splits_dropdown_store', storage_type='session'),
504
+ _resultsInfo,
505
+ _mainPlotContent
506
+ ],
507
+ )
508
+
509
+ def _registerCallbacks(self) -> None:
510
+ @self.app.callback(
511
+ Output("pop_help_accPlot", "is_open"),
512
+ [Input("help_accPlot", "n_clicks")],
513
+ [State("pop_help_accPlot", "is_open")],
514
+ )
515
+ def toggle_popover(n, is_open):
516
+ if n:
517
+ return not is_open
518
+ return is_open
519
+
520
+ @self.app.callback(
521
+ [Output("design_dropdown", "options"), Output("design_dropdown", "value")],
522
+ [Input("custom_big_tabs", "active_tab")],
523
+ State('design_dropdown_store', 'data'),
524
+ )
525
+ @log_exceptions(self._logger)
526
+ def update_results_dropdown_design(active, stored_value):
527
+ if active == "tab-3":
528
+ self.r = self.metabo_controller.get_all_results()
529
+ experiment_designs = list(self.r.keys())
530
+ if len(experiment_designs) == 0:
531
+ return dash.no_update, dash.no_update
532
+ if stored_value is not None and stored_value in experiment_designs:
533
+ return Utils.format_list_for_checklist(experiment_designs), stored_value
534
+ return (
535
+ Utils.format_list_for_checklist(experiment_designs),
536
+ experiment_designs[0],
537
+ )
538
+ else:
539
+ return dash.no_update, dash.no_update
540
+
541
+ @self.app.callback(
542
+ [Output("ml_dropdown", "options"), Output("ml_dropdown", "value")],
543
+ [Input("design_dropdown", "value")],
544
+ [State("custom_big_tabs", "active_tab"), State('ml_dropdown_store', 'data')],
545
+ )
546
+ @log_exceptions(self._logger)
547
+ def update_results_dropdown_algo(design, active, stored_value):
548
+ if active == "tab-3":
549
+ a = list(self.r[design].keys())
550
+ if stored_value is not None and stored_value in a:
551
+ return [{"label": i, "value": i} for i in a], stored_value
552
+ else:
553
+ return [{"label": i, "value": i} for i in a], a[0]
554
+ else:
555
+ return dash.no_update
556
+
557
+ @self.app.callback(
558
+ [Output("splits_dropdown", "options"), Output("splits_dropdown", "value")],
559
+ [Input("sub_tabs", "active_tab")],
560
+ [State("ml_dropdown", "value"), State("design_dropdown", "value"), State('splits_dropdown_store', 'data')],
561
+ )
562
+ @log_exceptions(self._logger)
563
+ def update_nbr_splits_dropdown(active, algo, design, stored_value):
564
+ if active == "tab-1":
565
+ a = list(self.r[design][algo].splits_number)
566
+ if stored_value is not None and stored_value in a:
567
+ return [{"label": i, "value": i} for i in a], stored_value
568
+ else:
569
+ return [{"label": i, "value": i} for i in a], a[0]
570
+ else:
571
+ return dash.no_update
572
+
573
+ @self.app.callback(
574
+ [Output("loading-output-1", "children")],
575
+ [Input("custom_big_tabs", "active_tab")],
576
+ )
577
+ def input_triggers_spinner(value):
578
+ time.sleep(1)
579
+ return
580
+
581
+ # --- Callbacks to Save Values (persist dropdown selection) ---
582
+ @self.app.callback(
583
+ Output('design_dropdown_store', 'data'),
584
+ Input('load_ML_results_button', 'n_clicks'),
585
+ State('design_dropdown', 'value'),
586
+ )
587
+ def save_design_dropdown_value(_, value):
588
+ return value
589
+
590
+ @self.app.callback(
591
+ Output('ml_dropdown_store', 'data'),
592
+ Input('load_ML_results_button', 'n_clicks'),
593
+ State('ml_dropdown', 'value'),
594
+ )
595
+ def save_ml_dropdown_value(_, value):
596
+ return value
597
+
598
+ @self.app.callback(
599
+ Output('splits_dropdown_store', 'data'),
600
+ Input('update_specific_results_button', 'n_clicks'),
601
+ State('splits_dropdown', 'value'),
602
+ )
603
+ def save_splits_dropdown_value(_, value):
604
+ return value
605
+
606
+ # @self.app.callback(
607
+ # Output("2features", "figure"),
608
+ # [Input("load_ML_results_button", "n_clicks"), Input("pca_slider", "value")],
609
+ # [State("ml_dropdown", "value"), State("design_dropdown", "value")],
610
+ # )
611
+ # def show_pca(n_clicks, features, algo, design_name):
612
+ # if n_clicks >= 1:
613
+ # df = self.r[design_name][algo].results["features_table"]
614
+ # classes = self.r[design_name][algo].results["classes"]
615
+ # return self._plots.show_two_most_important_feature(df[pca_value], classes, pca_value, algo)
616
+ # else:
617
+ # return dash.no_update
618
+
619
+ @self.app.callback(
620
+ [
621
+ Output("cooc_matrix_graph", "elements"),
622
+ Output("cooc_matrix_graph", "style"),
623
+ Output("cooc_matrix_graph_error", "children")
624
+ ],
625
+ [
626
+ Input("load_ML_results_button", "n_clicks")
627
+ ],
628
+ [
629
+ State("ml_dropdown", "value"),
630
+ State("design_dropdown", "value")
631
+ ]
632
+ )
633
+ @log_exceptions(self._logger)
634
+ def show_cooc_matrix(_, algo, design_name):
635
+ if algo == "None" or design_name == "None":
636
+ return [dash.no_update] * 3
637
+
638
+ (
639
+ counter,
640
+ mean_importance,
641
+ number_of_split,
642
+ cardinality
643
+ ) = self.r[design_name][algo].results["coocurence_matrix"]
644
+
645
+ if counter is None:
646
+ msg = "Due to the high cardinality of the features, " \
647
+ "the co-occurrence graph cannot be displayed. " \
648
+ "The estimated cardinality is " + str(int(cardinality)) + \
649
+ " and exceed the 1000 links limit."
650
+ return dash.no_update, {'display': 'none'}, msg
651
+
652
+ parameters = self._plots.create_coocurence_graph(counter, mean_importance, number_of_split)
653
+ return parameters, {'display': 'block', "width": "100%", "height": "800px"}, ""
654
+
655
+ @self.app.callback(Output('cooc_matrix_graph', 'stylesheet'),
656
+ [Input('cooc_matrix_graph', 'selectedNodeData')])
657
+ @log_exceptions(self._logger)
658
+ def update_stylesheet(nodes):
659
+ default_stylesheet = self._plots.get_default_stylesheet_for_cooc_graph()
660
+ if nodes is None:
661
+ return default_stylesheet
662
+ else:
663
+ updated_stylesheet = default_stylesheet.copy()
664
+ self._logger.info(f"nodes:\n{nodes}")
665
+ for node in nodes:
666
+ updated_stylesheet.append(self._plots.format_style_for_selected_node(node))
667
+ return updated_stylesheet
668
+
669
+ @self.app.callback(
670
+ [
671
+ Output("pca_slider", "marks"),
672
+ Output("umap_slider", "marks"),
673
+ Output("strip_chart_slider", "marks"),
674
+ Output("pca_slider", "value"),
675
+ Output("umap_slider", "value"),
676
+ Output("strip_chart_slider", "value"),
677
+ ],
678
+ [
679
+ Input("load_ML_results_button", "n_clicks")
680
+ ],
681
+ [
682
+ State("ml_dropdown", "value"), State("design_dropdown", "value")
683
+ ]
684
+ )
685
+ @log_exceptions(self._logger)
686
+ def update_sliders_with_used(_, algo, design_name):
687
+ """Update PCA, UMAP and Strip chart sliders marks and triggers each plots by updating there values"""
688
+ if algo == "None" or design_name == "None":
689
+ return [dash.no_update] * 6
690
+
691
+ feature_df = self.r[design_name][algo].results["features_table"]
692
+ number_of_used_feature = len(feature_df[feature_df["times_used"] > 0])
693
+
694
+ marks_container = []
695
+ locations_container = []
696
+
697
+ marks, used_location = utils.update_marks(
698
+ custom_value=number_of_used_feature,
699
+ add_all_value=True
700
+ )
701
+ pca_marks, umap_marks = marks, marks
702
+ pca_location, umap_location = used_location, used_location
703
+ marks_container.extend([pca_marks, umap_marks])
704
+ locations_container.extend([pca_location, umap_location])
705
+
706
+ strip_chart_marks, strip_location = utils.update_marks(
707
+ custom_value=number_of_used_feature,
708
+ add_all_value=False
709
+ )
710
+ marks_container.append(strip_chart_marks)
711
+ locations_container.append(strip_location)
712
+
713
+ return (*marks_container, *locations_container)
714
+
715
+
716
+ @self.app.callback(
717
+ [
718
+ Output("PCA", "figure")
719
+ ],
720
+ [
721
+ Input("pca_slider", "value"),
722
+ Input("pca_dimensions", "value")
723
+ ],
724
+ [
725
+ State("ml_dropdown", "value"),
726
+ State("design_dropdown", "value"),
727
+ State("pca_slider", "marks")
728
+ ],
729
+ prevent_initial_call=True
730
+ )
731
+ @log_exceptions(self._logger)
732
+ def show_pca(pca_value, dimensions, algo, design_name, marks):
733
+ """
734
+ pca_value : represent the number of feature selected by the slider, but is given as indexes
735
+ """
736
+ if algo == "None" or design_name == "None":
737
+ return dash.no_update
738
+
739
+ classes = self.r[design_name][algo].results["classes"]
740
+
741
+ index = utils.get_index_from_marks(pca_value, marks)
742
+
743
+ if dimensions == "2d":
744
+ data_list, labels_list = self.r[design_name][algo].results["pca_data"]
745
+ fig = self._plots.show_PCA(
746
+ data_list[index], labels_list[index], classes, index, algo,
747
+ self.r[design_name][algo].results["samples_id"]
748
+ )
749
+ elif dimensions == "3d":
750
+ data_list, labels_list = self.r[design_name][algo].results["3d_pca_data"]
751
+ fig = self._plots.show_3D_PCA(
752
+ data_list[index], labels_list[index], classes, index, algo,
753
+ self.r[design_name][algo].results["samples_id"]
754
+ )
755
+
756
+ return [fig]
757
+
758
+ @self.app.callback(
759
+ [
760
+ Output("umap_overview", "figure")
761
+ ],
762
+ [
763
+ Input("load_ML_results_button", "n_clicks"),
764
+ Input("umap_slider", "value"),
765
+ Input("umap_dimensions", "value"),
766
+ ],
767
+ [
768
+ State("ml_dropdown", "value"),
769
+ State("design_dropdown", "value"),
770
+ State("umap_slider", "marks")
771
+ ],
772
+ )
773
+ @log_exceptions(self._logger)
774
+ def show_umap(_, slider_value, dimensions, algo, design_name, marks):
775
+ if algo == "None" or design_name == "None":
776
+ return dash.no_update
777
+
778
+ classes = self.r[design_name][algo].results["classes"]
779
+
780
+ index = utils.get_index_from_marks(slider_value, marks)
781
+
782
+ if dimensions == "2d":
783
+ df = self.r[design_name][algo].results["umap_data"]
784
+ fig = self._plots.show_umap(
785
+ df[index], classes, algo, index,
786
+ self.r[design_name][algo].results["samples_id"]
787
+ )
788
+ elif dimensions == "3d":
789
+ df = self.r[design_name][algo].results["3d_umap_data"]
790
+ fig = self._plots.show_3D_umap(
791
+ df[index], classes, algo, index,
792
+ self.r[design_name][algo].results["samples_id"]
793
+ )
794
+
795
+ return [fig]
796
+
797
+
798
+ @self.app.callback(
799
+ [
800
+ Output("2d_overview", "figure")
801
+ ],
802
+ [
803
+ Input("load_ML_results_button", "n_clicks")
804
+ ],
805
+ [
806
+ State("ml_dropdown", "value"),
807
+ State("design_dropdown", "value")
808
+ ],
809
+ )
810
+ @log_exceptions(self._logger)
811
+ def show_2d(_, algo, design_name):
812
+ if algo == "None" or design_name == "None":
813
+ return dash.no_update
814
+
815
+ df = (
816
+ self.r[design_name][algo].results["features_2d_and_3d"].iloc[:, :-1]
817
+ )
818
+ classes = self.r[design_name][algo].results["classes"]
819
+ fig = self._plots.show_2d(
820
+ df, classes,
821
+ self.r[design_name][algo].results["samples_id"]
822
+ )
823
+ return [fig]
824
+
825
+
826
+ @self.app.callback(
827
+ [
828
+ Output("3d_overview", "figure")
829
+ ],
830
+ [
831
+ Input("load_ML_results_button", "n_clicks")
832
+ ],
833
+ [
834
+ State("ml_dropdown", "value"),
835
+ State("design_dropdown", "value")
836
+ ],
837
+ )
838
+ @log_exceptions(self._logger)
839
+ def show_3d(_, algo, design_name):
840
+ if algo == "None" or design_name == "None":
841
+ return dash.no_update
842
+
843
+ df = self.r[design_name][algo].results["features_2d_and_3d"]
844
+ classes = self.r[design_name][algo].results["classes"]
845
+ fig = self._plots.show_3d(
846
+ df, classes,
847
+ self.r[design_name][algo].results["samples_id"]
848
+ )
849
+ return [fig]
850
+
851
+ @self.app.callback(
852
+ [
853
+ Output("expe_table", "children")
854
+ ],
855
+ [
856
+ Input("load_ML_results_button", "n_clicks")
857
+ ],
858
+ [
859
+ State("ml_dropdown", "value"),
860
+ State("design_dropdown", "value")
861
+ ],
862
+ )
863
+ @log_exceptions(self._logger)
864
+ def get_experiment_statistics(_, algo, design_name):
865
+ if algo == "None" or design_name == "None":
866
+ return dash.no_update
867
+
868
+ df = self.r[design_name][algo].results["info_expe"]
869
+ table_body = self._plots.show_exp_info_all(df)
870
+ table = dbc.Table(
871
+ table_body, id="table_exp_info", borderless=True, hover=True
872
+ ) # dbc.Table.from_dataframe(df, borderless=True)
873
+ return [table]
874
+
875
+
876
+ @self.app.callback(
877
+ [
878
+ Output("accuracy_overview", "figure")
879
+ ],
880
+ [
881
+ Input("load_ML_results_button", "n_clicks")
882
+ ],
883
+ [
884
+ State("ml_dropdown", "value"),
885
+ State("design_dropdown", "value")
886
+ ],
887
+ )
888
+ @log_exceptions(self._logger)
889
+ def generates_accuracyPlot_global(_, algo, design_name):
890
+ if algo == "None" or design_name == "None":
891
+ return dash.no_update
892
+
893
+ df = self.r[design_name][algo].results["accuracies_table"]
894
+ fig = self._plots.show_accuracy_all(df, algo)
895
+ return [fig]
896
+
897
+ @self.app.callback(
898
+ [
899
+ Output("metrics_score_table", "children")
900
+ ],
901
+ [
902
+ Input("load_ML_results_button", "n_clicks")
903
+ ],
904
+ [
905
+ State("ml_dropdown", "value"),
906
+ State("design_dropdown", "value")
907
+ ],
908
+ )
909
+ @log_exceptions(self._logger)
910
+ def show_metrics(_, algo, design_name):
911
+ if algo == "None" or design_name == "None":
912
+ return dash.no_update
913
+
914
+ df = self.r[design_name][algo].results["metrics_table"]
915
+ table = dbc.Table.from_dataframe(df, borderless=True)
916
+ return [table]
917
+
918
+
919
+ @self.app.callback(
920
+ [
921
+ Output("split_conf_matrix", "figure"),
922
+ Output("hyperparam_table", "children")
923
+ ],
924
+ [
925
+ Input("update_specific_results_button", "n_clicks")],
926
+ [
927
+ State("ml_dropdown", "value"),
928
+ State("design_dropdown", "value"),
929
+ State("splits_dropdown", "value"),
930
+ ],
931
+ )
932
+ @log_exceptions(self._logger)
933
+ def compute_split_conf_matrix(_, algo, design_name, split):
934
+ if algo == "None" or design_name == "None":
935
+ return dash.no_update, dash.no_update
936
+
937
+ cm = self.r[design_name][algo].results[split]["Confusion_matrix"][1]
938
+ labels = self.r[design_name][algo].results[split]["Confusion_matrix"][0]
939
+
940
+ text_mat = []
941
+ for i, line in enumerate(cm):
942
+ text_mat.append([])
943
+ for j, col in enumerate(line):
944
+ text_mat[i].append(str(col))
945
+
946
+ hps = self.r[design_name][algo].results[split]["hyperparameters"]
947
+
948
+ hps_df = pd.DataFrame.from_dict({"Hyperparameters": hps.keys(), "Values": hps.values()})
949
+
950
+ dash_table_element = dbc.Table.from_dataframe(hps_df, borderless=True)
951
+ fig = self._plots.show_general_confusion_matrix(
952
+ cm, labels, text_mat, algo, split
953
+ )
954
+
955
+ return fig, dash_table_element
956
+
957
+
958
+ @self.app.callback(
959
+ Output("features_table", "children"),
960
+ Input("load_ML_results_button", "n_clicks"),
961
+ [
962
+ State("ml_dropdown", "value"),
963
+ State("design_dropdown", "value")
964
+ ],
965
+ )
966
+ @log_exceptions(self._logger)
967
+ def show_features(_, algo, design_name):
968
+ if algo == "None" or design_name == "None":
969
+ return dash.no_update
970
+
971
+ df = self.r[design_name][algo].results["features_table"].copy()
972
+ df = df.sort_values(by="importance_usage", ascending=False)
973
+ df = df.round(4)
974
+
975
+ return dbc.Table.from_dataframe(df.iloc[:10, :], borderless=True)
976
+
977
+
978
+ @self.app.callback(
979
+ Output("download_dataframe_csv", "data"),
980
+ [Input("export_features", "n_clicks")],
981
+ [State("ml_dropdown", "value"), State("design_dropdown", "value")],
982
+ prevent_initial_call=True,
983
+ )
984
+ @log_exceptions(self._logger)
985
+ def export_download_features_table(n_click, algo, design_name):
986
+ if n_click >= 1:
987
+ df = self.r[design_name][algo].results["features_table"]
988
+ return dcc.send_data_frame(
989
+ df.to_csv, "featuresImportancesTable" + algo + ".csv"
990
+ )
991
+ else:
992
+ return dash.no_update
993
+
994
+
995
+ @self.app.callback(
996
+ [
997
+ Output("features_stripChart", "figure")
998
+ ],
999
+ [
1000
+ Input("strip_chart_slider", "value")
1001
+ ],
1002
+ [
1003
+ State("ml_dropdown", "value"),
1004
+ State("design_dropdown", "value"),
1005
+ State("strip_chart_slider", "marks")
1006
+ ],
1007
+ )
1008
+ @log_exceptions(self._logger)
1009
+ def show_stripChart_features(slider_value, algo, design_name, marks):
1010
+ if algo == "None" or design_name == "None":
1011
+ return dash.no_update
1012
+
1013
+ try:
1014
+ real_value = utils.get_index_from_marks(slider_value, marks)
1015
+ strip_chart_data = self.r[design_name][algo].results["features_stripchart"][real_value]
1016
+ fig = self._plots.show_metabolite_levels(
1017
+ strip_chart_data, algo,
1018
+ self.r[design_name][algo].results["samples_id"]
1019
+ )
1020
+ return [fig]
1021
+ except IndexError:
1022
+ return dash.no_update
1023
+
1024
+ @self.app.callback(
1025
+ [
1026
+ Output("DTTT", "disabled"),
1027
+ Output("DTTT_graph", "dot_source")
1028
+ ],
1029
+ [
1030
+ Input("load_ML_results_button", "n_clicks")
1031
+ ],
1032
+ [
1033
+ State("ml_dropdown", "value"),
1034
+ State("design_dropdown", "value")
1035
+ ],
1036
+ )
1037
+ @log_exceptions(self._logger)
1038
+ def disable_DTTT(_, algo, design_name):
1039
+ if algo == "None" or design_name == "None":
1040
+ return dash.no_update, dash.no_update
1041
+
1042
+ if algo == "DecisionTree":
1043
+ model = self.r[design_name][algo].results["best_model"]
1044
+ classes = list(set(self.r[design_name][algo].results["classes"]))
1045
+ plt.margins(0.05)
1046
+ df = self.r[design_name][algo].results["features_table"]
1047
+ df.sort_index(inplace=True)
1048
+ features_name = list(df["features"])
1049
+ dot_data = tree.export_graphviz(
1050
+ model,
1051
+ out_file=None,
1052
+ class_names=classes,
1053
+ feature_names=features_name,
1054
+ proportion=True,
1055
+ filled=True,
1056
+ rounded=True,
1057
+ special_characters=True,
1058
+ )
1059
+
1060
+ return False, dot_data
1061
+
1062
+ return True, ""