graphunslopify 0.8.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.
Files changed (77) hide show
  1. graphunslopify-0.8.0/LICENSE +21 -0
  2. graphunslopify-0.8.0/PKG-INFO +136 -0
  3. graphunslopify-0.8.0/README.md +98 -0
  4. graphunslopify-0.8.0/graphunslopify/ZOD-LICENSE.txt +21 -0
  5. graphunslopify-0.8.0/graphunslopify/__init__.py +36 -0
  6. graphunslopify-0.8.0/graphunslopify/_translator.mjs +25539 -0
  7. graphunslopify-0.8.0/graphunslopify/audit.py +527 -0
  8. graphunslopify-0.8.0/graphunslopify/audit_worker.py +47 -0
  9. graphunslopify-0.8.0/graphunslopify/build.py +464 -0
  10. graphunslopify-0.8.0/graphunslopify/cell_colour.py +127 -0
  11. graphunslopify-0.8.0/graphunslopify/cli.py +447 -0
  12. graphunslopify-0.8.0/graphunslopify/colour.py +164 -0
  13. graphunslopify-0.8.0/graphunslopify/demo.py +40 -0
  14. graphunslopify-0.8.0/graphunslopify/describe.py +155 -0
  15. graphunslopify-0.8.0/graphunslopify/errors.py +13 -0
  16. graphunslopify-0.8.0/graphunslopify/examples/quickstart.ipynb +176 -0
  17. graphunslopify-0.8.0/graphunslopify/export_size.py +45 -0
  18. graphunslopify-0.8.0/graphunslopify/inspect.py +689 -0
  19. graphunslopify-0.8.0/graphunslopify/lockfile.py +80 -0
  20. graphunslopify-0.8.0/graphunslopify/mcpserver.py +121 -0
  21. graphunslopify-0.8.0/graphunslopify/notebook.py +61 -0
  22. graphunslopify-0.8.0/graphunslopify/pdf_review.py +242 -0
  23. graphunslopify-0.8.0/graphunslopify/preview.py +436 -0
  24. graphunslopify-0.8.0/graphunslopify/provenance.py +128 -0
  25. graphunslopify-0.8.0/graphunslopify/schemas/audit-report.schema.json +221 -0
  26. graphunslopify-0.8.0/graphunslopify/schemas/manifest.schema.json +31 -0
  27. graphunslopify-0.8.0/graphunslopify/schemas/runtime-report.schema.json +58 -0
  28. graphunslopify-0.8.0/graphunslopify/transport.py +86 -0
  29. graphunslopify-0.8.0/graphunslopify/web/app.css +381 -0
  30. graphunslopify-0.8.0/graphunslopify/web/app.js +424 -0
  31. graphunslopify-0.8.0/graphunslopify/web/index.html +125 -0
  32. graphunslopify-0.8.0/graphunslopify.egg-info/PKG-INFO +136 -0
  33. graphunslopify-0.8.0/graphunslopify.egg-info/SOURCES.txt +75 -0
  34. graphunslopify-0.8.0/graphunslopify.egg-info/dependency_links.txt +1 -0
  35. graphunslopify-0.8.0/graphunslopify.egg-info/entry_points.txt +2 -0
  36. graphunslopify-0.8.0/graphunslopify.egg-info/requires.txt +31 -0
  37. graphunslopify-0.8.0/graphunslopify.egg-info/top_level.txt +1 -0
  38. graphunslopify-0.8.0/pyproject.toml +49 -0
  39. graphunslopify-0.8.0/setup.cfg +4 -0
  40. graphunslopify-0.8.0/tests/test_audit.py +308 -0
  41. graphunslopify-0.8.0/tests/test_bar_intervals.py +193 -0
  42. graphunslopify-0.8.0/tests/test_build.py +153 -0
  43. graphunslopify-0.8.0/tests/test_calibration_references.py +348 -0
  44. graphunslopify-0.8.0/tests/test_cell_contrast.py +334 -0
  45. graphunslopify-0.8.0/tests/test_core_plot_references.py +612 -0
  46. graphunslopify-0.8.0/tests/test_density_references.py +261 -0
  47. graphunslopify-0.8.0/tests/test_describe.py +97 -0
  48. graphunslopify-0.8.0/tests/test_exported_text_size.py +275 -0
  49. graphunslopify-0.8.0/tests/test_figure_ci.py +79 -0
  50. graphunslopify-0.8.0/tests/test_group_projection.py +156 -0
  51. graphunslopify-0.8.0/tests/test_identity_references.py +656 -0
  52. graphunslopify-0.8.0/tests/test_inspect.py +432 -0
  53. graphunslopify-0.8.0/tests/test_interactive.py +278 -0
  54. graphunslopify-0.8.0/tests/test_local.py +91 -0
  55. graphunslopify-0.8.0/tests/test_mcpserver.py +127 -0
  56. graphunslopify-0.8.0/tests/test_notebook.py +45 -0
  57. graphunslopify-0.8.0/tests/test_numeric_measurement_views.py +163 -0
  58. graphunslopify-0.8.0/tests/test_overlay_coordinates.py +299 -0
  59. graphunslopify-0.8.0/tests/test_paired_references.py +348 -0
  60. graphunslopify-0.8.0/tests/test_paper_benchmark.py +57 -0
  61. graphunslopify-0.8.0/tests/test_pdf_review.py +199 -0
  62. graphunslopify-0.8.0/tests/test_preview.py +133 -0
  63. graphunslopify-0.8.0/tests/test_provenance.py +179 -0
  64. graphunslopify-0.8.0/tests/test_publication_readiness.py +63 -0
  65. graphunslopify-0.8.0/tests/test_qq_references.py +457 -0
  66. graphunslopify-0.8.0/tests/test_research_benchmark.py +59 -0
  67. graphunslopify-0.8.0/tests/test_runtime_report.py +70 -0
  68. graphunslopify-0.8.0/tests/test_scaling_references.py +510 -0
  69. graphunslopify-0.8.0/tests/test_sem_estimator.py +116 -0
  70. graphunslopify-0.8.0/tests/test_shared_categories.py +267 -0
  71. graphunslopify-0.8.0/tests/test_shared_series.py +248 -0
  72. graphunslopify-0.8.0/tests/test_signed_bars.py +174 -0
  73. graphunslopify-0.8.0/tests/test_significance.py +66 -0
  74. graphunslopify-0.8.0/tests/test_survival_references.py +299 -0
  75. graphunslopify-0.8.0/tests/test_table_context.py +337 -0
  76. graphunslopify-0.8.0/tests/test_text_exports.py +197 -0
  77. graphunslopify-0.8.0/tests/test_verification_defaults.py +146 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GraphUnslopify contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: graphunslopify
