plot-io 0.12.0__py3-none-win_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plot_io/__init__.py +73 -0
- plot_io/_methods.py +1691 -0
- plot_io/_native/__init__.py +199 -0
- plot_io/_native/__main__.py +197 -0
- plot_io/_native/_api.py +457 -0
- plot_io/_native/bin/windows-arm64.dll +0 -0
- plot_io/_native/kernels.py +335 -0
- plot_io/_native/manifest.json +49 -0
- plot_io/axis.py +1347 -0
- plot_io/boxes.py +1156 -0
- plot_io/canvas.py +389 -0
- plot_io/color/__init__.py +3 -0
- plot_io/color/data.py +1646 -0
- plot_io/color/maps.py +922 -0
- plot_io/color/values.py +295 -0
- plot_io/color/variants.py +1246 -0
- plot_io/colorbar.py +1426 -0
- plot_io/columns.py +614 -0
- plot_io/decorations.py +920 -0
- plot_io/defaults.py +809 -0
- plot_io/density.py +113 -0
- plot_io/ext.py +68 -0
- plot_io/facets.py +240 -0
- plot_io/figure.py +788 -0
- plot_io/formatters.py +97 -0
- plot_io/genome/__init__.py +17 -0
- plot_io/genome/adapters.py +356 -0
- plot_io/genome/combine.py +123 -0
- plot_io/genome/contacts.py +508 -0
- plot_io/genome/intervals.py +750 -0
- plot_io/genome/lanes.py +191 -0
- plot_io/genome/layout.py +184 -0
- plot_io/genome/links.py +364 -0
- plot_io/genome/pack.py +27 -0
- plot_io/genome/readers.py +145 -0
- plot_io/genome/regions.py +228 -0
- plot_io/genome/scale.py +349 -0
- plot_io/genome/series.py +344 -0
- plot_io/genome/signal.py +621 -0
- plot_io/genome/sites.py +782 -0
- plot_io/genome/sources.py +459 -0
- plot_io/genome/testing.py +161 -0
- plot_io/geometry.py +289 -0
- plot_io/groups.py +308 -0
- plot_io/guides.py +503 -0
- plot_io/helpers/__init__.py +17 -0
- plot_io/helpers/clustermap.py +202 -0
- plot_io/helpers/dendrogram.py +172 -0
- plot_io/helpers/grids.py +304 -0
- plot_io/helpers/qq.py +334 -0
- plot_io/helpers/raincloud.py +249 -0
- plot_io/helpers/tree.py +214 -0
- plot_io/helpers/volcano.py +505 -0
- plot_io/hints.py +125 -0
- plot_io/kernels.py +740 -0
- plot_io/labels.py +566 -0
- plot_io/layers/__init__.py +100 -0
- plot_io/layers/base.py +630 -0
- plot_io/layers/context.py +87 -0
- plot_io/layers/core.py +446 -0
- plot_io/layers/geoms.py +1362 -0
- plot_io/layers/grammar.py +586 -0
- plot_io/layers/paint.py +614 -0
- plot_io/layers/pipeline.py +170 -0
- plot_io/layers/positions.py +431 -0
- plot_io/layers/stats.py +1088 -0
- plot_io/layout.py +1381 -0
- plot_io/legend.py +605 -0
- plot_io/levels.py +509 -0
- plot_io/limits.py +124 -0
- plot_io/lines.py +42 -0
- plot_io/mapped.py +522 -0
- plot_io/markers.py +110 -0
- plot_io/markup.py +128 -0
- plot_io/numbers.py +354 -0
- plot_io/occupancy.py +295 -0
- plot_io/plot.py +597 -0
- plot_io/presets/__init__.py +51 -0
- plot_io/presets/_util.py +153 -0
- plot_io/presets/area.py +145 -0
- plot_io/presets/bar.py +261 -0
- plot_io/presets/box.py +400 -0
- plot_io/presets/catpoints.py +177 -0
- plot_io/presets/contour.py +353 -0
- plot_io/presets/curves.py +30 -0
- plot_io/presets/dots.py +355 -0
- plot_io/presets/ecdf.py +97 -0
- plot_io/presets/errorbar.py +106 -0
- plot_io/presets/errors.py +296 -0
- plot_io/presets/fill.py +74 -0
- plot_io/presets/heatmap.py +322 -0
- plot_io/presets/hexbin.py +198 -0
- plot_io/presets/hist.py +391 -0
- plot_io/presets/hist2d.py +87 -0
- plot_io/presets/kde.py +162 -0
- plot_io/presets/kde2d.py +147 -0
- plot_io/presets/line.py +143 -0
- plot_io/presets/pie.py +502 -0
- plot_io/presets/regression.py +115 -0
- plot_io/presets/scatter.py +194 -0
- plot_io/presets/stem.py +100 -0
- plot_io/presets/violin.py +323 -0
- plot_io/py.typed +0 -0
- plot_io/registry.py +82 -0
- plot_io/render.py +480 -0
- plot_io/rows.py +491 -0
- plot_io/scales.py +103 -0
- plot_io/seams.py +138 -0
- plot_io/settings.py +807 -0
- plot_io/shapes.py +66 -0
- plot_io/sharing.py +232 -0
- plot_io/sizemaps.py +97 -0
- plot_io/spec.py +240 -0
- plot_io/states.py +216 -0
- plot_io/styles/__init__.py +307 -0
- plot_io/styles/library.py +397 -0
- plot_io/tables.py +138 -0
- plot_io/text.py +412 -0
- plot_io/ticks.py +400 -0
- plot_io/times.py +287 -0
- plot_io/titles.py +225 -0
- plot_io/transform.py +114 -0
- plot_io/types.py +13604 -0
- plot_io/units.py +768 -0
- plot_io/validators.py +1029 -0
- plot_io/values.py +190 -0
- plot_io-0.12.0.dist-info/METADATA +215 -0
- plot_io-0.12.0.dist-info/RECORD +130 -0
- plot_io-0.12.0.dist-info/WHEEL +4 -0
- plot_io-0.12.0.dist-info/licenses/LICENSE +28 -0
plot_io/values.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""Values given to ``color``, ``size`` and ``opacity``: colors, numbers to map, or computed
|
|
2
|
+
values (``"density"``).
|
|
3
|
+
|
|
4
|
+
The rules: a color string or a tuple of 3 or 4 numbers is one color; a list of colors is
|
|
5
|
+
one color per point; a list, array or other buffer of numbers is one value per point,
|
|
6
|
+
mapped through the series' ``color_map`` (or, for ``size``, its ``size_map``);
|
|
7
|
+
``"density"`` or a :class:`~plot_io.Density` is computed from the series' points.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import array
|
|
11
|
+
import math
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from vec_io.arrays import doubles
|
|
16
|
+
|
|
17
|
+
from . import kernels
|
|
18
|
+
from .validators import Custom, length, real, typed
|
|
19
|
+
|
|
20
|
+
__all__ = ["Values", "paint", "category_paint", "size_value", "is_computed",
|
|
21
|
+
"check_size_map", "lazy"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class _Lazy:
|
|
25
|
+
"""The function ``name`` of ``plot_io.module``, imported when first called."""
|
|
26
|
+
|
|
27
|
+
__slots__ = ("module", "__name__")
|
|
28
|
+
|
|
29
|
+
def __init__(self, module: str, name: str) -> None:
|
|
30
|
+
self.module = module
|
|
31
|
+
self.__name__ = name
|
|
32
|
+
|
|
33
|
+
def _fn(self) -> Any:
|
|
34
|
+
from importlib import import_module
|
|
35
|
+
return getattr(import_module("plot_io." + self.module), self.__name__)
|
|
36
|
+
|
|
37
|
+
def __call__(self, *args: Any, **kw: Any) -> Any:
|
|
38
|
+
return self._fn()(*args, **kw)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def value_type(self) -> str:
|
|
42
|
+
"""The type of the values the function accepts (:func:`~plot_io.validators.typed`)."""
|
|
43
|
+
return getattr(self._fn(), "value_type", "Any")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def lazy(module: str, name: str) -> Callable[..., Any]:
|
|
47
|
+
"""The function ``name`` of ``plot_io.module``, imported when first called (for
|
|
48
|
+
validators of modules that import this one)."""
|
|
49
|
+
return _Lazy(module, name)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class Values:
|
|
53
|
+
"""Numbers to map through a color or size map: an ``array('d')`` (one per point), or a
|
|
54
|
+
dict ``{category: number}``."""
|
|
55
|
+
|
|
56
|
+
__slots__ = ("data",)
|
|
57
|
+
|
|
58
|
+
def __init__(self, data: Any) -> None:
|
|
59
|
+
self.data = data
|
|
60
|
+
|
|
61
|
+
def __len__(self) -> int:
|
|
62
|
+
return len(self.data)
|
|
63
|
+
|
|
64
|
+
def __repr__(self) -> str:
|
|
65
|
+
return f"Values({len(self.data)})"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def is_computed(v: Any) -> bool:
|
|
69
|
+
from .density import Density
|
|
70
|
+
return isinstance(v, Density)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _number(x: Any) -> bool:
|
|
74
|
+
return real(x) is not None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _is_color_tuple(v: Any) -> bool:
|
|
78
|
+
return isinstance(v, tuple) and len(v) in (3, 4) and all(_number(c) for c in v)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _buffer(v: Any) -> Any:
|
|
82
|
+
if isinstance(v, (str, bytes, bytearray, list, tuple, dict)):
|
|
83
|
+
return None
|
|
84
|
+
try:
|
|
85
|
+
return memoryview(v)
|
|
86
|
+
except TypeError:
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _rgba_rows(v: Any) -> Any:
|
|
91
|
+
"""An ``(n, 3)`` or ``(n, 4)`` numeric buffer as ``(n, 4)`` doubles (alpha 1 added)."""
|
|
92
|
+
n, k, _, flat = kernels.grid(v)
|
|
93
|
+
if any(x > 1.0 for x in flat[:4096]): # 0–255 integers
|
|
94
|
+
flat = array.array("d", (x / 255.0 for x in flat))
|
|
95
|
+
if k == 3:
|
|
96
|
+
out = array.array("d", [1.0]) * (n * 4)
|
|
97
|
+
for i in range(n):
|
|
98
|
+
out[4 * i:4 * i + 3] = flat[3 * i:3 * i + 3]
|
|
99
|
+
flat = out
|
|
100
|
+
mv: Any = memoryview(flat).cast("B")
|
|
101
|
+
return mv.cast("d", (n, 4))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _color_map_error(name: str) -> ValueError:
|
|
105
|
+
return ValueError(f"a ColorMap goes in color_map (alias cmap), and the values in {name}")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def paint(v: Any, name: str = "color") -> Any:
|
|
109
|
+
"""A color, colors per point, values per point (``Values``), or ``"density"``."""
|
|
110
|
+
from .density import Density
|
|
111
|
+
from .color.maps import ColorMap
|
|
112
|
+
from .color.values import color
|
|
113
|
+
|
|
114
|
+
if isinstance(v, ColorMap):
|
|
115
|
+
raise _color_map_error(name)
|
|
116
|
+
if isinstance(v, Density):
|
|
117
|
+
return v
|
|
118
|
+
if isinstance(v, str):
|
|
119
|
+
if v.strip().lower() == "density":
|
|
120
|
+
return Density()
|
|
121
|
+
return color(v)
|
|
122
|
+
if _is_color_tuple(v):
|
|
123
|
+
return color(v)
|
|
124
|
+
if isinstance(v, dict):
|
|
125
|
+
raise ValueError(f"a dict of {name}s applies to categorical series (box, bar, violin)")
|
|
126
|
+
mv = _buffer(v)
|
|
127
|
+
if mv is not None:
|
|
128
|
+
if mv.ndim == 2 and mv.shape[1] in (3, 4):
|
|
129
|
+
return _rgba_rows(v)
|
|
130
|
+
if mv.ndim == 1:
|
|
131
|
+
return Values(doubles(v))
|
|
132
|
+
raise ValueError(f"{name}: expected a 1-D buffer of values or an (n, 3|4) buffer of "
|
|
133
|
+
f"colors, got shape {tuple(mv.shape)}")
|
|
134
|
+
if hasattr(v, "to_numpy") and not isinstance(v, (list, tuple)):
|
|
135
|
+
return paint(v.to_numpy(), name)
|
|
136
|
+
if isinstance(v, (list, tuple)):
|
|
137
|
+
items = list(v)
|
|
138
|
+
if items and all(_number(x) or x is None for x in items):
|
|
139
|
+
if isinstance(v, tuple):
|
|
140
|
+
raise ValueError(f"{name}: a tuple of numbers is one color (3 or 4 numbers "
|
|
141
|
+
f"in [0, 1], or 0–255); use a list for one value per point")
|
|
142
|
+
return Values(doubles(items))
|
|
143
|
+
return [color(c) if c is not None else None for c in items]
|
|
144
|
+
return color(v)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@typed("ColorLike | Column | Density | Mapping[Any, Any]")
|
|
148
|
+
def category_paint(v: Any, name: str = "color") -> Any:
|
|
149
|
+
"""``paint`` for categorical series: also a dict ``{category: color or number}``."""
|
|
150
|
+
if isinstance(v, dict):
|
|
151
|
+
if v and all(_number(x) or x is None for x in v.values()):
|
|
152
|
+
return Values({k: (math.nan if x is None else float(x)) for k, x in v.items()})
|
|
153
|
+
from .color.values import color
|
|
154
|
+
return {k: (color(c) if c is not None else None) for k, c in v.items()}
|
|
155
|
+
return paint(v, name)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@typed("SupportsFloat | str | Column | Density")
|
|
159
|
+
def _size_value(v: Any) -> Any:
|
|
160
|
+
from .density import Density
|
|
161
|
+
from .sizemaps import SizeMap
|
|
162
|
+
|
|
163
|
+
if isinstance(v, SizeMap):
|
|
164
|
+
raise ValueError("a SizeMap goes in size_map (alias smap), and the values in size")
|
|
165
|
+
if isinstance(v, Density):
|
|
166
|
+
return v
|
|
167
|
+
if isinstance(v, str) and v.strip().lower() == "density":
|
|
168
|
+
return Density()
|
|
169
|
+
if _number(v) or isinstance(v, str):
|
|
170
|
+
return _SIZE(v)
|
|
171
|
+
try:
|
|
172
|
+
return doubles(v.to_numpy() if hasattr(v, "to_numpy") else v)
|
|
173
|
+
except (TypeError, ValueError):
|
|
174
|
+
raise ValueError(f"expected a size, sizes or \"density\", got {v!r}") from None
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
_SIZE = length(lo=0)
|
|
178
|
+
#: A size (px), sizes per point, or ``"density"`` (mapped through ``size_map``); resolved
|
|
179
|
+
#: as a length (single values).
|
|
180
|
+
size_value = Custom(_size_value, like=_SIZE)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@typed("SizeMap | tuple[SupportsFloat | str, SupportsFloat | str] | list[SupportsFloat | str]")
|
|
184
|
+
def check_size_map(v: Any) -> Any:
|
|
185
|
+
from .sizemaps import SizeMap
|
|
186
|
+
if isinstance(v, SizeMap):
|
|
187
|
+
return v
|
|
188
|
+
if isinstance(v, (tuple, list)) and len(v) == 2:
|
|
189
|
+
return SizeMap(tuple(v))
|
|
190
|
+
raise ValueError(f"expected a SizeMap or a pair of sizes, got {v!r}")
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: plot_io
|
|
3
|
+
Version: 0.12.0
|
|
4
|
+
Summary: Plots for PDF, EPS, SVG, PNG, JPEG, JPEG XL and AVIF, drawn with vec_io
|
|
5
|
+
Project-URL: Repository, https://github.com/ajgouhier/plot_io
|
|
6
|
+
Author-email: Arthur Gouhier <ajgouhier@gmail.com>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Requires-Dist: vec-io<0.8,>=0.7
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
13
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
14
|
+
Requires-Dist: ziglang==0.15.1; extra == 'dev'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# plot_io
|
|
18
|
+
|
|
19
|
+
Plotting library in Python. No dependency other than [vec_io](https://github.com/ajgouhier/vec_io).
|
|
20
|
+
|
|
21
|
+
* **Familiar:** a figure of plots; `scatter`, `line`, `fill`, `box`, `heatmap`, `bar`,
|
|
22
|
+
`hist`, `kde` (1-D and 2-D), `ecdf`, `violin`, `strip`, `swarm`, `area`, `errorbar`, `stem`,
|
|
23
|
+
`regression`, `hist2d`, `hexbin`, `contour`, `pie`, `dots`; reference lines, spans, text and
|
|
24
|
+
annotations; `color`, `marker`, `opacity`, `limits`, `scale`, `legend`.
|
|
25
|
+
* **Statistical helpers:** `qq`, `raincloud`, `volcano`, `ma`, `manhattan`, `dendrogram`
|
|
26
|
+
plot types; significance brackets; point labels placed without overlaps; hierarchical
|
|
27
|
+
clustering (`plt.linkage`, scipy's methods); `plt.joint`, `plt.pairs` and `plt.clustermap`
|
|
28
|
+
figures in one call.
|
|
29
|
+
* **Units:** lengths in px, pt, in, mm, `em`, `%` of the axes or of another setting, data
|
|
30
|
+
units and durations (`width="1.5in"`, `tick_length="0.5em"`, `width="60%"`,
|
|
31
|
+
`cap_length="12h"`); `var()` and `calc()` relate settings (`"calc(var(--gap) * 2)"`).
|
|
32
|
+
* **One way to set things:** keywords at creation or `set(...)` on any object; figure
|
|
33
|
+
settings (font, color maps, line width…) are inherited by plots and series.
|
|
34
|
+
* **Layouts:** an explicit grid of ids with spans, or automatic rows and columns; plots
|
|
35
|
+
sized individually; axis lines (or plot borders) aligned across the figure; margins from
|
|
36
|
+
the real text metrics; shared axes; secondary axes; facets of a table.
|
|
37
|
+
* **Titles, legends and colorbars on any side:** several titles per plot; titles,
|
|
38
|
+
legends and colorbar keys shared by any rectangle of plots, nested as headers;
|
|
39
|
+
`share_legend` for one legend per row, column or figure; markup (`<i>`, `<b>`,
|
|
40
|
+
`<sup>`, …) in any text.
|
|
41
|
+
* **Data:** columns of any table by name (`data=`: dicts, pandas, polars, numpy), one
|
|
42
|
+
series per group (`group=`), numbers given as colors or sizes, point density (scipy's
|
|
43
|
+
`gaussian_kde`, in C) for colors, sizes, opacity and drawing order.
|
|
44
|
+
* **Axes:** linear, log, log2, log10, sqrt, exp, symlog, logit, time and category scales;
|
|
45
|
+
limits such as `"0/max"` or `"q:0.01/q:0.99"`; ticks with shared decimals and ×10ᵏ
|
|
46
|
+
factors, calendar ticks for dates.
|
|
47
|
+
* **Colors:** one system of color maps with kinds (qualitative, sequential, diverging,
|
|
48
|
+
cyclic; `okabe_ito` for color-vision deficiencies), a default map per kind, `center=`
|
|
49
|
+
for data about a value, interpolation in Oklab, colorbars;
|
|
50
|
+
marker sizes by area, equal for every shape.
|
|
51
|
+
* **Styles:** `style="matplotlib"`, `"seaborn"`, `"ggplot2"`, `"altair"`, `"matlab"`,
|
|
52
|
+
`"tufte"` give the look of those libraries; styles are presets of settings, and your
|
|
53
|
+
own build on them (a variant: `{"base": "seaborn", …}`).
|
|
54
|
+
* **Output:** PDF, EPS (transparency flattened), SVG, PNG, JPEG, JPEG XL and AVIF, by the
|
|
55
|
+
file's extension; CMYK, PDF/A and text as outlines are options of the save
|
|
56
|
+
(`color="cmyk"`, `pdf={"a": "2b"}`, `text="paths"`).
|
|
57
|
+
* **Large data:** one million points mapped and drawn in C; `simplify="auto"` drops what
|
|
58
|
+
cannot be seen, `rasterize=` turns a series into an image inside the PDF.
|
|
59
|
+
* **Genome tracks:** `bigwig` signals, `bed` intervals, `genes` and `gtf` gene models,
|
|
60
|
+
`hic` triangles and `links` over a region, and `site_profile` and `site_heatmap` around
|
|
61
|
+
sites, read from gwseq_io's readers (or any object with their methods) without
|
|
62
|
+
depending on gwseq_io.
|
|
63
|
+
|
|
64
|
+
## Install
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
pip install plot_io
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Python 3.11+. Text is shaped (kerned) and its fonts embedded by vec_io; it needs an
|
|
71
|
+
installed outline font, the default family list (`Helvetica, Nimbus Sans, Nimbus Sans L,
|
|
72
|
+
TeX Gyre Heros, FreeSans, Arial, Liberation Sans, Arimo`) taking its first installed family
|
|
73
|
+
([docs/api.md](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md#1-conventions)). JPEG XL
|
|
74
|
+
and AVIF output need vec_io's optional libjxl and libavif.
|
|
75
|
+
|
|
76
|
+
Wheels hold plot_io's C library prebuilt for Linux (x86_64, aarch64; glibc or musl),
|
|
77
|
+
Windows (x86_64, arm64) and macOS 13+ (arm64). Elsewhere (Intel Macs, other CPUs), pip
|
|
78
|
+
builds it from the sdist with the local C compiler (gcc or clang; on Windows clang or MinGW,
|
|
79
|
+
not MSVC); `pip install --no-binary plot_io plot_io` does so on any platform, and
|
|
80
|
+
`pip install .` from a checkout. With the pinned zig in the environment (`pip install
|
|
81
|
+
--require-hashes -r tools/zig.lock`, then `--no-build-isolation`), the sdist builds the
|
|
82
|
+
release binary itself.
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
python -m plot_io._native verify # the library loads, is the release binary, computes as it should
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Quick start
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import math
|
|
92
|
+
import random
|
|
93
|
+
|
|
94
|
+
import plot_io as plt
|
|
95
|
+
|
|
96
|
+
rng = random.Random(1)
|
|
97
|
+
x = [rng.uniform(0, 10) for _ in range(100)]
|
|
98
|
+
y = [v + rng.gauss(0, 1) for v in x]
|
|
99
|
+
s = plt.Scatter(x, y, name="data")
|
|
100
|
+
s.plot.x_axis(label="Time (s)")
|
|
101
|
+
s.plot.save("scatter.pdf")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
t = [i / 10 for i in range(1, 101)]
|
|
106
|
+
v = [math.exp(-k / 4) * (2 + math.sin(3 * k)) for k in t]
|
|
107
|
+
upper, lower = [a * 1.3 for a in v], [a * 0.7 for a in v]
|
|
108
|
+
va, vb = [rng.gauss(0, 1) for _ in range(50)], [rng.gauss(1, 1) for _ in range(50)]
|
|
109
|
+
matrix = [[math.sin(i / 2) * math.cos(j / 3) for j in range(6)] for i in range(4)]
|
|
110
|
+
columns, rows = list("ABCDEF"), ["w", "x", "y", "z"]
|
|
111
|
+
z = [a - b for a, b in zip(x, y)]
|
|
112
|
+
|
|
113
|
+
fig = plt.Figure(layout=[[1, 1, 2], [3, 4, 2]])
|
|
114
|
+
p = fig.plot(1, title="Signal")
|
|
115
|
+
p.line(t, v, name="raw")
|
|
116
|
+
p.fill(t, upper, lower, opacity=0.3)
|
|
117
|
+
p.y_axis(scale="log", label="Power")
|
|
118
|
+
fig.plot(2).box({"a": va, "b": vb})
|
|
119
|
+
h = fig.plot(3).heatmap(matrix, x=columns, y=rows, colorbar=True)
|
|
120
|
+
fig.plot(4).scatter(x, y, c=z)
|
|
121
|
+
fig.save("figure.pdf")
|
|
122
|
+
fig.save("figure.png", dpi="2x") # 192 dpi; a number is dots per inch
|
|
123
|
+
fig.save("figure.eps") # PostScript: transparency flattened
|
|
124
|
+
fig.save("figure.svg")
|
|
125
|
+
data = fig.write("pdf", compression="small") # bytes
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
fig = plt.Figure(style="ggplot2") # or a dict: {"base": "seaborn", "font_size": 9}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
categories, counts = ["a", "b", "c"], [3, 5, 2]
|
|
134
|
+
p = plt.Plot(width="3in", font_size="9pt", vars={"accent": "#c00"})
|
|
135
|
+
p.x_axis(tick_length="0.5em", minor_tick_length="50%")
|
|
136
|
+
p.bar(categories, counts, width="60%", color="var(--accent)") # a custom variable
|
|
137
|
+
p.x_axis.explain("tick_length") # where a value comes from
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
genes = {"umap_x": x, "umap_y": y}
|
|
142
|
+
df = {"x": x, "y": y, "cluster": [int(a) % 3 for a in x],
|
|
143
|
+
"condition": ["ctrl" if a < 5 else "drug" for a in y],
|
|
144
|
+
"replicate": [i % 2 + 1 for i in range(len(x))]}
|
|
145
|
+
p = plt.Plot()
|
|
146
|
+
p.scatter("umap_x", "umap_y", data=genes, c="density", draw_order="density") # columns
|
|
147
|
+
p.scatter("x", "y", data=df, group="cluster", marker="auto") # one series per group
|
|
148
|
+
fig, panels = plt.facet(df, col="condition", row="replicate") # small multiples
|
|
149
|
+
panels.scatter("x", "y")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Documentation
|
|
153
|
+
|
|
154
|
+
* [Tutorial](https://github.com/ajgouhier/plot_io/blob/main/docs/tutorial.md): first steps, from a figure to its file.
|
|
155
|
+
* [Guide](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md): the concepts by topic, with the settings tables.
|
|
156
|
+
* [Examples](https://github.com/ajgouhier/plot_io/blob/main/docs/examples.md): every image of the docs, the scripts that draw them, recipes.
|
|
157
|
+
* [Plot types](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md#plot-types): a page per plot type and figure helper, in
|
|
158
|
+
[docs/plots/](https://github.com/ajgouhier/plot_io/tree/main/docs/plots).
|
|
159
|
+
* [Reference](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md#reference): a page per other class, in
|
|
160
|
+
[docs/reference/](https://github.com/ajgouhier/plot_io/tree/main/docs/reference).
|
|
161
|
+
* [Coming from matplotlib](https://github.com/ajgouhier/plot_io/blob/main/docs/from_matplotlib.md): its calls and names in plot_io.
|
|
162
|
+
|
|
163
|
+
## Development
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
python tools/check.py # every check, one after the other (--list shows them)
|
|
167
|
+
python tools/check.py --fast # without the slow ones (~25 s)
|
|
168
|
+
python tools/check.py --only suite,ruff,mypy
|
|
169
|
+
python -m unittest discover -s tests -t tests
|
|
170
|
+
python tools/bench.py --check # timings: fails over 1.5 × a target
|
|
171
|
+
python tools/gen_docs.py # regenerate the generated sections and pages of docs/
|
|
172
|
+
python tools/gen_docs.py --images # ... and the images of the plot-type pages and the tutorial
|
|
173
|
+
python tools/visual_check.py --save # render the examples as references
|
|
174
|
+
python tools/visual_check.py # ... and later compare with them (pixels, tolerances)
|
|
175
|
+
PLOT_IO_GOLDEN=update python -m unittest discover -s tests -t tests -p test_golden.py
|
|
176
|
+
python tools/record_stats.py > tests/stats_reference.json # with numpy, scipy, statsmodels
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The tests use only their own fonts (`tests/fonts`: VioTest, from vec_io's tests, through
|
|
180
|
+
`VEC_IO_FONT_DIRS`; installed fonts are ignored), so their text is the same on every
|
|
181
|
+
machine. The goldens (`tests/golden.json`) are keyed by meaning: the laid-out geometry of
|
|
182
|
+
each scene (rounded to 1/64 px), its drawing calls and its 96 dpi pixels (the last two
|
|
183
|
+
compared where the fonts match those recorded). Pixels are compared exactly, whatever
|
|
184
|
+
vec_io's version, against `tests/golden/*.png` (in the repository, not in the sdist; else
|
|
185
|
+
against a hash in `golden.json`); a changed scene writes its actual image and a diff to
|
|
186
|
+
`$PLOT_IO_GOLDEN_OUT` (default `<tempdir>/plot_io-golden/`) and names them. A missing
|
|
187
|
+
`golden.json`, or a recorded scene no longer drawn, fails. `PLOT_IO_GOLDEN=update` rewrites
|
|
188
|
+
only the files that changed; `PLOT_IO_GOLDEN=dump:DIR` writes the geometry, the drawing
|
|
189
|
+
calls and the PNG of each scene to `DIR` to see what changed.
|
|
190
|
+
|
|
191
|
+
The tests that read real files with gwseq_io run when it is importable: installed, or a
|
|
192
|
+
built checkout beside this one (`../gwseq_io/crates/gwseq-io-py/python`, added to the path
|
|
193
|
+
by `tests/test_genome.py`; elsewhere, put that directory on `PYTHONPATH`). Otherwise they
|
|
194
|
+
are skipped.
|
|
195
|
+
|
|
196
|
+
`PLOT_IO_NATIVE_LIB=PATH` loads that build of plot_io's C library instead of the one in
|
|
197
|
+
`plot_io/_native/bin/` (a sanitizer build, any other build; see
|
|
198
|
+
`plot_io/_native/README.md`).
|
|
199
|
+
|
|
200
|
+
The statistics kernels and color mapping are in plot_io's own C library, `plio`
|
|
201
|
+
(`plot_io/_native`, built like vec_io's: zig, freestanding, five targets). Building and its
|
|
202
|
+
checks:
|
|
203
|
+
|
|
204
|
+
```sh
|
|
205
|
+
pip install --require-hashes -r tools/zig.lock # the pinned zig
|
|
206
|
+
python tools/build_native.py # bindings from src/plio_api.h, then all targets (not in git)
|
|
207
|
+
python tools/build_native.py --check # every target rebuilt byte for byte as manifest.json says
|
|
208
|
+
python tools/crosscheck.py --qemu PATH/qemu-aarch64-static # same results on aarch64
|
|
209
|
+
python tools/dist.py # the sdist and one wheel per platform built from it
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The binaries are built, not committed: `manifest.json` records each target's hash. In a
|
|
213
|
+
checkout, `pip install -e .` builds the host's binary the way pip does from the sdist.
|
|
214
|
+
|
|
215
|
+
See [plot_io/_native/README.md](plot_io/_native/README.md).
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
plot_io/__init__.py,sha256=yZSU-se8vJoacjq6VLDZzxWZ28yAwlQxD12hTXDDdf0,2893
|
|
2
|
+
plot_io/_methods.py,sha256=NYM_SwKqhVMyGC-PiPGh3Dzneg89NyEuiBC2K7qKV3U,98692
|
|
3
|
+
plot_io/axis.py,sha256=ENIg2yMiNMY0trssq9IWuWVj3ss_55vjbDauApdCYU8,71219
|
|
4
|
+
plot_io/boxes.py,sha256=QLTJ-YaN5XYV5Wgerm6rIcvOz9C9fOEZy9TSclbpq3c,52983
|
|
5
|
+
plot_io/canvas.py,sha256=3mg8AEFlsk8z0YwVL5jFqoxI2QmAo7Fz-At-S3tfk8k,16775
|
|
6
|
+
plot_io/colorbar.py,sha256=wTpQuHLcuLjNltjbk45sAZHtynTYNiW1WRf9LIGtNn8,68863
|
|
7
|
+
plot_io/columns.py,sha256=3Z4B0oavf9I0iB8IEXr-BeyfGEtK0m7cCq5_kzX7AW8,25581
|
|
8
|
+
plot_io/decorations.py,sha256=q73CA-HXiAuxfaYZcIIojzid2kAVCJ01TtksbGH5Xlw,39650
|
|
9
|
+
plot_io/defaults.py,sha256=o2ZsVoDSqs_7bT1mssKBgrNIWJNfGTPqETHZPv7ueJM,24423
|
|
10
|
+
plot_io/density.py,sha256=MFLybA0UPXbIoFKrD0NTZyrzV0bkQqcW3QMZ8Ip7olI,5315
|
|
11
|
+
plot_io/ext.py,sha256=w_WRFQBQxhvMNlX6mlCkk0SxxeZPNejsMInRO0ikiNM,3978
|
|
12
|
+
plot_io/facets.py,sha256=_XuyJtxWiy0-vw9Gtkac0CQmdRoKvAsS9lB0cMCHHjY,10524
|
|
13
|
+
plot_io/figure.py,sha256=0gOB6pz2hDf-Cam_P7xSqaQhrliyWzMB_JyDctHUHrA,40382
|
|
14
|
+
plot_io/formatters.py,sha256=FKtFpvhBCbH5Hc-tLy2n85o_3L9g4stCtXwsrZgUXBE,4356
|
|
15
|
+
plot_io/geometry.py,sha256=AA2NOZ3oWtWyfWiB0h_5iX5jrHAx9mFOcGjaFoP03_c,11538
|
|
16
|
+
plot_io/groups.py,sha256=AO1Cw25Vs7AzwEF6Tyo9D3J2kwj2_C8JffhOWaa0Z-0,12903
|
|
17
|
+
plot_io/guides.py,sha256=LyZQh2LD-AcCUzw0FoJxzkTIq8NaFEPRXJxxl_AsjWY,23515
|
|
18
|
+
plot_io/hints.py,sha256=T5lnEaudybVt-mDk7INE-ciy7IPHcIOsE1KFW29gXPc,4909
|
|
19
|
+
plot_io/kernels.py,sha256=GkBbtTwSZO1S8aCFEn3LIKhff3ovNacJcpzUFoN7Fcw,34276
|
|
20
|
+
plot_io/labels.py,sha256=wgrZrxx96WdR--Xbpywm1C9SroMSty5v4Me-LyW0B4o,24776
|
|
21
|
+
plot_io/layout.py,sha256=uc0G6XIKtnv9pepygPUN8ccbZwv6sfUe8aAFtiVH2GQ,63681
|
|
22
|
+
plot_io/legend.py,sha256=vr3K6Nk2o4yquPBU96CHlFwMmzFEyj8-vwYvrjxOez0,26744
|
|
23
|
+
plot_io/levels.py,sha256=bztn9yDlcYZC3M3y0UPB5NZ1AZr8b_1i_sDb5X3IVtI,21752
|
|
24
|
+
plot_io/limits.py,sha256=kvEjWnez_2iKgAJQc6N_z0pEl2aoX4E_lGegvwXQRWI,4568
|
|
25
|
+
plot_io/lines.py,sha256=MVvO8QvsowYN7emKsAnoCymbWil_XMQQj7s78un3S7w,1224
|
|
26
|
+
plot_io/mapped.py,sha256=msNWg5Tc9LLXG9uu5F-Nw-Jd5MvQXjoWmSqwbj75LJU,21950
|
|
27
|
+
plot_io/markers.py,sha256=wJpv0NSeHATtfp6xCZ2Mm9AlqgY_d_Dga5KLI8nLaGA,3476
|
|
28
|
+
plot_io/markup.py,sha256=gcakejPA_jvq0q6dAtb_NHxkSvCx2U0nnTNDZOMBQ0I,4547
|
|
29
|
+
plot_io/numbers.py,sha256=xJJiOJKie-TCYvcC7o_S3mbscG0XddBCXLJo7pK2orE,13935
|
|
30
|
+
plot_io/occupancy.py,sha256=D_Tt4ESKkd731yfen2hcmvZsTi0MpEHv4rMr_9vpFzM,12952
|
|
31
|
+
plot_io/plot.py,sha256=VuflyonaRWkqWz_nekpb_uSab16PRgCkeir0WuPuTlo,31143
|
|
32
|
+
plot_io/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
plot_io/registry.py,sha256=pXdydUPrk2nBVvqzsBvPEnZcRt5ZgiqmwYX1o7Omh1k,3118
|
|
34
|
+
plot_io/render.py,sha256=al38zuZOSz0ukIXI5j4sFxCKQTyemKWo1Wgf2JcblHo,19254
|
|
35
|
+
plot_io/rows.py,sha256=jlMi5-DwtmSpomoDyaivozct6gCc8a-JVt642jgAT08,21114
|
|
36
|
+
plot_io/scales.py,sha256=DhKj7J_YmvWSOq2Xqp-SR74XbuaJUuhRu3HLvhH2wFU,3787
|
|
37
|
+
plot_io/seams.py,sha256=ySOQUQl9cPovhWwkRJdj_jfc7ik3kO6UJ5MzY-ybWaU,6272
|
|
38
|
+
plot_io/settings.py,sha256=6srh8yTSaVYiVYIWm2fUx7Mw6RMpFEp5_4LI5qK5P_M,34801
|
|
39
|
+
plot_io/shapes.py,sha256=MXYpvfyrBTwriXrTY-AnCkp_FlGoM-4VZh5_-6bBP3E,2858
|
|
40
|
+
plot_io/sharing.py,sha256=9MJSAkkmmVDQNV1g2Dsd5nte44efefXES2utwi8b1YY,9823
|
|
41
|
+
plot_io/sizemaps.py,sha256=Bu70z3RGtJDUCn357-Hn4naYkg3oR71JkLieiYTgD54,4059
|
|
42
|
+
plot_io/spec.py,sha256=H-RAnWrLkVbXgoDcK1sdPjcxLHii5cQ5DDKMQaaWNmk,9433
|
|
43
|
+
plot_io/states.py,sha256=tZk8NqccqUrMwjmR0Td68eWiR3Qair7DiixHE4f_41o,9062
|
|
44
|
+
plot_io/tables.py,sha256=FskqlobZWCThHvU_sjWUs6AMdnw1X4YHl1u0Ht0PSio,4981
|
|
45
|
+
plot_io/text.py,sha256=J3okY8ayTGL6j_qE2pz_IovVEttWOTlr0A1War9yZ-8,16901
|
|
46
|
+
plot_io/ticks.py,sha256=yPsAnhrP88CsQOaMuShhg1Eob9pd1rrnTTi22pvTljQ,17356
|
|
47
|
+
plot_io/times.py,sha256=ZMABzNN4TThWFYSVzgm-AHmrniEM51Kb6a8dhKlVTh0,11725
|
|
48
|
+
plot_io/titles.py,sha256=xW20tQcPq2wFIzZdlEMRoGrG6OdFmTU-jG_H1yXTGeE,10160
|
|
49
|
+
plot_io/transform.py,sha256=AAnn1Tc9igIrkkYgo23-Iu8voY9I8_1j4AvxS-9YF-Q,4838
|
|
50
|
+
plot_io/types.py,sha256=ndsfrIqSnWanTiSsdW9I0ldTpMicRI-3N0hzajpKyKw,716681
|
|
51
|
+
plot_io/units.py,sha256=NI1HM3yaBUOhOy9jj8GG1GWB-BuSYmH1uzZzeLbHbNA,29698
|
|
52
|
+
plot_io/validators.py,sha256=k3uPAABWi8s4E3VYSuf9TZsaQOv5Etr2fY7gnD1pRfg,36760
|
|
53
|
+
plot_io/values.py,sha256=nxaQuVhDZPGnY724quUZDJiLs3XBk0a-P5tIaF-S4b8,6600
|
|
54
|
+
plot_io/_native/__init__.py,sha256=25TRoB6NBAdqEunu_y1hQ_SE_zsLjuEfeIEUL2ZpeI0,7470
|
|
55
|
+
plot_io/_native/__main__.py,sha256=IB7B_qfjro4xibz42ZCFoZ2Aa7FIaVPXOwy2uCIxBQ8,7222
|
|
56
|
+
plot_io/_native/_api.py,sha256=liv5XzVcyUeGbuCrlGcYxtZdemdFw2SAGrKiu_9CgRQ,14193
|
|
57
|
+
plot_io/_native/kernels.py,sha256=gh1u3oJ3j6ot8es5nmj0gY0PjE2c6RnTp9WhS8vDeyA,12765
|
|
58
|
+
plot_io/_native/manifest.json,sha256=1S6annqCaryfVPBU7Ekmj54Z8wOe4DssWyJrMz7UKVA,1318
|
|
59
|
+
plot_io/color/__init__.py,sha256=Gbboslj7958lrMCMHhjREk_k__RD2oKBKmnPvxbgiCo,260
|
|
60
|
+
plot_io/color/data.py,sha256=_YXAcBxrWaId3is0ny2pCaT3IaSVzK3HZVId1_g9lX0,121856
|
|
61
|
+
plot_io/color/maps.py,sha256=R8xkB-Pu5Eky73OTng8ZRcgpHdkwn6rE3fu_LqrEf1Y,45352
|
|
62
|
+
plot_io/color/values.py,sha256=T4pcog0x6TeL0ieSnoIf2HYJwF0KipfmIeO5Khkf0Gc,11796
|
|
63
|
+
plot_io/color/variants.py,sha256=-V0Nlb76WtbASrcjBIS6FWHA2h5zQjqEHTg9dFugZb8,73189
|
|
64
|
+
plot_io/genome/__init__.py,sha256=wSAlyxn-kVQioA3HWqwvBu1WcJmmlg-1bGH8bD-4xAA,820
|
|
65
|
+
plot_io/genome/adapters.py,sha256=7Zx9aAt5hcqLtA4b-eO-WQ8dnUc8WAT17hr3G0pQfbk,15392
|
|
66
|
+
plot_io/genome/combine.py,sha256=ftLD8iX_wElIWENT6lasyuXvIXBVOL8ppwQeWWaFDA8,5241
|
|
67
|
+
plot_io/genome/contacts.py,sha256=sNi438h2yboaIAS7D_8BhWWFr1cAa5xcQr1KttRUmJ0,24314
|
|
68
|
+
plot_io/genome/intervals.py,sha256=L9RQPtCvFhYnRXrxxhx1LYMiKu9xTYXcOrsQn6X9N2g,36328
|
|
69
|
+
plot_io/genome/lanes.py,sha256=JKwRBZHMUngTDabW1c5g6v342bVvMqzTkCxbo3_6Yi8,8072
|
|
70
|
+
plot_io/genome/layout.py,sha256=HpuKjTLjplavmXEWWSIV1arG0AF8A3ymqqIZ50p6wK8,9679
|
|
71
|
+
plot_io/genome/links.py,sha256=ODfrgLr_Q6qXlJxKtDE32tLST53AwUlPcpbAesiGt0E,17166
|
|
72
|
+
plot_io/genome/pack.py,sha256=fMCNJgPs99xkHlmWQOZTIBQMf_GYiI58KSiIDB5QWmw,1000
|
|
73
|
+
plot_io/genome/readers.py,sha256=Wrhkecm84I_a2lOWacHoYI2t3Fljc7gPofp3AlrqmYc,6693
|
|
74
|
+
plot_io/genome/regions.py,sha256=d5SbRsu_4EIW3iCYdAREBB0TLaJ-JJgdngsLX0oeIVI,9523
|
|
75
|
+
plot_io/genome/scale.py,sha256=f2af7kAO658ynu-6dd-WmZk-aTP3YP5f1DrIUeXvEcM,14165
|
|
76
|
+
plot_io/genome/series.py,sha256=KEFcCAk9sewOa4fhjCjuv2jUo1UjBnZ_Yn8OrPK-Ok8,14053
|
|
77
|
+
plot_io/genome/signal.py,sha256=EOhRSuVxVhiiyvkrSzDnsslqS7MaTY2mARxXXf_RCuA,29187
|
|
78
|
+
plot_io/genome/sites.py,sha256=R5Q_iS-RVR0XG0jykckH7cGyYhv6CoZ64T5hcm279wY,33576
|
|
79
|
+
plot_io/genome/sources.py,sha256=IjY3ayH4RHdJ2aR2ve0vTW1ij8GH1jLlhkaoRqrhh9w,21441
|
|
80
|
+
plot_io/genome/testing.py,sha256=cChSDCn-CgFUJWjWboNvHviYJYuMomEU_CwIdhXBBxg,7149
|
|
81
|
+
plot_io/helpers/__init__.py,sha256=vR_BhAcofFmN5wCV4wSwiZhEf0Zfn2j2jB_wXGPbdao,928
|
|
82
|
+
plot_io/helpers/clustermap.py,sha256=A7YoKQQ6dgFre8IZLhIgvW7y2rjDQUCvddpPMJvEd58,9462
|
|
83
|
+
plot_io/helpers/dendrogram.py,sha256=HXd5Kse6u18mIIcdf-dz2D_u81ylFUvVUWGqmg_SFM4,7089
|
|
84
|
+
plot_io/helpers/grids.py,sha256=PoELr-MQgnD1p5EwnpQlbtmQTqlPjgnTyGNHVKyJEJc,12917
|
|
85
|
+
plot_io/helpers/qq.py,sha256=vb-A7ejucENvpLdMMyFGcB2DUihRhfi1aS9-IXyyymQ,12824
|
|
86
|
+
plot_io/helpers/raincloud.py,sha256=7H3yW-5DG33OzcugO2kHwBeVRDFfgPkGdtYf8ajHlPA,11102
|
|
87
|
+
plot_io/helpers/tree.py,sha256=3FqiI_RIZz_aGf78k7gOE0S0uyATZ4-2vyIxCPYOF_0,9030
|
|
88
|
+
plot_io/helpers/volcano.py,sha256=b9HV1xL0155Ja7aX8Bk8emT9HbRwmg6gLlFTB3T77Yc,21113
|
|
89
|
+
plot_io/layers/__init__.py,sha256=KIazkYBMb_ziB4oIFK6JGHCnIib2HwKCIjFJUIzf7i8,4440
|
|
90
|
+
plot_io/layers/base.py,sha256=pq7IMf6qzsQmfMCvno267VfJtU0vHdW4Y1yuvYtlZ5s,31238
|
|
91
|
+
plot_io/layers/context.py,sha256=4IcJY61OacRLsDkn7fNhmK5dw1SjRgiDMPjSkpfwYE4,3517
|
|
92
|
+
plot_io/layers/core.py,sha256=xM-kQPWlKlNZ00w9__fLxbcdy4aDJSICssAZHXYx5tI,19111
|
|
93
|
+
plot_io/layers/geoms.py,sha256=P0XtBMzdJa2GP8Q-60EGktc5UnifaupqEHFlaxK8BZA,60565
|
|
94
|
+
plot_io/layers/grammar.py,sha256=3o9xDZaAPan4tGAGm3zvyl_b7e0WtVWzs988JM4Or2k,25257
|
|
95
|
+
plot_io/layers/paint.py,sha256=3gqWCtMZYOxkz4QjwisiaFm06VZGLcgVgK1waB98RjQ,26684
|
|
96
|
+
plot_io/layers/pipeline.py,sha256=t-tw_dGplxBdJU4rqjn2nfgsQIzrF0EGtk1M3QzgsnY,6843
|
|
97
|
+
plot_io/layers/positions.py,sha256=9-7px3BFFTgC5Zk7rlf9Dq8q5z5FN-7-L9zdgxm5FgQ,17604
|
|
98
|
+
plot_io/layers/stats.py,sha256=-NK8V3dUloQZVwAb1ScxytZzB_ZtILmkedXBFHeDecY,46690
|
|
99
|
+
plot_io/presets/__init__.py,sha256=A17hkpgLG-90sqYelcE6CFuUuJwLOWtR7wTV7QjFZ1k,2034
|
|
100
|
+
plot_io/presets/_util.py,sha256=8rXoyzv4BlND5VDE-C-FMHH_LwA-PC58xyRxHPoUyss,6342
|
|
101
|
+
plot_io/presets/area.py,sha256=WH1khN16_XTaMtyPEuAw0-BEm9vFcp23LZHgCWUSCjc,6408
|
|
102
|
+
plot_io/presets/bar.py,sha256=cN2KJ2TulVtYNEXLwepKrhjuNiYSoltDELrVxnJVB1s,12893
|
|
103
|
+
plot_io/presets/box.py,sha256=wx4qJRj8Daq3YWm6-O5oiSJjr8TYInRZy63JWPLIRZw,18104
|
|
104
|
+
plot_io/presets/catpoints.py,sha256=j6ouBAhhnxgB_EJuigbtARyq-U1FLTMFIZMjlEdzIIk,7512
|
|
105
|
+
plot_io/presets/contour.py,sha256=iTSID5uyTcaOeOCILtO6gvoiiUcn-WOzf3xkFx2c12k,15889
|
|
106
|
+
plot_io/presets/curves.py,sha256=JBDusm6dezS60O3dB6-yH4wHIUugLSQtWlDNd0-rYag,1147
|
|
107
|
+
plot_io/presets/dots.py,sha256=fc0xl294izcwIrnt_KQZWXGrx8LEpSVZX-GA5BMAe7U,15649
|
|
108
|
+
plot_io/presets/ecdf.py,sha256=3L282ywuESnAr29dv1YLRQtWbQx0jtyf1tgTMEPbZUc,4252
|
|
109
|
+
plot_io/presets/errorbar.py,sha256=Vd4-gkqgtglbfiA9FKwItO0TR8LW3nbxnwjjxR2s47M,4900
|
|
110
|
+
plot_io/presets/errors.py,sha256=EBfuQtShRM8HwKMcKbpY6bRmTFlJZ0V6YHI6ST1wv9k,12322
|
|
111
|
+
plot_io/presets/fill.py,sha256=t_Y8LAnp3R-eloap_LXRLJvKIgwjl2DD_f98rjC0xLo,3106
|
|
112
|
+
plot_io/presets/heatmap.py,sha256=l3BeT37xTP1_RSHgG0Qx1v4K5C4m7fUDlOJ-DF-y6J8,14361
|
|
113
|
+
plot_io/presets/hexbin.py,sha256=azmgxSLvjPxexz4nn7o-4bJx9dnQ8pSnxts0iXylq-s,8151
|
|
114
|
+
plot_io/presets/hist.py,sha256=vdqQ5Axe--sZbWr7gqzthRX_RhlBxlNo71_ZQzap8-Y,18649
|
|
115
|
+
plot_io/presets/hist2d.py,sha256=5S6DP9YdCVHxvFbcyB3Y8p0ncsV2_8RB5UIrrZ2Z_UU,3271
|
|
116
|
+
plot_io/presets/kde.py,sha256=zdKCo_RRjSc25K1vcJeyn3K8F1AkFr5pVfImpjJqbZc,7229
|
|
117
|
+
plot_io/presets/kde2d.py,sha256=lgzY_KWplYKNGOg3KxN1-uDAW41-xcIx9iJrMC0sd5U,6424
|
|
118
|
+
plot_io/presets/line.py,sha256=DKOH0k6m1DkCNpfavhGcdhrsmA_GSCVFbJgXhWpSvq4,6839
|
|
119
|
+
plot_io/presets/pie.py,sha256=e3dyqTAqIqCQDILrbqdm-1ORTBYfDAzYwGHr2tvqtqo,23522
|
|
120
|
+
plot_io/presets/regression.py,sha256=rRehS2oGlH-TqKL0_Uo9nnM-jHCXcAEJFtUXBARcWlg,5814
|
|
121
|
+
plot_io/presets/scatter.py,sha256=ZSYmqCs_LCUaQLkKI9kcCoaSval62jSgklGJUu8Bfuo,9062
|
|
122
|
+
plot_io/presets/stem.py,sha256=8F0DV2grOAOpVvAItChrmrgxPFmx5axqV1DHFLR_PCQ,3994
|
|
123
|
+
plot_io/presets/violin.py,sha256=WxlyEPoAcl_Mocoh1C8ILFn4CqfziCWwWCSHZUmshN8,15342
|
|
124
|
+
plot_io/styles/__init__.py,sha256=HDPy1_vCIC87pRT1rimRBFGT-DLMC7hVN1eOqQeSxfM,11907
|
|
125
|
+
plot_io/styles/library.py,sha256=ReOqS741mxvBDoiRmZx9WZ_ESz01jQTFhkMRfkPLRB0,15283
|
|
126
|
+
plot_io/_native/bin/windows-arm64.dll,sha256=bv9wrv28sOKJv8EEAqogeFZA3u8OyEhhMZkXdqVKy8w,69632
|
|
127
|
+
plot_io-0.12.0.dist-info/METADATA,sha256=93KmR66u-PpYOLKRyceh15_mXWb_s6RzBNTCKA82Dkg,11433
|
|
128
|
+
plot_io-0.12.0.dist-info/WHEEL,sha256=WFezGyxI7afY59fTEbTiueKbbEV_hMxzB_HK5n-3eUY,94
|
|
129
|
+
plot_io-0.12.0.dist-info/licenses/LICENSE,sha256=KD-5bsauyA0Kh68YcImL7q5yE6OCTZwHnhvybthBbNg,1501
|
|
130
|
+
plot_io-0.12.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Arthur Gouhier
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|