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,394 @@
1
+ from collections import Counter
2
+
3
+ import dash_bootstrap_components as dbc
4
+ import numpy as np
5
+ from dash import html, dcc, Output, Input, State, dash, Dash
6
+
7
+ from .MetaTab import MetaTab
8
+ from ...service import Plots, init_logger, log_exceptions
9
+ from ...domain import Controller
10
+
11
+ CONFIG = {
12
+ "toImageButtonOptions": {
13
+ "format": "svg", # one of png, svg, jpeg, webp
14
+ "height": None,
15
+ "width": None,
16
+ "scale": 1, # Multiply title/legend/axis/canvas sizes by this factor
17
+ }
18
+ }
19
+
20
+
21
+ class AggregatedResultsTab(MetaTab):
22
+ def __init__(self, app: Dash, metabo_controller: Controller):
23
+ super().__init__(app, metabo_controller)
24
+ self._logger = init_logger()
25
+ self.r = self.metabo_controller.get_all_results()
26
+ self._plots = Plots("blues")
27
+
28
+ def getLayout(self) -> dbc.Tab:
29
+ _resultsMenuDropdowns = dbc.Card(
30
+ className="results_menu_dropdowns",
31
+ children=[
32
+ dbc.CardBody(
33
+ [
34
+ html.Div(
35
+ className="dropdowns",
36
+ children=[
37
+ html.H6("Classification Design : "),
38
+ dbc.Select(
39
+ id="design_dropdown_summary",
40
+ className="form_select",
41
+ options=[{"label": "None", "value": "None"}],
42
+ value="None",
43
+ ),
44
+ dcc.Store(id='design_dropdown_summary_store', storage_type='session'),
45
+ ],
46
+ ),
47
+ dbc.Button(
48
+ "Load",
49
+ color="primary",
50
+ id="load_results_button",
51
+ className="custom_buttons",
52
+ n_clicks=0,
53
+ ),
54
+ html.Div(id="output_button_load_results"),
55
+ ],
56
+ id="all_algo_results",
57
+ )
58
+ ],
59
+ )
60
+
61
+ __currentExperimentInfo = dbc.Card(
62
+ children=[
63
+ dbc.CardBody(
64
+ children=[
65
+ html.H6(
66
+ "Current experiment info"
67
+ ),
68
+ dcc.Loading(
69
+ id="loading_expe_table_summary",
70
+ children=html.Div(id="expe_table_summary", children=""),
71
+ type="circle",
72
+ ),
73
+ ]
74
+ )
75
+ ],
76
+ className="w-25",
77
+ )
78
+
79
+ _resultsInfo = html.Div(
80
+ className="Results_info",
81
+ children=[
82
+ _resultsMenuDropdowns,
83
+ __currentExperimentInfo,
84
+ ],
85
+ )
86
+
87
+
88
+ _heatmapUsedFeatures = html.Div(
89
+ className="umap_plot_and_title",
90
+ children=[
91
+ html.Div(
92
+ className="title_and_help",
93
+ children=[
94
+ html.H6("Features Usage"),
95
+ dbc.Button(
96
+ "[?]",
97
+ className="text-muted btn-secondary popover_btn",
98
+ id="help_heatmapFeatures",
99
+ ),
100
+ dbc.Popover(
101
+ children=[dbc.PopoverBody("Blablabla wout wout")],
102
+ id="pop_help_heatmapFeatures",
103
+ is_open=False,
104
+ target="help_hHeatmapFeatures",
105
+ ),
106
+ ],
107
+ ),
108
+ dcc.Loading(
109
+ dcc.Graph(id="heatmapFeatures", config=CONFIG),
110
+ type="dot",
111
+ color="#13BD00",
112
+ ),
113
+ dcc.Slider(-3, 0, 0.1,
114
+ id='slider_heatmapFeatures',
115
+ marks={i: '{}'.format(10 ** i) for i in range(-3, 1, 1)},
116
+ value=-2,
117
+ updatemode='drag',
118
+ ),
119
+ ],
120
+ )
121
+
122
+ _heatmapSamplesAlwaysWrong = html.Div(
123
+ className="umap_plot_and_title",
124
+ children=[
125
+ html.Div(
126
+ className="title_and_help",
127
+ children=[
128
+ html.H6("Errors on samples in test"),
129
+ dbc.Button(
130
+ "[?]",
131
+ className="text-muted btn-secondary popover_btn",
132
+ id="help_heatmapSamples",
133
+ ),
134
+ dbc.Popover(
135
+ children=[dbc.PopoverBody("Blablabla wout wout")],
136
+ id="pop_help_heatmapSamples",
137
+ is_open=False,
138
+ target="help_heatmapSamples",
139
+ ),
140
+ ],
141
+ ),
142
+ dcc.Loading(
143
+ dcc.Graph(id="heatmapSamples", config=CONFIG),
144
+ type="dot",
145
+ color="#13BD00",
146
+ ),
147
+ # dcc.Slider(min=0, max=3, step=1, value=0, marks={0: "10", 1: "40", 2: "100", 3: "All"},
148
+ # id="features_stripChart_dropdown")
149
+ ],
150
+ )
151
+
152
+ _barplotComparaisonAlgo = html.Div(
153
+ className="umap_plot_and_title",
154
+ children=[
155
+ html.Div(
156
+ className="title_and_help",
157
+ children=[
158
+ html.H6("Comparaison of algorithms performances"),
159
+ dbc.Button(
160
+ "[?]",
161
+ className="text-muted btn-secondary popover_btn",
162
+ id="help_barplotAlgo",
163
+ ),
164
+ dbc.Popover(
165
+ children=[dbc.PopoverBody("Blablabla wout wout")],
166
+ id="pop_help_barplotAlgo",
167
+ is_open=False,
168
+ target="help_barplotAlgo",
169
+ ),
170
+ ],
171
+ ),
172
+ dcc.Loading(
173
+ dcc.Graph(id="barplotAlgo", config=CONFIG),
174
+ type="dot",
175
+ color="#13BD00",
176
+ ),
177
+ ],
178
+ )
179
+
180
+ return dbc.Tab(
181
+ className="global_tab",
182
+ label="Results aggregated",
183
+ children=[
184
+ _resultsInfo,
185
+ html.Div(
186
+ className="fig_group",
187
+ children=[
188
+ _barplotComparaisonAlgo
189
+ ],
190
+ ),
191
+ html.Div(className="fig_group", children=[
192
+ _heatmapSamplesAlwaysWrong,
193
+ _heatmapUsedFeatures
194
+ ]),
195
+ ],
196
+ )
197
+ # html.Div(className="column_content",
198
+ # # WARNING !! : _infoFigure is not with the card, it's in a separate column
199
+ # children=[_heatmapSamplesAlwaysWrong])])])
200
+
201
+ def _registerCallbacks(self) -> None:
202
+ @self.app.callback(
203
+ [
204
+ Output("design_dropdown_summary", "options"),
205
+ Output("design_dropdown_summary", "value"),
206
+ ],
207
+ Input("custom_big_tabs", "active_tab"),
208
+ State('design_dropdown_summary_store', 'data'),
209
+ )
210
+ @log_exceptions(self._logger)
211
+ def update_results_dropdown_design(active, stored_value):
212
+ if active == "tab-4":
213
+ try:
214
+ self.r = self.metabo_controller.get_all_results()
215
+ a = list(self.r.keys())
216
+ if stored_value is not None and stored_value in a:
217
+ return [{"label": i, "value": i} for i in a], stored_value
218
+ return [{"label": i, "value": i} for i in a], a[0]
219
+ except: # TODO: wrong practice ???
220
+ return dash.no_update, dash.no_update
221
+ else:
222
+ return dash.no_update, dash.no_update
223
+
224
+ @self.app.callback(
225
+ Output('design_dropdown_summary_store', 'data'),
226
+ Input('load_results_button', 'n_clicks'),
227
+ State('design_dropdown_summary', 'value')
228
+ )
229
+ def save_design_dropdown_summary_value(_, value):
230
+ return value
231
+
232
+ @self.app.callback(
233
+ [
234
+ Output("expe_table_summary", "children")
235
+ ],
236
+ [
237
+ Input("load_results_button", "n_clicks")
238
+ ],
239
+ [
240
+ State("design_dropdown_summary", "value")
241
+ ],
242
+ )
243
+ @log_exceptions(self._logger)
244
+ def get_experiment_statistics(_, design_name):
245
+ if design_name == "None":
246
+ return dash.no_update
247
+
248
+ df = self.r[design_name][list(self.r[design_name].keys())[0]].results["info_expe"]
249
+ table_body = self._plots.show_exp_info_all(df)
250
+ table = dbc.Table(
251
+ table_body, id="table_exp_info", borderless=True, hover=True
252
+ )
253
+ return [table]
254
+
255
+ @self.app.callback(
256
+ [
257
+ Output("heatmapFeatures", "figure"),
258
+ ],
259
+ [Input("load_results_button", "n_clicks"),
260
+ Input("slider_heatmapFeatures", "value")],
261
+ [State("design_dropdown_summary", "value"),
262
+ ],
263
+ )
264
+ @log_exceptions(self._logger)
265
+ def show_heatmap_features_usage(n_clicks, log_importance_threshold, design):
266
+ if n_clicks >= 1:
267
+
268
+ importance_threshold = 10 ** log_importance_threshold
269
+
270
+ algos = list(self.r[design].keys())
271
+ global_df = None
272
+ for a in algos:
273
+ if global_df is None:
274
+ self._logger.info("Global df is none")
275
+ global_df = self.r[design][a].results["features_table"]
276
+ global_df = global_df.loc[
277
+ :, ("features", "importance_usage")
278
+ ] # reduce dataframe to 2 columns
279
+ global_df.rename(
280
+ columns={"importance_usage": a}, inplace=True
281
+ ) # rename column to identify algorithm
282
+ else:
283
+ self._logger.info(f"Global df not none, algo : {a}")
284
+ df = self.r[design][a].results[
285
+ "features_table"
286
+ ] # retrieve features table of algo a
287
+ df = df.loc[
288
+ :, ("features", "importance_usage")
289
+ ] # reduce dataframe to 2 columns
290
+ df.rename(
291
+ columns={"importance_usage": a}, inplace=True
292
+ ) # rename column to identify algorithm
293
+ global_df = global_df.merge(
294
+ df, how="outer", on="features"
295
+ ) # join data with global dataset
296
+
297
+ global_df = global_df.set_index("features")
298
+ global_df = global_df.fillna(0)
299
+
300
+ global_df = global_df.loc[global_df.max(axis=1) >= importance_threshold]
301
+
302
+ hm_fig = self._plots.show_heatmap_features_usage(global_df, importance_threshold)
303
+
304
+ return [hm_fig]
305
+ else:
306
+ return dash.no_update
307
+
308
+ @self.app.callback(
309
+ Output("heatmapSamples", "figure"),
310
+ [Input("load_results_button", "n_clicks")],
311
+ State("design_dropdown_summary", "value"),
312
+ )
313
+ @log_exceptions(self._logger)
314
+ def show_heatmap_samples_always_wrong(n_clicks, design):
315
+ if n_clicks >= 1:
316
+ algos = list(self.r[design].keys())
317
+
318
+ data_train = []
319
+ data_test = []
320
+ all_samples = []
321
+
322
+ for i, a in enumerate(algos):
323
+ data_train.append([])
324
+ data_test.append([])
325
+ train = []
326
+ test = []
327
+ for j, s in enumerate(self.r[design][a].splits_number):
328
+ train_d, test_d = self.r[design][a].results[s]["failed_samples"]
329
+ train.append(train_d)
330
+ test.append(test_d)
331
+
332
+ counter_train = Counter()
333
+ for d in train:
334
+ counter_train.update(d)
335
+
336
+ counter_test = Counter()
337
+ for d in test:
338
+ counter_test.update(d)
339
+
340
+ all_samples = list(counter_train.keys()) + list(counter_test.keys())
341
+ for s in all_samples:
342
+ if s in counter_train.keys():
343
+ data_train[i].append(counter_train[s])
344
+ else:
345
+ data_train[i].append(0)
346
+
347
+ if s in counter_test.keys():
348
+ data_test[i].append(counter_test[s])
349
+ else:
350
+ data_test[i].append(0)
351
+
352
+ data_train = np.array(data_train).T
353
+ data_test = np.array(data_test).T
354
+
355
+ fig = self._plots.show_heatmap_wrong_samples(
356
+ data_train, data_test, all_samples, algos
357
+ )
358
+
359
+ return fig
360
+ else:
361
+ return dash.no_update
362
+
363
+ @self.app.callback(
364
+ Output("barplotAlgo", "figure"),
365
+ [Input("load_results_button", "n_clicks")],
366
+ State("design_dropdown_summary", "value"),
367
+ )
368
+ @log_exceptions(self._logger)
369
+ def show_barplot_compare_accuracy_algo(n_clicks, design_name):
370
+ """
371
+ retrieve balanced accuracy values now
372
+ """
373
+ if n_clicks >= 1:
374
+ algos = list(self.r[design_name].keys())
375
+
376
+ train_acc = []
377
+ train_std = []
378
+ test_acc = []
379
+ test_std = []
380
+ for a in algos:
381
+ df = self.r[design_name][a].results["metrics_table"]
382
+ train_m, train_s = df["train"][1].split("(")
383
+ train_acc.append(float(train_m))
384
+ train_std.append(float(train_s.split(")")[0]))
385
+
386
+ test_m, test_s = df["test"][1].split("(")
387
+ test_acc.append(float(test_m))
388
+ test_std.append(float(test_s.split(")")[0]))
389
+
390
+ fig = self._plots.show_barplot_comparaison_algo(algos, train_acc, train_std, test_acc, test_std)
391
+ return fig
392
+ else:
393
+ return dash.no_update
394
+