plot-io 0.8.0__tar.gz → 0.12.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plot_io-0.12.0/PKG-INFO +215 -0
- plot_io-0.12.0/README.md +199 -0
- plot_io-0.12.0/docs/api.md +1275 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/annotated.py +6 -6
- plot_io-0.12.0/docs/examples/bars.py +21 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/box_plots.py +4 -4
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/colorbars.py +11 -11
- plot_io-0.12.0/docs/examples/density.py +24 -0
- plot_io-0.12.0/docs/examples/distributions.py +24 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/dots.py +7 -7
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/error_bars.py +3 -3
- plot_io-0.12.0/docs/examples/facets.py +19 -0
- plot_io-0.12.0/docs/examples/genome_matrices.py +59 -0
- plot_io-0.12.0/docs/examples/genome_regions.py +53 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/genome_tracks.py +32 -18
- plot_io-0.12.0/docs/examples/grids2d.py +24 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/groups.py +6 -6
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/heatmap.py +4 -4
- plot_io-0.12.0/docs/examples/helpers.py +61 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/large_data.py +5 -6
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/layouts.py +4 -4
- plot_io-0.12.0/docs/examples/levels.py +40 -0
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/line_band.py +4 -4
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/scales.py +5 -5
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/scatter_groups.py +3 -3
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/shared_colorbar.py +4 -4
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/shared_legend.py +11 -11
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/shared_sizes.py +6 -6
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/styles.py +19 -12
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/time_twin.py +4 -4
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/titles.py +5 -5
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/units.py +12 -11
- {plot_io-0.8.0 → plot_io-0.12.0/docs}/examples/variable_fonts.py +6 -6
- plot_io-0.12.0/docs/examples.md +1473 -0
- plot_io-0.12.0/docs/from_matplotlib.md +149 -0
- plot_io-0.12.0/docs/plots/area.md +64 -0
- plot_io-0.12.0/docs/plots/bar.md +89 -0
- plot_io-0.12.0/docs/plots/bed.md +105 -0
- plot_io-0.12.0/docs/plots/bigwig.md +107 -0
- plot_io-0.12.0/docs/plots/box.md +98 -0
- plot_io-0.12.0/docs/plots/clustermap.md +34 -0
- plot_io-0.12.0/docs/plots/contour.md +76 -0
- plot_io-0.12.0/docs/plots/dendrogram.md +49 -0
- plot_io-0.12.0/docs/plots/dots.md +88 -0
- plot_io-0.12.0/docs/plots/ecdf.md +63 -0
- plot_io-0.12.0/docs/plots/errorbar.md +77 -0
- plot_io-0.12.0/docs/plots/facet.md +30 -0
- plot_io-0.12.0/docs/plots/fill.md +65 -0
- plot_io-0.12.0/docs/plots/genes.md +39 -0
- plot_io-0.12.0/docs/plots/gtf.md +43 -0
- plot_io-0.12.0/docs/plots/heatmap.md +74 -0
- plot_io-0.12.0/docs/plots/hexbin.md +65 -0
- plot_io-0.12.0/docs/plots/hic.md +109 -0
- plot_io-0.12.0/docs/plots/hist.md +87 -0
- plot_io-0.12.0/docs/plots/hist2d.md +39 -0
- plot_io-0.12.0/docs/plots/joint.md +29 -0
- plot_io-0.12.0/docs/plots/kde.md +74 -0
- plot_io-0.12.0/docs/plots/kde2d.md +46 -0
- plot_io-0.12.0/docs/plots/line.md +100 -0
- plot_io-0.12.0/docs/plots/linkage.md +34 -0
- plot_io-0.12.0/docs/plots/links.md +63 -0
- plot_io-0.12.0/docs/plots/ma.md +49 -0
- plot_io-0.12.0/docs/plots/manhattan.md +51 -0
- plot_io-0.12.0/docs/plots/pairs.md +31 -0
- plot_io-0.12.0/docs/plots/pie.md +76 -0
- plot_io-0.12.0/docs/plots/qq.md +67 -0
- plot_io-0.12.0/docs/plots/raincloud.md +86 -0
- plot_io-0.12.0/docs/plots/regression.md +91 -0
- plot_io-0.12.0/docs/plots/scatter.md +99 -0
- plot_io-0.12.0/docs/plots/site_heatmap.md +86 -0
- plot_io-0.12.0/docs/plots/site_profile.md +59 -0
- plot_io-0.12.0/docs/plots/stem.md +73 -0
- plot_io-0.12.0/docs/plots/strip.md +83 -0
- plot_io-0.12.0/docs/plots/swarm.md +81 -0
- plot_io-0.12.0/docs/plots/violin.md +84 -0
- plot_io-0.12.0/docs/plots/volcano.md +57 -0
- plot_io-0.12.0/docs/reference/axis.md +151 -0
- plot_io-0.12.0/docs/reference/canvas.md +48 -0
- plot_io-0.12.0/docs/reference/color_axes.md +295 -0
- plot_io-0.12.0/docs/reference/colorbars.md +95 -0
- plot_io-0.12.0/docs/reference/decorations.md +176 -0
- plot_io-0.12.0/docs/reference/figure.md +300 -0
- plot_io-0.12.0/docs/reference/figure_rows.md +69 -0
- plot_io-0.12.0/docs/reference/legends.md +118 -0
- plot_io-0.12.0/docs/reference/plot.md +220 -0
- plot_io-0.12.0/docs/reference/sets.md +107 -0
- plot_io-0.12.0/docs/reference/titles.md +107 -0
- plot_io-0.12.0/docs/reference/tracks.md +70 -0
- plot_io-0.12.0/docs/tutorial.md +159 -0
- plot_io-0.12.0/hatch_build.py +47 -0
- plot_io-0.12.0/plot_io/__init__.py +73 -0
- plot_io-0.12.0/plot_io/_methods.py +1691 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/README.md +37 -10
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/__init__.py +22 -11
- plot_io-0.12.0/plot_io/_native/__main__.py +197 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/_api.py +65 -3
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/kernels.py +31 -12
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/manifest.json +12 -12
- plot_io-0.12.0/plot_io/_native/src/cluster.c +554 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/colormap.c +22 -5
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/plio.h +1 -1
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/plio_api.h +56 -12
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/plot.c +119 -28
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/signatures.c +39 -3
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/stats.c +50 -8
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/axis.py +617 -96
- plot_io-0.12.0/plot_io/boxes.py +1156 -0
- plot_io-0.12.0/plot_io/canvas.py +389 -0
- plot_io-0.12.0/plot_io/color/__init__.py +3 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/color/data.py +66 -38
- plot_io-0.12.0/plot_io/color/maps.py +922 -0
- plot_io-0.12.0/plot_io/color/values.py +295 -0
- plot_io-0.12.0/plot_io/color/variants.py +1246 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/colorbar.py +373 -147
- plot_io-0.12.0/plot_io/columns.py +614 -0
- plot_io-0.12.0/plot_io/decorations.py +920 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/defaults.py +158 -35
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/density.py +23 -7
- plot_io-0.12.0/plot_io/ext.py +68 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/facets.py +69 -24
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/figure.py +195 -68
- plot_io-0.12.0/plot_io/formatters.py +97 -0
- plot_io-0.12.0/plot_io/genome/__init__.py +17 -0
- plot_io-0.12.0/plot_io/genome/adapters.py +356 -0
- plot_io-0.12.0/plot_io/genome/combine.py +123 -0
- plot_io-0.12.0/plot_io/genome/contacts.py +508 -0
- plot_io-0.12.0/plot_io/genome/intervals.py +750 -0
- plot_io-0.12.0/plot_io/genome/lanes.py +191 -0
- plot_io-0.12.0/plot_io/genome/layout.py +184 -0
- plot_io-0.12.0/plot_io/genome/links.py +364 -0
- plot_io-0.12.0/plot_io/genome/readers.py +145 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/genome/regions.py +101 -6
- plot_io-0.12.0/plot_io/genome/scale.py +349 -0
- plot_io-0.12.0/plot_io/genome/series.py +344 -0
- plot_io-0.12.0/plot_io/genome/signal.py +621 -0
- plot_io-0.12.0/plot_io/genome/sites.py +782 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/genome/sources.py +160 -53
- plot_io-0.12.0/plot_io/genome/testing.py +161 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/geometry.py +4 -11
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/groups.py +36 -24
- plot_io-0.12.0/plot_io/guides.py +503 -0
- plot_io-0.12.0/plot_io/helpers/__init__.py +17 -0
- plot_io-0.12.0/plot_io/helpers/clustermap.py +202 -0
- plot_io-0.12.0/plot_io/helpers/dendrogram.py +172 -0
- plot_io-0.12.0/plot_io/helpers/grids.py +304 -0
- plot_io-0.12.0/plot_io/helpers/qq.py +334 -0
- plot_io-0.12.0/plot_io/helpers/raincloud.py +249 -0
- plot_io-0.12.0/plot_io/helpers/tree.py +214 -0
- plot_io-0.12.0/plot_io/helpers/volcano.py +505 -0
- plot_io-0.12.0/plot_io/hints.py +125 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/kernels.py +260 -43
- plot_io-0.12.0/plot_io/labels.py +566 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/layers/__init__.py +36 -9
- plot_io-0.12.0/plot_io/layers/base.py +630 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/layers/context.py +27 -12
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/layers/core.py +192 -21
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/layers/geoms.py +331 -167
- plot_io-0.12.0/plot_io/layers/grammar.py +586 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/layers/paint.py +255 -28
- plot_io-0.12.0/plot_io/layers/pipeline.py +170 -0
- plot_io-0.12.0/plot_io/layers/positions.py +431 -0
- plot_io-0.12.0/plot_io/layers/stats.py +1088 -0
- plot_io-0.12.0/plot_io/layout.py +1381 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/legend.py +175 -289
- plot_io-0.12.0/plot_io/levels.py +509 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/limits.py +47 -18
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/lines.py +11 -7
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/mapped.py +78 -22
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/markers.py +2 -3
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/numbers.py +100 -16
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/occupancy.py +99 -24
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/plot.py +241 -104
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/__init__.py +11 -3
- plot_io-0.12.0/plot_io/presets/_util.py +153 -0
- plot_io-0.12.0/plot_io/presets/area.py +145 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/bar.py +134 -125
- plot_io-0.12.0/plot_io/presets/box.py +400 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/catpoints.py +80 -77
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/contour.py +103 -52
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/curves.py +1 -1
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/dots.py +112 -101
- plot_io-0.12.0/plot_io/presets/ecdf.py +97 -0
- plot_io-0.12.0/plot_io/presets/errorbar.py +106 -0
- plot_io-0.12.0/plot_io/presets/errors.py +296 -0
- plot_io-0.12.0/plot_io/presets/fill.py +74 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/heatmap.py +84 -51
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/hexbin.py +49 -35
- plot_io-0.12.0/plot_io/presets/hist.py +391 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/hist2d.py +23 -14
- plot_io-0.12.0/plot_io/presets/kde.py +162 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/kde2d.py +35 -19
- plot_io-0.12.0/plot_io/presets/line.py +143 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/presets/pie.py +131 -86
- plot_io-0.12.0/plot_io/presets/regression.py +115 -0
- plot_io-0.12.0/plot_io/presets/scatter.py +194 -0
- plot_io-0.12.0/plot_io/presets/stem.py +100 -0
- plot_io-0.12.0/plot_io/presets/violin.py +323 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/registry.py +15 -21
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/render.py +146 -112
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/rows.py +101 -26
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/scales.py +16 -7
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/seams.py +40 -21
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/settings.py +245 -303
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/shapes.py +8 -7
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/sharing.py +24 -1
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/sizemaps.py +10 -3
- plot_io-0.12.0/plot_io/spec.py +240 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/states.py +42 -34
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/styles/__init__.py +36 -6
- plot_io-0.12.0/plot_io/styles/library.py +397 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/tables.py +13 -16
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/text.py +135 -12
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/ticks.py +154 -53
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/times.py +82 -11
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/titles.py +43 -6
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/transform.py +7 -1
- plot_io-0.12.0/plot_io/types.py +13604 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/units.py +299 -383
- plot_io-0.12.0/plot_io/validators.py +1029 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/values.py +40 -23
- {plot_io-0.8.0 → plot_io-0.12.0}/pyproject.toml +14 -8
- plot_io-0.8.0/tests/fonts/PioTest-Bold.ttf → plot_io-0.12.0/tests/fonts/VioTest-Bold.ttf +0 -0
- plot_io-0.8.0/tests/fonts/PioTest-Regular.ttf → plot_io-0.12.0/tests/fonts/VioTest-Regular.ttf +0 -0
- plot_io-0.12.0/tests/fuzz_native.py +178 -0
- plot_io-0.12.0/tests/golden.json +166 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/helpers.py +38 -25
- plot_io-0.12.0/tests/preset_ref.json +1656 -0
- plot_io-0.12.0/tests/recording.py +871 -0
- plot_io-0.12.0/tests/stats_reference.json +8382 -0
- plot_io-0.12.0/tests/test_api.py +169 -0
- plot_io-0.12.0/tests/test_bars.py +549 -0
- plot_io-0.12.0/tests/test_boundary.py +113 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_box.py +38 -10
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_colorbars.py +189 -44
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_decorations.py +50 -17
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_defaults.py +63 -14
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_density.py +44 -41
- plot_io-0.12.0/tests/test_distributions.py +458 -0
- plot_io-0.12.0/tests/test_docs.py +88 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_dots.py +43 -38
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_edge_cases.py +28 -2
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_entry.py +18 -18
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_figure_title.py +36 -7
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_fonts.py +14 -14
- plot_io-0.12.0/tests/test_genome.py +1746 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_geometry.py +22 -22
- plot_io-0.12.0/tests/test_golden.py +593 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_grids.py +9 -9
- plot_io-0.12.0/tests/test_heatmap.py +147 -0
- plot_io-0.12.0/tests/test_invariants.py +36 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_jxl_output.py +2 -5
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_layers.py +48 -22
- plot_io-0.12.0/tests/test_layout.py +573 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_limits.py +33 -9
- plot_io-0.12.0/tests/test_maps.py +602 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_markers.py +4 -5
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_markup.py +24 -43
- plot_io-0.12.0/tests/test_native.py +299 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_numbers.py +7 -7
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_occupancy.py +140 -18
- plot_io-0.12.0/tests/test_output.py +468 -0
- plot_io-0.12.0/tests/test_pie.py +75 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_reflines.py +40 -9
- plot_io-0.12.0/tests/test_registry.py +73 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_rows.py +26 -15
- plot_io-0.12.0/tests/test_series.py +249 -0
- plot_io-0.12.0/tests/test_settings.py +506 -0
- plot_io-0.12.0/tests/test_settings_fuzz.py +22 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_shared_legends.py +70 -13
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_sharing.py +7 -7
- plot_io-0.12.0/tests/test_simplify.py +116 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_size_keys.py +24 -14
- plot_io-0.12.0/tests/test_stats.py +293 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_style_settings.py +39 -37
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_style_types.py +11 -11
- plot_io-0.12.0/tests/test_styles.py +330 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_tables.py +207 -30
- plot_io-0.12.0/tests/test_ticks.py +310 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_time_twin.py +47 -10
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_titles.py +24 -30
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_transform.py +27 -10
- plot_io-0.12.0/tests/test_typing.py +48 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_units.py +139 -55
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_values.py +107 -81
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/test_vocabulary.py +38 -38
- plot_io-0.12.0/tests/typing/user_code.py +40 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tools/build_native.py +356 -24
- plot_io-0.12.0/tools/gen_api.py +405 -0
- plot_io-0.12.0/tools/gen_docs.py +1139 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tools/settings_doc.py +28 -82
- plot_io-0.12.0/tools/zig.lock +17 -0
- plot_io-0.8.0/API.md +0 -3425
- plot_io-0.8.0/EXAMPLES.md +0 -1050
- plot_io-0.8.0/PKG-INFO +0 -178
- plot_io-0.8.0/README.md +0 -162
- plot_io-0.8.0/examples/bars.py +0 -21
- plot_io-0.8.0/examples/density.py +0 -23
- plot_io-0.8.0/examples/distributions.py +0 -24
- plot_io-0.8.0/examples/facets.py +0 -19
- plot_io-0.8.0/examples/grids2d.py +0 -23
- plot_io-0.8.0/plot_io/__init__.py +0 -55
- plot_io-0.8.0/plot_io/_backend.py +0 -46
- plot_io-0.8.0/plot_io/_native/bin/linux-aarch64.so +0 -0
- plot_io-0.8.0/plot_io/_native/bin/linux-x86_64.so +0 -0
- plot_io-0.8.0/plot_io/_native/bin/macos-arm64.dylib +0 -0
- plot_io-0.8.0/plot_io/_native/bin/windows-arm64.dll +0 -0
- plot_io-0.8.0/plot_io/_native/bin/windows-x86_64.dll +0 -0
- plot_io-0.8.0/plot_io/color/__init__.py +0 -4
- plot_io-0.8.0/plot_io/color/maps.py +0 -358
- plot_io-0.8.0/plot_io/color/palettes.py +0 -206
- plot_io-0.8.0/plot_io/color/values.py +0 -278
- plot_io-0.8.0/plot_io/decorations.py +0 -521
- plot_io-0.8.0/plot_io/genome/__init__.py +0 -11
- plot_io-0.8.0/plot_io/genome/layout.py +0 -136
- plot_io-0.8.0/plot_io/genome/scale.py +0 -137
- plot_io-0.8.0/plot_io/genome/tracks.py +0 -1241
- plot_io-0.8.0/plot_io/labels.py +0 -77
- plot_io-0.8.0/plot_io/layers/base.py +0 -426
- plot_io-0.8.0/plot_io/layers/pipeline.py +0 -91
- plot_io-0.8.0/plot_io/layers/positions.py +0 -243
- plot_io-0.8.0/plot_io/layers/stats.py +0 -596
- plot_io-0.8.0/plot_io/layout.py +0 -1925
- plot_io-0.8.0/plot_io/presets/_util.py +0 -301
- plot_io-0.8.0/plot_io/presets/area.py +0 -180
- plot_io-0.8.0/plot_io/presets/box.py +0 -362
- plot_io-0.8.0/plot_io/presets/ecdf.py +0 -93
- plot_io-0.8.0/plot_io/presets/errorbar.py +0 -119
- plot_io-0.8.0/plot_io/presets/errors.py +0 -159
- plot_io-0.8.0/plot_io/presets/fill.py +0 -94
- plot_io-0.8.0/plot_io/presets/hist.py +0 -372
- plot_io-0.8.0/plot_io/presets/kde.py +0 -176
- plot_io-0.8.0/plot_io/presets/line.py +0 -154
- plot_io-0.8.0/plot_io/presets/regression.py +0 -120
- plot_io-0.8.0/plot_io/presets/scatter.py +0 -125
- plot_io-0.8.0/plot_io/presets/stem.py +0 -96
- plot_io-0.8.0/plot_io/presets/violin.py +0 -308
- plot_io-0.8.0/plot_io/spec.py +0 -204
- plot_io-0.8.0/plot_io/styles/library.py +0 -761
- plot_io-0.8.0/tests/golden.json +0 -191
- plot_io-0.8.0/tests/stats_reference.json +0 -839
- plot_io-0.8.0/tests/test_api.py +0 -129
- plot_io-0.8.0/tests/test_bars.py +0 -276
- plot_io-0.8.0/tests/test_distributions.py +0 -149
- plot_io-0.8.0/tests/test_docs.py +0 -70
- plot_io-0.8.0/tests/test_genome.py +0 -851
- plot_io-0.8.0/tests/test_genome_fixes.py +0 -231
- plot_io-0.8.0/tests/test_golden.py +0 -384
- plot_io-0.8.0/tests/test_heatmap.py +0 -70
- plot_io-0.8.0/tests/test_layout.py +0 -223
- plot_io-0.8.0/tests/test_layout_fixes.py +0 -242
- plot_io-0.8.0/tests/test_maps.py +0 -281
- plot_io-0.8.0/tests/test_native.py +0 -148
- plot_io-0.8.0/tests/test_output.py +0 -263
- plot_io-0.8.0/tests/test_output_settings_fixes.py +0 -217
- plot_io-0.8.0/tests/test_palettes.py +0 -117
- plot_io-0.8.0/tests/test_pie.py +0 -48
- plot_io-0.8.0/tests/test_plot_fixes.py +0 -312
- plot_io-0.8.0/tests/test_registry.py +0 -56
- plot_io-0.8.0/tests/test_series.py +0 -112
- plot_io-0.8.0/tests/test_settings.py +0 -240
- plot_io-0.8.0/tests/test_simplify.py +0 -101
- plot_io-0.8.0/tests/test_stats.py +0 -98
- plot_io-0.8.0/tests/test_styles.py +0 -213
- plot_io-0.8.0/tests/test_ticks.py +0 -93
- {plot_io-0.8.0 → plot_io-0.12.0}/LICENSE +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/alloc.c +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/math.c +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/rt.c +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/_native/src/sort.c +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/genome/pack.py +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/markup.py +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/plot_io/py.typed +0 -0
- {plot_io-0.8.0 → plot_io-0.12.0}/tests/fonts/VarTest.ttf +0 -0
plot_io-0.12.0/PKG-INFO
ADDED
|
@@ -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).
|
plot_io-0.12.0/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# plot_io
|
|
2
|
+
|
|
3
|
+
Plotting library in Python. No dependency other than [vec_io](https://github.com/ajgouhier/vec_io).
|
|
4
|
+
|
|
5
|
+
* **Familiar:** a figure of plots; `scatter`, `line`, `fill`, `box`, `heatmap`, `bar`,
|
|
6
|
+
`hist`, `kde` (1-D and 2-D), `ecdf`, `violin`, `strip`, `swarm`, `area`, `errorbar`, `stem`,
|
|
7
|
+
`regression`, `hist2d`, `hexbin`, `contour`, `pie`, `dots`; reference lines, spans, text and
|
|
8
|
+
annotations; `color`, `marker`, `opacity`, `limits`, `scale`, `legend`.
|
|
9
|
+
* **Statistical helpers:** `qq`, `raincloud`, `volcano`, `ma`, `manhattan`, `dendrogram`
|
|
10
|
+
plot types; significance brackets; point labels placed without overlaps; hierarchical
|
|
11
|
+
clustering (`plt.linkage`, scipy's methods); `plt.joint`, `plt.pairs` and `plt.clustermap`
|
|
12
|
+
figures in one call.
|
|
13
|
+
* **Units:** lengths in px, pt, in, mm, `em`, `%` of the axes or of another setting, data
|
|
14
|
+
units and durations (`width="1.5in"`, `tick_length="0.5em"`, `width="60%"`,
|
|
15
|
+
`cap_length="12h"`); `var()` and `calc()` relate settings (`"calc(var(--gap) * 2)"`).
|
|
16
|
+
* **One way to set things:** keywords at creation or `set(...)` on any object; figure
|
|
17
|
+
settings (font, color maps, line width…) are inherited by plots and series.
|
|
18
|
+
* **Layouts:** an explicit grid of ids with spans, or automatic rows and columns; plots
|
|
19
|
+
sized individually; axis lines (or plot borders) aligned across the figure; margins from
|
|
20
|
+
the real text metrics; shared axes; secondary axes; facets of a table.
|
|
21
|
+
* **Titles, legends and colorbars on any side:** several titles per plot; titles,
|
|
22
|
+
legends and colorbar keys shared by any rectangle of plots, nested as headers;
|
|
23
|
+
`share_legend` for one legend per row, column or figure; markup (`<i>`, `<b>`,
|
|
24
|
+
`<sup>`, …) in any text.
|
|
25
|
+
* **Data:** columns of any table by name (`data=`: dicts, pandas, polars, numpy), one
|
|
26
|
+
series per group (`group=`), numbers given as colors or sizes, point density (scipy's
|
|
27
|
+
`gaussian_kde`, in C) for colors, sizes, opacity and drawing order.
|
|
28
|
+
* **Axes:** linear, log, log2, log10, sqrt, exp, symlog, logit, time and category scales;
|
|
29
|
+
limits such as `"0/max"` or `"q:0.01/q:0.99"`; ticks with shared decimals and ×10ᵏ
|
|
30
|
+
factors, calendar ticks for dates.
|
|
31
|
+
* **Colors:** one system of color maps with kinds (qualitative, sequential, diverging,
|
|
32
|
+
cyclic; `okabe_ito` for color-vision deficiencies), a default map per kind, `center=`
|
|
33
|
+
for data about a value, interpolation in Oklab, colorbars;
|
|
34
|
+
marker sizes by area, equal for every shape.
|
|
35
|
+
* **Styles:** `style="matplotlib"`, `"seaborn"`, `"ggplot2"`, `"altair"`, `"matlab"`,
|
|
36
|
+
`"tufte"` give the look of those libraries; styles are presets of settings, and your
|
|
37
|
+
own build on them (a variant: `{"base": "seaborn", …}`).
|
|
38
|
+
* **Output:** PDF, EPS (transparency flattened), SVG, PNG, JPEG, JPEG XL and AVIF, by the
|
|
39
|
+
file's extension; CMYK, PDF/A and text as outlines are options of the save
|
|
40
|
+
(`color="cmyk"`, `pdf={"a": "2b"}`, `text="paths"`).
|
|
41
|
+
* **Large data:** one million points mapped and drawn in C; `simplify="auto"` drops what
|
|
42
|
+
cannot be seen, `rasterize=` turns a series into an image inside the PDF.
|
|
43
|
+
* **Genome tracks:** `bigwig` signals, `bed` intervals, `genes` and `gtf` gene models,
|
|
44
|
+
`hic` triangles and `links` over a region, and `site_profile` and `site_heatmap` around
|
|
45
|
+
sites, read from gwseq_io's readers (or any object with their methods) without
|
|
46
|
+
depending on gwseq_io.
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
pip install plot_io
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Python 3.11+. Text is shaped (kerned) and its fonts embedded by vec_io; it needs an
|
|
55
|
+
installed outline font, the default family list (`Helvetica, Nimbus Sans, Nimbus Sans L,
|
|
56
|
+
TeX Gyre Heros, FreeSans, Arial, Liberation Sans, Arimo`) taking its first installed family
|
|
57
|
+
([docs/api.md](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md#1-conventions)). JPEG XL
|
|
58
|
+
and AVIF output need vec_io's optional libjxl and libavif.
|
|
59
|
+
|
|
60
|
+
Wheels hold plot_io's C library prebuilt for Linux (x86_64, aarch64; glibc or musl),
|
|
61
|
+
Windows (x86_64, arm64) and macOS 13+ (arm64). Elsewhere (Intel Macs, other CPUs), pip
|
|
62
|
+
builds it from the sdist with the local C compiler (gcc or clang; on Windows clang or MinGW,
|
|
63
|
+
not MSVC); `pip install --no-binary plot_io plot_io` does so on any platform, and
|
|
64
|
+
`pip install .` from a checkout. With the pinned zig in the environment (`pip install
|
|
65
|
+
--require-hashes -r tools/zig.lock`, then `--no-build-isolation`), the sdist builds the
|
|
66
|
+
release binary itself.
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
python -m plot_io._native verify # the library loads, is the release binary, computes as it should
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Quick start
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import math
|
|
76
|
+
import random
|
|
77
|
+
|
|
78
|
+
import plot_io as plt
|
|
79
|
+
|
|
80
|
+
rng = random.Random(1)
|
|
81
|
+
x = [rng.uniform(0, 10) for _ in range(100)]
|
|
82
|
+
y = [v + rng.gauss(0, 1) for v in x]
|
|
83
|
+
s = plt.Scatter(x, y, name="data")
|
|
84
|
+
s.plot.x_axis(label="Time (s)")
|
|
85
|
+
s.plot.save("scatter.pdf")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
t = [i / 10 for i in range(1, 101)]
|
|
90
|
+
v = [math.exp(-k / 4) * (2 + math.sin(3 * k)) for k in t]
|
|
91
|
+
upper, lower = [a * 1.3 for a in v], [a * 0.7 for a in v]
|
|
92
|
+
va, vb = [rng.gauss(0, 1) for _ in range(50)], [rng.gauss(1, 1) for _ in range(50)]
|
|
93
|
+
matrix = [[math.sin(i / 2) * math.cos(j / 3) for j in range(6)] for i in range(4)]
|
|
94
|
+
columns, rows = list("ABCDEF"), ["w", "x", "y", "z"]
|
|
95
|
+
z = [a - b for a, b in zip(x, y)]
|
|
96
|
+
|
|
97
|
+
fig = plt.Figure(layout=[[1, 1, 2], [3, 4, 2]])
|
|
98
|
+
p = fig.plot(1, title="Signal")
|
|
99
|
+
p.line(t, v, name="raw")
|
|
100
|
+
p.fill(t, upper, lower, opacity=0.3)
|
|
101
|
+
p.y_axis(scale="log", label="Power")
|
|
102
|
+
fig.plot(2).box({"a": va, "b": vb})
|
|
103
|
+
h = fig.plot(3).heatmap(matrix, x=columns, y=rows, colorbar=True)
|
|
104
|
+
fig.plot(4).scatter(x, y, c=z)
|
|
105
|
+
fig.save("figure.pdf")
|
|
106
|
+
fig.save("figure.png", dpi="2x") # 192 dpi; a number is dots per inch
|
|
107
|
+
fig.save("figure.eps") # PostScript: transparency flattened
|
|
108
|
+
fig.save("figure.svg")
|
|
109
|
+
data = fig.write("pdf", compression="small") # bytes
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
fig = plt.Figure(style="ggplot2") # or a dict: {"base": "seaborn", "font_size": 9}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
categories, counts = ["a", "b", "c"], [3, 5, 2]
|
|
118
|
+
p = plt.Plot(width="3in", font_size="9pt", vars={"accent": "#c00"})
|
|
119
|
+
p.x_axis(tick_length="0.5em", minor_tick_length="50%")
|
|
120
|
+
p.bar(categories, counts, width="60%", color="var(--accent)") # a custom variable
|
|
121
|
+
p.x_axis.explain("tick_length") # where a value comes from
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
genes = {"umap_x": x, "umap_y": y}
|
|
126
|
+
df = {"x": x, "y": y, "cluster": [int(a) % 3 for a in x],
|
|
127
|
+
"condition": ["ctrl" if a < 5 else "drug" for a in y],
|
|
128
|
+
"replicate": [i % 2 + 1 for i in range(len(x))]}
|
|
129
|
+
p = plt.Plot()
|
|
130
|
+
p.scatter("umap_x", "umap_y", data=genes, c="density", draw_order="density") # columns
|
|
131
|
+
p.scatter("x", "y", data=df, group="cluster", marker="auto") # one series per group
|
|
132
|
+
fig, panels = plt.facet(df, col="condition", row="replicate") # small multiples
|
|
133
|
+
panels.scatter("x", "y")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Documentation
|
|
137
|
+
|
|
138
|
+
* [Tutorial](https://github.com/ajgouhier/plot_io/blob/main/docs/tutorial.md): first steps, from a figure to its file.
|
|
139
|
+
* [Guide](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md): the concepts by topic, with the settings tables.
|
|
140
|
+
* [Examples](https://github.com/ajgouhier/plot_io/blob/main/docs/examples.md): every image of the docs, the scripts that draw them, recipes.
|
|
141
|
+
* [Plot types](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md#plot-types): a page per plot type and figure helper, in
|
|
142
|
+
[docs/plots/](https://github.com/ajgouhier/plot_io/tree/main/docs/plots).
|
|
143
|
+
* [Reference](https://github.com/ajgouhier/plot_io/blob/main/docs/api.md#reference): a page per other class, in
|
|
144
|
+
[docs/reference/](https://github.com/ajgouhier/plot_io/tree/main/docs/reference).
|
|
145
|
+
* [Coming from matplotlib](https://github.com/ajgouhier/plot_io/blob/main/docs/from_matplotlib.md): its calls and names in plot_io.
|
|
146
|
+
|
|
147
|
+
## Development
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
python tools/check.py # every check, one after the other (--list shows them)
|
|
151
|
+
python tools/check.py --fast # without the slow ones (~25 s)
|
|
152
|
+
python tools/check.py --only suite,ruff,mypy
|
|
153
|
+
python -m unittest discover -s tests -t tests
|
|
154
|
+
python tools/bench.py --check # timings: fails over 1.5 × a target
|
|
155
|
+
python tools/gen_docs.py # regenerate the generated sections and pages of docs/
|
|
156
|
+
python tools/gen_docs.py --images # ... and the images of the plot-type pages and the tutorial
|
|
157
|
+
python tools/visual_check.py --save # render the examples as references
|
|
158
|
+
python tools/visual_check.py # ... and later compare with them (pixels, tolerances)
|
|
159
|
+
PLOT_IO_GOLDEN=update python -m unittest discover -s tests -t tests -p test_golden.py
|
|
160
|
+
python tools/record_stats.py > tests/stats_reference.json # with numpy, scipy, statsmodels
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The tests use only their own fonts (`tests/fonts`: VioTest, from vec_io's tests, through
|
|
164
|
+
`VEC_IO_FONT_DIRS`; installed fonts are ignored), so their text is the same on every
|
|
165
|
+
machine. The goldens (`tests/golden.json`) are keyed by meaning: the laid-out geometry of
|
|
166
|
+
each scene (rounded to 1/64 px), its drawing calls and its 96 dpi pixels (the last two
|
|
167
|
+
compared where the fonts match those recorded). Pixels are compared exactly, whatever
|
|
168
|
+
vec_io's version, against `tests/golden/*.png` (in the repository, not in the sdist; else
|
|
169
|
+
against a hash in `golden.json`); a changed scene writes its actual image and a diff to
|
|
170
|
+
`$PLOT_IO_GOLDEN_OUT` (default `<tempdir>/plot_io-golden/`) and names them. A missing
|
|
171
|
+
`golden.json`, or a recorded scene no longer drawn, fails. `PLOT_IO_GOLDEN=update` rewrites
|
|
172
|
+
only the files that changed; `PLOT_IO_GOLDEN=dump:DIR` writes the geometry, the drawing
|
|
173
|
+
calls and the PNG of each scene to `DIR` to see what changed.
|
|
174
|
+
|
|
175
|
+
The tests that read real files with gwseq_io run when it is importable: installed, or a
|
|
176
|
+
built checkout beside this one (`../gwseq_io/crates/gwseq-io-py/python`, added to the path
|
|
177
|
+
by `tests/test_genome.py`; elsewhere, put that directory on `PYTHONPATH`). Otherwise they
|
|
178
|
+
are skipped.
|
|
179
|
+
|
|
180
|
+
`PLOT_IO_NATIVE_LIB=PATH` loads that build of plot_io's C library instead of the one in
|
|
181
|
+
`plot_io/_native/bin/` (a sanitizer build, any other build; see
|
|
182
|
+
`plot_io/_native/README.md`).
|
|
183
|
+
|
|
184
|
+
The statistics kernels and color mapping are in plot_io's own C library, `plio`
|
|
185
|
+
(`plot_io/_native`, built like vec_io's: zig, freestanding, five targets). Building and its
|
|
186
|
+
checks:
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
pip install --require-hashes -r tools/zig.lock # the pinned zig
|
|
190
|
+
python tools/build_native.py # bindings from src/plio_api.h, then all targets (not in git)
|
|
191
|
+
python tools/build_native.py --check # every target rebuilt byte for byte as manifest.json says
|
|
192
|
+
python tools/crosscheck.py --qemu PATH/qemu-aarch64-static # same results on aarch64
|
|
193
|
+
python tools/dist.py # the sdist and one wheel per platform built from it
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The binaries are built, not committed: `manifest.json` records each target's hash. In a
|
|
197
|
+
checkout, `pip install -e .` builds the host's binary the way pip does from the sdist.
|
|
198
|
+
|
|
199
|
+
See [plot_io/_native/README.md](plot_io/_native/README.md).
|