ridgeplot-py 0.2.3__tar.gz → 0.2.5__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.
@@ -1,21 +1,22 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ridgeplot-py
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: Plotting ridgeplots with matplotlib
5
5
  License: MIT
6
6
  Author: Douglas Wu
7
7
  Author-email: wckdouglas@gmail.com
8
- Requires-Python: >=3.8,<4.0
8
+ Requires-Python: >=3.9,<4.0
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.8
12
11
  Classifier: Programming Language :: Python :: 3.9
13
12
  Classifier: Programming Language :: Python :: 3.10
14
13
  Classifier: Programming Language :: Python :: 3.11
15
- Provides-Extra: dev
16
- Requires-Dist: matplotlib (>=3.1.3,<4.0.0)
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: matplotlib (>=3.8,<4.0)
17
16
  Requires-Dist: more-itertools (>=8.9.0,<9.0.0)
18
17
  Requires-Dist: numpy (>=1.21.1,<2.0.0)
18
+ Requires-Dist: pandas (>=2.2.2,<3.0.0)
19
+ Requires-Dist: poetry (>=1.8.3,<2.0.0)
19
20
  Requires-Dist: scipy (>=1.8.0,<2.0.0)
20
21
  Description-Content-Type: text/markdown
21
22
 
@@ -1,35 +1,38 @@
1
1
  [tool.poetry]
2
2
  name = "ridgeplot-py"
3
- version = "0.2.3" # managed by poetry-dynamic-versioning
3
+ version = "0.2.5" # managed by poetry-dynamic-versioning
4
4
  description = "Plotting ridgeplots with matplotlib"
5
5
  authors = ["Douglas Wu <wckdouglas@gmail.com>"]
6
6
  license = "MIT"
7
- packages = [
8
- {"include" = "ridgeplot"}
9
- ]
7
+ packages = [{ "include" = "ridgeplot" }]
10
8
  readme = "README.md"
11
9
 
12
10
  [tool.poetry.dependencies]
13
- python = "^3.8"
11
+ python = "^3.9"
14
12
  scipy = "^1.8.0"
15
- matplotlib = "^3.1.3"
13
+ matplotlib = "^3.8"
16
14
  more-itertools = "^8.9.0"
17
15
  numpy = "^1.21.1"
16
+ pandas = "^2.2.2"
17
+ poetry = "^1.8.3"
18
18
 
19
- [tool.poetry.dev-dependencies]
19
+ [tool.poetry.group.dev]
20
+ optional = true
21
+
22
+ [tool.poetry.group.dev.dependencies]
20
23
  pytest = "^6.2.5"
21
24
  pytest-cov = "^2.12.1"
22
- mypy = "^0.910"
23
- black = "22.3.0"
25
+ mypy = "^0.990"
24
26
  ruff = "^0.0.290"
27
+ pre-commit = "^3.7.0"
25
28
 
26
29
  [tool.poetry-dynamic-versioning]
27
30
  enable = false
28
31
  vcs = "git"
29
- metadata= false
32
+ metadata = false
30
33
  bump = true
31
34
  style = "pep440"
32
- pattern = "^(?P<base>\\d+\\.\\d+\\.\\d+)(-?((?P<stage>[a-zA-Z]+)\\.?(?P<revision>\\d+)?))?"
35
+ pattern = "^(?P<base>\\d+\\.\\d+\\.\\d+)(-?((?P<stage>[a-zA-Z]+)\\.?(?P<revision>\\d+)?))?"
33
36
  format-jinja = """
34
37
  {%- set ns = namespace(version=base) -%}
35
38
  {%- for i in range(distance) -%}
@@ -42,20 +45,17 @@ format-jinja = """
42
45
  requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
43
46
  build-backend = "poetry_dynamic_versioning.backend"
44
47
 
45
- [tool.poetry.extras]
46
- dev = ["pytest", "pytest-cov", "mypy", "ruff", "black"]
47
-
48
48
  [tool.mypy]
49
49
  plugins = "numpy.typing.mypy_plugin"
50
+ ignore_missing_imports = true
51
+ strict_optional = true
52
+ check_untyped_defs = true
50
53
 
51
54
  [[tool.mypy.overrides]]
52
- module = [
53
- "matplotlib.*",
54
- "scipy.*"
55
- ]
56
- ignore_missing_imports = true
55
+ module = ["matplotlib.*", "scipy.*"]
56
+ ignore_errors = true
57
+
57
58
 
58
59
  [tool.ruff]
59
60
  line-length = 120
60
61
  select = ['E', 'F', 'W', 'I']
