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.
Files changed (130) hide show
  1. plot_io/__init__.py +73 -0
  2. plot_io/_methods.py +1691 -0
  3. plot_io/_native/__init__.py +199 -0
  4. plot_io/_native/__main__.py +197 -0
  5. plot_io/_native/_api.py +457 -0
  6. plot_io/_native/bin/windows-arm64.dll +0 -0
  7. plot_io/_native/kernels.py +335 -0
  8. plot_io/_native/manifest.json +49 -0
  9. plot_io/axis.py +1347 -0
  10. plot_io/boxes.py +1156 -0
  11. plot_io/canvas.py +389 -0
  12. plot_io/color/__init__.py +3 -0
  13. plot_io/color/data.py +1646 -0
  14. plot_io/color/maps.py +922 -0
  15. plot_io/color/values.py +295 -0
  16. plot_io/color/variants.py +1246 -0
  17. plot_io/colorbar.py +1426 -0
  18. plot_io/columns.py +614 -0
  19. plot_io/decorations.py +920 -0
  20. plot_io/defaults.py +809 -0
  21. plot_io/density.py +113 -0
  22. plot_io/ext.py +68 -0
  23. plot_io/facets.py +240 -0
  24. plot_io/figure.py +788 -0
  25. plot_io/formatters.py +97 -0
  26. plot_io/genome/__init__.py +17 -0
  27. plot_io/genome/adapters.py +356 -0
  28. plot_io/genome/combine.py +123 -0
  29. plot_io/genome/contacts.py +508 -0
  30. plot_io/genome/intervals.py +750 -0
  31. plot_io/genome/lanes.py +191 -0
  32. plot_io/genome/layout.py +184 -0
  33. plot_io/genome/links.py +364 -0
  34. plot_io/genome/pack.py +27 -0
  35. plot_io/genome/readers.py +145 -0
  36. plot_io/genome/regions.py +228 -0
  37. plot_io/genome/scale.py +349 -0
  38. plot_io/genome/series.py +344 -0
  39. plot_io/genome/signal.py +621 -0
  40. plot_io/genome/sites.py +782 -0
  41. plot_io/genome/sources.py +459 -0
  42. plot_io/genome/testing.py +161 -0
  43. plot_io/geometry.py +289 -0
  44. plot_io/groups.py +308 -0
  45. plot_io/guides.py +503 -0
  46. plot_io/helpers/__init__.py +17 -0
  47. plot_io/helpers/clustermap.py +202 -0
  48. plot_io/helpers/dendrogram.py +172 -0
  49. plot_io/helpers/grids.py +304 -0
  50. plot_io/helpers/qq.py +334 -0
  51. plot_io/helpers/raincloud.py +249 -0
  52. plot_io/helpers/tree.py +214 -0
  53. plot_io/helpers/volcano.py +505 -0
  54. plot_io/hints.py +125 -0
  55. plot_io/kernels.py +740 -0
  56. plot_io/labels.py +566 -0
  57. plot_io/layers/__init__.py +100 -0
  58. plot_io/layers/base.py +630 -0
  59. plot_io/layers/context.py +87 -0
  60. plot_io/layers/core.py +446 -0
  61. plot_io/layers/geoms.py +1362 -0
  62. plot_io/layers/grammar.py +586 -0
  63. plot_io/layers/paint.py +614 -0
  64. plot_io/layers/pipeline.py +170 -0
  65. plot_io/layers/positions.py +431 -0
  66. plot_io/layers/stats.py +1088 -0
  67. plot_io/layout.py +1381 -0
  68. plot_io/legend.py +605 -0
  69. plot_io/levels.py +509 -0
  70. plot_io/limits.py +124 -0
  71. plot_io/lines.py +42 -0
  72. plot_io/mapped.py +522 -0
  73. plot_io/markers.py +110 -0
  74. plot_io/markup.py +128 -0
  75. plot_io/numbers.py +354 -0
  76. plot_io/occupancy.py +295 -0
  77. plot_io/plot.py +597 -0
  78. plot_io/presets/__init__.py +51 -0
  79. plot_io/presets/_util.py +153 -0
  80. plot_io/presets/area.py +145 -0
  81. plot_io/presets/bar.py +261 -0
  82. plot_io/presets/box.py +400 -0
  83. plot_io/presets/catpoints.py +177 -0
  84. plot_io/presets/contour.py +353 -0
  85. plot_io/presets/curves.py +30 -0
  86. plot_io/presets/dots.py +355 -0
  87. plot_io/presets/ecdf.py +97 -0
  88. plot_io/presets/errorbar.py +106 -0
  89. plot_io/presets/errors.py +296 -0
  90. plot_io/presets/fill.py +74 -0
  91. plot_io/presets/heatmap.py +322 -0
  92. plot_io/presets/hexbin.py +198 -0
  93. plot_io/presets/hist.py +391 -0
  94. plot_io/presets/hist2d.py +87 -0
  95. plot_io/presets/kde.py +162 -0
  96. plot_io/presets/kde2d.py +147 -0
  97. plot_io/presets/line.py +143 -0
  98. plot_io/presets/pie.py +502 -0
  99. plot_io/presets/regression.py +115 -0
  100. plot_io/presets/scatter.py +194 -0
  101. plot_io/presets/stem.py +100 -0
  102. plot_io/presets/violin.py +323 -0
  103. plot_io/py.typed +0 -0
  104. plot_io/registry.py +82 -0
  105. plot_io/render.py +480 -0
  106. plot_io/rows.py +491 -0
  107. plot_io/scales.py +103 -0
  108. plot_io/seams.py +138 -0
  109. plot_io/settings.py +807 -0
  110. plot_io/shapes.py +66 -0
  111. plot_io/sharing.py +232 -0
  112. plot_io/sizemaps.py +97 -0
  113. plot_io/spec.py +240 -0
  114. plot_io/states.py +216 -0
  115. plot_io/styles/__init__.py +307 -0
  116. plot_io/styles/library.py +397 -0
  117. plot_io/tables.py +138 -0
  118. plot_io/text.py +412 -0
  119. plot_io/ticks.py +400 -0
  120. plot_io/times.py +287 -0
  121. plot_io/titles.py +225 -0
  122. plot_io/transform.py +114 -0
  123. plot_io/types.py +13604 -0
  124. plot_io/units.py +768 -0
  125. plot_io/validators.py +1029 -0
  126. plot_io/values.py +190 -0
  127. plot_io-0.12.0.dist-info/METADATA +215 -0
  128. plot_io-0.12.0.dist-info/RECORD +130 -0
  129. plot_io-0.12.0.dist-info/WHEEL +4 -0
  130. 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,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_arm64
@@ -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.