marsilea 0.4.1__tar.gz → 0.4.3__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.
Files changed (41) hide show
  1. marsilea-0.4.3/PKG-INFO +168 -0
  2. marsilea-0.4.3/README.md +113 -0
  3. {marsilea-0.4.1 → marsilea-0.4.3}/pyproject.toml +20 -3
  4. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/__init__.py +1 -1
  5. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/_deform.py +17 -3
  6. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/base.py +30 -6
  7. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/dendrogram.py +37 -5
  8. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/exceptions.py +5 -4
  9. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/heatmap.py +2 -0
  10. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/__init__.py +1 -1
  11. marsilea-0.4.3/src/marsilea/plotter/_images.py +293 -0
  12. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/_seaborn.py +5 -4
  13. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/arc.py +1 -2
  14. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/bar.py +8 -7
  15. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/base.py +12 -2
  16. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/bio.py +3 -2
  17. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/mesh.py +26 -14
  18. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/text.py +69 -32
  19. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/utils.py +3 -6
  20. marsilea-0.4.1/.github/workflows/build.yaml +0 -70
  21. marsilea-0.4.1/.github/workflows/deploy_streamlit.yaml +0 -39
  22. marsilea-0.4.1/.github/workflows/lint.yaml +0 -10
  23. marsilea-0.4.1/.streamlit/config.toml +0 -6
  24. marsilea-0.4.1/CITATION.cff +0 -37
  25. marsilea-0.4.1/CODE_OF_CONDUCT.md +0 -128
  26. marsilea-0.4.1/PKG-INFO +0 -76
  27. marsilea-0.4.1/README.md +0 -42
  28. marsilea-0.4.1/src/marsilea/plotter/_images.py +0 -99
  29. {marsilea-0.4.1 → marsilea-0.4.3}/.gitignore +0 -0
  30. {marsilea-0.4.1 → marsilea-0.4.3}/LICENSE +0 -0
  31. {marsilea-0.4.1 → marsilea-0.4.3}/setup.py +0 -0
  32. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/_api.py +0 -0
  33. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/dataset.py +0 -0
  34. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/layers.py +0 -0
  35. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/layout.py +0 -0
  36. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/_utils.py +0 -0
  37. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/plotter/area.py +0 -0
  38. {marsilea-0.4.1 → marsilea-0.4.3}/src/marsilea/upset.py +0 -0
  39. {marsilea-0.4.1 → marsilea-0.4.3}/src/oncoprinter/__init__.py +0 -0
  40. {marsilea-0.4.1 → marsilea-0.4.3}/src/oncoprinter/core.py +0 -0
  41. {marsilea-0.4.1 → marsilea-0.4.3}/src/oncoprinter/preset.py +0 -0
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.3
2
+ Name: marsilea
3
+ Version: 0.4.3
4
+ Dynamic: Summary
5
+ Project-URL: Home, https://github.com/Marsilea-viz/marsilea
6
+ Author: Zhihang Zheng
7
+ Author-email: Mr-Milk <yzheng@cemm.at>
8
+ License: The MIT License (MIT)
9
+
10
+ Copyright (c) 2024 Mr-Milk
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in
20
+ all copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
+ THE SOFTWARE.
29
+ License-File: LICENSE
30
+ Classifier: Framework :: Matplotlib
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Programming Language :: Python :: 3
33
+ Requires-Python: >=3.8
34
+ Requires-Dist: legendkit
35
+ Requires-Dist: matplotlib>=3.6
36
+ Requires-Dist: numpy
37
+ Requires-Dist: pandas
38
+ Requires-Dist: platformdirs
39
+ Requires-Dist: scipy
40
+ Requires-Dist: seaborn
41
+ Provides-Extra: dev
42
+ Requires-Dist: icecream; extra == 'dev'
43
+ Requires-Dist: mpl-fontkit; extra == 'dev'
44
+ Requires-Dist: numpydoc; extra == 'dev'
45
+ Requires-Dist: pydata-sphinx-theme; extra == 'dev'
46
+ Requires-Dist: pytest; extra == 'dev'
47
+ Requires-Dist: python-hmr; extra == 'dev'
48
+ Requires-Dist: ruff; extra == 'dev'
49
+ Requires-Dist: scikit-learn; extra == 'dev'
50
+ Requires-Dist: sphinx; extra == 'dev'
51
+ Requires-Dist: sphinx-copybutton; extra == 'dev'
52
+ Requires-Dist: sphinx-design; extra == 'dev'
53
+ Requires-Dist: sphinx-gallery; extra == 'dev'
54
+ Description-Content-Type: text/markdown
55
+
56
+ <p align="center">
57
+ <picture align="center">
58
+ <source media="(prefers-color-scheme: dark)" srcset="https://github.com/Marsilea-viz/marsilea/raw/main/img/banner-dark.jpg">
59
+ <source media="(prefers-color-scheme: light)" srcset="https://github.com/Marsilea-viz/marsilea/raw/main/img/banner-blue.jpg">
60
+ <img alt="Shows a bar chart with benchmark results." src="https://github.com/Marsilea-viz/marsilea/raw/main/img/banner-dark.jpg" width="400">
61
+ </picture>
62
+ </p>
63
+
64
+ [![Documentation Status](https://img.shields.io/readthedocs/marsilea?color=57B77E&logo=readthedocs&logoColor=white&style=flat-square)](https://marsilea.readthedocs.io/en/stable)
65
+ ![pypi version](https://img.shields.io/pypi/v/marsilea?color=0098FF&logo=python&logoColor=white&style=flat-square)
66
+ ![PyPI - License](https://img.shields.io/pypi/l/marsilea?color=FFD43B&style=flat-square)
67
+
68
+ # Marsilea: Declarative creation of composable visualization!
69
+
70
+ ---
71
+
72
+ ## Documentation
73
+
74
+ You can read the documentation on Read the Docs.
75
+
76
+ [Read Documentation](https://marsilea.readthedocs.io/)
77
+
78
+ ## Installation
79
+
80
+ ```shell
81
+ pip install marsilea
82
+ ```
83
+
84
+ ## What is Composable Visualization?
85
+
86
+ <p align="center">
87
+ <picture align="center">
88
+ <img alt="Shows a bar chart with benchmark results." src="https://github.com/Marsilea-viz/marsilea/raw/main/img/showcase.gif" width="300">
89
+ </picture>
90
+ </p>
91
+
92
+ When we do visualization, we often need to combine multiple plots to show different aspects of the data.
93
+ For example, we may need to create a heatmap to show the expression of genes in different cells,
94
+ and then create a bar chart to show the expression of genes in different cell types.
95
+ A visualization contains multiple plots is called a composable visualization.
96
+ In Marsilea, we employ a declarative approach for user to create composable visualization incrementally.
97
+
98
+ ## Examples
99
+
100
+ <table>
101
+ <thead>
102
+ <tr>
103
+ <th>
104
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_tiobe_index.html">
105
+ Bar Chart With Image
106
+ </a>
107
+ </th>
108
+ <th>
109
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_oil_well.html">
110
+ Stacked Bar
111
+ </a>
112
+ </th>
113
+ <th>
114
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_arc_diagram.html">
115
+ Arc Diagram
116
+ </a>
117
+ </th>
118
+ </tr>
119
+ </thead>
120
+ <tbody>
121
+ <tr>
122
+ <td>
123
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_tiobe_index_001_2_00x.png" height="300px">
124
+ </td>
125
+ <td>
126
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_oil_well_001_2_00x.png" height="300px">
127
+ </td>
128
+ <td>
129
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_arc_diagram_001_2_00x.png" width="300px">
130
+ </td>
131
+ </tr>
132
+ </tbody>
133
+ </table>
134
+
135
+ <table>
136
+ <thead>
137
+ <tr>
138
+ <th>
139
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_pbmc3k.html">
140
+ Heatmap
141
+ </a>
142
+ </th>
143
+ <th>
144
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_oncoprint.html">
145
+ Oncoprint
146
+ </a>
147
+ </th>
148
+ <th>
149
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_upset.html">
150
+ Upsetplot
151
+ </a>
152
+ </th>
153
+ </tr>
154
+ </thead>
155
+ <tbody>
156
+ <tr>
157
+ <td>
158
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_pbmc3k_001_2_00x.png" width="300px">
159
+ </td>
160
+ <td>
161
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_oncoprint_005_2_00x.png" width="300px">
162
+ </td>
163
+ <td>
164
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_upset_001_2_00x.png" width="300px">
165
+ </td>
166
+ </tr>
167
+ </tbody>
168
+ </table>
@@ -0,0 +1,113 @@
1
+ <p align="center">
2
+ <picture align="center">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://github.com/Marsilea-viz/marsilea/raw/main/img/banner-dark.jpg">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://github.com/Marsilea-viz/marsilea/raw/main/img/banner-blue.jpg">
5
+ <img alt="Shows a bar chart with benchmark results." src="https://github.com/Marsilea-viz/marsilea/raw/main/img/banner-dark.jpg" width="400">
6
+ </picture>
7
+ </p>
8
+
9
+ [![Documentation Status](https://img.shields.io/readthedocs/marsilea?color=57B77E&logo=readthedocs&logoColor=white&style=flat-square)](https://marsilea.readthedocs.io/en/stable)
10
+ ![pypi version](https://img.shields.io/pypi/v/marsilea?color=0098FF&logo=python&logoColor=white&style=flat-square)
11
+ ![PyPI - License](https://img.shields.io/pypi/l/marsilea?color=FFD43B&style=flat-square)
12
+
13
+ # Marsilea: Declarative creation of composable visualization!
14
+
15
+ ---
16
+
17
+ ## Documentation
18
+
19
+ You can read the documentation on Read the Docs.
20
+
21
+ [Read Documentation](https://marsilea.readthedocs.io/)
22
+
23
+ ## Installation
24
+
25
+ ```shell
26
+ pip install marsilea
27
+ ```
28
+
29
+ ## What is Composable Visualization?
30
+
31
+ <p align="center">
32
+ <picture align="center">
33
+ <img alt="Shows a bar chart with benchmark results." src="https://github.com/Marsilea-viz/marsilea/raw/main/img/showcase.gif" width="300">
34
+ </picture>
35
+ </p>
36
+
37
+ When we do visualization, we often need to combine multiple plots to show different aspects of the data.
38
+ For example, we may need to create a heatmap to show the expression of genes in different cells,
39
+ and then create a bar chart to show the expression of genes in different cell types.
40
+ A visualization contains multiple plots is called a composable visualization.
41
+ In Marsilea, we employ a declarative approach for user to create composable visualization incrementally.
42
+
43
+ ## Examples
44
+
45
+ <table>
46
+ <thead>
47
+ <tr>
48
+ <th>
49
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_tiobe_index.html">
50
+ Bar Chart With Image
51
+ </a>
52
+ </th>
53
+ <th>
54
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_oil_well.html">
55
+ Stacked Bar
56
+ </a>
57
+ </th>
58
+ <th>
59
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_arc_diagram.html">
60
+ Arc Diagram
61
+ </a>
62
+ </th>
63
+ </tr>
64
+ </thead>
65
+ <tbody>
66
+ <tr>
67
+ <td>
68
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_tiobe_index_001_2_00x.png" height="300px">
69
+ </td>
70
+ <td>
71
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_oil_well_001_2_00x.png" height="300px">
72
+ </td>
73
+ <td>
74
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_arc_diagram_001_2_00x.png" width="300px">
75
+ </td>
76
+ </tr>
77
+ </tbody>
78
+ </table>
79
+
80
+ <table>
81
+ <thead>
82
+ <tr>
83
+ <th>
84
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_pbmc3k.html">
85
+ Heatmap
86
+ </a>
87
+ </th>
88
+ <th>
89
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_oncoprint.html">
90
+ Oncoprint
91
+ </a>
92
+ </th>
93
+ <th>
94
+ <a href="https://marsilea.readthedocs.io/en/latest/examples/Gallery/plot_upset.html">
95
+ Upsetplot
96
+ </a>
97
+ </th>
98
+ </tr>
99
+ </thead>
100
+ <tbody>
101
+ <tr>
102
+ <td>
103
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_pbmc3k_001_2_00x.png" width="300px">
104
+ </td>
105
+ <td>
106
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_oncoprint_005_2_00x.png" width="300px">
107
+ </td>
108
+ <td>
109
+ <img src="https://marsilea.readthedocs.io/en/latest/_images/sphx_glr_plot_upset_001_2_00x.png" width="300px">
110
+ </td>
111
+ </tr>
112
+ </tbody>
113
+ </table>
@@ -1,6 +1,6 @@
1
1
  [build-system]
2
- requires = ["flit_core >=3.2,<4"]
3
- build-backend = "flit_core.buildapi"
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "marsilea"
@@ -44,7 +44,13 @@ dev = [
44
44
  "mpl_fontkit"
45
45
  ]
46
46
 
47
- [tool.flit.sdist]
47
+ [tool.hatch.version]
48
+ path = "src/marsilea/__init__.py"
49
+
50
+ [tool.hatch.build.targets.wheel]
51
+ packages = ["src/marsilea", "src/oncoprinter"]
52
+
53
+ [tool.hatch.build.targets.sdist]
48
54
  exclude = [
49
55
  "docs",
50
56
  "app",
@@ -54,6 +60,17 @@ exclude = [
54
60
  "scripts",
55
61
  "readthedocs.yaml",
56
62
  ]
63
+ include = [
64
+ "README.md",
65
+ "LICENSE",
66
+ "pyproject.toml",
67
+ "setup.py",
68
+ "src/marsilea",
69
+ "src/oncoprinter",
70
+ ]
71
+
72
+ [tool.ruff.format]
73
+ docstring-code-format = true
57
74
 
58
75
  [tool.ruff.lint.per-file-ignores]
59
76
  "__init__.py" = ["F401"]
@@ -1,6 +1,6 @@
1
1
  """Declarative creation of composable visualization"""
2
2
 
3
- __version__ = "0.4.1"
3
+ __version__ = "0.4.3"
4
4
 
5
5
  import marsilea.plotter as plotter
6
6
  from ._deform import Deformation
@@ -84,19 +84,29 @@ class Deformation:
84
84
  self.data_col_reindex = reindex
85
85
  self._col_clustered = False
86
86
 
87
- def set_cluster(self, col=None, row=None, use_meta=True, linkage=None, **kwargs):
87
+ def set_cluster(
88
+ self,
89
+ col=None,
90
+ row=None,
91
+ use_meta=True,
92
+ linkage=None,
93
+ meta_linkage=None,
94
+ **kwargs,
95
+ ):
88
96
  if col is not None:
89
97
  self.is_col_cluster = col
90
98
  self.col_cluster_kws = kwargs
91
99
  self._col_clustered = False
92
100
  self._use_col_meta = use_meta
93
101
  self.col_linkage = linkage
102
+ self.col_meta_linkage = meta_linkage
94
103
  if row is not None:
95
104
  self.is_row_cluster = row
96
105
  self.row_cluster_kws = kwargs
97
106
  self._row_clustered = False
98
107
  self._use_row_meta = use_meta
99
108
  self.row_linkage = linkage
109
+ self.row_meta_linkage = meta_linkage
100
110
 
101
111
  def get_data(self):
102
112
  data = self.data
@@ -204,7 +214,9 @@ class Deformation:
204
214
  Dendrogram(chunk, linkage=linkage, key=k, **self.row_cluster_kws)
205
215
  )
206
216
 
207
- dg = GroupDendrogram(dens, **self.row_cluster_kws)
217
+ dg = GroupDendrogram(
218
+ dens, linkage=self.row_meta_linkage, **self.row_cluster_kws
219
+ )
208
220
  if self._use_row_meta:
209
221
  self.row_chunk_index = dg.reorder_index
210
222
  else:
@@ -232,7 +244,9 @@ class Deformation:
232
244
  dens.append(
233
245
  Dendrogram(chunk.T, linkage=linkage, key=k, **self.col_cluster_kws)
234
246
  )
235
- dg = GroupDendrogram(dens, **self.col_cluster_kws)
247
+ dg = GroupDendrogram(
248
+ dens, linkage=self.col_meta_linkage, **self.col_cluster_kws
249
+ )
236
250
  if self._use_col_meta:
237
251
  self.col_chunk_index = dg.reorder_index
238
252
  else:
@@ -606,9 +606,15 @@ class WhiteBoard(LegendMaker):
606
606
  return compose_board
607
607
 
608
608
  def _freeze_flex_plots(self, figure):
609
+ main_cell = self.layout.main_cell
610
+ main_width = main_cell.width
611
+ main_height = main_cell.height
612
+
609
613
  for plan in self._col_plan + self._row_plan:
610
614
  if plan.size is None:
611
- render_size = plan.get_canvas_size(figure)
615
+ render_size = plan.get_canvas_size(
616
+ figure, main_width=main_width, main_height=main_height
617
+ )
612
618
  if render_size is not None:
613
619
  self.layout.set_render_size(plan.name, render_size)
614
620
 
@@ -835,6 +841,7 @@ class ClusterBoard(WhiteBoard):
835
841
  method=None,
836
842
  metric=None,
837
843
  linkage=None,
844
+ meta_linkage=None,
838
845
  add_meta=True,
839
846
  add_base=True,
840
847
  add_divider=True,
@@ -848,6 +855,7 @@ class ClusterBoard(WhiteBoard):
848
855
  size=0.5,
849
856
  pad=0.0,
850
857
  get_meta_center=None,
858
+ rasterized=False,
851
859
  ):
852
860
  """Run cluster and add dendrogram
853
861
 
@@ -869,6 +877,10 @@ class ClusterBoard(WhiteBoard):
869
877
  Precomputed linkage matrix.
870
878
  See scipy's :meth:`linkage <scipy.cluster.hierarchy.linkage>` for
871
879
  specific format.
880
+ meta_linkage : ndarray
881
+ Precomputed chunk-level linkage matrix.
882
+ See scipy's :meth:`linkage <scipy.cluster.hierarchy.linkage>` for
883
+ specific format.
872
884
  add_meta : None | bool
873
885
  By default, add_meta is set to False if the linkage is provided, otherwise True.
874
886
  If the data is split, a meta dendrogram can be drawn for data
@@ -905,6 +917,8 @@ class ClusterBoard(WhiteBoard):
905
917
  array as input and return a 1D numpy array of the same length as the number
906
918
  of columns in the input, representing the centroid. The default will use the
907
919
  mean values.
920
+ rasterized : bool
921
+ If True, the dendrogram will be rasterized
908
922
 
909
923
  Examples
910
924
  --------
@@ -926,7 +940,7 @@ class ClusterBoard(WhiteBoard):
926
940
  :context: close-figs
927
941
 
928
942
  >>> h = ma.Heatmap(data)
929
- >>> h.hsplit(cut=[4, 8])
943
+ >>> h.cut_rows(cut=[4, 8])
930
944
  >>> h.add_dendrogram("left", add_base=False)
931
945
  >>> h.render()
932
946
 
@@ -936,7 +950,7 @@ class ClusterBoard(WhiteBoard):
936
950
  :context: close-figs
937
951
 
938
952
  >>> h = ma.Heatmap(data)
939
- >>> h.hsplit(cut=[4, 8])
953
+ >>> h.cut_rows(cut=[4, 8])
940
954
  >>> h.add_dendrogram("left", colors=["#5470c6", "#91cc75", "#fac858"])
941
955
  >>> h.render()
942
956
 
@@ -974,6 +988,7 @@ class ClusterBoard(WhiteBoard):
974
988
  colors=colors,
975
989
  divider_style=divider_style,
976
990
  meta_ratio=meta_ratio,
991
+ rasterized=rasterized,
977
992
  )
978
993
 
979
994
  deform = self.get_deform()
@@ -985,8 +1000,10 @@ class ClusterBoard(WhiteBoard):
985
1000
  method=method,
986
1001
  metric=metric,
987
1002
  linkage=linkage,
1003
+ meta_linkage=meta_linkage,
988
1004
  use_meta=add_meta,
989
1005
  get_meta_center=get_meta_center,
1006
+ rasterized=rasterized,
990
1007
  )
991
1008
  else:
992
1009
  den_options["pos"] = "col"
@@ -996,8 +1013,10 @@ class ClusterBoard(WhiteBoard):
996
1013
  method=method,
997
1014
  metric=metric,
998
1015
  linkage=linkage,
1016
+ meta_linkage=meta_linkage,
999
1017
  use_meta=add_meta,
1000
1018
  get_meta_center=get_meta_center,
1019
+ rasterized=rasterized,
1001
1020
  )
1002
1021
 
1003
1022
  def hsplit(self, cut=None, labels=None, order=None, spacing=0.01):
@@ -1160,7 +1179,7 @@ class ClusterBoard(WhiteBoard):
1160
1179
  >>> h = ma.Heatmap(data)
1161
1180
  >>> labels = ["A", "B", "C", "A", "B", "C", "A", "B", "C", "A"]
1162
1181
  >>> h.group_rows(labels, order=["A", "B", "C"])
1163
- >>> h.add_left(ma.plotter.Labels(labels), pad=.1)
1182
+ >>> h.add_left(ma.plotter.Labels(labels), pad=0.1)
1164
1183
  >>> h.render()
1165
1184
 
1166
1185
  """
@@ -1202,7 +1221,7 @@ class ClusterBoard(WhiteBoard):
1202
1221
  >>> h = ma.Heatmap(data)
1203
1222
  >>> labels = ["A", "B", "C", "A", "B", "C", "A", "B", "C", "A"]
1204
1223
  >>> h.group_cols(labels, order=["A", "B", "C"])
1205
- >>> h.add_top(ma.plotter.Labels(labels), pad=.1)
1224
+ >>> h.add_top(ma.plotter.Labels(labels), pad=0.1)
1206
1225
  >>> h.render()
1207
1226
 
1208
1227
  """
@@ -1334,7 +1353,11 @@ class ClusterBoard(WhiteBoard):
1334
1353
  if (color is not None) & (not is_color_like(color)):
1335
1354
  color = color[0]
1336
1355
  den_obj.draw(
1337
- ax, orient=den["side"], color=color, linewidth=den["linewidth"]
1356
+ ax,
1357
+ orient=den["side"],
1358
+ color=color,
1359
+ linewidth=den["linewidth"],
1360
+ rasterized=den["rasterized"],
1338
1361
  )
1339
1362
  else:
1340
1363
  den_obj.draw(
@@ -1349,6 +1372,7 @@ class ClusterBoard(WhiteBoard):
1349
1372
  divide=den["add_divider"],
1350
1373
  divide_style=den["divider_style"],
1351
1374
  meta_ratio=den["meta_ratio"],
1375
+ rasterized=den["rasterized"],
1352
1376
  )
1353
1377
 
1354
1378
  def _render_plan(self):
@@ -18,6 +18,7 @@ class _DendrogramBase:
18
18
  linkage=None,
19
19
  get_meta_center=None,
20
20
  key=None,
21
+ **kwargs,
21
22
  ):
22
23
  self.key = key
23
24
  self.data = data
@@ -137,7 +138,9 @@ class _DendrogramBase:
137
138
  y1 = yc[1]
138
139
  return x1, y1
139
140
 
140
- def _draw_dendrogram(self, ax, orient="top", color=".1", linewidth=0.7):
141
+ def _draw_dendrogram(
142
+ self, ax, orient="top", color=".1", linewidth=0.7, rasterized=False
143
+ ):
141
144
  x_coords = self._render_x_coords
142
145
  y_coords = self._render_y_coords
143
146
  if orient in ["right", "left"]:
@@ -147,6 +150,7 @@ class _DendrogramBase:
147
150
  [list(zip(x, y)) for x, y in zip(x_coords, y_coords)],
148
151
  color=color,
149
152
  linewidth=linewidth,
153
+ rasterized=rasterized,
150
154
  )
151
155
  ax.add_collection(lines)
152
156
 
@@ -173,6 +177,7 @@ class Dendrogram(_DendrogramBase):
173
177
  linkage=None,
174
178
  get_meta_center=None,
175
179
  key=None,
180
+ **kwargs,
176
181
  ):
177
182
  super().__init__(
178
183
  data,
@@ -181,6 +186,7 @@ class Dendrogram(_DendrogramBase):
181
186
  key=key,
182
187
  linkage=linkage,
183
188
  get_meta_center=get_meta_center,
189
+ **kwargs,
184
190
  )
185
191
 
186
192
  # here we left an empty **kwargs to align api with GroupDendrogram
@@ -193,6 +199,7 @@ class Dendrogram(_DendrogramBase):
193
199
  add_root=False,
194
200
  root_color=None,
195
201
  control_ax=True,
202
+ rasterized=False,
196
203
  **kwargs,
197
204
  ):
198
205
  """
@@ -210,6 +217,8 @@ class Dendrogram(_DendrogramBase):
210
217
  The color of the root line
211
218
  control_ax : bool
212
219
  Adjust the axes to ensure the dendrogram will display correctly
220
+ rasterized : bool
221
+ Rasterize the dendrogram to speed up rendering
213
222
 
214
223
  Returns
215
224
  -------
@@ -219,7 +228,9 @@ class Dendrogram(_DendrogramBase):
219
228
  root_color = color if root_color is None else root_color
220
229
  linewidth = 0.7 if linewidth is None else linewidth
221
230
 
222
- self._draw_dendrogram(ax, orient=orient, color=color, linewidth=linewidth)
231
+ self._draw_dendrogram(
232
+ ax, orient=orient, color=color, linewidth=linewidth, rasterized=rasterized
233
+ )
223
234
 
224
235
  xlim = self._render_xlim
225
236
  ylim = self._render_ylim
@@ -244,7 +255,11 @@ class Dendrogram(_DendrogramBase):
244
255
  x2 = x1
245
256
  y2 = ylim[1]
246
257
  root_line = Line2D(
247
- [x1, x2], [y1, y2], color=root_color, linewidth=linewidth
258
+ [x1, x2],
259
+ [y1, y2],
260
+ color=root_color,
261
+ linewidth=linewidth,
262
+ rasterized=rasterized,
248
263
  )
249
264
  ax.add_artist(root_line)
250
265
 
@@ -267,13 +282,20 @@ class GroupDendrogram(_DendrogramBase):
267
282
  dens: List[Dendrogram],
268
283
  method=None,
269
284
  metric=None,
285
+ linkage=None,
270
286
  get_meta_center=None,
271
287
  key=None,
272
288
  **kwargs,
273
289
  ):
274
290
  data = np.vstack([d.center for d in dens])
275
291
  super().__init__(
276
- data, method=method, metric=metric, get_meta_center=get_meta_center, key=key
292
+ data,
293
+ method=method,
294
+ metric=metric,
295
+ linkage=linkage,
296
+ get_meta_center=get_meta_center,
297
+ key=key,
298
+ **kwargs,
277
299
  )
278
300
  self.orig_dens = np.asarray(dens)
279
301
  self.dens = np.asarray(dens)[self.reorder_index]
@@ -305,6 +327,7 @@ class GroupDendrogram(_DendrogramBase):
305
327
  divide=True,
306
328
  divide_style="--",
307
329
  meta_ratio=0.2,
330
+ rasterized=False,
308
331
  ):
309
332
  """
310
333
 
@@ -330,6 +353,8 @@ class GroupDendrogram(_DendrogramBase):
330
353
  The linestyle of the divide line
331
354
  meta_ratio : float
332
355
  The size of meta dendrogram relative to the base dendrogram
356
+ rasterized : bool
357
+ Rasterize the dendrogram to speed up rendering
333
358
 
334
359
  """
335
360
 
@@ -418,7 +443,11 @@ class GroupDendrogram(_DendrogramBase):
418
443
  if add_meta:
419
444
  # Add meta dendrogram
420
445
  self._draw_dendrogram(
421
- ax, orient=orient, color=meta_color, linewidth=linewidth
446
+ ax,
447
+ orient=orient,
448
+ color=meta_color,
449
+ linewidth=linewidth,
450
+ rasterized=rasterized,
422
451
  )
423
452
 
424
453
  if divide & add_base & add_meta:
@@ -432,6 +461,7 @@ class GroupDendrogram(_DendrogramBase):
432
461
  linestyles=divide_style,
433
462
  color=meta_color,
434
463
  linewidth=linewidth,
464
+ rasterized=rasterized,
435
465
  )
436
466
  else:
437
467
  ax.vlines(
@@ -441,6 +471,7 @@ class GroupDendrogram(_DendrogramBase):
441
471
  linestyles=divide_style,
442
472
  color=meta_color,
443
473
  linewidth=linewidth,
474
+ rasterized=rasterized,
444
475
  )
445
476
 
446
477
  if add_base:
@@ -455,6 +486,7 @@ class GroupDendrogram(_DendrogramBase):
455
486
  linewidth=linewidth,
456
487
  root_color=meta_color,
457
488
  control_ax=False,
489
+ rasterized=rasterized,
458
490
  )
459
491
 
460
492
  xlim = render_xlim