61
-
@@ -3,11 +3,13 @@ for matplotlib plots and a collections of color palettes.
3
3
  """
4
4
 
5
5
  from collections import OrderedDict
6
- from typing import Any, Dict, List
6
+ from typing import Any, Dict, List, Tuple
7
7
 
8
8
  import matplotlib.axes
9
9
  import matplotlib.patches as mpatches
10
10
  from matplotlib import legend
11
+ from matplotlib.cm import get_cmap
12
+ from matplotlib.colors import to_hex
11
13
 
12
14
  ColorPalette: Dict[str, List[str]] = dict(
13
15
  # 1. maximum
@@ -248,7 +250,12 @@ class ColorEncoder:
248
250
  self.fit(categories, colors=colors)
249
251
  return self.transform(categories)
250
252
 
251
- def show_legend(self, ax: matplotlib.axes, sort: bool = False, **kwargs: Dict[str, Any]) -> legend.Legend:
253
+ def show_legend(
254
+ self,
255
+ ax: matplotlib.axes._axes.Axes,
256
+ sort: bool = False,
257
+ **kwargs: Dict[str, Any],
258
+ ) -> legend.Legend:
252
259
  """
253
260
  Adding matplotlib legend describing the color encoder to a matplotlib ax object
254
261
 
@@ -266,3 +273,14 @@ class ColorEncoder:
266
273
  pat = [mpatches.Patch(color=col, label=lab) for lab, col in self.encoder.items()]
267
274
  lgd = ax.legend(handles=pat, **kwargs)
268
275
  return lgd
276
+
277
+
278
+ def get_cmap_color_values(cmap_name: str) -> Tuple[str, str]:
279
+ """
280
+ Get color values for the min and max color in a color map
281
+
282
+ :param str cmap_name: color map name (e.g. viridis)
283
+ :return Tuple[str, str]: hex code for the min and max color
284
+ """
285
+ cmap = get_cmap(cmap_name)
286
+ return to_hex(cmap(0.0)), to_hex(cmap(1.0))
@@ -0,0 +1,68 @@
1
+ """
2
+ for most of the part, this is copied from:
3
+ https://stackoverflow.com/questions/59381273/heatmap-with-circles-indicating-size-of-population
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Optional
9
+
10
+ import matplotlib.axes
11
+ import matplotlib.pyplot as plt
12
+ import numpy as np
13
+ import pandas as pd
14
+ from matplotlib.collections import PatchCollection
15
+
16
+
17
+ def dotted_heatmap(
18
+ data: pd.DataFrame,
19
+ ax: matplotlib.axes._axes.Axes,
20
+ cmap: str = "cividis",
21
+ circle_size: Optional[float] = None,
22
+ ):
23
+ """
24
+ Plotting dotted heatmap
25
+
26
+ Example:
27
+ ```
28
+ >>> import matplotlib.pyplot as plt
29
+ >>> fig = plt.figure()
30
+ >>> ax = fig.add_subplot(111)
31
+ >>> data = pd.DataFrame(
32
+ ... np.random.randn(n, n),
33
+ ... index=[f"feature{i}" for i in range(n)],
34
+ ... columns=[f"sample{i}" for i in range(n)],
35
+ ... )
36
+ >>> dotted_heatmap(data=data,ax=ax, cmap="viridis")
37
+ ```
38
+
39
+ :param pd.DataFrame data: data to plot
40
+ :param matplotlib.axes ax: matplotlib ax object
41
+ :param str cmap: cmap value, defaults to "cividis"
42
+ :param Optional[float] circle_size: raidus of the circles,
43
+ if None, we will use relaive sizes, defaults to None
44
+ """
45
+ nrows, ncols = data.shape
46
+ x, y = np.meshgrid(np.arange(ncols), np.arange(nrows))
47
+ radii = data.values / 2 / data.values.max()
48
+ # radius is relative if circle_size is None
49
+ circles = [
50
+ plt.Circle((j, i), radius=circle_size if circle_size is not None else r)
51
+ for r, j, i in zip(radii.flat, x.flat, y.flat)
52
+ ]
53
+ col = PatchCollection(circles, array=data.values.flatten(), cmap=cmap)
54
+ ax.add_collection(col)
55
+
56
+ ax.set_xticks(np.arange(ncols))
57
+ ax.set_xticklabels(data.columns)
58
+ ax.set_yticks(np.arange(nrows))
59
+ ax.set_yticklabels(data.index)
60
+
61
+ ax.set_xticks(np.arange(ncols + 1) - 0.5, minor=True)
62
+ ax.set_yticks(np.arange(nrows + 1) - 0.5, minor=True)
63
+ ax.grid(which="minor", alpha=0.5, color="white")
64
+ ax.tick_params(left=False, bottom=False)
65
+ for d in ["top", "bottom", "left", "right"]:
66
+ ax.spines[d].set(alpha=0.5)
67
+ cbar = plt.colorbar(col)
68
+ return cbar
@@ -1,6 +1,7 @@
1
1
  """This module contains the main function to plot
