marsilea 0.3.6__tar.gz → 0.4.0__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.
- {marsilea-0.3.6 → marsilea-0.4.0}/PKG-INFO +1 -1
- {marsilea-0.3.6 → marsilea-0.4.0}/pyproject.toml +11 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/__init__.py +1 -1
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/base.py +7 -5
- marsilea-0.3.6/app/.gitignore +0 -2
- marsilea-0.3.6/app/.streamlit/pages.toml +0 -24
- marsilea-0.3.6/app/Dockerfile +0 -20
- marsilea-0.3.6/app/Home.py +0 -102
- marsilea-0.3.6/app/README.md +0 -17
- marsilea-0.3.6/app/components/__init__.py +0 -0
- marsilea-0.3.6/app/components/cmap_selector/__init__.py +0 -1
- marsilea-0.3.6/app/components/cmap_selector/selector.py +0 -176
- marsilea-0.3.6/app/components/data_input.py +0 -154
- marsilea-0.3.6/app/components/example_download.py +0 -71
- marsilea-0.3.6/app/components/initialize.py +0 -126
- marsilea-0.3.6/app/components/main_plots.py +0 -289
- marsilea-0.3.6/app/components/resource.py +0 -131
- marsilea-0.3.6/app/components/saver.py +0 -45
- marsilea-0.3.6/app/components/side_plots.py +0 -880
- marsilea-0.3.6/app/components/state.py +0 -158
- marsilea-0.3.6/app/components/transformation.py +0 -93
- marsilea-0.3.6/app/components/upset_example.csv +0 -1000
- marsilea-0.3.6/app/img/V1.mp4 +0 -0
- marsilea-0.3.6/app/img/V2.mp4 +0 -0
- marsilea-0.3.6/app/img/annolabels.png +0 -0
- marsilea-0.3.6/app/img/bar.png +0 -0
- marsilea-0.3.6/app/img/box.png +0 -0
- marsilea-0.3.6/app/img/boxen.png +0 -0
- marsilea-0.3.6/app/img/colors.png +0 -0
- marsilea-0.3.6/app/img/dendrogram.svg +0 -102
- marsilea-0.3.6/app/img/favicon.png +0 -0
- marsilea-0.3.6/app/img/favicon.svg +0 -61
- marsilea-0.3.6/app/img/heatmap.png +0 -0
- marsilea-0.3.6/app/img/heatmap.svg +0 -191
- marsilea-0.3.6/app/img/logo.png +0 -0
- marsilea-0.3.6/app/img/mark_map.png +0 -0
- marsilea-0.3.6/app/img/mark_map.svg +0 -112
- marsilea-0.3.6/app/img/point.png +0 -0
- marsilea-0.3.6/app/img/sized_heatmap.png +0 -0
- marsilea-0.3.6/app/img/sized_heatmap.svg +0 -357
- marsilea-0.3.6/app/img/sized_onlymap.png +0 -0
- marsilea-0.3.6/app/img/strip.png +0 -0
- marsilea-0.3.6/app/img/swarm.png +0 -0
- marsilea-0.3.6/app/img/violin.png +0 -0
- marsilea-0.3.6/app/img/x-layout.png +0 -0
- marsilea-0.3.6/app/pages/01 Simple_Heatmap.py +0 -243
- marsilea-0.3.6/app/pages/02 Cross-Layout_Heatmap.py +0 -239
- marsilea-0.3.6/app/pages/03 Upsetplot.py +0 -225
- marsilea-0.3.6/app/pages/04 Manual.py +0 -60
- marsilea-0.3.6/app/requirements.txt +0 -10
- marsilea-0.3.6/app/script/heatmap_data.py +0 -25
- marsilea-0.3.6/app/script/plot_layer_example_images.py +0 -32
- marsilea-0.3.6/app/script/plotter_example_images.py +0 -116
- marsilea-0.3.6/app/set_data_memberships.txt +0 -4
- marsilea-0.3.6/app/test.xlsx +0 -0
- marsilea-0.3.6/app/test_data/Stats_plot.txt +0 -10
- marsilea-0.3.6/app/test_data/example_data.txt +0 -20
- marsilea-0.3.6/app/test_data/number.txt +0 -20
- marsilea-0.3.6/app/test_data/row_labels.txt +0 -20
- marsilea-0.3.6/app/test_data/set_data_memberships.txt +0 -4
- marsilea-0.3.6/app/upset.xlsx +0 -0
- marsilea-0.3.6/data/IMDB.csv +0 -1000
- marsilea-0.3.6/data/PATIENT_DATA_oncoprint.tsv +0 -138
- marsilea-0.3.6/data/pbmc3k.h5ad +0 -0
- marsilea-0.3.6/docs/Makefile +0 -30
- marsilea-0.3.6/docs/README.md +0 -57
- marsilea-0.3.6/docs/examples/.gitignore +0 -2
- marsilea-0.3.6/docs/examples/Basics/README.rst +0 -2
- marsilea-0.3.6/docs/examples/Basics/plot_adv_heatmap.py +0 -25
- marsilea-0.3.6/docs/examples/Basics/plot_heatmap.py +0 -21
- marsilea-0.3.6/docs/examples/Basics/plot_stacked_bar.py +0 -44
- marsilea-0.3.6/docs/examples/Basics/plot_two_heatmap.py +0 -24
- marsilea-0.3.6/docs/examples/Gallery/README.rst +0 -4
- marsilea-0.3.6/docs/examples/Gallery/plot_arc_diagram.py +0 -77
- marsilea-0.3.6/docs/examples/Gallery/plot_available_plotters.py +0 -188
- marsilea-0.3.6/docs/examples/Gallery/plot_bivariate_dist.py +0 -94
- marsilea-0.3.6/docs/examples/Gallery/plot_mouse_embryo.py +0 -122
- marsilea-0.3.6/docs/examples/Gallery/plot_oil_well.py +0 -122
- marsilea-0.3.6/docs/examples/Gallery/plot_oncoprint.py +0 -124
- marsilea-0.3.6/docs/examples/Gallery/plot_pbmc3k.py +0 -99
- marsilea-0.3.6/docs/examples/Gallery/plot_sc_multiomics.py +0 -140
- marsilea-0.3.6/docs/examples/Gallery/plot_seqalign.py +0 -129
- marsilea-0.3.6/docs/examples/Gallery/plot_upset.py +0 -72
- marsilea-0.3.6/docs/examples/Plotters/README.rst +0 -4
- marsilea-0.3.6/docs/examples/Plotters/plot_anno_labels.py +0 -21
- marsilea-0.3.6/docs/examples/Plotters/plot_arc.py +0 -19
- marsilea-0.3.6/docs/examples/Plotters/plot_area.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_bar.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_box.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_boxen.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_center_bar.py +0 -19
- marsilea-0.3.6/docs/examples/Plotters/plot_chunk.py +0 -20
- marsilea-0.3.6/docs/examples/Plotters/plot_color_mesh.py +0 -20
- marsilea-0.3.6/docs/examples/Plotters/plot_colors.py +0 -20
- marsilea-0.3.6/docs/examples/Plotters/plot_fixed_chunk.py +0 -28
- marsilea-0.3.6/docs/examples/Plotters/plot_labels.py +0 -20
- marsilea-0.3.6/docs/examples/Plotters/plot_marker_mesh.py +0 -19
- marsilea-0.3.6/docs/examples/Plotters/plot_numbers.py +0 -17
- marsilea-0.3.6/docs/examples/Plotters/plot_point.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_seq_logo.py +0 -20
- marsilea-0.3.6/docs/examples/Plotters/plot_sized_mesh.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_stack_bar.py +0 -19
- marsilea-0.3.6/docs/examples/Plotters/plot_strip.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_swarm.py +0 -18
- marsilea-0.3.6/docs/examples/Plotters/plot_text_mesh.py +0 -19
- marsilea-0.3.6/docs/examples/Plotters/plot_title.py +0 -20
- marsilea-0.3.6/docs/examples/Plotters/plot_violin.py +0 -18
- marsilea-0.3.6/docs/examples/README.rst +0 -2
- marsilea-0.3.6/docs/how_to/README.rst +0 -4
- marsilea-0.3.6/docs/how_to/customization/README.rst +0 -8
- marsilea-0.3.6/docs/how_to/customization/plot_add_border.py +0 -31
- marsilea-0.3.6/docs/how_to/customization/plot_get_axes.py +0 -42
- marsilea-0.3.6/docs/how_to/dendrogram/README.rst +0 -2
- marsilea-0.3.6/docs/how_to/dendrogram/plot_color_dendrogram.py +0 -31
- marsilea-0.3.6/docs/how_to/dendrogram/plot_dendrogram_control.py +0 -19
- marsilea-0.3.6/docs/how_to/layout/README.rst +0 -3
- marsilea-0.3.6/docs/how_to/layout/plot_adjust_figure_size.py +0 -58
- marsilea-0.3.6/docs/how_to/layout/plot_labeling.py +0 -45
- marsilea-0.3.6/docs/how_to/layout/plot_margin.py +0 -28
- marsilea-0.3.6/docs/how_to/legends/README.rst +0 -7
- marsilea-0.3.6/docs/how_to/legends/plot_disable_legend.py +0 -29
- marsilea-0.3.6/docs/how_to/legends/plot_legends.py +0 -23
- marsilea-0.3.6/docs/how_to/save/README.rst +0 -5
- marsilea-0.3.6/docs/how_to/save/plot.pdf +0 -0
- marsilea-0.3.6/docs/how_to/save/plot.png +0 -0
- marsilea-0.3.6/docs/how_to/save/plot_save.py +0 -29
- marsilea-0.3.6/docs/make.bat +0 -35
- marsilea-0.3.6/docs/requirements.txt +0 -10
- marsilea-0.3.6/docs/source/.gitignore +0 -4
- marsilea-0.3.6/docs/source/_static/css/custom.css +0 -57
- marsilea-0.3.6/docs/source/_templates/autosummary.rst +0 -15
- marsilea-0.3.6/docs/source/api/index.rst +0 -308
- marsilea-0.3.6/docs/source/conf.py +0 -163
- marsilea-0.3.6/docs/source/img/code_example.png +0 -0
- marsilea-0.3.6/docs/source/img/cover.png +0 -0
- marsilea-0.3.6/docs/source/img/marsilea-renderplan-logic.drawio.svg +0 -4
- marsilea-0.3.6/docs/source/index.rst +0 -97
- marsilea-0.3.6/docs/source/installation.rst +0 -14
- marsilea-0.3.6/docs/source/sg_execution_times.rst +0 -175
- marsilea-0.3.6/docs/source/tutorial/axes-level.rst +0 -73
- marsilea-0.3.6/docs/source/tutorial/concatenation.rst +0 -90
- marsilea-0.3.6/docs/source/tutorial/heatmap.rst +0 -187
- marsilea-0.3.6/docs/source/tutorial/index.rst +0 -142
- marsilea-0.3.6/docs/source/tutorial/intro.rst +0 -181
- marsilea-0.3.6/docs/source/tutorial/intro2.rst +0 -146
- marsilea-0.3.6/docs/source/tutorial/new_renderplan.rst +0 -162
- marsilea-0.3.6/docs/source/tutorial/upset.rst +0 -125
- marsilea-0.3.6/img/Logo(1).zip +0 -0
- marsilea-0.3.6/img/Logo.zip +0 -0
- marsilea-0.3.6/img/banner-blue.jpg +0 -0
- marsilea-0.3.6/img/banner-dark-gradient.jpg +0 -0
- marsilea-0.3.6/img/banner-dark.jpg +0 -0
- marsilea-0.3.6/img/banner-rice-white.jpg +0 -0
- marsilea-0.3.6/img/banner-white.jpg +0 -0
- marsilea-0.3.6/img/logo/Logo/.DS_Store +0 -0
- marsilea-0.3.6/img/logo/Logo/Logo.svg +0 -27
- marsilea-0.3.6/img/logo/Logo/logo.png +0 -0
- marsilea-0.3.6/img/logo/Logo//346/265/205/350/223/235/346/270/220/345/217/230.jpg +0 -0
- marsilea-0.3.6/img/logo/Logo//346/267/261/350/211/262/350/203/214/346/231/257.jpg +0 -0
- marsilea-0.3.6/img/logo/Logo//347/261/263/350/211/262.jpg +0 -0
- marsilea-0.3.6/img/logo/Logo//347/272/257/347/231/275.jpg +0 -0
- marsilea-0.3.6/img/logo/Logo//350/247/222/345/272/246/346/270/220/345/217/230.jpg +0 -0
- marsilea-0.3.6/img/logo/__MACOSX/Logo/._.DS_Store +0 -0
- marsilea-0.3.6/img/logo.png +0 -0
- marsilea-0.3.6/img/logo.svg +0 -27
- marsilea-0.3.6/img/publication/API-interface.png +0 -0
- marsilea-0.3.6/img/publication/Snap-1.png +0 -0
- marsilea-0.3.6/img/publication/Snap-2.png +0 -0
- marsilea-0.3.6/img/publication/Snap-3.png +0 -0
- marsilea-0.3.6/img/publication/Stacked bar.png +0 -0
- marsilea-0.3.6/img/publication/bivar_kde.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-canvas-size-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-canvas-size.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-location-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-location.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-pad-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-pad.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-plotter-size-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-plotter-size.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-plotter-type-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-change-plotter-type.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-basic.png +0 -0
- marsilea-0.3.6/img/publication/layout-skeleton-step1.png +0 -0
- marsilea-0.3.6/img/publication/layout-skeleton-step2.png +0 -0
- marsilea-0.3.6/img/publication/layout-skeleton-step3.png +0 -0
- marsilea-0.3.6/img/publication/layout-skeleton-step4.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-1a-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-1a.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-1b-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-1b.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-2-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-2.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-3-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-3.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-4-code.png +0 -0
- marsilea-0.3.6/img/publication/layout-step-4.png +0 -0
- marsilea-0.3.6/img/publication/oncoprint.png +0 -0
- marsilea-0.3.6/img/publication/upset.png +0 -0
- marsilea-0.3.6/img/publication/web-app-screenshot-1.png +0 -0
- marsilea-0.3.6/img/publication/web-app-screenshot-2.png +0 -0
- marsilea-0.3.6/readthedocs.yaml +0 -12
- marsilea-0.3.6/scripts/benchmark/marsilea/marsilea_cooking_oils_base.py +0 -97
- marsilea-0.3.6/scripts/benchmark/marsilea/marsilea_cooking_oils_v1.py +0 -105
- marsilea-0.3.6/scripts/benchmark/marsilea/marsilea_cooking_oils_v2.py +0 -118
- marsilea-0.3.6/scripts/benchmark/marsilea_vs_matplotlib.png +0 -0
- marsilea-0.3.6/scripts/benchmark/marsilea_vs_matplotlib.svg +0 -1846
- marsilea-0.3.6/scripts/benchmark/matplotlib/matplotlib_cooking_oils_base.py +0 -180
- marsilea-0.3.6/scripts/benchmark/matplotlib/matplotlib_cooking_oils_v1.py +0 -230
- marsilea-0.3.6/scripts/benchmark/matplotlib/matplotlib_cooking_oils_v2.py +0 -220
- marsilea-0.3.6/scripts/benchmark/result.py +0 -168
- marsilea-0.3.6/scripts/example_figures/arc-diagrams.py +0 -164
- marsilea-0.3.6/scripts/example_figures/cooking_oils.py +0 -122
- marsilea-0.3.6/scripts/example_figures/mouse_map.py +0 -157
- marsilea-0.3.6/scripts/example_figures/msa.py +0 -148
- marsilea-0.3.6/scripts/example_figures/oncoprint.py +0 -143
- marsilea-0.3.6/scripts/example_figures/single-heatmap.py +0 -101
- marsilea-0.3.6/scripts/example_figures/tracks.py +0 -141
- marsilea-0.3.6/scripts/example_figures/two-heatmap.py +0 -141
- marsilea-0.3.6/scripts/example_figures/upset.py +0 -56
- marsilea-0.3.6/scripts/example_figures/violin_swarm.py +0 -71
- marsilea-0.3.6/scripts/publication/arc_diagram.svg +0 -5974
- marsilea-0.3.6/scripts/publication/bivariate_dist.svg +0 -32
- marsilea-0.3.6/scripts/publication/mouse_embryo.svg +0 -168201
- marsilea-0.3.6/tests/test_data_input.py +0 -63
- marsilea-0.3.6/tests/test_deform.py +0 -92
- marsilea-0.3.6/tests/test_mesh.py +0 -30
- {marsilea-0.3.6 → marsilea-0.4.0}/.github/workflows/build.yaml +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/.github/workflows/deploy_streamlit.yaml +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/.github/workflows/lint.yaml +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/.gitignore +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/.streamlit/config.toml +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/CITATION.cff +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/LICENSE +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/README.md +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/setup.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/_api.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/_deform.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/dataset.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/dendrogram.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/exceptions.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/heatmap.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/layers.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/layout.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/__init__.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/_images.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/_seaborn.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/_utils.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/arc.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/area.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/bar.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/base.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/bio.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/mesh.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/plotter/text.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/upset.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/marsilea/utils.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/oncoprinter/__init__.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/oncoprinter/core.py +0 -0
- {marsilea-0.3.6 → marsilea-0.4.0}/src/oncoprinter/preset.py +0 -0
|
@@ -67,21 +67,22 @@ class LegendMaker:
|
|
|
67
67
|
"""
|
|
68
68
|
raise NotImplementedError("Should be implemented in derived class")
|
|
69
69
|
|
|
70
|
-
def custom_legend(self,
|
|
70
|
+
def custom_legend(self, legend_func, name=None):
|
|
71
71
|
"""Add a custom legend
|
|
72
72
|
|
|
73
73
|
Parameters
|
|
74
74
|
----------
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
A legend object
|
|
76
|
+
legend_func : Callable
|
|
77
|
+
A function that return the legend object,
|
|
78
|
+
the legend must be an `Artist <matplotlib.artist.Artists>`
|
|
78
79
|
name : str, optional
|
|
79
80
|
The name of the legend
|
|
80
81
|
|
|
81
82
|
"""
|
|
82
83
|
if name is None:
|
|
83
84
|
name = str(uuid4())
|
|
84
|
-
self._user_legends[name] =
|
|
85
|
+
self._user_legends[name] = legend_func
|
|
85
86
|
|
|
86
87
|
def add_legends(
|
|
87
88
|
self,
|
|
@@ -159,7 +160,8 @@ class LegendMaker:
|
|
|
159
160
|
self.layout.remove_legend_ax()
|
|
160
161
|
|
|
161
162
|
def _legends_drawer(self, ax):
|
|
162
|
-
|
|
163
|
+
user_legends = {k: [v()] for k, v in self._user_legends.items()}
|
|
164
|
+
legends = {**self.get_legends(), **user_legends}
|
|
163
165
|
|
|
164
166
|
# force to remove all legends before drawing
|
|
165
167
|
# In case some legends are added implicitly
|
marsilea-0.3.6/app/.gitignore
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
[[pages]]
|
|
2
|
-
path = "index.py"
|
|
3
|
-
name = "Home"
|
|
4
|
-
icon = "🏠"
|
|
5
|
-
|
|
6
|
-
#[[pages]]
|
|
7
|
-
#path = "other_pages/page2.py"
|
|
8
|
-
#name = "Page 2"
|
|
9
|
-
#icon = ":books:"
|
|
10
|
-
#
|
|
11
|
-
#[[pages]]
|
|
12
|
-
#name = "My second"
|
|
13
|
-
#icon = "🎈️"
|
|
14
|
-
#is_section = true
|
|
15
|
-
#
|
|
16
|
-
## Pages after an `is_section = true` will be indented
|
|
17
|
-
#[[pages]]
|
|
18
|
-
#name = "Another page"
|
|
19
|
-
#icon = "💪"
|
|
20
|
-
#
|
|
21
|
-
## Unless you explicitly say in_section = false`
|
|
22
|
-
#[[pages]]
|
|
23
|
-
#name = "Not in a section"
|
|
24
|
-
#in_section = false
|
marsilea-0.3.6/app/Dockerfile
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Use the official Python image as the base image
|
|
2
|
-
FROM python:3.10
|
|
3
|
-
|
|
4
|
-
# Set the working directory in the container
|
|
5
|
-
WORKDIR /app
|
|
6
|
-
|
|
7
|
-
# Copy the requirements.txt file into the container
|
|
8
|
-
COPY requirements.txt .
|
|
9
|
-
|
|
10
|
-
# Install any dependencies
|
|
11
|
-
RUN pip install --no-cache-dir -r requirements.txt
|
|
12
|
-
|
|
13
|
-
# Copy the content of the local src directory to the working directory
|
|
14
|
-
COPY . .
|
|
15
|
-
|
|
16
|
-
# Expose the port that Streamlit will run on
|
|
17
|
-
EXPOSE 8501
|
|
18
|
-
|
|
19
|
-
# Command to run the application when the container starts
|
|
20
|
-
CMD ["streamlit", "run", "Home.py", "--server.port=8501", "--server.address=0.0.0.0"]
|
marsilea-0.3.6/app/Home.py
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import streamlit as st
|
|
2
|
-
from components.initialize import init_page, inject_css
|
|
3
|
-
|
|
4
|
-
init_page("Marsilea")
|
|
5
|
-
inject_css()
|
|
6
|
-
|
|
7
|
-
banner, title = st.columns([1, 1.5])
|
|
8
|
-
with banner:
|
|
9
|
-
st.markdown(
|
|
10
|
-
'<video controls width="250" autoplay="true" muted="true" '
|
|
11
|
-
'loop="true" playsinline style="pointer-events: none;">'
|
|
12
|
-
'<source src="https://raw.githubusercontent.com/Marsilea-viz/'
|
|
13
|
-
'marsilea/main/app/img/V1.mp4" '
|
|
14
|
-
'type="video/mp4" /></video>',
|
|
15
|
-
unsafe_allow_html=True,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
with title:
|
|
19
|
-
st.title("Marsilea")
|
|
20
|
-
st.subheader("Create :blue[composable] visualization")
|
|
21
|
-
st.text("")
|
|
22
|
-
st.markdown(
|
|
23
|
-
"*By [Mr.Milk](https://github.com/Mr-Milk) and "
|
|
24
|
-
"[Squirtle692](https://github.com/Squirtle692)*"
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
st.markdown("---")
|
|
28
|
-
|
|
29
|
-
st.subheader("About")
|
|
30
|
-
st.markdown(
|
|
31
|
-
"Marsilea is a tool for you to create composable visualization. "
|
|
32
|
-
"A single-plot visualization can be combined with other plots to capture"
|
|
33
|
-
"the full picture of your data."
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
st.markdown("---")
|
|
37
|
-
|
|
38
|
-
st.subheader("Online Toolbox")
|
|
39
|
-
st.text("")
|
|
40
|
-
t1, t2, t3 = st.columns(3)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def tools(name, img, page, size=150):
|
|
44
|
-
st.markdown(
|
|
45
|
-
f'<div style="display: flex; justify-content: center; '
|
|
46
|
-
f'align-items: center; flex-direction: column;">'
|
|
47
|
-
f'<p style="font-weight: 600;">{name}</p>'
|
|
48
|
-
f'<a target="_self" href="{page}">'
|
|
49
|
-
f'<img style="width: {size}px;" src="{img}"></a>'
|
|
50
|
-
f"</div>",
|
|
51
|
-
unsafe_allow_html=True,
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
with t1:
|
|
56
|
-
tools(
|
|
57
|
-
"Simple Heatmap",
|
|
58
|
-
"https://marsilea.readthedocs.io/en/latest/" "_images/concatenation-1.png",
|
|
59
|
-
page="/Simple_Heatmap",
|
|
60
|
-
size=130,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
with t2:
|
|
64
|
-
tools(
|
|
65
|
-
"Complex Heatmap",
|
|
66
|
-
"https://marsilea.readthedocs.io/en/latest/"
|
|
67
|
-
"_images/sphx_glr_plot_pbmc3k_thumb.png",
|
|
68
|
-
page="X-Layout_Heatmap",
|
|
69
|
-
size=200,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
with t3:
|
|
73
|
-
tools(
|
|
74
|
-
"Upset Plot",
|
|
75
|
-
"https://marsilea.readthedocs.io/en/latest/"
|
|
76
|
-
"_images/sphx_glr_plot_upset_thumb.png",
|
|
77
|
-
page="/Upsetplot",
|
|
78
|
-
size=220,
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
st.markdown("---")
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
st.subheader("Python Package")
|
|
85
|
-
s1, s2, s3 = st.columns([1, 4, 5])
|
|
86
|
-
with s1:
|
|
87
|
-
st.image(
|
|
88
|
-
"https://cdn3.iconfinder.com/data/icons/logos-and-brands-adobe/512/267_Python-512.png",
|
|
89
|
-
width=50,
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
with s2:
|
|
93
|
-
st.markdown(
|
|
94
|
-
"Familiar with Python? Try our Python package "
|
|
95
|
-
"that can be easily integrated into your data pipeline!"
|
|
96
|
-
)
|
|
97
|
-
with s3:
|
|
98
|
-
st.code("pip install marsilea", language="bash")
|
|
99
|
-
|
|
100
|
-
st.markdown("---")
|
|
101
|
-
|
|
102
|
-
st.markdown("Copyright © 2024 [Marsilea](https://github.com/Marsilea-viz)")
|
marsilea-0.3.6/app/README.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# How to run the app version of Marsilea
|
|
2
|
-
|
|
3
|
-
## Using Docker
|
|
4
|
-
|
|
5
|
-
### Step 1: Build the image
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
docker build -t marsilea-app .
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
### Step 2: Run the container
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
docker run -p 8501:8501 marsilea-app
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Go to http://localhost:8501 to see the app.
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .selector import ColormapSelector
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import matplotlib as mpl
|
|
2
|
-
import matplotlib.pyplot as plt
|
|
3
|
-
import numpy as np
|
|
4
|
-
import streamlit as st
|
|
5
|
-
from matplotlib.cm import get_cmap
|
|
6
|
-
from matplotlib.colors import (
|
|
7
|
-
LinearSegmentedColormap,
|
|
8
|
-
Normalize,
|
|
9
|
-
CenteredNorm,
|
|
10
|
-
TwoSlopeNorm,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@st.cache_data
|
|
15
|
-
def get_colormap_names():
|
|
16
|
-
cmap_mapper = {}
|
|
17
|
-
for i in mpl.colormaps:
|
|
18
|
-
if not i.endswith("_r"):
|
|
19
|
-
cmap_name = i
|
|
20
|
-
cmap_mapper[i] = cmap_name.capitalize()
|
|
21
|
-
return cmap_mapper
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def get_colormap_images(cmap):
|
|
25
|
-
gradient = np.linspace(0, 1, 256)
|
|
26
|
-
gradient = np.vstack((gradient, gradient))
|
|
27
|
-
|
|
28
|
-
fig = plt.figure(figsize=(6, 0.5), dpi=90)
|
|
29
|
-
ax = fig.add_axes([0, 0, 1, 1])
|
|
30
|
-
ax.imshow(gradient, aspect="auto", cmap=cmap)
|
|
31
|
-
ax.set_axis_off()
|
|
32
|
-
plt.close(fig)
|
|
33
|
-
return fig
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def random_color():
|
|
37
|
-
return "#" + "".join(np.random.choice(list("0123456789ABCDEF"), 6))
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class ColormapSelector:
|
|
41
|
-
def __init__(self, key, default="coolwarm", data_mapping=True):
|
|
42
|
-
cmap_data = get_colormap_names()
|
|
43
|
-
cmap_options = sorted(cmap_data.keys())
|
|
44
|
-
default_index = cmap_options.index(default)
|
|
45
|
-
self.reverse = False
|
|
46
|
-
|
|
47
|
-
st.markdown("**Colormap**")
|
|
48
|
-
|
|
49
|
-
radio_box, rev_box = st.columns(2)
|
|
50
|
-
|
|
51
|
-
with radio_box:
|
|
52
|
-
input_cmap = st.radio(
|
|
53
|
-
label="cmap_input",
|
|
54
|
-
label_visibility="collapsed",
|
|
55
|
-
options=["Preset", "Create New"],
|
|
56
|
-
horizontal=True,
|
|
57
|
-
key=f"{key}-input-cmap",
|
|
58
|
-
)
|
|
59
|
-
with rev_box:
|
|
60
|
-
self.reverse = st.checkbox("Reverse colormap", key=f"{key}-rev-cmap")
|
|
61
|
-
|
|
62
|
-
if input_cmap == "Preset":
|
|
63
|
-
color_box, cmap_box = st.columns(2)
|
|
64
|
-
with color_box:
|
|
65
|
-
cmap = st.selectbox(
|
|
66
|
-
"Select Preset Colormap",
|
|
67
|
-
label_visibility="collapsed",
|
|
68
|
-
key=f"{key}-preset-cmap",
|
|
69
|
-
options=cmap_options,
|
|
70
|
-
index=default_index,
|
|
71
|
-
format_func=lambda v: cmap_data[v],
|
|
72
|
-
help="The preset colormap are illuminated "
|
|
73
|
-
"compensated for best visual effect",
|
|
74
|
-
)
|
|
75
|
-
cmap = get_cmap(cmap)
|
|
76
|
-
if self.reverse:
|
|
77
|
-
cmap = cmap.reversed()
|
|
78
|
-
self.cmap = cmap
|
|
79
|
-
with cmap_box:
|
|
80
|
-
cmap_fig = get_colormap_images(self.cmap)
|
|
81
|
-
st.pyplot(cmap_fig)
|
|
82
|
-
else:
|
|
83
|
-
select_box, cmap_box = st.columns(2)
|
|
84
|
-
with select_box:
|
|
85
|
-
ncolors = st.selectbox(
|
|
86
|
-
label="Colormap Type",
|
|
87
|
-
key=f"{key}-select-gradient",
|
|
88
|
-
label_visibility="collapsed",
|
|
89
|
-
options=["One Gradient", "Two Gradient"],
|
|
90
|
-
)
|
|
91
|
-
_, c_lower, c_center, c_upper = st.columns([4, 1, 1, 1])
|
|
92
|
-
with c_lower:
|
|
93
|
-
lower = st.color_picker(
|
|
94
|
-
label="Lower",
|
|
95
|
-
value="#CB1B45",
|
|
96
|
-
key=f"{key}-lower-cmap-2",
|
|
97
|
-
)
|
|
98
|
-
with c_upper:
|
|
99
|
-
upper = st.color_picker(
|
|
100
|
-
label="Upper",
|
|
101
|
-
value="#7B90D2",
|
|
102
|
-
key=f"{key}-upper-cmap-2",
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
if ncolors == "One Gradient":
|
|
106
|
-
colors = [lower, upper]
|
|
107
|
-
else:
|
|
108
|
-
with c_center:
|
|
109
|
-
center = st.color_picker(
|
|
110
|
-
label="Center",
|
|
111
|
-
value="#BDC0BA",
|
|
112
|
-
key=f"{key}-center-cmap-3",
|
|
113
|
-
)
|
|
114
|
-
colors = [lower, center, upper]
|
|
115
|
-
self.cmap = LinearSegmentedColormap.from_list("user_cmap", colors)
|
|
116
|
-
|
|
117
|
-
if self.reverse:
|
|
118
|
-
self.cmap = self.cmap.reversed()
|
|
119
|
-
|
|
120
|
-
with cmap_box:
|
|
121
|
-
cmap_fig = get_colormap_images(self.cmap)
|
|
122
|
-
st.pyplot(cmap_fig)
|
|
123
|
-
|
|
124
|
-
if data_mapping:
|
|
125
|
-
norm_strategy = st.selectbox(
|
|
126
|
-
"Mapping Strategy",
|
|
127
|
-
key=f"{key}-norm-selector",
|
|
128
|
-
options=["Linear", "Min-Max", "Centered On", "Two Range"],
|
|
129
|
-
)
|
|
130
|
-
self.norm = None
|
|
131
|
-
if norm_strategy == "Min-Max":
|
|
132
|
-
st.caption("Value outside the min/max will be mapped to min/max")
|
|
133
|
-
v1, v2 = st.columns(2)
|
|
134
|
-
with v1:
|
|
135
|
-
vmin = st.number_input("Min", key=f"{key}-norm-vmin")
|
|
136
|
-
with v2:
|
|
137
|
-
vmax = st.number_input("Max", key=f"{key}-norm-vmax")
|
|
138
|
-
self.norm = Normalize(vmin=vmin, vmax=vmax)
|
|
139
|
-
elif norm_strategy == "Centered On":
|
|
140
|
-
st.caption("Center on a specific value and extend symmetrically")
|
|
141
|
-
v1, v2 = st.columns(2)
|
|
142
|
-
with v1:
|
|
143
|
-
vcenter = st.number_input(
|
|
144
|
-
"Center", key=f"{key}-center_norm-vcenter"
|
|
145
|
-
)
|
|
146
|
-
with v2:
|
|
147
|
-
vhalf = st.number_input(
|
|
148
|
-
"Extend",
|
|
149
|
-
min_value=0.0,
|
|
150
|
-
value=1.0,
|
|
151
|
-
key=f"{key}-center_norm-vhalf",
|
|
152
|
-
)
|
|
153
|
-
self.norm = CenteredNorm(vcenter=vcenter, halfrange=vhalf)
|
|
154
|
-
elif norm_strategy == "Two Range":
|
|
155
|
-
st.caption("Map to two range")
|
|
156
|
-
v1, v2, v3 = st.columns(3)
|
|
157
|
-
with v1:
|
|
158
|
-
vmin = st.number_input("Min", value=0.0, key=f"{key}-tsnorm-vmin")
|
|
159
|
-
with v2:
|
|
160
|
-
vcenter = st.number_input(
|
|
161
|
-
"Center", value=vmin + 1, key=f"{key}-tsnorm-vcenter"
|
|
162
|
-
)
|
|
163
|
-
with v3:
|
|
164
|
-
vmax = st.number_input(
|
|
165
|
-
"Max", value=vcenter + 1, key=f"{key}-tsnorm-vmax"
|
|
166
|
-
)
|
|
167
|
-
if not ((vmin < vcenter) and (vcenter < vmax)):
|
|
168
|
-
st.error("Min, Center, Max must be ascending.", icon="📉")
|
|
169
|
-
else:
|
|
170
|
-
self.norm = TwoSlopeNorm(vcenter=vcenter, vmin=vmin, vmax=vmax)
|
|
171
|
-
|
|
172
|
-
def get_cmap(self):
|
|
173
|
-
return self.cmap
|
|
174
|
-
|
|
175
|
-
def get_norm(self):
|
|
176
|
-
return self.norm
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
import numpy as np
|
|
5
|
-
import pandas as pd
|
|
6
|
-
import streamlit as st
|
|
7
|
-
|
|
8
|
-
from openpyxl import load_workbook
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class InputBase:
|
|
12
|
-
sep: str
|
|
13
|
-
user_input: Any
|
|
14
|
-
|
|
15
|
-
def __init__(self, key=None):
|
|
16
|
-
self.key = f"{self.__class__.__name__}-{key}"
|
|
17
|
-
|
|
18
|
-
def parse(self):
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
def seperator(self):
|
|
22
|
-
sep_options = {"Tab (\\t)": "\t", "Comma (,)": ",", "Space (' ')": " "}
|
|
23
|
-
user_sep = st.selectbox("Seperator", key=self.key, options=sep_options.keys())
|
|
24
|
-
self.sep = sep_options[user_sep]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@st.cache_data
|
|
28
|
-
def parse_file(file, header=False, index=False, sheet_name=0):
|
|
29
|
-
index_col = None if not index else 0
|
|
30
|
-
suffix = file.name.split(".")[-1]
|
|
31
|
-
if suffix in ["csv", "txt", "tsv"]:
|
|
32
|
-
header = None if not header else "infer"
|
|
33
|
-
reader = pd.read_csv
|
|
34
|
-
sep = "," if suffix == "csv" else "\t"
|
|
35
|
-
kws = dict(sep=sep, header=header, index_col=index_col)
|
|
36
|
-
else:
|
|
37
|
-
header = None if not header else 0
|
|
38
|
-
reader = pd.read_excel
|
|
39
|
-
kws = dict(header=header, index_col=index_col, sheet_name=sheet_name)
|
|
40
|
-
data = reader(file, **kws)
|
|
41
|
-
return data
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class FileUpload(InputBase):
|
|
45
|
-
def __init__(
|
|
46
|
-
self, key=None, header=False, index=False, use_header=False, use_index=False
|
|
47
|
-
):
|
|
48
|
-
super().__init__(key=key)
|
|
49
|
-
self.header = use_header
|
|
50
|
-
self.index = use_index
|
|
51
|
-
self.user_input = st.file_uploader(
|
|
52
|
-
"Choose a table file",
|
|
53
|
-
key=f"table_reader-{self.key}",
|
|
54
|
-
accept_multiple_files=False,
|
|
55
|
-
label_visibility="collapsed",
|
|
56
|
-
type=["txt", "csv", "xlsx"],
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
if index & header:
|
|
60
|
-
h1, h2 = st.columns(2)
|
|
61
|
-
with h1:
|
|
62
|
-
self.header = self._header_checkbox()
|
|
63
|
-
with h2:
|
|
64
|
-
self.index = self._index_checkbox()
|
|
65
|
-
|
|
66
|
-
elif header:
|
|
67
|
-
self.header = self._header_checkbox()
|
|
68
|
-
|
|
69
|
-
elif index:
|
|
70
|
-
self.index = self._index_checkbox()
|
|
71
|
-
|
|
72
|
-
self.sheet_name = 0
|
|
73
|
-
if self.user_input is not None:
|
|
74
|
-
suffix = self.user_input.name.split(".")[-1]
|
|
75
|
-
if suffix == "xlsx":
|
|
76
|
-
wb = load_workbook(self.user_input, read_only=True, keep_links=False)
|
|
77
|
-
sheetnames = wb.sheetnames
|
|
78
|
-
if len(sheetnames) > 1:
|
|
79
|
-
self.sheet_name = st.selectbox(
|
|
80
|
-
"Please select a sheet", options=sheetnames
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
def _header_checkbox(self):
|
|
84
|
-
return st.checkbox(
|
|
85
|
-
"Use first row as header?",
|
|
86
|
-
value=self.header,
|
|
87
|
-
key=f"select-header-{self.key}",
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
def _index_checkbox(self):
|
|
91
|
-
return st.checkbox(
|
|
92
|
-
"Use first column as row labels?",
|
|
93
|
-
value=self.index,
|
|
94
|
-
key=f"select-index-{self.key}",
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
def _parse_to_df(self):
|
|
98
|
-
if self.user_input is not None:
|
|
99
|
-
return parse_file(
|
|
100
|
-
self.user_input,
|
|
101
|
-
header=self.header,
|
|
102
|
-
index=self.index,
|
|
103
|
-
sheet_name=self.sheet_name,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
def parse(self) -> np.ndarray:
|
|
107
|
-
if self.user_input is not None:
|
|
108
|
-
data = self._parse_to_df()
|
|
109
|
-
if len(data.columns) == 1:
|
|
110
|
-
return data.to_numpy().flatten()
|
|
111
|
-
return data.to_numpy()
|
|
112
|
-
|
|
113
|
-
def parse_parts(self, row_label=True, col_label=True):
|
|
114
|
-
if self.user_input is not None:
|
|
115
|
-
data = parse_file(
|
|
116
|
-
self.user_input,
|
|
117
|
-
header=col_label,
|
|
118
|
-
index=row_label,
|
|
119
|
-
sheet_name=self.sheet_name,
|
|
120
|
-
)
|
|
121
|
-
row = data.index.to_numpy(dtype=str)
|
|
122
|
-
col = data.columns.to_numpy(dtype=str)
|
|
123
|
-
data = data.to_numpy()
|
|
124
|
-
return data, row, col
|
|
125
|
-
|
|
126
|
-
def parse_dataframe(self) -> pd.DataFrame:
|
|
127
|
-
return self._parse_to_df()
|
|
128
|
-
|
|
129
|
-
@property
|
|
130
|
-
def name(self):
|
|
131
|
-
if self.user_input is None:
|
|
132
|
-
return ""
|
|
133
|
-
else:
|
|
134
|
-
return Path(self.user_input.name).stem
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
class PasteText(InputBase):
|
|
138
|
-
def __init__(self, cast_number=True, key=None):
|
|
139
|
-
super().__init__(key=key)
|
|
140
|
-
self.cast_number = cast_number
|
|
141
|
-
self.user_input = st.text_area("Paste data here", key=self.key)
|
|
142
|
-
self.seperator()
|
|
143
|
-
|
|
144
|
-
def parse(self):
|
|
145
|
-
if len(self.user_input) > 0:
|
|
146
|
-
rows = self.user_input.strip().split("\n")
|
|
147
|
-
raw_data = [row.split(self.sep) for row in rows]
|
|
148
|
-
try:
|
|
149
|
-
data = np.array(raw_data)
|
|
150
|
-
if self.cast_number:
|
|
151
|
-
data = data.astype(float)
|
|
152
|
-
return pd.DataFrame(data)
|
|
153
|
-
except Exception:
|
|
154
|
-
st.error("Your seperator seems incorrect")
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
import io
|
|
3
|
-
import zipfile
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
import pandas as pd
|
|
7
|
-
import streamlit as st
|
|
8
|
-
from random_word.random_word import RandomWords
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class ExampleDataGenerator:
|
|
12
|
-
def __init__(self, col, row):
|
|
13
|
-
np.random.seed(0)
|
|
14
|
-
self.col = col
|
|
15
|
-
self.row = row
|
|
16
|
-
self.words = RandomWords()
|
|
17
|
-
self.export_kws = dict(sep="\t", index=False, header=None)
|
|
18
|
-
|
|
19
|
-
def matrix(self):
|
|
20
|
-
return np.random.randint(0, 101, (self.row, self.col))
|
|
21
|
-
|
|
22
|
-
def col_labels(self):
|
|
23
|
-
labels = [self.words.get_random_word() for _ in range(self.col)]
|
|
24
|
-
return np.array(labels)
|
|
25
|
-
|
|
26
|
-
def row_labels(self):
|
|
27
|
-
labels = [self.words.get_random_word() for _ in range(self.row)]
|
|
28
|
-
return np.array(labels)
|
|
29
|
-
|
|
30
|
-
def stats_data(self):
|
|
31
|
-
return np.random.randn(10, self.row)
|
|
32
|
-
|
|
33
|
-
def numbers(self):
|
|
34
|
-
return np.random.randint(10, 100, self.row)
|
|
35
|
-
|
|
36
|
-
def get_text(self, data):
|
|
37
|
-
return pd.DataFrame(data=data).to_csv(**self.export_kws)
|
|
38
|
-
|
|
39
|
-
def to_zip(self):
|
|
40
|
-
zip_buffer = io.BytesIO()
|
|
41
|
-
with zipfile.ZipFile(zip_buffer, "a") as z:
|
|
42
|
-
z.writestr("matrix_data.txt", self.get_text(self.matrix()))
|
|
43
|
-
z.writestr("labels (row).txt", self.get_text(self.row_labels()))
|
|
44
|
-
z.writestr("labels (col).txt", self.get_text(self.col_labels()))
|
|
45
|
-
z.writestr("statistic plot.txt", self.get_text(self.stats_data()))
|
|
46
|
-
z.writestr("numbers.txt", self.get_text(self.numbers()))
|
|
47
|
-
return zip_buffer
|
|
48
|
-
|
|
49
|
-
def to_base64(self):
|
|
50
|
-
zip_bytes = self.to_zip()
|
|
51
|
-
return base64.b64encode(zip_bytes.getvalue()).decode()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@st.cache_resource
|
|
55
|
-
def get_base64():
|
|
56
|
-
g = ExampleDataGenerator(20, 20)
|
|
57
|
-
return g.to_base64()
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class ExampleDownloader:
|
|
61
|
-
def __init__(self):
|
|
62
|
-
self.b64 = get_base64()
|
|
63
|
-
href = (
|
|
64
|
-
f'<a href="data:file/zip;base64,{self.b64}" '
|
|
65
|
-
f'download="example.zip">Example Data</a>'
|
|
66
|
-
)
|
|
67
|
-
st.markdown(href, unsafe_allow_html=True)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if __name__ == "__main__":
|
|
71
|
-
g = ExampleDataGenerator(20, 20)
|