3
+ Version: 0.8.0
4
+ Summary: Local semantic figure generation and render-time scientific figure checks.
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://unluckyjet.github.io/GraphUnslopify/
7
+ Project-URL: Source, https://github.com/unluckyjet/GraphUnslopify
8
+ Project-URL: Documentation, https://github.com/unluckyjet/GraphUnslopify/tree/v0.8.0/docs
9
+ Project-URL: Changelog, https://github.com/unluckyjet/GraphUnslopify/releases/tag/v0.8.0
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: matplotlib>=3.9
14
+ Requires-Dist: pandas>=2.0
15
+ Requires-Dist: numpy>=1.24
16
+ Requires-Dist: pypdf>=5
17
+ Requires-Dist: typing_extensions>=4.4
18
+ Requires-Dist: nodejs-wheel-binaries<25,>=22.13.1
19
+ Requires-Dist: jsonschema>=4
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=8; extra == "dev"
22
+ Requires-Dist: jsonschema>=4; extra == "dev"
23
+ Provides-Extra: interactive
24
+ Requires-Dist: plotly>=5.24; extra == "interactive"
25
+ Provides-Extra: parquet
26
+ Requires-Dist: pyarrow>=15; extra == "parquet"
27
+ Provides-Extra: pdf
28
+ Requires-Dist: pypdfium2<6,>=4.30; extra == "pdf"
29
+ Provides-Extra: statistics
30
+ Requires-Dist: scipy>=1.11; extra == "statistics"
31
+ Provides-Extra: notebook
32
+ Requires-Dist: jupyterlab>=4; extra == "notebook"
33
+ Requires-Dist: ipykernel>=6.29; extra == "notebook"
34
+ Requires-Dist: nbclient>=0.10; extra == "notebook"
35
+ Provides-Extra: agent
36
+ Requires-Dist: mcp<3,>=2.3; extra == "agent"
37
+ Dynamic: license-file
38
+
39
+ # GraphUnslopify
40
+
41
+ Translate semantic JSON into reviewable Python figures, render local data, and check claims,
42
+ readability and accessibility. The package includes the TypeScript translator and a Node runtime;
43
+ translation and rendering need no hosted service after installation.
44
+
45
+ In a Python 3.10+ virtual environment:
46
+
47
+ ```sh
48
+ python -m pip install "https://github.com/unluckyjet/GraphUnslopify/releases/download/v0.8.0/graphunslopify-0.8.0-py3-none-any.whl"
49
+ ```
50
+
51
+ From a source checkout, `python -m pip install ./python` remains supported.
52
+
53
+ ```sh
54
+ graphunslopify doctor
55
+ graphunslopify demo
56
+ graphunslopify render graphunslopify-demo/figure.json --strict --json
57
+ ```
58
+
59
+ The demo creates public synthetic CSV data and PNG/SVG/PDF figures, a standalone Python program,
60
+ and a JSON verification report. Data paths in a JSON spec resolve beside the spec file.
61
+ `graphunslopify translate figure.json --output figure.py` emits code without rendering.
62
+
63
+ `graphunslopify preview --open` launches the packaged offline browser editor. Choose data, edit a
64
+ spec or recipe, review live strict previews and apply an offered fix. Download figures, Python,
65
+ spec and report together; input data enters the ZIP only when explicitly selected.
66
+ See [the local editor workflow](../docs/local-editor.md), including VS Code's integrated terminal.
67
+
68
+ ```python
69
+ from graphunslopify import Figure
70
+
71
+ Figure.line("results.csv").x("epoch", "Epoch").y("score", "Score").render(strict=True)
72
+ ```
73
+
74
+ `Figure.translate()` and `Figure.from_profile()` default to the packaged local translator.
75
+ Select a hosted translator explicitly with `api="https://your-service"` or
76
+ `GRAPHUNSLOPIFY_API`; use `api="local"` to override that environment setting.
77
+ `GRAPHUNSLOPIFY_NODE` can select a specific Node executable.
78
+
79
+ Current development source enables strict verification by default in `Figure.render()` and
80
+ execution commands. Explicit `strict=False` / `--no-strict` opts out while retaining failed or
81
+ incomplete report verdicts; warning rejection always implies strict mode. The pinned0.8.0 wheel uses these defaults. Older 0.7.0 installs require `strict=True` / `--strict`.
82
+
83
+ Use `[interactive]` for supported self-contained Plotly HTML. Strict verification rejects failed
84
+ or untested required checks; literal data claims are not statistical significance tests.
85
+ Read the repository documentation for the supported combinations and limits.
86
+
87
+ ## What it checks
88
+
89
+ `text_too_small` and `text_near_minimum` measure every text element at the width the figure will
90
+ occupy on the page. Generated programs measure their written PNG/SVG/PDF widths, including
91
+ tight cropping and padding, before calculating manuscript scaling. For your own figure, pass
92
+ `target_width_in` and `export_paths=["figure.pdf"]` after saving; without paths the API uses the
93
+ nominal canvas. Reports retain the measured widths and scale. See
94
+ [the measurement contract and limits](../docs/export-legibility.md).
95
+
96
+ `tick_labels_collide` compares neighbouring tick label bounding boxes. `legend_covers_data` counts
97
+ plotted points falling inside the legend box. `overplotting` measures marker ink against plotting
98
+ area.
99
+
100
+ `series_indistinguishable` measures CIEDE2000 between every pair of legend colours as composited
101
+ over white, then repeats it under simulated protanopia, deuteranopia and tritanopia.
102
+ `greyscale_collision` catches pairs that survive colour but merge in a black and white print, and
103
+ stays quiet when a second channel such as line style or marker already separates them.
104
+
105
+ `truncated_bar_axis` is an error, because a bar's length encodes its value. `axis_exaggeration`
106
+ warns when a line axis is zoomed so far that a rounding error fills the frame.
107
+
108
+ Every check is geometric or colorimetric. Nothing asks a model for an opinion, so the same figure
109
+ always yields the same findings. Reasoning and sources are in [research notes](https://github.com/unluckyjet/GraphUnslopify/blob/v0.8.0/docs/research.md).
110
+
111
+
112
+ [Source](https://github.com/unluckyjet/GraphUnslopify) · [Versioned 0.8.0 documentation](https://github.com/unluckyjet/GraphUnslopify/tree/v0.8.0/docs) · [Release assets](https://github.com/unluckyjet/GraphUnslopify/releases/tag/v0.8.0).
113
+ MIT license. The bundled translator includes Zod's MIT license; runtime/dependency licenses ship
114
+ with their respective Python distributions.
115
+
116
+ ## Paper audits
117
+
118
+ `graphunslopify audit paper/ --out-dir audit-output` regenerates all figures in the directory’s
119
+ `graphunslopify.json` manifest with strict verification. `--baseline previous/audit.report.json`
120
+ adds data, numeric-representation, claim, description and artifact differences. It writes aggregate
121
+ JSON/Markdown plus individual programs, figures, logs and reports. See the repository paper-audit
122
+ guide for the manifest contract and supported metadata-backed artifact checks.
123
+
124
+ ## Notebook example
125
+
126
+ Install the notebook extra for JupyterLab and kernel execution. Run
127
+ `graphunslopify notebook --output quickstart.ipynb`, then `jupyter lab quickstart.ipynb`, or add
128
+ `--execute` to run it through the current Python environment. All 21 figure kinds have named
129
+ Python constructors and a shared Kind typing Literal. See the repository notebook guide.
130
+
131
+ ## Local MCP server
132
+
133
+ Install the agent extra, then run `graphunslopify mcp-config` (or `--client codex`) to print a
134
+ configuration for the current environment. The host launches `graphunslopify mcp` over stdio.
135
+ Seven read-only compiler tools share the canonical emitter; data profiling/rendering remain local
136
+ CLI operations. See the repository agent guide for setup, error semantics and protocol tests.
@@ -0,0 +1,98 @@
1
+ # GraphUnslopify
2
+
3
+ Translate semantic JSON into reviewable Python figures, render local data, and check claims,
4
+ readability and accessibility. The package includes the TypeScript translator and a Node runtime;
5
+ translation and rendering need no hosted service after installation.
6
+
7
+ In a Python 3.10+ virtual environment:
8
+
9
+ ```sh
10
+ python -m pip install "https://github.com/unluckyjet/GraphUnslopify/releases/download/v0.8.0/graphunslopify-0.8.0-py3-none-any.whl"
11
+ ```
12
+
13
+ From a source checkout, `python -m pip install ./python` remains supported.
14
+
15
+ ```sh
16
+ graphunslopify doctor
17
+ graphunslopify demo
18
+ graphunslopify render graphunslopify-demo/figure.json --strict --json
19
+ ```
20
+
21
+ The demo creates public synthetic CSV data and PNG/SVG/PDF figures, a standalone Python program,
22
+ and a JSON verification report. Data paths in a JSON spec resolve beside the spec file.
23
+ `graphunslopify translate figure.json --output figure.py` emits code without rendering.
24
+
25
+ `graphunslopify preview --open` launches the packaged offline browser editor. Choose data, edit a
26
+ spec or recipe, review live strict previews and apply an offered fix. Download figures, Python,
27
+ spec and report together; input data enters the ZIP only when explicitly selected.
28
+ See [the local editor workflow](../docs/local-editor.md), including VS Code's integrated terminal.
29
+
30
+ ```python
31
+ from graphunslopify import Figure
32
+
33
+ Figure.line("results.csv").x("epoch", "Epoch").y("score", "Score").render(strict=True)
34
+ ```
35
+
36
+ `Figure.translate()` and `Figure.from_profile()` default to the packaged local translator.
37
+ Select a hosted translator explicitly with `api="https://your-service"` or
38
+ `GRAPHUNSLOPIFY_API`; use `api="local"` to override that environment setting.
39
+ `GRAPHUNSLOPIFY_NODE` can select a specific Node executable.
40
+
41
+ Current development source enables strict verification by default in `Figure.render()` and
42
+ execution commands. Explicit `strict=False` / `--no-strict` opts out while retaining failed or
43
+ incomplete report verdicts; warning rejection always implies strict mode. The pinned0.8.0 wheel uses these defaults. Older 0.7.0 installs require `strict=True` / `--strict`.
44
+
45
+ Use `[interactive]` for supported self-contained Plotly HTML. Strict verification rejects failed
46
+ or untested required checks; literal data claims are not statistical significance tests.
47
+ Read the repository documentation for the supported combinations and limits.
48
+
49
+ ## What it checks
50
+
51
+ `text_too_small` and `text_near_minimum` measure every text element at the width the figure will
52
+ occupy on the page. Generated programs measure their written PNG/SVG/PDF widths, including
53
+ tight cropping and padding, before calculating manuscript scaling. For your own figure, pass
54
+ `target_width_in` and `export_paths=["figure.pdf"]` after saving; without paths the API uses the
55
+ nominal canvas. Reports retain the measured widths and scale. See
56
+ [the measurement contract and limits](../docs/export-legibility.md).
57
+
58
+ `tick_labels_collide` compares neighbouring tick label bounding boxes. `legend_covers_data` counts
59
+ plotted points falling inside the legend box. `overplotting` measures marker ink against plotting
60
+ area.
61
+
62
+ `series_indistinguishable` measures CIEDE2000 between every pair of legend colours as composited
63
+ over white, then repeats it under simulated protanopia, deuteranopia and tritanopia.
64
+ `greyscale_collision` catches pairs that survive colour but merge in a black and white print, and
65
+ stays quiet when a second channel such as line style or marker already separates them.
66
+
67
+ `truncated_bar_axis` is an error, because a bar's length encodes its value. `axis_exaggeration`
68
+ warns when a line axis is zoomed so far that a rounding error fills the frame.
69
+
70
+ Every check is geometric or colorimetric. Nothing asks a model for an opinion, so the same figure
71
+ always yields the same findings. Reasoning and sources are in [research notes](https://github.com/unluckyjet/GraphUnslopify/blob/v0.8.0/docs/research.md).
72
+
73
+
74
+ [Source](https://github.com/unluckyjet/GraphUnslopify) · [Versioned 0.8.0 documentation](https://github.com/unluckyjet/GraphUnslopify/tree/v0.8.0/docs) · [Release assets](https://github.com/unluckyjet/GraphUnslopify/releases/tag/v0.8.0).
75
+ MIT license. The bundled translator includes Zod's MIT license; runtime/dependency licenses ship
76
+ with their respective Python distributions.
77
+
78
+ ## Paper audits
79
+
80
+ `graphunslopify audit paper/ --out-dir audit-output` regenerates all figures in the directory’s
81
+ `graphunslopify.json` manifest with strict verification. `--baseline previous/audit.report.json`
82
+ adds data, numeric-representation, claim, description and artifact differences. It writes aggregate
83
+ JSON/Markdown plus individual programs, figures, logs and reports. See the repository paper-audit
84
+ guide for the manifest contract and supported metadata-backed artifact checks.
85
+
86
+ ## Notebook example
87
+
88
+ Install the notebook extra for JupyterLab and kernel execution. Run
89
+ `graphunslopify notebook --output quickstart.ipynb`, then `jupyter lab quickstart.ipynb`, or add
90
+ `--execute` to run it through the current Python environment. All 21 figure kinds have named
91
+ Python constructors and a shared Kind typing Literal. See the repository notebook guide.
92
+
93
+ ## Local MCP server
94
+
95
+ Install the agent extra, then run `graphunslopify mcp-config` (or `--client codex`) to print a
96
+ configuration for the current environment. The host launches `graphunslopify mcp` over stdio.
97
+ Seven read-only compiler tools share the canonical emitter; data profiling/rendering remain local
98
+ CLI operations. See the repository agent guide for setup, error semantics and protocol tests.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Colin McDonnell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,36 @@
1
+ """Render-time checks for figures produced by GraphUnslopify.
2
+
3
+ The MCP server checks a spec. This checks the picture. Import it in a generated
4
+ script and it reports what a reviewer would complain about, before you submit.
5
+
6
+ from graphunslopify import inspect_figure
7
+
8
+ report = inspect_figure(fig, target_width_in=3.4)
9
+ print(report)
10
+ """
11
+
12
+ from .build import Figure, Kind, SpecError
13
+ from .colour import ciede2000, distance, simulate, worst_case_distance
14
+ from .describe import profile
15
+ from .inspect import Finding, Report, inspect_figure
16
+ from .lockfile import appearance
17
+ from .provenance import ProvenanceError, read_provenance
18
+
19
+ __all__ = [
20
+ "Figure",
21
+ "Finding",
22
+ "Kind",
23
+ "ProvenanceError",
24
+ "Report",
25
+ "SpecError",
26
+ "appearance",
27
+ "ciede2000",
28
+ "distance",
29
+ "inspect_figure",
30
+ "profile",
31
+ "read_provenance",
32
+ "simulate",
33
+ "worst_case_distance",
34
+ ]
35
+
36
+ __version__ = "0.8.0"