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,6 @@
1
+ from .InfoTab import InfoTab
2
+ from .SplitsTab import SplitsTab
3
+ from .MLTab import MLTab
4
+ from .ResultsTab import ResultsTab
5
+ from .AggregatedResultsTab import AggregatedResultsTab
6
+ from .InterpretTab import InterpretTab
pico/ui/tabs/utils.py ADDED
@@ -0,0 +1,101 @@
1
+ import numpy as np
2
+
3
+ from ...conf import parameters as cfg
4
+
5
+
6
+ def update_marks(custom_value: int, add_all_value: bool = False) -> dict:
7
+ """
8
+ Update the marks of the features slider to include a custom value.
9
+
10
+ If the custom value is already in the default marks, it will be used and
11
+ marked as "(used)".
12
+
13
+ If the custom value is not in the default marks, it will be added to the
14
+ marks at a position that is the closest to its value.
15
+
16
+ If add_all_value is True, the "All" mark will be added to the marks.
17
+
18
+ Returns a tuple containing the updated marks and the location of the custom
19
+ value.
20
+ """
21
+ locations = [int(l) for l in cfg.default_marks.keys()]
22
+ values = np.array([int(v) for v in cfg.default_marks.values()])
23
+
24
+ # If the custom value is already there, we use it a used feature
25
+ if custom_value in values:
26
+ marks = cfg.default_marks.copy()
27
+ idx = np.where(values == custom_value)[0].item()
28
+ location_key = str(locations[idx])
29
+ marks[location_key] = marks[location_key] + " (used)"
30
+
31
+ if add_all_value:
32
+ marks.update(cfg.all_mark)
33
+
34
+ return marks, location_key
35
+
36
+ greater_indicator = values > custom_value
37
+ if np.all(greater_indicator):
38
+ # The value is on the far left
39
+ custom_location = locations[0] - cfg.custom_mark_offset
40
+ elif not np.any(greater_indicator):
41
+ # The value is on the far right
42
+ custom_location = locations[-1] + cfg.custom_mark_offset
43
+ else:
44
+ greater_idx = np.argmax(greater_indicator)
45
+ distance_from_greater = values[greater_idx] - custom_value
46
+ distance_from_smaller = custom_value - values[greater_idx - 1]
47
+ if distance_from_smaller < distance_from_greater:
48
+ # Closer to the left, we will add the offset on the left mark
49
+ custom_location = locations[greater_idx - 1] + cfg.custom_mark_offset
50
+ elif distance_from_smaller == distance_from_greater:
51
+ # Equal distance
52
+ custom_location = (locations[greater_idx - 1] + locations[greater_idx]) / 2
53
+ else:
54
+ # Closer the the right, we will remove the offset from the right mark
55
+ custom_location = locations[greater_idx] - cfg.custom_mark_offset
56
+
57
+ marks = cfg.default_marks.copy()
58
+ value_label = {
59
+ 'label': str(custom_value) + ' (used)',
60
+ 'style': {
61
+ "top": "-3em"
62
+ }
63
+ }
64
+ marks[str(custom_location)] = value_label
65
+
66
+ if add_all_value:
67
+ marks = {**marks, **cfg.all_mark}
68
+
69
+ return marks, custom_location
70
+
71
+
72
+
73
+ def get_index_from_marks(number: float, marks: dict) -> int:
74
+ """This is really specific to how the results are saved.
75
+ See pico.domain.Results._produce_PCA (or _produce_UMAP).
76
+
77
+ The first results are from cfg.features, then used_features, then all.
78
+
79
+ The result differs when there is "All" features (e.g. strip chart doesnt not include All).
80
+ """
81
+ contain_all = False
82
+ for v in marks.values():
83
+ if isinstance(v, str) and v == "All":
84
+ contain_all = True
85
+
86
+ match marks[str(number)]:
87
+ case dict(value):
88
+ # We have the used feature case, index is -2 or -1 when
89
+ index = -2 if contain_all else -1
90
+ case "All":
91
+ # We have the "All" case, index is -1
92
+ index = -1
93
+ case str(value) if "used" in value:
94
+ # We have the feature case
95
+ index = -2 if contain_all else -1
96
+ case _:
97
+ # The number is the index
98
+ index = int(number)
99
+
100
+
101
+ return index
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: pico-ml
3
+ Version: 2.0.0
4
+ Summary: Pipeline for Interpretable Classification on Omics
5
+ Project-URL: Homepage, https://elinaff.github.io/PICO/
6
+ Project-URL: Issues, https://github.com/ElinaFF/PICO/issues
7
+ Project-URL: Source, https://github.com/ElinaFF/PICO
8
+ Author-email: Elina Francovic-Fontaine <elina.francovic-fontaine.1@ulaval.ca>
9
+ License-File: LICENSE
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Requires-Python: <3.13,>=3.8
14
+ Requires-Dist: coloredlogs
15
+ Requires-Dist: dash
16
+ Requires-Dist: dash-bio
17
+ Requires-Dist: dash-bootstrap-components
18
+ Requires-Dist: dash-core-components
19
+ Requires-Dist: dash-cytoscape
20
+ Requires-Dist: dash-html-components
21
+ Requires-Dist: dash-interactive-graphviz
22
+ Requires-Dist: dash-renderer
23
+ Requires-Dist: dash-table
24
+ Requires-Dist: matplotlib
25
+ Requires-Dist: numba
26
+ Requires-Dist: numpy<2
27
+ Requires-Dist: openpyxl
28
+ Requires-Dist: pandas
29
+ Requires-Dist: plotly
30
+ Requires-Dist: pyscm-ml>=1.1.2
31
+ Requires-Dist: randomscm>=0.1.2
32
+ Requires-Dist: rich
33
+ Requires-Dist: scikit-learn>1.4
34
+ Requires-Dist: scipy
35
+ Requires-Dist: typer
36
+ Requires-Dist: umap-learn
37
+ Provides-Extra: dev
38
+ Requires-Dist: dash[testing]; extra == 'dev'
39
+ Requires-Dist: pytest; extra == 'dev'
40
+ Description-Content-Type: text/markdown
41
+
42
+ # PICO
43
+ Pipeline for Interpretable Classification on Omics
44
+
45
+ ## Description
46
+ The PICO is a tool to apply machine learning algorithms to omics datasets. The goal is to extract the most important features because they are potential novel biomarkers.
47
+ The interface is made to be easy to use and intuitive even for those with small to nonexistant experience in programming and AI.
48
+
49
+ More generally, it is a tool to apply interpretable machine learning algorithms to tabular data. It focuses on analyzing the features selected by the models.
50
+
51
+ ## The documentation
52
+ You can find the documentation [here](https://elinaff.github.io/PICO/).
53
+ It explains how to use PICO but also how it works.
54
+
55
+ ## Authors and contributors
56
+ - [Élina Francovic-Fontaine](https://github.com/ElinaFF)
57
+ - [Vincent Primpied](https://github.com/le-smog)
58
+ - [Vincent Vilain](https://github.com/VincentVilain)
59
+ - [Gabriel Leclerc](https://github.com/PandaGab)
60
+ - [Thierry Moszkowicz](https://github.com/ThierryAM)
61
+ - [Mathieu Bazinet](https://github.com/MathieuBazinet)
62
+ - [Thibaud Godon](https://github.com/thibgo)
63
+ - [Pier-Luc Plante](https://github.com/plpla)
64
+ - [Baptiste Bauvin](https://github.com/babau1)
65
+ - [Louis-Philippe Vignault](https://scholar.google.com/citations?user=QXye6lEAAAAJ&hl=fr)
66
+
67
+ ## Disclaimer
68
+ PICO is still in development. If you encounter any issue or have any suggestion, feel free to contact us at [elina.francovic-fontaine.1@ulaval.ca](mailto:elina.francovic-fontaine.1@ulaval.ca). Or you can leave an issue [here](https://github.com/ElinaFF/PICO/issues) with the tag "bug".
69
+
70
+ ## For developers
71
+
72
+ ### Setup
73
+
74
+ Clone the project with :
75
+ ```shell
76
+ git clone https://github.com/ElinaFF/PICO.git
77
+ ```
78
+
79
+ It is recommanded to setup a virtual environment. When it's done, use your isolated python and install `pico` package locally and in editable mode with :
80
+ ```shell
81
+ python -m pip install -e ".[dev]"
82
+ ```
83
+
84
+ ## License
85
+ <a href="https://github.com/ElinaFF/PICO">Pipeline for Interpretable Classification on Omics (PICO)</a> © 2025 by <a href="https://creativecommons.org">Elina Francovic-Fontaine</a> is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a>
86
+
@@ -0,0 +1,52 @@
1
+ pico/__init__.py,sha256=PIFwmFSIbz4T6kPrvSr90M8Dj7WCndTv1oph5kCGO_U,43
2
+ pico/__main__.py,sha256=2pEnS7f2JU7U3_GHXrmNWAIzXhPqN27zSHCZT6Ij4KE,33
3
+ pico/cli/__init__.py,sha256=0m1GuS3w88DNt0kc72N_ugOxa5LH4ibYqrw92To5qWg,53
4
+ pico/cli/main.py,sha256=1crrzeupD3Cb6QgW24nbDzMUB6Rt_nVrwq6SvQVSK04,3368
5
+ pico/conf/SupportedCV.py,sha256=jJftCmsXwZWQOfshCcjxHYd1YFgx2z4qvYuDy82Y0pA,402
6
+ pico/conf/SupportedModels.py,sha256=YTVAd8-ltYFqXGQwEIvL-P5gNCr7TkCkZYhDS3cU1cs,2766
7
+ pico/conf/algo_sklearn.json,sha256=gbX8EJ-f7IrpgmbkH0BqwgONn_TFtbMsK4k33Xcxr8E,664
8
+ pico/conf/parameters.py,sha256=s4gqg4rZlb-iVi7GC2yUmSwcYnQQlAWZsqhK-EuupAM,398
9
+ pico/domain/ClassificationDesign.py,sha256=VED0xqONvnxFFl-Y6b6fVclqkIa7eXvpnmwL98xoyCo,4740
10
+ pico/domain/Controller.py,sha256=xoJ1q0C4mWKVIpVhsbSsm6g1aRGyvxRAxbzJCiQT0Yg,16103
11
+ pico/domain/DataMatrix.py,sha256=ABMFbbLnZ2Nj4TCNyHs9kwySBSWm5AW78uzLRVS5jA0,5720
12
+ pico/domain/ExperimentDTO.py,sha256=hkFyBTD7gfkolO-9uGNyqlEi5st2RnT8yrGEflTiqXI,691
13
+ pico/domain/MetaData.py,sha256=cGqdbrCyr2T4tSjfs63CJEa4PL3F_jnig6a1dTa7VhQ,8967
14
+ pico/domain/MetaboExperiment.py,sha256=io0Jeu-Hx5KT_CCpwgo_Xmz5lTaWoTCaEDjeLX_fOHU,30808
15
+ pico/domain/MetaboModel.py,sha256=Re1gffN_it8n2N5i7l-Ag4ZZiyal1LzKoSz6baBsMWc,1784
16
+ pico/domain/ModelFactory.py,sha256=Y2KpeZVEgfhU-1SA9_e3GmwGGhSLrqI50qeKrf_B2yo,1735
17
+ pico/domain/Results.py,sha256=4JY9BaGxIT35cPQkGTCBlXN9jGv_T2rpSuVWWBMGowQ,23988
18
+ pico/domain/SplitGroup.py,sha256=kTjvAZ_Q3osqKO2peq6DNpIHtGEsXNmEhLL_geJXgsM,11388
19
+ pico/domain/__init__.py,sha256=7WLgTGrvDDxiFyRTLXvP707E47rYnz-2VrK_MI8PffQ,343
20
+ pico/domain/dumps/metadata/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ pico/domain/dumps/splits/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ pico/service/DataFormat.py,sha256=nzC_e9OI7ST6WSxVRWOx-rawUikoiYyW24oGIEQuEWo,8136
23
+ pico/service/ExperimentDesign.py,sha256=A81A0gP6Z0WmLEhjwEtAKqjgFWfwHyksw_vdHvqmS6Q,685
24
+ pico/service/LoggerConfig.py,sha256=i3_mutoK9NNj97DePF33YQk7PS2BbsT79zwd7hon86Q,5524
25
+ pico/service/Plots.py,sha256=KHwNhYPe1-zubPI-4BSJ3nCp2B0M6ASyg6sznnBA1XI,16756
26
+ pico/service/RunMLalgo.py,sha256=ujpGYMszxoLvWzCsg0nctKnA7UebPeeg3Re6rm477Ks,3450
27
+ pico/service/SamplesPairing.py,sha256=3_AS1yl90v420wynwxDbw010ziqwGzAwneWmHIYRpzE,16121
28
+ pico/service/Utils.py,sha256=RHGSCB3vfGnvaQXi38WzTtKmPvD_KFnzSd-T66oDudg,18973
29
+ pico/service/__init__.py,sha256=M5R-zD4k2ow1Z8cRJzHFEg6Fu3Aopt8E65wIgWrlf5Y,228
30
+ pico/ui/__init__.py,sha256=8G-rLhbTJsxt8QMNfYPDILcn9K1Psojh3Vq-lntPyS4,21
31
+ pico/ui/app.py,sha256=UqMeDGM6a_UYnQzkEswH8bO2-p0u7kGHVMF_IPXsUz4,5565
32
+ pico/ui/assets/000_Stylesheet.css,sha256=saRlyjSuwxFeE29eATw6cDRruHvlmNfAjl6R_Iwkgls,6530
33
+ pico/ui/assets/DecisionTree.png,sha256=JNVvyvjOuAka4e_ic7njqUrhOZe20RFovUQribFXCAA,203270
34
+ pico/ui/assets/Figure_home_wider.png,sha256=Tv424vLbQ7Fjtw8jO8ffyrLDRnvLyQ-Da_7PeRaoBrA,60314
35
+ pico/ui/assets/favicon.ico,sha256=BwmZGm94ENHB2CPfb4AKTDqH286JLSHPVP04_LTBzo8,8532
36
+ pico/ui/assets/help_icon.png,sha256=jhVapWHX6nZ7qwEdwp9WC7LW-kkWVaWA_08SCbB2s84,10134
37
+ pico/ui/assets/help_icon.svg,sha256=l1z39WE4nG5duOb30Tl89hK520yzrt5E5UOAWJqLvuo,755
38
+ pico/ui/assets/update_figure_steps_MeDIC_4.svg,sha256=2wDhHeM5sBjmBLCD7KTjKmFTVjqV5x6y20vvXSDqBUI,9721
39
+ pico/ui/tabs/AggregatedResultsTab.py,sha256=xiaBhLYToBK72wGaRokOXpj6nmROgElK0whK-ITQo58,15108
40
+ pico/ui/tabs/InfoTab.py,sha256=CWldI9f3Ll2gZ7dW80sz2y8L3ZCslUiXGN_TiRHiC0Q,19786
41
+ pico/ui/tabs/InterpretTab.py,sha256=yJeNDtBOiY2FINVdxkXVKbmVf5b2wJ6E-GchNfShMhw,543
42
+ pico/ui/tabs/MLTab.py,sha256=Oqnc8_4-eu-qQhzcX3uuuqtmovqkGVf83vSgCDV1JII,21106
43
+ pico/ui/tabs/MetaTab.py,sha256=g7fELzDs5VHj_1FfxQX1s6mznI_dKwSmIBY8cTIXM08,537
44
+ pico/ui/tabs/ResultsTab.py,sha256=sJS3w9Kgvqo6rBlYsUl7pvO8ZS3CbMvClDCBhmsZNfk,39867
45
+ pico/ui/tabs/SplitsTab.py,sha256=ybIY09foDoHyR25o6y8iEn5UHyd6SOy0eIXuvsdKh_0,52517
46
+ pico/ui/tabs/__init__.py,sha256=snlgOGrMRN9hgg7jXFM2g7TaoIwA1ufkZxdI9DOLNxY,216
47
+ pico/ui/tabs/utils.py,sha256=BTDgNQV1FqCEKqkeIjr2Zcee6FDHZcHL9EY5NdLqpNo,3606
48
+ pico_ml-2.0.0.dist-info/METADATA,sha256=AmRVytsVhQMpzH7wbvzeGeS2mI5aj4UFhRRghwuoMXc,3503
49
+ pico_ml-2.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
50
+ pico_ml-2.0.0.dist-info/entry_points.txt,sha256=uSuwbxFEWXXiwg-TQsAEwcHshBOo-0hj1AWupayX46s,43
51
+ pico_ml-2.0.0.dist-info/licenses/LICENSE,sha256=E0mkthSEkrRPYp5k7tZ2YS4jT-moOeTzsnfBSCyISfE,20849
52
+ pico_ml-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pico = pico.cli.main:app