marsilea 0.3.5__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.5 → marsilea-0.4.0}/PKG-INFO +2 -2
- {marsilea-0.3.5 → marsilea-0.4.0}/pyproject.toml +11 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/__init__.py +10 -5
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/base.py +85 -56
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/__init__.py +1 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/_images.py +7 -5
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/_seaborn.py +4 -2
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/arc.py +4 -2
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/area.py +18 -9
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/bar.py +3 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/base.py +25 -6
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/mesh.py +24 -2
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/upset.py +12 -2
- {marsilea-0.3.5 → marsilea-0.4.0}/src/oncoprinter/core.py +79 -15
- marsilea-0.3.5/app/.gitignore +0 -2
- marsilea-0.3.5/app/Dockerfile +0 -20
- marsilea-0.3.5/app/Home.py +0 -86
- marsilea-0.3.5/app/README.md +0 -17
- marsilea-0.3.5/app/components/__init__.py +0 -0
- marsilea-0.3.5/app/components/cmap_selector/__init__.py +0 -1
- marsilea-0.3.5/app/components/cmap_selector/selector.py +0 -159
- marsilea-0.3.5/app/components/data_input.py +0 -149
- marsilea-0.3.5/app/components/example_download.py +0 -71
- marsilea-0.3.5/app/components/initialize.py +0 -124
- marsilea-0.3.5/app/components/main_plots.py +0 -293
- marsilea-0.3.5/app/components/resource.py +0 -103
- marsilea-0.3.5/app/components/saver.py +0 -44
- marsilea-0.3.5/app/components/side_plots.py +0 -764
- marsilea-0.3.5/app/components/state.py +0 -153
- marsilea-0.3.5/app/components/transformation.py +0 -87
- marsilea-0.3.5/app/components/upset_example.csv +0 -1000
- marsilea-0.3.5/app/img/V1.mp4 +0 -0
- marsilea-0.3.5/app/img/V2.mp4 +0 -0
- marsilea-0.3.5/app/img/annolabels.png +0 -0
- marsilea-0.3.5/app/img/bar.png +0 -0
- marsilea-0.3.5/app/img/box.png +0 -0
- marsilea-0.3.5/app/img/boxen.png +0 -0
- marsilea-0.3.5/app/img/colors.png +0 -0
- marsilea-0.3.5/app/img/dendrogram.svg +0 -102
- marsilea-0.3.5/app/img/favicon.png +0 -0
- marsilea-0.3.5/app/img/favicon.svg +0 -61
- marsilea-0.3.5/app/img/heatmap.png +0 -0
- marsilea-0.3.5/app/img/heatmap.svg +0 -191
- marsilea-0.3.5/app/img/logo.png +0 -0
- marsilea-0.3.5/app/img/mark_map.png +0 -0
- marsilea-0.3.5/app/img/mark_map.svg +0 -112
- marsilea-0.3.5/app/img/point.png +0 -0
- marsilea-0.3.5/app/img/sized_heatmap.png +0 -0
- marsilea-0.3.5/app/img/sized_heatmap.svg +0 -357
- marsilea-0.3.5/app/img/sized_onlymap.png +0 -0
- marsilea-0.3.5/app/img/strip.png +0 -0
- marsilea-0.3.5/app/img/swarm.png +0 -0
- marsilea-0.3.5/app/img/violin.png +0 -0
- marsilea-0.3.5/app/img/x-layout.png +0 -0
- marsilea-0.3.5/app/pages/01 Simple_Heatmap.py +0 -218
- marsilea-0.3.5/app/pages/02 X-Layout_Heatmap.py +0 -236
- marsilea-0.3.5/app/pages/03 Upsetplot.py +0 -216
- marsilea-0.3.5/app/pages/04 Manual.py +0 -52
- marsilea-0.3.5/app/requirements.txt +0 -10
- marsilea-0.3.5/app/script/heatmap_data.py +0 -25
- marsilea-0.3.5/app/script/plot_layer_example_images.py +0 -33
- marsilea-0.3.5/app/script/plotter_example_images.py +0 -104
- marsilea-0.3.5/app/set_data_memberships.txt +0 -4
- marsilea-0.3.5/app/test.xlsx +0 -0
- marsilea-0.3.5/app/test_data/Stats_plot.txt +0 -10
- marsilea-0.3.5/app/test_data/example_data.txt +0 -20
- marsilea-0.3.5/app/test_data/number.txt +0 -20
- marsilea-0.3.5/app/test_data/row_labels.txt +0 -20
- marsilea-0.3.5/app/test_data/set_data_memberships.txt +0 -4
- marsilea-0.3.5/app/upset.xlsx +0 -0
- marsilea-0.3.5/data/IMDB.csv +0 -1000
- marsilea-0.3.5/data/PATIENT_DATA_oncoprint.tsv +0 -138
- marsilea-0.3.5/data/pbmc3k.h5ad +0 -0
- marsilea-0.3.5/docs/Makefile +0 -30
- marsilea-0.3.5/docs/README.md +0 -57
- marsilea-0.3.5/docs/examples/.gitignore +0 -2
- marsilea-0.3.5/docs/examples/Basics/README.rst +0 -2
- marsilea-0.3.5/docs/examples/Basics/plot_adv_heatmap.py +0 -23
- marsilea-0.3.5/docs/examples/Basics/plot_heatmap.py +0 -21
- marsilea-0.3.5/docs/examples/Basics/plot_stacked_bar.py +0 -42
- marsilea-0.3.5/docs/examples/Basics/plot_two_heatmap.py +0 -24
- marsilea-0.3.5/docs/examples/Gallery/README.rst +0 -4
- marsilea-0.3.5/docs/examples/Gallery/plot_arc_diagram.py +0 -67
- marsilea-0.3.5/docs/examples/Gallery/plot_available_plotters.py +0 -173
- marsilea-0.3.5/docs/examples/Gallery/plot_bivariate_dist.py +0 -94
- marsilea-0.3.5/docs/examples/Gallery/plot_mouse_embryo.py +0 -122
- marsilea-0.3.5/docs/examples/Gallery/plot_oil_well.py +0 -92
- marsilea-0.3.5/docs/examples/Gallery/plot_oncoprint.py +0 -108
- marsilea-0.3.5/docs/examples/Gallery/plot_pbmc3k.py +0 -78
- marsilea-0.3.5/docs/examples/Gallery/plot_sc_multiomics.py +0 -86
- marsilea-0.3.5/docs/examples/Gallery/plot_seqalign.py +0 -124
- marsilea-0.3.5/docs/examples/Gallery/plot_upset.py +0 -53
- marsilea-0.3.5/docs/examples/Plotters/README.rst +0 -4
- marsilea-0.3.5/docs/examples/Plotters/plot_anno_labels.py +0 -21
- marsilea-0.3.5/docs/examples/Plotters/plot_arc.py +0 -19
- marsilea-0.3.5/docs/examples/Plotters/plot_area.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_bar.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_box.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_boxen.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_center_bar.py +0 -19
- marsilea-0.3.5/docs/examples/Plotters/plot_chunk.py +0 -19
- marsilea-0.3.5/docs/examples/Plotters/plot_color_mesh.py +0 -20
- marsilea-0.3.5/docs/examples/Plotters/plot_colors.py +0 -20
- marsilea-0.3.5/docs/examples/Plotters/plot_fixed_chunk.py +0 -21
- marsilea-0.3.5/docs/examples/Plotters/plot_labels.py +0 -20
- marsilea-0.3.5/docs/examples/Plotters/plot_marker_mesh.py +0 -19
- marsilea-0.3.5/docs/examples/Plotters/plot_numbers.py +0 -17
- marsilea-0.3.5/docs/examples/Plotters/plot_point.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_seq_logo.py +0 -21
- marsilea-0.3.5/docs/examples/Plotters/plot_sized_mesh.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_stack_bar.py +0 -19
- marsilea-0.3.5/docs/examples/Plotters/plot_strip.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_swarm.py +0 -18
- marsilea-0.3.5/docs/examples/Plotters/plot_text_mesh.py +0 -19
- marsilea-0.3.5/docs/examples/Plotters/plot_title.py +0 -20
- marsilea-0.3.5/docs/examples/Plotters/plot_violin.py +0 -18
- marsilea-0.3.5/docs/examples/README.rst +0 -2
- marsilea-0.3.5/docs/how_to/README.rst +0 -4
- marsilea-0.3.5/docs/how_to/customization/README.rst +0 -8
- marsilea-0.3.5/docs/how_to/customization/plot_add_border.py +0 -32
- marsilea-0.3.5/docs/how_to/customization/plot_get_axes.py +0 -33
- marsilea-0.3.5/docs/how_to/dendrogram/README.rst +0 -2
- marsilea-0.3.5/docs/how_to/dendrogram/plot_color_dendrogram.py +0 -32
- marsilea-0.3.5/docs/how_to/dendrogram/plot_dendrogram_control.py +0 -19
- marsilea-0.3.5/docs/how_to/layout/README.rst +0 -3
- marsilea-0.3.5/docs/how_to/layout/plot_adjust_figure_size.py +0 -58
- marsilea-0.3.5/docs/how_to/layout/plot_labeling.py +0 -39
- marsilea-0.3.5/docs/how_to/layout/plot_margin.py +0 -28
- marsilea-0.3.5/docs/how_to/legends/README.rst +0 -7
- marsilea-0.3.5/docs/how_to/legends/plot_disable_legend.py +0 -29
- marsilea-0.3.5/docs/how_to/legends/plot_legends.py +0 -24
- marsilea-0.3.5/docs/how_to/save/README.rst +0 -5
- marsilea-0.3.5/docs/how_to/save/plot.pdf +0 -0
- marsilea-0.3.5/docs/how_to/save/plot.png +0 -0
- marsilea-0.3.5/docs/how_to/save/plot_save.py +0 -29
- marsilea-0.3.5/docs/make.bat +0 -35
- marsilea-0.3.5/docs/requirements.txt +0 -10
- marsilea-0.3.5/docs/source/.gitignore +0 -4
- marsilea-0.3.5/docs/source/_static/css/custom.css +0 -57
- marsilea-0.3.5/docs/source/_templates/autosummary.rst +0 -15
- marsilea-0.3.5/docs/source/api/index.rst +0 -308
- marsilea-0.3.5/docs/source/conf.py +0 -149
- marsilea-0.3.5/docs/source/img/code_example.png +0 -0
- marsilea-0.3.5/docs/source/img/cover.png +0 -0
- marsilea-0.3.5/docs/source/img/marsilea-renderplan-logic.drawio.svg +0 -4
- marsilea-0.3.5/docs/source/index.rst +0 -97
- marsilea-0.3.5/docs/source/installation.rst +0 -14
- marsilea-0.3.5/docs/source/sg_execution_times.rst +0 -169
- marsilea-0.3.5/docs/source/tutorial/axes-level.rst +0 -73
- marsilea-0.3.5/docs/source/tutorial/concatenation.rst +0 -90
- marsilea-0.3.5/docs/source/tutorial/heatmap.rst +0 -187
- marsilea-0.3.5/docs/source/tutorial/index.rst +0 -142
- marsilea-0.3.5/docs/source/tutorial/intro.rst +0 -181
- marsilea-0.3.5/docs/source/tutorial/intro2.rst +0 -146
- marsilea-0.3.5/docs/source/tutorial/new_renderplan.rst +0 -162
- marsilea-0.3.5/docs/source/tutorial/upset.rst +0 -125
- marsilea-0.3.5/img/Logo(1).zip +0 -0
- marsilea-0.3.5/img/Logo.zip +0 -0
- marsilea-0.3.5/img/banner-blue.jpg +0 -0
- marsilea-0.3.5/img/banner-dark-gradient.jpg +0 -0
- marsilea-0.3.5/img/banner-dark.jpg +0 -0
- marsilea-0.3.5/img/banner-rice-white.jpg +0 -0
- marsilea-0.3.5/img/banner-white.jpg +0 -0
- marsilea-0.3.5/img/logo/Logo/.DS_Store +0 -0
- marsilea-0.3.5/img/logo/Logo/Logo.svg +0 -27
- marsilea-0.3.5/img/logo/Logo/logo.png +0 -0
- marsilea-0.3.5/img/logo/Logo//346/265/205/350/223/235/346/270/220/345/217/230.jpg +0 -0
- marsilea-0.3.5/img/logo/Logo//346/267/261/350/211/262/350/203/214/346/231/257.jpg +0 -0
- marsilea-0.3.5/img/logo/Logo//347/261/263/350/211/262.jpg +0 -0
- marsilea-0.3.5/img/logo/Logo//347/272/257/347/231/275.jpg +0 -0
- marsilea-0.3.5/img/logo/Logo//350/247/222/345/272/246/346/270/220/345/217/230.jpg +0 -0
- marsilea-0.3.5/img/logo/__MACOSX/Logo/._.DS_Store +0 -0
- marsilea-0.3.5/img/logo.png +0 -0
- marsilea-0.3.5/img/logo.svg +0 -27
- marsilea-0.3.5/img/publication/API-interface.png +0 -0
- marsilea-0.3.5/img/publication/Snap-1.png +0 -0
- marsilea-0.3.5/img/publication/Snap-2.png +0 -0
- marsilea-0.3.5/img/publication/Snap-3.png +0 -0
- marsilea-0.3.5/img/publication/Stacked bar.png +0 -0
- marsilea-0.3.5/img/publication/bivar_kde.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-canvas-size-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-canvas-size.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-location-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-location.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-pad-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-pad.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-plotter-size-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-plotter-size.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-plotter-type-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-change-plotter-type.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-basic.png +0 -0
- marsilea-0.3.5/img/publication/layout-skeleton-step1.png +0 -0
- marsilea-0.3.5/img/publication/layout-skeleton-step2.png +0 -0
- marsilea-0.3.5/img/publication/layout-skeleton-step3.png +0 -0
- marsilea-0.3.5/img/publication/layout-skeleton-step4.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-1a-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-1a.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-1b-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-1b.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-2-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-2.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-3-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-3.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-4-code.png +0 -0
- marsilea-0.3.5/img/publication/layout-step-4.png +0 -0
- marsilea-0.3.5/img/publication/oncoprint.png +0 -0
- marsilea-0.3.5/img/publication/upset.png +0 -0
- marsilea-0.3.5/img/publication/web-app-screenshot-1.png +0 -0
- marsilea-0.3.5/img/publication/web-app-screenshot-2.png +0 -0
- marsilea-0.3.5/readthedocs.yaml +0 -12
- marsilea-0.3.5/scripts/benchmark/marsilea/marsilea_cooking_oils_base.py +0 -97
- marsilea-0.3.5/scripts/benchmark/marsilea/marsilea_cooking_oils_v1.py +0 -105
- marsilea-0.3.5/scripts/benchmark/marsilea/marsilea_cooking_oils_v2.py +0 -118
- marsilea-0.3.5/scripts/benchmark/marsilea_vs_matplotlib.png +0 -0
- marsilea-0.3.5/scripts/benchmark/marsilea_vs_matplotlib.svg +0 -1846
- marsilea-0.3.5/scripts/benchmark/matplotlib/matplotlib_cooking_oils_base.py +0 -180
- marsilea-0.3.5/scripts/benchmark/matplotlib/matplotlib_cooking_oils_v1.py +0 -230
- marsilea-0.3.5/scripts/benchmark/matplotlib/matplotlib_cooking_oils_v2.py +0 -220
- marsilea-0.3.5/scripts/benchmark/result.py +0 -159
- marsilea-0.3.5/scripts/logo.py +0 -78
- marsilea-0.3.5/scripts/pub_figure.py +0 -15
- marsilea-0.3.5/scripts/pub_figures/bivariate_kde.py +0 -77
- marsilea-0.3.5/scripts/pub_figures/layout-skeleton-step.py +0 -107
- marsilea-0.3.5/scripts/pub_figures/layout-step.py +0 -120
- marsilea-0.3.5/scripts/pub_figures/onco.py +0 -64
- marsilea-0.3.5/scripts/pub_figures/stacked_bar.py +0 -35
- marsilea-0.3.5/scripts/pub_figures/upset.py +0 -43
- marsilea-0.3.5/scripts/publication/arc_diagram.svg +0 -5974
- marsilea-0.3.5/scripts/publication/bivariate_dist.svg +0 -32
- marsilea-0.3.5/scripts/publication/mouse_embryo.svg +0 -168201
- marsilea-0.3.5/scripts/x-layout.py +0 -46
- marsilea-0.3.5/tests/test_data_input.py +0 -63
- marsilea-0.3.5/tests/test_deform.py +0 -92
- marsilea-0.3.5/tests/test_mesh.py +0 -30
- {marsilea-0.3.5 → marsilea-0.4.0}/.github/workflows/build.yaml +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/.github/workflows/deploy_streamlit.yaml +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/.github/workflows/lint.yaml +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/.gitignore +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/.streamlit/config.toml +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/CITATION.cff +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/LICENSE +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/README.md +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/setup.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/_api.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/_deform.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/dataset.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/dendrogram.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/exceptions.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/heatmap.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/layers.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/layout.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/_utils.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/bio.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/plotter/text.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/marsilea/utils.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/oncoprinter/__init__.py +0 -0
- {marsilea-0.3.5 → marsilea-0.4.0}/src/oncoprinter/preset.py +0 -0
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Declarative creation of composable visualization"""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.
|
|
3
|
+
__version__ = "0.4.0"
|
|
4
4
|
|
|
5
5
|
import marsilea.plotter as plotter
|
|
6
6
|
from ._deform import Deformation
|
|
7
|
-
from .base import (
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
from .base import (
|
|
8
|
+
WhiteBoard,
|
|
9
|
+
ClusterBoard,
|
|
10
|
+
ZeroWidth,
|
|
11
|
+
ZeroHeight,
|
|
12
|
+
ZeroWidthCluster,
|
|
13
|
+
ZeroHeightCluster,
|
|
14
|
+
)
|
|
10
15
|
from .dataset import load_data
|
|
11
16
|
from .dendrogram import Dendrogram, GroupDendrogram
|
|
12
17
|
from .heatmap import Heatmap, SizedHeatmap, CatHeatmap
|
|
@@ -46,6 +46,7 @@ def get_breakpoints(arr):
|
|
|
46
46
|
|
|
47
47
|
class LegendMaker:
|
|
48
48
|
"""The factory class to handle legends"""
|
|
49
|
+
|
|
49
50
|
layout: CrossLayout | CompositeCrossLayout
|
|
50
51
|
_legend_box: List[Artist] = None
|
|
51
52
|
_legend_name: str = None
|
|
@@ -66,34 +67,35 @@ class LegendMaker:
|
|
|
66
67
|
"""
|
|
67
68
|
raise NotImplementedError("Should be implemented in derived class")
|
|
68
69
|
|
|
69
|
-
def custom_legend(self,
|
|
70
|
+
def custom_legend(self, legend_func, name=None):
|
|
70
71
|
"""Add a custom legend
|
|
71
72
|
|
|
72
73
|
Parameters
|
|
73
74
|
----------
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
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>`
|
|
77
79
|
name : str, optional
|
|
78
80
|
The name of the legend
|
|
79
81
|
|
|
80
82
|
"""
|
|
81
83
|
if name is None:
|
|
82
84
|
name = str(uuid4())
|
|
83
|
-
self._user_legends[name] =
|
|
85
|
+
self._user_legends[name] = legend_func
|
|
84
86
|
|
|
85
87
|
def add_legends(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
self,
|
|
89
|
+
side="right",
|
|
90
|
+
pad=0.0,
|
|
91
|
+
order=None,
|
|
92
|
+
stack_by=None,
|
|
93
|
+
stack_size=3,
|
|
94
|
+
align_legends=None,
|
|
95
|
+
align_stacks=None,
|
|
96
|
+
legend_spacing=10,
|
|
97
|
+
stack_spacing=10,
|
|
98
|
+
box_padding=2,
|
|
97
99
|
):
|
|
98
100
|
"""Draw legend based on the order of annotation
|
|
99
101
|
|
|
@@ -128,6 +130,10 @@ class LegendMaker:
|
|
|
128
130
|
Add pad around the whole legend box
|
|
129
131
|
|
|
130
132
|
"""
|
|
133
|
+
# TODO: Allow user to control where to add legends,
|
|
134
|
+
# relative to the main canvas or the whole figure
|
|
135
|
+
# TODO: Allow user to add stack_size as a list
|
|
136
|
+
# Each stack can contain different number of legends
|
|
131
137
|
_check_side(side)
|
|
132
138
|
self._draw_legend = True
|
|
133
139
|
if stack_by is None:
|
|
@@ -154,7 +160,8 @@ class LegendMaker:
|
|
|
154
160
|
self.layout.remove_legend_ax()
|
|
155
161
|
|
|
156
162
|
def _legends_drawer(self, ax):
|
|
157
|
-
|
|
163
|
+
user_legends = {k: [v()] for k, v in self._user_legends.items()}
|
|
164
|
+
legends = {**self.get_legends(), **user_legends}
|
|
158
165
|
|
|
159
166
|
# force to remove all legends before drawing
|
|
160
167
|
# In case some legends are added implicitly
|
|
@@ -236,9 +243,9 @@ class WhiteBoard(LegendMaker):
|
|
|
236
243
|
|
|
237
244
|
Parameters
|
|
238
245
|
----------
|
|
239
|
-
width :
|
|
246
|
+
width : float, optional
|
|
240
247
|
The width of the main canvas in inches
|
|
241
|
-
height :
|
|
248
|
+
height : float, optional
|
|
242
249
|
The height of the main canvas in inches
|
|
243
250
|
name : str, optional
|
|
244
251
|
The name of the main canvas
|
|
@@ -305,7 +312,7 @@ class WhiteBoard(LegendMaker):
|
|
|
305
312
|
super().__init__()
|
|
306
313
|
|
|
307
314
|
def add_plot(
|
|
308
|
-
|
|
315
|
+
self, side, plot: RenderPlan, name=None, size=None, pad=0.0, legend=True
|
|
309
316
|
):
|
|
310
317
|
"""Add a plotter to the board
|
|
311
318
|
|
|
@@ -676,8 +683,9 @@ class ZeroWidth(WhiteBoard):
|
|
|
676
683
|
"""
|
|
677
684
|
|
|
678
685
|
def __init__(self, height, name=None, margin=0.2):
|
|
679
|
-
super().__init__(
|
|
680
|
-
|
|
686
|
+
super().__init__(
|
|
687
|
+
width=0, height=height, name=name, margin=margin, init_main=False
|
|
688
|
+
)
|
|
681
689
|
|
|
682
690
|
|
|
683
691
|
class ZeroHeight(WhiteBoard):
|
|
@@ -689,8 +697,9 @@ class ZeroHeight(WhiteBoard):
|
|
|
689
697
|
"""
|
|
690
698
|
|
|
691
699
|
def __init__(self, width, name=None, margin=0.2):
|
|
692
|
-
super().__init__(
|
|
693
|
-
|
|
700
|
+
super().__init__(
|
|
701
|
+
width=width, height=0, name=name, margin=margin, init_main=False
|
|
702
|
+
)
|
|
694
703
|
|
|
695
704
|
|
|
696
705
|
class CompositeBoard(LegendMaker):
|
|
@@ -771,9 +780,9 @@ class ClusterBoard(WhiteBoard):
|
|
|
771
780
|
----------
|
|
772
781
|
cluster_data : ndarray
|
|
773
782
|
The cluster data
|
|
774
|
-
width :
|
|
783
|
+
width : float, optional
|
|
775
784
|
The width of the main canvas in inches
|
|
776
|
-
height :
|
|
785
|
+
height : float, optional
|
|
777
786
|
The height of the main canvas in inches
|
|
778
787
|
name : str, optional
|
|
779
788
|
The name of the main canvas
|
|
@@ -799,13 +808,13 @@ class ClusterBoard(WhiteBoard):
|
|
|
799
808
|
_mesh = None
|
|
800
809
|
|
|
801
810
|
def __init__(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
811
|
+
self,
|
|
812
|
+
cluster_data,
|
|
813
|
+
width=None,
|
|
814
|
+
height=None,
|
|
815
|
+
name=None,
|
|
816
|
+
margin=0.2,
|
|
817
|
+
init_main=True,
|
|
809
818
|
):
|
|
810
819
|
super().__init__(
|
|
811
820
|
width=width, height=height, name=name, margin=margin, init_main=init_main
|
|
@@ -816,24 +825,24 @@ class ClusterBoard(WhiteBoard):
|
|
|
816
825
|
self._deform = Deformation(cluster_data)
|
|
817
826
|
|
|
818
827
|
def add_dendrogram(
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
828
|
+
self,
|
|
829
|
+
side,
|
|
830
|
+
method=None,
|
|
831
|
+
metric=None,
|
|
832
|
+
linkage=None,
|
|
833
|
+
add_meta=True,
|
|
834
|
+
add_base=True,
|
|
835
|
+
add_divider=True,
|
|
836
|
+
meta_color=None,
|
|
837
|
+
linewidth=None,
|
|
838
|
+
colors=None,
|
|
839
|
+
divider_style="--",
|
|
840
|
+
meta_ratio=0.2,
|
|
841
|
+
show=True,
|
|
842
|
+
name=None,
|
|
843
|
+
size=0.5,
|
|
844
|
+
pad=0.0,
|
|
845
|
+
get_meta_center=None,
|
|
837
846
|
):
|
|
838
847
|
"""Run cluster and add dendrogram
|
|
839
848
|
|
|
@@ -1031,7 +1040,11 @@ class ClusterBoard(WhiteBoard):
|
|
|
1031
1040
|
|
|
1032
1041
|
|
|
1033
1042
|
"""
|
|
1034
|
-
warnings.warn(
|
|
1043
|
+
warnings.warn(
|
|
1044
|
+
DeprecationWarning(
|
|
1045
|
+
"`hsplit` will be deprecated in v0.5.0, use `cut_rows` or `group_rows` instead"
|
|
1046
|
+
)
|
|
1047
|
+
)
|
|
1035
1048
|
if self._split_row:
|
|
1036
1049
|
raise SplitTwice(axis="horizontally")
|
|
1037
1050
|
self._split_row = True
|
|
@@ -1094,7 +1107,11 @@ class ClusterBoard(WhiteBoard):
|
|
|
1094
1107
|
|
|
1095
1108
|
|
|
1096
1109
|
"""
|
|
1097
|
-
warnings.warn(
|
|
1110
|
+
warnings.warn(
|
|
1111
|
+
DeprecationWarning(
|
|
1112
|
+
"`vsplit` will be deprecated in v0.5.0, use `cut_cols` or `group_cols` instead"
|
|
1113
|
+
)
|
|
1114
|
+
)
|
|
1098
1115
|
if self._split_col:
|
|
1099
1116
|
raise SplitTwice(axis="vertically")
|
|
1100
1117
|
self._split_col = True
|
|
@@ -1424,8 +1441,14 @@ class ZeroWidthCluster(ClusterBoard):
|
|
|
1424
1441
|
"""
|
|
1425
1442
|
|
|
1426
1443
|
def __init__(self, cluster_data, height, name=None, margin=0.2):
|
|
1427
|
-
super().__init__(
|
|
1428
|
-
|
|
1444
|
+
super().__init__(
|
|
1445
|
+
cluster_data=cluster_data,
|
|
1446
|
+
width=0,
|
|
1447
|
+
height=height,
|
|
1448
|
+
name=name,
|
|
1449
|
+
margin=margin,
|
|
1450
|
+
init_main=False,
|
|
1451
|
+
)
|
|
1429
1452
|
|
|
1430
1453
|
|
|
1431
1454
|
class ZeroHeightCluster(ClusterBoard):
|
|
@@ -1448,5 +1471,11 @@ class ZeroHeightCluster(ClusterBoard):
|
|
|
1448
1471
|
"""
|
|
1449
1472
|
|
|
1450
1473
|
def __init__(self, cluster_data, width, name=None, margin=0.2):
|
|
1451
|
-
super().__init__(
|
|
1452
|
-
|
|
1474
|
+
super().__init__(
|
|
1475
|
+
cluster_data=cluster_data,
|
|
1476
|
+
width=width,
|
|
1477
|
+
height=0,
|
|
1478
|
+
name=name,
|
|
1479
|
+
margin=margin,
|
|
1480
|
+
init_main=False,
|
|
1481
|
+
)
|
|
@@ -51,13 +51,11 @@ class Emoji(RenderPlan):
|
|
|
51
51
|
self.mode = mode
|
|
52
52
|
|
|
53
53
|
def _get_images_bbox(self, figure, imgs):
|
|
54
|
-
|
|
55
54
|
for img in imgs:
|
|
56
55
|
width, height = img.shape[:2]
|
|
57
56
|
|
|
58
57
|
return Bbox.from_bounds(0, 0, width, height)
|
|
59
58
|
|
|
60
|
-
|
|
61
59
|
def render_ax(self, spec):
|
|
62
60
|
ax = spec.ax
|
|
63
61
|
data = spec.data
|
|
@@ -89,9 +87,13 @@ class Emoji(RenderPlan):
|
|
|
89
87
|
x0, y0 = ax.transData.transform((loc, loc_y))
|
|
90
88
|
return Bbox.from_bounds(x0, y0, width, height)
|
|
91
89
|
|
|
92
|
-
partial_get_emoji_bbox = partial(
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
partial_get_emoji_bbox = partial(
|
|
91
|
+
get_emoji_bbox,
|
|
92
|
+
loc=loc,
|
|
93
|
+
loc_y=loc_y,
|
|
94
|
+
width=fit_scale_width,
|
|
95
|
+
height=fit_scale_height,
|
|
96
|
+
)
|
|
95
97
|
|
|
96
98
|
i1 = BboxImage(partial_get_emoji_bbox, data=img)
|
|
97
99
|
ax.add_artist(i1)
|
|
@@ -20,9 +20,11 @@ class _SeabornBase(StatsBase):
|
|
|
20
20
|
hue_order=None,
|
|
21
21
|
palette=None,
|
|
22
22
|
orient=None,
|
|
23
|
-
label=None,
|
|
24
23
|
legend_kws=None,
|
|
25
24
|
group_kws=None,
|
|
25
|
+
label=None,
|
|
26
|
+
label_loc=None,
|
|
27
|
+
label_props=None,
|
|
26
28
|
**kwargs,
|
|
27
29
|
):
|
|
28
30
|
if isinstance(data, Mapping):
|
|
@@ -62,7 +64,7 @@ class _SeabornBase(StatsBase):
|
|
|
62
64
|
self.kws = kwargs
|
|
63
65
|
|
|
64
66
|
self.orient = orient
|
|
65
|
-
self.label
|
|
67
|
+
self.set_label(label, label_loc, label_props)
|
|
66
68
|
self.legend_kws = {} if legend_kws is None else legend_kws
|
|
67
69
|
if group_kws is not None:
|
|
68
70
|
self.set_group_params(group_kws)
|
|
@@ -212,8 +212,8 @@ class Arc(StatsBase):
|
|
|
212
212
|
)
|
|
213
213
|
|
|
214
214
|
if self.side == "left":
|
|
215
|
-
xy = (
|
|
216
|
-
angle = 90
|
|
215
|
+
xy = (0, arc_mid)
|
|
216
|
+
angle = -90
|
|
217
217
|
elif self.side == "right":
|
|
218
218
|
xy = (0, arc_mid)
|
|
219
219
|
angle = -90
|
|
@@ -233,6 +233,8 @@ class Arc(StatsBase):
|
|
|
233
233
|
ax.set_xlim(0, 1)
|
|
234
234
|
if self.side == "top":
|
|
235
235
|
ax.invert_yaxis()
|
|
236
|
+
if self.side == "left":
|
|
237
|
+
ax.invert_xaxis()
|
|
236
238
|
ax.set_axis_off()
|
|
237
239
|
|
|
238
240
|
def get_legends(self):
|
|
@@ -42,11 +42,20 @@ class Area(StatsBase):
|
|
|
42
42
|
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
-
def __init__(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
data,
|
|
48
|
+
color=None,
|
|
49
|
+
add_outline=True,
|
|
50
|
+
alpha=0.4,
|
|
51
|
+
linecolor=None,
|
|
52
|
+
linewidth=1,
|
|
53
|
+
group_kws=None,
|
|
54
|
+
label=None,
|
|
55
|
+
label_loc=None,
|
|
56
|
+
label_props=None,
|
|
57
|
+
**kwargs,
|
|
58
|
+
):
|
|
50
59
|
if color is None:
|
|
51
60
|
color = "skyblue"
|
|
52
61
|
if linecolor is None:
|
|
@@ -71,22 +80,22 @@ class Area(StatsBase):
|
|
|
71
80
|
if gp is None:
|
|
72
81
|
gp = {}
|
|
73
82
|
|
|
74
|
-
fill_options = {
|
|
75
|
-
line_options = {
|
|
83
|
+
fill_options = {"color": self.color, "alpha": self.alpha, **self.kws, **gp}
|
|
84
|
+
line_options = {"color": self.linecolor, "linewidth": self.linewidth, **gp}
|
|
76
85
|
|
|
77
86
|
x = np.arange(len(data))
|
|
78
87
|
if self.get_orient() == "h":
|
|
79
88
|
ax.fill_betweenx(x, data, **fill_options)
|
|
80
89
|
if self.add_outline:
|
|
81
90
|
ax.plot(data, x, **line_options)
|
|
82
|
-
ax.set_ylim(
|
|
91
|
+
ax.set_ylim(-0.5, len(data) - 0.5)
|
|
83
92
|
if self.side == "left":
|
|
84
93
|
ax.invert_xaxis()
|
|
85
94
|
else:
|
|
86
95
|
ax.fill_between(x, data, **fill_options)
|
|
87
96
|
if self.add_outline:
|
|
88
97
|
ax.plot(x, data, **line_options)
|
|
89
|
-
ax.set_xlim(
|
|
98
|
+
ax.set_xlim(-0.5, len(data) - 0.5)
|
|
90
99
|
return ax
|
|
91
100
|
|
|
92
101
|
|
|
@@ -103,6 +103,8 @@ class Numbers(_BarBase):
|
|
|
103
103
|
show_value=True,
|
|
104
104
|
fmt=None,
|
|
105
105
|
label=None,
|
|
106
|
+
label_loc=None,
|
|
107
|
+
label_props=None,
|
|
106
108
|
value_pad=2.0,
|
|
107
109
|
props=None,
|
|
108
110
|
**kwargs,
|
|
@@ -114,6 +116,7 @@ class Numbers(_BarBase):
|
|
|
114
116
|
self._process_params(
|
|
115
117
|
width, orient, show_value, fmt, label, value_pad, props, **kwargs
|
|
116
118
|
)
|
|
119
|
+
self.set_label(label, label_loc, label_props)
|
|
117
120
|
|
|
118
121
|
def render_ax(self, spec):
|
|
119
122
|
ax = spec.ax
|
|
@@ -95,6 +95,7 @@ class RenderSpec:
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
"""
|
|
98
|
+
|
|
98
99
|
ax: Axes
|
|
99
100
|
|
|
100
101
|
data: Any
|
|
@@ -271,11 +272,15 @@ class RenderPlan:
|
|
|
271
272
|
if group_data is not None:
|
|
272
273
|
if self.has_deform:
|
|
273
274
|
group_data = np.asarray(group_data)
|
|
274
|
-
if
|
|
275
|
+
if (
|
|
276
|
+
self.deform.is_col_split
|
|
277
|
+
& (self.is_body | (self.side == "main"))
|
|
278
|
+
& self.deform.is_col_cluster
|
|
279
|
+
):
|
|
275
280
|
return group_data[self.deform.col_chunk_index]
|
|
276
281
|
elif (
|
|
277
282
|
self.deform.is_row_split
|
|
278
|
-
& self.is_flank
|
|
283
|
+
& (self.is_flank | (self.side == "main"))
|
|
279
284
|
& self.deform.is_row_cluster
|
|
280
285
|
):
|
|
281
286
|
return group_data[self.deform.row_chunk_index]
|
|
@@ -610,6 +615,13 @@ class StatsBase(RenderPlan):
|
|
|
610
615
|
ax.set_xlim(*lims) if is_h else ax.set_ylim(*lims)
|
|
611
616
|
|
|
612
617
|
def render(self, axes):
|
|
618
|
+
# check if self._plan_label.loc is None
|
|
619
|
+
is_loc = False
|
|
620
|
+
props = None
|
|
621
|
+
if self._plan_label is not None:
|
|
622
|
+
if self._plan_label.loc is not None:
|
|
623
|
+
is_loc = True
|
|
624
|
+
props = self._plan_label.props
|
|
613
625
|
if self.is_split:
|
|
614
626
|
for spec in self.get_render_spec(axes):
|
|
615
627
|
self.render_ax(spec)
|
|
@@ -619,11 +631,13 @@ class StatsBase(RenderPlan):
|
|
|
619
631
|
# leave axis for the first ax
|
|
620
632
|
if (i == 0) & (self.get_orient() == "v"):
|
|
621
633
|
self._setup_axis(ax)
|
|
622
|
-
|
|
634
|
+
if not is_loc:
|
|
635
|
+
ax.set_ylabel(self.label, fontdict=props)
|
|
623
636
|
# leave axis for the last ax
|
|
624
637
|
elif (i == len(axes) - 1) & (self.get_orient() == "h"):
|
|
625
638
|
self._setup_axis(ax)
|
|
626
|
-
|
|
639
|
+
if not is_loc:
|
|
640
|
+
ax.set_xlabel(self.label, fontdict=props)
|
|
627
641
|
else:
|
|
628
642
|
ax.set_axis_off()
|
|
629
643
|
else:
|
|
@@ -632,6 +646,11 @@ class StatsBase(RenderPlan):
|
|
|
632
646
|
self._setup_axis(axes)
|
|
633
647
|
if self.label is not None:
|
|
634
648
|
if self.get_orient() == "v":
|
|
635
|
-
|
|
649
|
+
if not is_loc:
|
|
650
|
+
axes.set_ylabel(self.label, fontdict=props)
|
|
636
651
|
else:
|
|
637
|
-
|
|
652
|
+
if not is_loc:
|
|
653
|
+
axes.set_xlabel(self.label, fontdict=props)
|
|
654
|
+
|
|
655
|
+
if self.allow_labeling & is_loc:
|
|
656
|
+
self._plan_label.add(axes, self.side)
|
|
@@ -430,6 +430,12 @@ class SizedMesh(MeshBase):
|
|
|
430
430
|
The width of the border of each elements
|
|
431
431
|
frameon : bool
|
|
432
432
|
Whether to draw a frame
|
|
433
|
+
grid : bool
|
|
434
|
+
Whether to draw grid
|
|
435
|
+
grid_color : color
|
|
436
|
+
The color of grid
|
|
437
|
+
grid_linewidth : float
|
|
438
|
+
The width of grid line
|
|
433
439
|
palette : dict
|
|
434
440
|
Use to map color if input categorical data
|
|
435
441
|
marker : str
|
|
@@ -494,6 +500,9 @@ class SizedMesh(MeshBase):
|
|
|
494
500
|
edgecolor=None,
|
|
495
501
|
linewidth=1,
|
|
496
502
|
frameon=True,
|
|
503
|
+
grid=False,
|
|
504
|
+
grid_color=".8",
|
|
505
|
+
grid_linewidth=1,
|
|
497
506
|
palette=None,
|
|
498
507
|
marker="o",
|
|
499
508
|
label=None,
|
|
@@ -534,8 +543,8 @@ class SizedMesh(MeshBase):
|
|
|
534
543
|
if palette is not None:
|
|
535
544
|
encoder = {}
|
|
536
545
|
render_colors = []
|
|
537
|
-
for i, (
|
|
538
|
-
encoder[
|
|
546
|
+
for i, (plabel, c) in enumerate(palette.items()):
|
|
547
|
+
encoder[plabel] = i
|
|
539
548
|
render_colors.append(c)
|
|
540
549
|
self.cmap = ListedColormap(render_colors)
|
|
541
550
|
self.color2d = encode_numeric(color, encoder)
|
|
@@ -548,6 +557,9 @@ class SizedMesh(MeshBase):
|
|
|
548
557
|
self.edgecolor = edgecolor
|
|
549
558
|
self.linewidth = linewidth
|
|
550
559
|
self.set_label(label, label_loc, label_props)
|
|
560
|
+
self.grid = grid
|
|
561
|
+
self.grid_color = grid_color
|
|
562
|
+
self.grid_linewidth = grid_linewidth
|
|
551
563
|
self.kwargs = kwargs
|
|
552
564
|
|
|
553
565
|
self._collections = None
|
|
@@ -606,6 +618,16 @@ class SizedMesh(MeshBase):
|
|
|
606
618
|
yticks = np.arange(Y) + 0.5
|
|
607
619
|
xv, yv = np.meshgrid(xticks, yticks)
|
|
608
620
|
|
|
621
|
+
if self.grid:
|
|
622
|
+
for x in xticks:
|
|
623
|
+
ax.axvline(
|
|
624
|
+
x, color=self.grid_color, linewidth=self.grid_linewidth, zorder=0
|
|
625
|
+
)
|
|
626
|
+
for y in yticks:
|
|
627
|
+
ax.axhline(
|
|
628
|
+
y, color=self.grid_color, linewidth=self.grid_linewidth, zorder=0
|
|
629
|
+
)
|
|
630
|
+
|
|
609
631
|
options = dict(
|
|
610
632
|
s=size,
|
|
611
633
|
edgecolor=self.edgecolor,
|
|
@@ -474,7 +474,10 @@ class Upset(WhiteBoard):
|
|
|
474
474
|
Whether or which side to add the label.
|
|
475
475
|
width : float
|
|
476
476
|
height : float
|
|
477
|
-
|
|
477
|
+
size_scale : float
|
|
478
|
+
The scale of the plot
|
|
479
|
+
size_aspect : float
|
|
480
|
+
The aspect ratio of the plot
|
|
478
481
|
|
|
479
482
|
Examples
|
|
480
483
|
--------
|
|
@@ -514,6 +517,8 @@ class Upset(WhiteBoard):
|
|
|
514
517
|
add_labels=True,
|
|
515
518
|
width=None,
|
|
516
519
|
height=None,
|
|
520
|
+
size_scale=0.3,
|
|
521
|
+
size_aspect=1.0,
|
|
517
522
|
):
|
|
518
523
|
# The modification happens inplace
|
|
519
524
|
upset_data = data
|
|
@@ -567,7 +572,11 @@ class Upset(WhiteBoard):
|
|
|
567
572
|
self.orient = orient
|
|
568
573
|
|
|
569
574
|
width, height = get_canvas_size_by_data(
|
|
570
|
-
main_shape,
|
|
575
|
+
main_shape,
|
|
576
|
+
scale=size_scale,
|
|
577
|
+
width=width,
|
|
578
|
+
height=height,
|
|
579
|
+
aspect=size_aspect,
|
|
571
580
|
)
|
|
572
581
|
|
|
573
582
|
super().__init__(width=width, height=height)
|
|
@@ -717,6 +726,7 @@ class Upset(WhiteBoard):
|
|
|
717
726
|
raise ValueError(msg)
|
|
718
727
|
|
|
719
728
|
def add_intersections(self, side, pad=0.1, size=1.0):
|
|
729
|
+
self._add_intersections = True
|
|
720
730
|
self._check_side(
|
|
721
731
|
side, "Intersections", dict(h=["top", "bottom"], v=["left", "right"])
|
|
722
732
|
)
|