2
2
  [ridgeplots](https://clauswilke.com/blog/2017/09/15/goodbye-joyplots/).
3
3
  """
4
+
4
5
  from __future__ import annotations
5
6
 
6
7
  from typing import Optional
@@ -18,7 +19,7 @@ class RidgePlotError(Exception):
18
19
 
19
20
 
20
21
  def ridgeplot(
21
- ax: matplotlib.axes,
22
+ ax: matplotlib.axes._axes.Axes,
22
23
  data: dict[str, list[float]],
23
24
  xlim: Optional[tuple[float, float]] = None,
24
25
  fill_colors: Optional[list[str]] = None,
@@ -1,33 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from setuptools import setup
3
-
4
- packages = \
5
- ['ridgeplot']
6
-
7
- package_data = \
8
- {'': ['*']}
9
-
10
- install_requires = \
11
- ['matplotlib>=3.1.3,<4.0.0',
12
- 'more-itertools>=8.9.0,<9.0.0',
13
- 'numpy>=1.21.1,<2.0.0',
14
- 'scipy>=1.8.0,<2.0.0']
15
-
16
- setup_kwargs = {
17
- 'name': 'ridgeplot-py',
18
- 'version': '0.2.3',
19
- 'description': 'Plotting ridgeplots with matplotlib',
20
- 'long_description': '# ridgeplot-py #\n\n[![CI](https://github.com/wckdouglas/ridgeplot-py/actions/workflows/ci.yaml/badge.svg)](https://github.com/wckdouglas/ridgeplot-py/actions/workflows/ci.yaml) [![codecov](https://codecov.io/gh/wckdouglas/ridgeplot-py/branch/main/graph/badge.svg?token=2owCGZa1K4)](https://codecov.io/gh/wckdouglas/ridgeplot-py) [![PyPI version](https://badge.fury.io/py/ridgeplot-py.svg)](https://badge.fury.io/py/ridgeplot-py) [![conda-forge](https://anaconda.org/conda-forge/ridgeplot-py/badges/version.svg)](https://anaconda.org/conda-forge/ridgeplot-py)\n\n\nThis is a simple module for plotting [ridgeplot](https://clauswilke.com/blog/2017/09/15/goodbye-joyplots/) with the [scipy ecosystem](https://www.scipy.org/about.html).\n\nRidgeplot is a great data visualization technique to compare distributions from multiple groups at the same time, and was first introduced in 2017 as joy plot:\n\n<blockquote class="twitter-tweet"><p lang="en" dir="ltr">I hereby propose that we call these &quot;joy plots&quot; <a href="https://twitter.com/hashtag/rstats?src=hash&amp;ref_src=twsrc%5Etfw">#rstats</a> <a href="https://t.co/uuLGpQLAwY">https://t.co/uuLGpQLAwY</a></p>&mdash; Jenny Bryan (@JennyBryan) <a href="https://twitter.com/JennyBryan/status/856674638981550080?ref_src=twsrc%5Etfw">April 25, 2017</a></blockquote> \n\n[ridgeplot-py](https://pypi.org/project/ridgeplot-py/) provides a simple API to produce matplotlib-compatible ridgeplots, as well as a handy [ColorEncoder](https://github.com/wckdouglas/ridgeplot-py/blob/0198628ce0622e2e7f4f4e9284165d5d09324ca9/ridgeplot/colors.py#L117) class with scikit-learn syntax for manipulating color annotations in a consistent way [through out manuscripts or presentations].\n\n## Install ##\n\n```bash\ngit clone git@github.com:wckdouglas/ridgeplot-py.git\ncd ridgeplot-py\npython setup.py install \n```\n\nor via conda:\n\n```bash\nconda install -c conda-forge ridgeplot-py\n```\n\nor via pypi:\n\n```bash\npip install ridgeplot-py\n```\n\n## Usage ##\n\n```python\nfrom ridgeplot import ridgeplot\nfrom ridgeplot.colors import ColorEncoder, ColorPalette\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# mocking some data\n# the input data should be a dict of\n# - keys: group names for the distributions\n# - values: list of values \ndata = {}\nfor i in range(8):\n data[\'data_{}\'.format(i)] = np.random.randn(100) * (i+1)\n\n# make the plot\nfig = plt.figure()\nax = fig.add_subplot(111)\nridgeplot(\n ax, \n data, \n xlim=(-20,20), \n label_size=15\n)\n```\n\n![img](https://raw.githubusercontent.com/wckdouglas/ridgeplot-py/main/img/ridgeplot.png)\n\n\n## Example ##\n\nA [notebook](https://github.com/wckdouglas/ridgeplot-py/blob/main/Example.ipynb) showing quick howto is included in this repo!\n\n\n## Build on Apple silicon ##\n\nscipy may cause error and may be able to solved by the [this stackoverflow answer](https://stackoverflow.com/a/71764028):\n\n```\nbrew install openblas\nexport OPENBLAS="$(brew --prefix openblas)" \npoetry install\n```\n',
21
- 'author': 'Douglas Wu',
22
- 'author_email': 'wckdouglas@gmail.com',
23
- 'maintainer': 'None',
24
- 'maintainer_email': 'None',
25
- 'url': 'None',
26
- 'packages': packages,
27
- 'package_data': package_data,
28
- 'install_requires': install_requires,
29
- 'python_requires': '>=3.8,<4.0',
30
- }
31
-
32
-
33
- setup(**setup_kwargs)
File without changes
File without changes