forgegraph 0.2.0__tar.gz → 0.4.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.
- {forgegraph-0.2.0 → forgegraph-0.4.0}/.gitignore +6 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/.pre-commit-config.yaml +4 -3
- forgegraph-0.4.0/CHANGELOG.md +122 -0
- forgegraph-0.4.0/CONTRIBUTING.md +44 -0
- forgegraph-0.2.0/README.md → forgegraph-0.4.0/PKG-INFO +73 -38
- forgegraph-0.2.0/PKG-INFO → forgegraph-0.4.0/README.md +43 -63
- {forgegraph-0.2.0/docs → forgegraph-0.4.0/docs/design}/architecture.md +223 -215
- forgegraph-0.4.0/docs/design/todo.md +10 -0
- forgegraph-0.4.0/docs/packs/acme/formats/slide.md +14 -0
- {forgegraph-0.2.0/docs/specs/pack → forgegraph-0.4.0/docs/packs}/acme/graphspecs/polarization-curve.md +14 -18
- forgegraph-0.4.0/docs/packs/acme/layouts/dashboard.md +17 -0
- {forgegraph-0.2.0/docs/specs/pack → forgegraph-0.4.0/docs/packs}/acme/pack.md +1 -1
- forgegraph-0.4.0/docs/packs/acme/schedules/workday.md +16 -0
- forgegraph-0.4.0/docs/packs/acme/themes/acme.md +26 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/catalogs/formats/compact_format.md +11 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/catalogs/formats/wide_format.md +11 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/catalogs/themes/light_theme.md +58 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/formats/compact_format.md +35 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/formats/wide_format.md +48 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/graphspecs/graphspec_example.md +116 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/layouts/layout.md +31 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/pack.md +29 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/schedules/schedule.md +30 -0
- forgegraph-0.4.0/docs/packs/forgegraph_default/themes/light_theme.md +153 -0
- forgegraph-0.4.0/docs/specifications/catalogs/graphtype_xy.md +55 -0
- forgegraph-0.4.0/docs/specifications/catalogs/layer_error_bar.md +18 -0
- forgegraph-0.4.0/docs/specifications/catalogs/layer_note.md +15 -0
- forgegraph-0.4.0/docs/specifications/catalogs/layer_reference.md +35 -0
- forgegraph-0.4.0/docs/specifications/config.md +24 -0
- forgegraph-0.4.0/docs/specifications/format.md +19 -0
- forgegraph-0.4.0/docs/specifications/graphspec_example.md +129 -0
- forgegraph-0.4.0/docs/specifications/graphtype_xy.md +74 -0
- forgegraph-0.4.0/docs/specifications/layer_error_bar.md +15 -0
- forgegraph-0.4.0/docs/specifications/layer_note.md +12 -0
- forgegraph-0.4.0/docs/specifications/layer_reference.md +55 -0
- forgegraph-0.4.0/docs/specifications/layout_example.md +28 -0
- forgegraph-0.4.0/docs/specifications/pack.md +25 -0
- {forgegraph-0.2.0/docs/specs/provenance → forgegraph-0.4.0/docs/specifications}/provenance.md +10 -10
- forgegraph-0.4.0/docs/specifications/schedule.md +30 -0
- forgegraph-0.4.0/docs/specifications/styles.md +12 -0
- forgegraph-0.4.0/docs/specifications/theme.md +109 -0
- forgegraph-0.4.0/docs/specs_and_packs_revisions/notes.docx +0 -0
- forgegraph-0.4.0/examples/layouts/README.md +10 -0
- forgegraph-0.4.0/examples/layouts/dashboard/forgegraph.toml +1 -0
- forgegraph-0.4.0/examples/layouts/dashboard/lab_throughput.layout.md +37 -0
- forgegraph-0.4.0/examples/layouts/dashboard/lab_throughput.layout.yaml +33 -0
- forgegraph-0.4.0/examples/layouts/dashboard/lost_runs.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/lost_runs.yaml +32 -0
- forgegraph-0.4.0/examples/layouts/dashboard/ops/formats/dashboard.md +17 -0
- forgegraph-0.4.0/examples/layouts/dashboard/ops/formats/dashboard.yaml +13 -0
- forgegraph-0.4.0/examples/layouts/dashboard/ops/pack.yaml +5 -0
- forgegraph-0.4.0/examples/layouts/dashboard/prep_lab_dashboard.py +40 -0
- forgegraph-0.4.0/examples/layouts/dashboard/run_time.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/run_time.yaml +32 -0
- forgegraph-0.4.0/examples/layouts/dashboard/runs_gc_ms_01.yaml +23 -0
- forgegraph-0.4.0/examples/layouts/dashboard/runs_hplc_01.yaml +23 -0
- forgegraph-0.4.0/examples/layouts/dashboard/runs_hplc_02.yaml +23 -0
- forgegraph-0.4.0/examples/layouts/dashboard/runs_icp_oes_01.yaml +23 -0
- forgegraph-0.4.0/examples/layouts/dashboard/samples_weekly.yaml +24 -0
- forgegraph-0.4.0/examples/layouts/dashboard/throughput_weekly.yaml +25 -0
- forgegraph-0.4.0/examples/layouts/dashboard/weekly_gc_ms_01.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/weekly_hplc_01.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/weekly_hplc_02.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/weekly_icp_oes_01.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/weekly_runs.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/dashboard/weekly_samples.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/paper/cell_durability.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/paper/cell_performance.layout.md +22 -0
- forgegraph-0.4.0/examples/layouts/paper/cell_performance.layout.yaml +18 -0
- forgegraph-0.4.0/examples/layouts/paper/cell_polarization.parquet +0 -0
- forgegraph-0.4.0/examples/layouts/paper/forgegraph.toml +1 -0
- forgegraph-0.4.0/examples/layouts/paper/hfr_time.yaml +26 -0
- forgegraph-0.4.0/examples/layouts/paper/journal/formats/journal-double.md +16 -0
- forgegraph-0.4.0/examples/layouts/paper/journal/formats/journal-double.yaml +12 -0
- forgegraph-0.4.0/examples/layouts/paper/journal/pack.yaml +5 -0
- forgegraph-0.4.0/examples/layouts/paper/polarization.yaml +24 -0
- forgegraph-0.4.0/examples/layouts/paper/prep_cells.py +10 -0
- forgegraph-0.4.0/examples/layouts/paper/voltage_time.yaml +26 -0
- forgegraph-0.4.0/examples/packs/acme/formats/slide.yaml +10 -0
- forgegraph-0.4.0/examples/packs/acme/graphspecs/polarization-curve.yaml +27 -0
- forgegraph-0.4.0/examples/packs/acme/layouts/dashboard.yaml +13 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/packs/acme/pack.yaml +1 -1
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/packs/acme/references/house.md +1 -1
- forgegraph-0.4.0/examples/packs/acme/schedules/workday.yaml +12 -0
- forgegraph-0.4.0/examples/packs/acme/themes/acme.yaml +22 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/pyproject.toml +12 -10
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/build_example_data.py +11 -10
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/build_recreations.py +12 -22
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/forgemark.py +2 -2
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/mirror_specs.py +5 -5
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/report_skill_evals.py +4 -4
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/run_skill_evals.py +260 -158
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/smoke_installed.py +8 -11
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/visual_changelog.py +12 -9
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/canvas.py +48 -58
- forgegraph-0.4.0/src/forgegraph/catalog_build/build.py +219 -0
- forgegraph-0.4.0/src/forgegraph/catalog_build/cards.py +426 -0
- forgegraph-0.4.0/src/forgegraph/catalog_build/examples.py +183 -0
- forgegraph-0.4.0/src/forgegraph/catalog_build/files.py +258 -0
- {forgegraph-0.2.0/src/forgegraph/catalog → forgegraph-0.4.0/src/forgegraph/catalog_build}/page.py +8 -0
- forgegraph-0.4.0/src/forgegraph/cli/__init__.py +135 -0
- forgegraph-0.4.0/src/forgegraph/cli/catalog.py +219 -0
- forgegraph-0.4.0/src/forgegraph/cli/graphs.py +171 -0
- forgegraph-0.4.0/src/forgegraph/cli/jobs.py +42 -0
- forgegraph-0.4.0/src/forgegraph/cli/schema.py +230 -0
- forgegraph-0.4.0/src/forgegraph/cli/skill.py +41 -0
- forgegraph-0.4.0/src/forgegraph/data.py +42 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/axes.py +98 -301
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/colorbar.py +51 -21
- forgegraph-0.4.0/src/forgegraph/drawing/dates.py +283 -0
- forgegraph-0.4.0/src/forgegraph/drawing/errors.py +9 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/export.py +2 -1
- forgegraph-0.4.0/src/forgegraph/drawing/figure.py +157 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/key.py +34 -28
- forgegraph-0.4.0/src/forgegraph/drawing/labels.py +433 -0
- forgegraph-0.4.0/src/forgegraph/drawing/layers.py +874 -0
- forgegraph-0.4.0/src/forgegraph/drawing/layout.py +495 -0
- forgegraph-0.4.0/src/forgegraph/drawing/limits.py +50 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/lint.py +55 -39
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/marks.py +252 -186
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/spacing.py +29 -19
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/style.py +112 -26
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/text.py +60 -6
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/ticks.py +97 -12
- forgegraph-0.4.0/src/forgegraph/drawing/xy.py +1196 -0
- forgegraph-0.4.0/src/forgegraph/drawn.py +144 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/__init__.py +28 -7
- forgegraph-0.4.0/src/forgegraph/forgemark.py +101 -0
- forgegraph-0.4.0/src/forgegraph/graph.py +401 -0
- forgegraph-0.4.0/src/forgegraph/jobs/__init__.py +9 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/jobs/run.py +42 -93
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/jobs/status.py +1 -1
- forgegraph-0.4.0/src/forgegraph/layouts/__init__.py +553 -0
- forgegraph-0.4.0/src/forgegraph/layouts/separators.py +184 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/packs/__init__.py +34 -22
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/catalogs/formats/compact_format.yaml +7 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/catalogs/formats/wide_format.yaml +7 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/catalogs/themes/light_theme.yaml +54 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/formats/compact_format.yaml +15 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/formats/wide_format.yaml +15 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/graphspecs/graphspec_example.yaml +112 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/layouts/layout.yaml +27 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/pack.yaml +5 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/schedules/schedule.yaml +26 -0
- forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default/themes/light_theme.yaml +149 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/__init__.py +3 -11
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/SKILL.md +3 -3
- forgegraph-0.4.0/src/forgegraph/skill/forgegraph/examples/bars.yaml +32 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/examples/figure.layout.yaml +4 -4
- forgegraph-0.4.0/src/forgegraph/skill/forgegraph/examples/figure.schedule.yaml +12 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/examples/layers.yaml +13 -14
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/examples/xy.yaml +7 -10
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/references/themes_formats_configs.md +3 -3
- forgegraph-0.4.0/src/forgegraph/spec/__init__.py +12 -0
- forgegraph-0.4.0/src/forgegraph/spec/access.py +99 -0
- forgegraph-0.4.0/src/forgegraph/spec/common.py +38 -0
- forgegraph-0.4.0/src/forgegraph/spec/explain.py +83 -0
- forgegraph-0.4.0/src/forgegraph/spec/layers.py +229 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/spec/layout.py +43 -34
- forgegraph-0.4.0/src/forgegraph/spec/loaded.py +82 -0
- forgegraph-0.4.0/src/forgegraph/spec/parameters.py +858 -0
- forgegraph-0.4.0/src/forgegraph/spec/provenance.py +133 -0
- forgegraph-0.4.0/src/forgegraph/spec/registry.py +192 -0
- forgegraph-0.4.0/src/forgegraph/spec/resolve.py +231 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/spec/schedule.py +12 -10
- forgegraph-0.4.0/src/forgegraph/spec/series.py +169 -0
- forgegraph-0.4.0/src/forgegraph/spec/tags.py +230 -0
- forgegraph-0.4.0/src/forgegraph/spec/validate.py +416 -0
- forgegraph-0.4.0/src/forgegraph/specifications/catalogs/graphtype_xy.yaml +51 -0
- forgegraph-0.4.0/src/forgegraph/specifications/catalogs/layer_error_bar.yaml +14 -0
- forgegraph-0.4.0/src/forgegraph/specifications/catalogs/layer_note.yaml +11 -0
- forgegraph-0.4.0/src/forgegraph/specifications/catalogs/layer_reference.yaml +31 -0
- forgegraph-0.4.0/src/forgegraph/specifications/config.toml +1 -0
- forgegraph-0.4.0/src/forgegraph/specifications/format.yaml +15 -0
- forgegraph-0.4.0/src/forgegraph/specifications/graphspec_example.yaml +125 -0
- forgegraph-0.4.0/src/forgegraph/specifications/graphtype_xy.yaml +70 -0
- forgegraph-0.4.0/src/forgegraph/specifications/layer_error_bar.yaml +11 -0
- forgegraph-0.4.0/src/forgegraph/specifications/layer_note.yaml +8 -0
- forgegraph-0.4.0/src/forgegraph/specifications/layer_reference.yaml +22 -0
- forgegraph-0.4.0/src/forgegraph/specifications/layout_example.yaml +24 -0
- forgegraph-0.4.0/src/forgegraph/specifications/pack.yaml +5 -0
- {forgegraph-0.2.0/src/forgegraph/spec → forgegraph-0.4.0/src/forgegraph/specifications}/provenance.yaml +9 -9
- forgegraph-0.4.0/src/forgegraph/specifications/schedule.yaml +26 -0
- forgegraph-0.4.0/src/forgegraph/specifications/styles.yaml +8 -0
- forgegraph-0.4.0/src/forgegraph/specifications/theme.yaml +105 -0
- forgegraph-0.4.0/tests/baselines/crowded_runs.png +0 -0
- forgegraph-0.4.0/tests/baselines/flow_sweep_wide.png +0 -0
- forgegraph-0.4.0/tests/baselines/layout_anode_layers.png +0 -0
- forgegraph-0.4.0/tests/baselines/layout_screening_and_rate.png +0 -0
- forgegraph-0.4.0/tests/baselines/separator_colorbar.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/conftest.py +2 -2
- forgegraph-0.4.0/tests/pack_helpers.py +128 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/recreations.py +70 -84
- forgegraph-0.4.0/tests/render_helpers.py +121 -0
- forgegraph-0.4.0/tests/spec_mirror.py +204 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_axes.py +156 -43
- forgegraph-0.4.0/tests/test_blank.py +105 -0
- forgegraph-0.4.0/tests/test_catalog.py +148 -0
- forgegraph-0.4.0/tests/test_catalog_files.py +310 -0
- forgegraph-0.4.0/tests/test_catalog_inputs.py +131 -0
- forgegraph-0.4.0/tests/test_catalog_page.py +81 -0
- forgegraph-0.4.0/tests/test_cli.py +483 -0
- forgegraph-0.4.0/tests/test_dates.py +478 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_jobs.py +92 -55
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_key_position.py +13 -7
- forgegraph-0.4.0/tests/test_labels.py +88 -0
- forgegraph-0.4.0/tests/test_layers.py +843 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_layout.py +240 -124
- forgegraph-0.4.0/tests/test_lint.py +229 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_marks.py +141 -69
- forgegraph-0.4.0/tests/test_packaging.py +30 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_packs.py +128 -88
- forgegraph-0.4.0/tests/test_perturbation.py +58 -0
- forgegraph-0.4.0/tests/test_regression.py +25 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_render.py +352 -90
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_schedule.py +11 -12
- forgegraph-0.4.0/tests/test_series.py +294 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_smoke.py +38 -0
- forgegraph-0.4.0/tests/test_spec_comments.py +126 -0
- forgegraph-0.4.0/tests/test_specs.py +938 -0
- forgegraph-0.4.0/tests/test_styles.py +234 -0
- forgegraph-0.4.0/tests/test_tags.py +140 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_text.py +103 -4
- {forgegraph-0.2.0 → forgegraph-0.4.0}/uv.lock +3 -3
- forgegraph-0.2.0/CHANGELOG.md +0 -48
- forgegraph-0.2.0/CONTRIBUTING.md +0 -39
- forgegraph-0.2.0/docs/build-plan.md +0 -382
- forgegraph-0.2.0/docs/decisions.md +0 -222
- forgegraph-0.2.0/docs/forgemark-repro-reattach.md +0 -80
- forgegraph-0.2.0/docs/forgemark-request.md +0 -56
- forgegraph-0.2.0/docs/specs/catalog/base_format.md +0 -22
- forgegraph-0.2.0/docs/specs/catalog/base_theme.md +0 -222
- forgegraph-0.2.0/docs/specs/catalog/graph_type_xy.md +0 -202
- forgegraph-0.2.0/docs/specs/catalog/layer_error_bar.md +0 -26
- forgegraph-0.2.0/docs/specs/catalog/layer_note.md +0 -20
- forgegraph-0.2.0/docs/specs/catalog/layer_reference_line.md +0 -36
- forgegraph-0.2.0/docs/specs/config/config.md +0 -5
- forgegraph-0.2.0/docs/specs/format/base_format.md +0 -22
- forgegraph-0.2.0/docs/specs/format/base_layout_format.md +0 -14
- forgegraph-0.2.0/docs/specs/graph_type/xy.md +0 -90
- forgegraph-0.2.0/docs/specs/graphspec/polarization.md +0 -142
- forgegraph-0.2.0/docs/specs/layer/error_bar.md +0 -16
- forgegraph-0.2.0/docs/specs/layer/note.md +0 -12
- forgegraph-0.2.0/docs/specs/layer/reference_line.md +0 -19
- forgegraph-0.2.0/docs/specs/layout/base_layout.md +0 -30
- forgegraph-0.2.0/docs/specs/pack/acme/formats/slide.md +0 -16
- forgegraph-0.2.0/docs/specs/pack/acme/layouts/dashboard.md +0 -18
- forgegraph-0.2.0/docs/specs/pack/acme/schedules/workday.md +0 -17
- forgegraph-0.2.0/docs/specs/pack/acme/themes/acme.md +0 -28
- forgegraph-0.2.0/docs/specs/pack/forgegraph_base.md +0 -9
- forgegraph-0.2.0/docs/specs/schedule/base_schedule.md +0 -30
- forgegraph-0.2.0/docs/specs/theme/base_theme.md +0 -161
- forgegraph-0.2.0/examples/packs/acme/formats/slide.yaml +0 -12
- forgegraph-0.2.0/examples/packs/acme/graphspecs/polarization-curve.yaml +0 -31
- forgegraph-0.2.0/examples/packs/acme/layouts/dashboard.yaml +0 -14
- forgegraph-0.2.0/examples/packs/acme/schedules/workday.yaml +0 -13
- forgegraph-0.2.0/examples/packs/acme/themes/acme.yaml +0 -24
- forgegraph-0.2.0/scripts/build_api_notebook.py +0 -196
- forgegraph-0.2.0/scripts/build_bundled_skill.py +0 -48
- forgegraph-0.2.0/src/forgegraph/catalog/build.py +0 -362
- forgegraph-0.2.0/src/forgegraph/catalog/examples.py +0 -120
- forgegraph-0.2.0/src/forgegraph/catalog/files.py +0 -224
- forgegraph-0.2.0/src/forgegraph/catalog/forgemark.py +0 -59
- forgegraph-0.2.0/src/forgegraph/catalogs/graph_types/xy.yaml +0 -198
- forgegraph-0.2.0/src/forgegraph/catalogs/layers/error_bar.yaml +0 -22
- forgegraph-0.2.0/src/forgegraph/catalogs/layers/note.yaml +0 -16
- forgegraph-0.2.0/src/forgegraph/catalogs/layers/reference_line.yaml +0 -32
- forgegraph-0.2.0/src/forgegraph/cli/__init__.py +0 -740
- forgegraph-0.2.0/src/forgegraph/drawing/figure.py +0 -319
- forgegraph-0.2.0/src/forgegraph/drawing/labels.py +0 -312
- forgegraph-0.2.0/src/forgegraph/drawing/layers.py +0 -560
- forgegraph-0.2.0/src/forgegraph/drawing/xy.py +0 -852
- forgegraph-0.2.0/src/forgegraph/graph.py +0 -563
- forgegraph-0.2.0/src/forgegraph/graph_types/__init__.py +0 -1
- forgegraph-0.2.0/src/forgegraph/graph_types/xy.yaml +0 -85
- forgegraph-0.2.0/src/forgegraph/jobs/__init__.py +0 -9
- forgegraph-0.2.0/src/forgegraph/layers/error_bar.yaml +0 -12
- forgegraph-0.2.0/src/forgegraph/layers/note.yaml +0 -8
- forgegraph-0.2.0/src/forgegraph/layers/reference_line.yaml +0 -15
- forgegraph-0.2.0/src/forgegraph/layouts/__init__.py +0 -639
- forgegraph-0.2.0/src/forgegraph/layouts/arrange.py +0 -403
- forgegraph-0.2.0/src/forgegraph/packs/config.toml +0 -1
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/catalogs/formats/base_format.yaml +0 -18
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/catalogs/formats/base_layout_format.yaml +0 -9
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/catalogs/themes/base_theme.yaml +0 -218
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/formats/base_format.yaml +0 -18
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/formats/base_layout_format.yaml +0 -10
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/graphspecs/polarization.yaml +0 -138
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/layouts/base_layout.yaml +0 -26
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/pack.yaml +0 -5
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/schedules/base_schedule.yaml +0 -26
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base/themes/base_theme.yaml +0 -157
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/catalogs/formats/compact_format.yaml +0 -9
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/catalogs/themes/base_theme.yaml +0 -26
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/formats/compact_format.yaml +0 -13
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/graphspecs/dated.parquet +0 -0
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/graphspecs/example.yaml +0 -13
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/graphspecs/fanned.parquet +0 -0
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/graphspecs/polarization.parquet +0 -0
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/graphspecs/reinforced.parquet +0 -0
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/pack.yaml +0 -5
- forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base_2/themes/base_theme.yaml +0 -72
- forgegraph-0.2.0/src/forgegraph/skill/forgegraph/examples/bars.yaml +0 -35
- forgegraph-0.2.0/src/forgegraph/skill/forgegraph/examples/figure.schedule.yaml +0 -11
- forgegraph-0.2.0/src/forgegraph/spec/__init__.py +0 -9
- forgegraph-0.2.0/src/forgegraph/spec/common.py +0 -11
- forgegraph-0.2.0/src/forgegraph/spec/documents.py +0 -874
- forgegraph-0.2.0/src/forgegraph/spec/parameters.py +0 -468
- forgegraph-0.2.0/src/forgegraph/spec/provenance.py +0 -63
- forgegraph-0.2.0/tests/baselines/crowded_runs.png +0 -0
- forgegraph-0.2.0/tests/baselines/flow_sweep_wide.png +0 -0
- forgegraph-0.2.0/tests/baselines/layout_anode_layers.png +0 -0
- forgegraph-0.2.0/tests/baselines/layout_screening_and_rate.png +0 -0
- forgegraph-0.2.0/tests/baselines/separator_colorbar.png +0 -0
- forgegraph-0.2.0/tests/pack_helpers.py +0 -25
- forgegraph-0.2.0/tests/render_helpers.py +0 -96
- forgegraph-0.2.0/tests/spec_mirror.py +0 -221
- forgegraph-0.2.0/tests/test_blank.py +0 -56
- forgegraph-0.2.0/tests/test_catalog.py +0 -290
- forgegraph-0.2.0/tests/test_cli.py +0 -364
- forgegraph-0.2.0/tests/test_layers.py +0 -513
- forgegraph-0.2.0/tests/test_lint.py +0 -105
- forgegraph-0.2.0/tests/test_perturbation.py +0 -48
- forgegraph-0.2.0/tests/test_regression.py +0 -42
- forgegraph-0.2.0/tests/test_specs.py +0 -542
- {forgegraph-0.2.0 → forgegraph-0.4.0}/LICENSE +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/TRADEMARKS.md +0 -0
- /forgegraph-0.2.0/docs/initial specification.md → /forgegraph-0.4.0/docs/design/initial-specification.md +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/README.md +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/air_passengers.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/air_passengers_by_month.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/anscombe.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/assay_summary.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/cell_durability.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/cell_polarization.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/co2_monthly.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/diamonds.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/dose_response.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/economics.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/enzyme_kinetics.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/fmri.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/gapminder.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/geyser.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/growth.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/iris.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/lab_export.xlsx +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/lab_runs.xlsx +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/penguins.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/seaice.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/sensor_log_eu.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/stocks.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/tips.csv +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/examples/sample-data/weather.xlsx +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/build_sample_data.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/scripts/check_denylist.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/__init__.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/__main__.py +0 -0
- {forgegraph-0.2.0/src/forgegraph/catalog → forgegraph-0.4.0/src/forgegraph/catalog_build}/__init__.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/__init__.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/markup.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/drawing/page.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/IBMPlexSerif-Bold.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/IBMPlexSerif-Light.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/IBMPlexSerif-Medium.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/IBMPlexSerif-Regular.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/IBMPlexSerif-SemiBold.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/OFL-IBMPlexSerif.txt +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/OFL-Roboto.txt +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/OFL-SourceSans3.md +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/Roboto-Bold.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/Roboto-Italic.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/Roboto-Light.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/Roboto-Medium.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/Roboto-Regular.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/Roboto-SemiBold.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/SourceSans3-Bold.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/SourceSans3-It.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/SourceSans3-Light.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/SourceSans3-Medium.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/SourceSans3-Regular.ttf +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/fonts/SourceSans3-Semibold.ttf +0 -0
- {forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base → forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default}/graphspecs/dated.parquet +0 -0
- {forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base → forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default}/graphspecs/fanned.parquet +0 -0
- {forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base → forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default}/graphspecs/polarization.parquet +0 -0
- {forgegraph-0.2.0/src/forgegraph/packs/forgegraph_base → forgegraph-0.4.0/src/forgegraph/packs/forgegraph_default}/graphspecs/reinforced.parquet +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/examples/xy.parquet +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/src/forgegraph/skill/forgegraph/references/requests.md +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/baselines/fuel_by_size.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/baselines/polarization.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/baselines/polarization_narrow.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/baselines/precipitation_loglog.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/baselines/replicates.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/baselines/screening_scatter.png +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/fixtures/catalog_comments.html +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_denylist.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_markup.py +0 -0
- {forgegraph-0.2.0 → forgegraph-0.4.0}/tests/test_spec_mirrors.py +0 -0
|
@@ -3,14 +3,15 @@ repos:
|
|
|
3
3
|
rev: v6.0.0
|
|
4
4
|
hooks:
|
|
5
5
|
- id: check-yaml
|
|
6
|
+
args: [--unsafe] # syntax only, so specs may carry !var and !fix tags
|
|
6
7
|
- id: check-toml
|
|
7
8
|
- id: end-of-file-fixer
|
|
8
|
-
exclude: \.md$|^(review|catalog)/
|
|
9
|
+
exclude: \.md$|^(review|catalog|docs/visual-changelog)/
|
|
9
10
|
- id: trailing-whitespace
|
|
10
|
-
exclude: \.md$|^(review|catalog)/
|
|
11
|
+
exclude: \.md$|^(review|catalog|docs/visual-changelog)/
|
|
11
12
|
- id: check-added-large-files
|
|
12
13
|
args: [--maxkb=600]
|
|
13
|
-
exclude: ^(review|catalog)/ # self-contained HTML pages embed
|
|
14
|
+
exclude: ^(review|catalog|docs/visual-changelog)/ # self-contained HTML pages embed images
|
|
14
15
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
15
16
|
rev: v0.17.1
|
|
16
17
|
hooks:
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
ForgeGraph follows [semantic versioning](https://semver.org). Before 1.0, a minor version may change how graphs look or how specs are written. From 0.2.0 on, each release's entry links its visual changelog: before and after images of every catalog card and regression graph that changed, made with `scripts/visual_changelog.py`.
|
|
4
|
+
|
|
5
|
+
## 0.4.0 (2026-10-27)
|
|
6
|
+
|
|
7
|
+
Images that changed: the [visual changelog](docs/visual-changelog/0.4.0.html).
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Breaking for existing specs and configs:** one built-in pack, `forgegraph_default`, replaces `forgegraph_base` and `forgegraph_base_2`. Its specs are `light_theme` (in place of `forgegraph_base/base_theme`), `compact_format` (`base_format`), `wide_format` (`base_layout_format`), `layout` (`layout_example`), `schedule` (`base_schedule`) and `graphspec_example`; `forgegraph_base_2` has no replacement. A main config listing `forgegraph_base` or `forgegraph_base_2` is an error: list `forgegraph_default` instead. light_theme draws 0.3's look. It fixes every text's font and gap, the palettes (the colors, line styles, marker shapes and fills that series take in turn), the ticks' direction, sides and algorithms, and the grid, so a GraphSpec that sets `grid.x.show` needs a theme that leaves it variable; a series may still set its own color, line style, marker shape and line width. The default layout draws no line between tiles and leaves 0.25 × the base size at the figure's edges.
|
|
12
|
+
- The specification files, which define each kind, are in `src/forgegraph/specifications/`, and their pages in `docs/specifications/`; no spec can name or extend them. The built-in pack's pages are in `docs/packs/forgegraph_default/`, and the catalog page is `catalog/forgegraph_default.html`.
|
|
13
|
+
- A category's brackets in a specification file say what the code reads about it, from a fixed set: its style, `same as <sibling>` for a category with a sibling's parameters, and `look from <theme category>` for a layer category whose look comes from the theme. Anything else there is an error, and descriptions are never read, so rewording one changes nothing.
|
|
14
|
+
- A style's member that no file tags, itself or through a category inside `parameters`, is fixed or variable as its general parameter is: a fixed `text.font` fixes every text style's font, even where the theme sets the style's own.
|
|
15
|
+
- `forgegraph schema <kind>` no longer says whether a parameter is fixed: it shows the kind's specification, which isn't what graphs are drawn with. `forgegraph schema graphspec` lists what a GraphSpec can set, and `forgegraph explain` shows what's fixed.
|
|
16
|
+
- A reference layer's `fill.color` may be None: two lines with values make a band only when it isn't.
|
|
17
|
+
- **Breaking for existing specs:** a GraphSpec lists its series by name under `series`, each drawn from its own column (by default, the column of its name) with its own settings: `aggregation`, `split`, `order`, `color`, `color_scale`, `line`, `marker`, `bar` and `value_label`, and the theme's variable series parameters it sets for itself. They replace `axis.*.data.aggregation`, `encoding.*` and `mark.*`; the value axis's `data.column` is None. `arrangement.base_axis`, `arrangement.stacking`, `arrangement.offset` and `arrangement.total.show` replace `series.base_axis`, `series.aggregation`, `series.offset` and `series.value_label.total.show`. A series' color, line style, marker shape and fill take `first`, `series`, a value or a column; series take palette colors in the order they're listed.
|
|
18
|
+
- **Breaking for existing specs:** the `reference` layer replaces `reference_line`: `line_1` and `line_2`, each at a value or from a column, with its own `aggregation` and `offset` (aggregation styles), `scope`, line and label (with `label.inside`), and the `fill` of a band between them. The theme's `layer.reference` replaces `layer.reference_line`.
|
|
19
|
+
- An aggregation style (`function`, `multiplier`, `percentile`) for a series, a reference line and error bars; functions include `percentile`, `stddev`, `stderr` and `ci`.
|
|
20
|
+
- `line.interpolate` draws a series' line straight, in steps (`step_after`, `step_before`, `step_center`) or as a smooth curve that never overshoots its points.
|
|
21
|
+
- A note and a reference layer's lines, labels and fill may set the theme's variable look for themselves.
|
|
22
|
+
- A style key (one from `encoding.line.style.column`, `encoding.marker.shape.column` or `encoding.marker.fill.column`) follows `legend.key.title.text`, as the series' key does: `column_name`, the default, gives each key its own column's name, so default graphs are unchanged; `None` removes every key's title; a text titles one key, and with more than one key drawn it's an error. With no `encoding.color.column`, a style key's samples are drawn in the one series color, not the text color. `render --json` reports `style_keys`, the column each style key drawn explains (for a layout, each tile's), beside `labelling`.
|
|
23
|
+
- A range type `date`: a date, or a date and time, as YAML's bare date (`2025-08-25`, `2025-08-25 06:00:00`) or ISO 8601 text (`"2025-08-25T06:00"`); a time with a zone is at its clock time, as the data's are. `axis.x.min`, `axis.x.max`, `axis.y.min` and `axis.y.max`, a reference line's `value` and `benchmark.value` take it: on a datetime axis or column, a date is drawn exactly where its day number is, and numbers keep working as day numbers. A date on an axis that isn't dates is an error naming the axis's type. Text that reads as a date is a reference line's column only if the data has a column of that name. Provenance records write dates as ISO 8601 text.
|
|
24
|
+
- On a date value axis, what would draw nonsense is an error that says what to do: stacking (`series.aggregation` sum or percent), adding up rows (`axis.*.data.aggregation` sum), bars (`mark.bar.show`, which would start at 1970), and value labels without a date format. A reference line at a date column's aggregate is on a date axis only, at its mean, median, min or max, with multiplier 1. A date axis's `tick.label.format` must have a date directive.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- In a theme whose text is light, powers of ten on a log axis and superscripts in labels no longer give a `font-fallback` lint issue. They were always drawn in the theme's font and weight; the issue came from the faces matplotlib loads for maths but doesn't draw these with.
|
|
29
|
+
- The `outside-limits` and `log-axis-values` lint checks count only data points. A reference line's ends and an error bar's ends no longer count as points outside a set axis limit, or as values of 0 or below on a log axis.
|
|
30
|
+
- A style key on the benchmark's column matches the drawing: its entries are the groups the series are styled by, so a value after the benchmark no longer gets the next value's style, and the benchmark, drawn in its own style, has no style sample and is named once, by `legend.method`. When `legend.method: key` doesn't fit, the error says why: every position in `legend.key.positions` is taken or covers data, naming the position each style key took.
|
|
31
|
+
- YAML's null (`null`, `~` or nothing) is None everywhere a spec can say None. `extends: null` failed with `KeyError: None`, and a file extending null wasn't required to list every parameter.
|
|
32
|
+
- Computed values are compared with an axis's limits allowing for float noise: a value is past a limit only if it's past by more than 1e-9 of the axis's span, measured in powers of ten on a log axis. A stack that totals `axis.y.max` but for its last digits isn't reported by `outside-limits`; a reference line at a computed value that equals a set limit isn't an error; bars whose values are 0 but for float noise still stand on the axis; and a tick a hair past the end of the view, which matplotlib draws, is measured for layout and lint and counts when log labels choose between plain numbers and powers of ten.
|
|
33
|
+
- Dates and times draw the same on y as on x: every value placed on an axis (the data, its aggregates, stacks, reference lines, error bars and limits) becomes a number the same way, so a date y axis has date ticks, a reference line at a date column's aggregate lands on it, and error bars from a date column's spread are in days. With value labels off, a date `tick.label.format` such as `"%H:%M"` on y is no longer refused as a number format; value labels and a reference line's value on a date axis are written in a date format.
|
|
34
|
+
|
|
35
|
+
## 0.3.0 (2026-10-25)
|
|
36
|
+
|
|
37
|
+
Images that changed: the [visual changelog](docs/visual-changelog/0.3.0.html).
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- `fg.blank` takes `registry=`, as `fg.render` does, and a blank canvas's `save` path is optional, as a graph's is: with none, it saves `canvas.png` and the format's other file types.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **Breaking for existing specs:** parameters follow one naming system. `_` joins words that name one thing (`error_bar`, `plot_area`), `.` goes from a thing to its parts and properties (`line.width`), an on/off switch is the thing's `.show`, and nothing is abbreviated. A spec still using an old name is an error that suggests the new one; an old name that's now a category, such as `encoding.color`, suggests that category's parameters. The Python API's keyword arguments (`fg.xy`'s `color=`, `line_style=`, `marker_shape=`, `marker_fill=`, `detail=`) are unchanged and set the new paths. Graphs draw the same as before. The renames, old → new:
|
|
46
|
+
1. `grid.line_style` → `grid.line.style`; `grid.line_width` → `grid.line.width`
|
|
47
|
+
2. `plot_area.line_color` → `plot_area.line.color`; `plot_area.line_width` → `plot_area.line.width`
|
|
48
|
+
3. `layer.error_bar.line_width` → `layer.error_bar.line.width`; `layer.error_bar.cap_size` → `layer.error_bar.cap.width`
|
|
49
|
+
4. `layer.reference_line.line_style` → `layer.reference_line.line.style`; `layer.reference_line.line_width` → `layer.reference_line.line.width`
|
|
50
|
+
5. `series.marker.edge_color`, `series.marker.edge_width` → `series.marker.edge.color`, `series.marker.edge.width`, and the same in `series.bar`, `series.benchmark.marker` and `series.benchmark.bar`
|
|
51
|
+
6. `legend.key.frame_width` → `legend.key.frame.width`
|
|
52
|
+
7. `legend.key.sample.marker_size` → `legend.key.sample.marker.size`
|
|
53
|
+
8. `legend.key.frame` → `legend.key.frame.show`
|
|
54
|
+
9. `series.value_label.total` → `series.value_label.total.show`
|
|
55
|
+
10. `axis.tick.minor.num` → `axis.tick.minor.count`
|
|
56
|
+
11. `encoding.color` → `encoding.color.column`; `encoding.color_type` → `encoding.color.type`; `encoding.line_style` → `encoding.line.style.column`; `encoding.marker_shape` → `encoding.marker.shape.column`; `encoding.marker_fill` → `encoding.marker.fill.column`; `encoding.detail` → `encoding.detail.column` (`encoding.order` is unchanged)
|
|
57
|
+
12. Layouts: `separators.line.border` → `separators.border.show`
|
|
58
|
+
13. Schedules: `freshness.stamp` → `freshness.stamp.show`; `cadence.interval` → `cadence.interval.count`; `cadence.interval_unit` → `cadence.interval.unit`
|
|
59
|
+
- **Breaking for packs' catalog files:** a catalog's cards are chosen by a rule, not by hand. Every parameter gets one card, its value taken from its range and the baseline's data, drawn on the first baseline where it changes the drawing; the page shows the variable parameters' cards. A catalog file lists only its baselines, and a layer's settings: `variations`, `no_card` and the `{value, from, with}` forms are gone. A pack's catalog page draws with the pack's own theme and format values.
|
|
60
|
+
- Drawing and saving are about 3.7 times faster. Graphs and their files are the same as before.
|
|
61
|
+
- A pack's fonts are registered when a file drawn uses one of its specs, not whenever a config lists the pack.
|
|
62
|
+
- `forgegraph --help` gives each command a one-sentence summary, and `forgegraph catalog --help` names every kind it lists.
|
|
63
|
+
- The internal package `forgegraph.catalog` is `forgegraph.catalog_build`. The API is unchanged.
|
|
64
|
+
- One name is one pack. A config can't give a built-in pack's name, or a name the main config already gives, to another folder. Before, a folder config's copy of a pack replaced the one the main config lists, and what it drew wasn't marked non-standard.
|
|
65
|
+
- ForgeGraph needs matplotlib 3.11.2 and typer 0.15.4 or later; earlier versions installed but didn't work.
|
|
66
|
+
- The package's description and classifiers say what it is now: released, in alpha.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- Error bars on a date axis stand on their points, and error bars of aggregated rows on a date axis draw.
|
|
71
|
+
- Times with a time zone are drawn at the times their clocks show. Before, they raised an error.
|
|
72
|
+
- A reference line at a column's sum or standard deviation counts each row once when several y columns are drawn.
|
|
73
|
+
- Value labels written with format auto use the value axis's tick label format when it's set, as reference lines do.
|
|
74
|
+
- The catalog's record of what it was built from covers every module it draws with, so a change to the drawing code marks the catalog out of date.
|
|
75
|
+
- The package's metadata lists the bundled fonts' licences.
|
|
76
|
+
- A GraphSpec naming a list as its theme, format or graph type gets the error "must be a single value", not a crash.
|
|
77
|
+
- A config naming a pack that can't be found, or another pack problem, stops `catalog`, `pack-notes`, `schema` and `explain` with its problems listed (`error:` lines, exit 1), not a traceback; with `--json`, one problem each, not one joined line.
|
|
78
|
+
|
|
79
|
+
## 0.2.0 (2026-10-24)
|
|
80
|
+
|
|
81
|
+
Images that changed: the [visual changelog](docs/visual-changelog/0.2.0.html).
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- Error bars are black by default in both built-in themes, and their color (`layer.error_bar.color`) is a variable parameter: a GraphSpec may set `series` or any hex color.
|
|
86
|
+
- Three internal modules are renamed so none shares a name with the API: `forgegraph.render` is `forgegraph.drawing`, `forgegraph.layout` is `forgegraph.layouts` and `forgegraph.blank` is `forgegraph.canvas`. `import forgegraph.layouts as m` now gives the module, not `fg.layout`. The API is unchanged.
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
|
|
90
|
+
- `forgegraph --version` and `--help` no longer load matplotlib and pandas, so they answer at once, even on a new install. The API loads on first use.
|
|
91
|
+
- The README and the skill's reference say when the main config is written: the first time a command reads the configs, such as `catalog` or `render`.
|
|
92
|
+
- Error bars on side-by-side bars (`series.offset: side_by_side`) are drawn on their own bars. Before, every series but the middle one had its error bars drawn where they were first placed, before layout, usually off the axes.
|
|
93
|
+
|
|
94
|
+
## 0.1.0 (2026-10-24)
|
|
95
|
+
|
|
96
|
+
The first public release.
|
|
97
|
+
|
|
98
|
+
### Added
|
|
99
|
+
|
|
100
|
+
- **GraphSpecs:** a graph described in YAML or as a Python dict, drawn with `forgegraph render` or `fg.render`; `fg.xy` draws straight from a DataFrame.
|
|
101
|
+
- **The `xy` graph type:**
|
|
102
|
+
- lines, markers and bars: grouped, stacked, 100 % stacked and horizontal;
|
|
103
|
+
- dates and log axes, value labels, a benchmark series;
|
|
104
|
+
- series named beside their lines or in a key.
|
|
105
|
+
- **Layers:** reference lines, notes and error bars, from the data or given.
|
|
106
|
+
- **Themes and formats:** a theme fixes what must stay the same and gives defaults for the rest; a format sets size, base font size, file types and resolution.
|
|
107
|
+
- **Packs and configs:**
|
|
108
|
+
- every named spec comes from a pack, named `pack/name`; ForgeGraph's own is `forgegraph_base`, and `forgegraph_base_2` is a second look in this repository;
|
|
109
|
+
- the main config (written on first use, or named by `FORGEGRAPH_CONFIG`) and folder configs (`forgegraph.toml`) say which packs may be used;
|
|
110
|
+
- a pack only a folder config lists is non-standard: it works, and what's drawn with it is watermarked.
|
|
111
|
+
- **Lint on every render:** overlapping or clipped text, a key covering data, fonts too small for the format, missing fonts, dropped rows and more.
|
|
112
|
+
- **Provenance:** every saved file (PNG, JPEG, TIFF, SVG, PDF and HTML) records its GraphSpec and the specs it was drawn with, at the format's provenance level; `forgegraph load` reads it back.
|
|
113
|
+
- **Layouts:** several GraphSpecs in one figure, with spanning tiles, blank cells and set widths; tabs, and HTML dashboards.
|
|
114
|
+
- **Scheduled renders:** schedule files, `forgegraph job run`, a status file, `on_failure` and `on_success` hooks, a "data as of" footnote and a stale banner.
|
|
115
|
+
- **The themed canvas:** `forgegraph.blank(theme, format)` for what no graph type can draw, always watermarked as non-standard.
|
|
116
|
+
- **The agent skill** for Claude Code, installed with `forgegraph skill install`, with reference notes for themes, formats and configs, and for filing requests.
|
|
117
|
+
- **Commands:** `render`, `explain`, `catalog`, `schema`, `pack-notes`, `load`, `job run` and `skill install`, each with `--json`.
|
|
118
|
+
- **Catalogs:** a page for each pack in this repository, with a card for every parameter.
|
|
119
|
+
|
|
120
|
+
## 0.0.1 (2026-10-17)
|
|
121
|
+
|
|
122
|
+
The name, reserved on PyPI. No functionality.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contributions are welcome. For a bug or a feature request, open an [issue](https://github.com/sskaye/forgegraph/issues). For a change, open a pull request with tests, after running the checks below.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync
|
|
9
|
+
uv run pre-commit install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
While you work, `uv run pytest` runs the development suite: every test not marked slow, in parallel. The full suite adds the slow ones (every catalog card drawn, the image baselines, the catalog pages, and any test over a second). CI runs it on every pull request, and it's the one to run before a release:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
uv run pytest --full && uv run ruff check . && uv run ruff format --check && uv run pyright
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Mark a new test `@pytest.mark.slow` if it takes over a second (`uv run pytest --durations=20` lists the slowest).
|
|
19
|
+
|
|
20
|
+
## After changing a definition or how graphs are drawn
|
|
21
|
+
|
|
22
|
+
Every parameter gets one catalog card, its value and baseline chosen by a rule (`src/forgegraph/catalog_build/cards.py`), so a new parameter needs no card of its own; the page shows the variable parameters' cards, and the perturbation test draws them all. It needs a baseline that shows it only if none does: the build (for a variable parameter) or the perturbation test (for any) names a parameter that changes no baseline's drawing, and the fix is a generic scenario added to the baselines in the matching catalog file under `src/forgegraph/specifications/catalogs/` (or the pack's `catalogs/`).
|
|
23
|
+
|
|
24
|
+
Rebuild the catalog (it keeps its review comments; Node 18+ is needed once it has some), the mirrors, and the image baselines if graphs look different on purpose:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv run forgegraph catalog build
|
|
28
|
+
uv run python scripts/mirror_specs.py
|
|
29
|
+
uv run python scripts/build_recreations.py --baselines
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`uv run python scripts/visual_changelog.py main` then shows every image that changed.
|
|
33
|
+
|
|
34
|
+
## Requesting a graph type
|
|
35
|
+
|
|
36
|
+
Open a GitHub issue describing the graph you need, ideally with an example image or sketch and a little sample data. No code is needed.
|
|
37
|
+
|
|
38
|
+
## Releasing
|
|
39
|
+
|
|
40
|
+
1. Set the new version in pyproject.toml and in the built-in pack's pack.yaml, and for a new minor version, its `requires` (`">=0.4, <0.5"` for 0.4).
|
|
41
|
+
2. Rebuild the catalog and mirrors (above).
|
|
42
|
+
3. Write the visual changelog, `uv run python scripts/visual_changelog.py v<last version>`, and the CHANGELOG entry, linking it.
|
|
43
|
+
4. Merge with CI green, and tag the merge commit `v<version>`.
|
|
44
|
+
5. Run the Publish workflow.
|
|
@@ -1,6 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: forgegraph
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Fast, consistent, publication-quality graphs from pandas DataFrames, usable by people and AI agents.
|
|
5
|
+
Project-URL: Repository, https://github.com/sskaye/forgegraph
|
|
6
|
+
Project-URL: Issues, https://github.com/sskaye/forgegraph/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/sskaye/forgegraph/blob/main/CHANGELOG.md
|
|
8
|
+
Author: Steven Kaye
|
|
9
|
+
License-Expression: MIT AND OFL-1.1
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: src/forgegraph/fonts/OFL-IBMPlexSerif.txt
|
|
12
|
+
License-File: src/forgegraph/fonts/OFL-Roboto.txt
|
|
13
|
+
License-File: src/forgegraph/fonts/OFL-SourceSans3.md
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: matplotlib>=3.11.2
|
|
23
|
+
Requires-Dist: packaging>=23
|
|
24
|
+
Requires-Dist: pandas>=2.2
|
|
25
|
+
Requires-Dist: pyarrow>=17
|
|
26
|
+
Requires-Dist: pydantic>=2.7
|
|
27
|
+
Requires-Dist: ruamel-yaml>=0.18
|
|
28
|
+
Requires-Dist: typer>=0.15.4
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
1
31
|
# ForgeGraph
|
|
2
32
|
|
|
3
|
-
Fast, consistent, publication-quality graphs from pandas DataFrames,
|
|
33
|
+
Fast, consistent, publication-quality graphs from pandas DataFrames, usable by people and AI agents.
|
|
4
34
|
|
|
5
35
|
You describe a graph in a **GraphSpec**. ForgeGraph draws it in a house style set by a **theme** and a **format**. It checks what it drew, and records how the graph was made inside the saved file. An agent skill lets agents make and revise graphs the same way.
|
|
6
36
|
|
|
@@ -18,7 +48,7 @@ You describe a graph in a **GraphSpec**. ForgeGraph draws it in a house style se
|
|
|
18
48
|
- **Configs:** control which packs may be used, per user or folder. Used to enforce use of style pack(s) and watermark non-standard graphs.
|
|
19
49
|
- **Lint:** Graphs are linted on rendering, with warnings for issues including overlapping or clipped text, a key covering data, or fonts too small.
|
|
20
50
|
|
|
21
|
-
**Status:** 0.x. `xy` graph type (lines, markers, & bars), reference lines, error bars, and notes layers, initial style packs. More graph types
|
|
51
|
+
**Status:** 0.x. `xy` graph type (lines, markers, & bars), reference lines, error bars, and notes layers, initial style packs. More graph types are planned. If there’s specific ones you want, [open an issue](https://github.com/sskaye/forgegraph/issues).
|
|
22
52
|
|
|
23
53
|
## Install
|
|
24
54
|
|
|
@@ -59,6 +89,16 @@ g = fg.xy(runs, x="hours", y="voltage", color="cell", title="Cell voltage")
|
|
|
59
89
|
g.save("voltage") # voltage.png, with its GraphSpec inside
|
|
60
90
|
```
|
|
61
91
|
|
|
92
|
+
The Python API (each function has a docstring):
|
|
93
|
+
|
|
94
|
+
- `fg.xy(df, x, y, ...)`: draw y against x from a DataFrame.
|
|
95
|
+
- `fg.render(spec, data=None)`: draw a GraphSpec, given as a file or a document.
|
|
96
|
+
- `fg.graphspec(name, graph_type, ...)`: write a GraphSpec document.
|
|
97
|
+
- `fg.layout(spec, data=None)`: draw a layout.
|
|
98
|
+
- `fg.load(path)`: a saved graph's record; its GraphSpec is under `"graphspec"`.
|
|
99
|
+
- `fg.blank(theme, format)`: a themed canvas for drawing with matplotlib what no graph type can; what's drawn on it is watermarked.
|
|
100
|
+
- A `Graph` has `.save(path)`, `.figure` and `.axes` (matplotlib's), `.issues` (the lint) and `.check()`.
|
|
101
|
+
|
|
62
102
|
From the command line, with the DataFrame saved as runs.parquet and a GraphSpec, voltage.yaml:
|
|
63
103
|
|
|
64
104
|
```yaml
|
|
@@ -66,12 +106,11 @@ name: voltage
|
|
|
66
106
|
version: 0
|
|
67
107
|
description: Cell voltage over a test, one line per cell.
|
|
68
108
|
extends: None
|
|
69
|
-
|
|
70
|
-
variable_parameters:
|
|
109
|
+
parameters: !var
|
|
71
110
|
specifications:
|
|
72
111
|
graph_type: xy
|
|
73
|
-
theme:
|
|
74
|
-
format:
|
|
112
|
+
theme: forgegraph_default/light_theme
|
|
113
|
+
format: forgegraph_default/compact_format
|
|
75
114
|
text:
|
|
76
115
|
title: Cell voltage
|
|
77
116
|
data:
|
|
@@ -81,11 +120,9 @@ variable_parameters:
|
|
|
81
120
|
x:
|
|
82
121
|
data:
|
|
83
122
|
column: hours
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
encoding:
|
|
88
|
-
color: cell
|
|
123
|
+
series:
|
|
124
|
+
voltage:
|
|
125
|
+
color: cell
|
|
89
126
|
```
|
|
90
127
|
|
|
91
128
|
```bash
|
|
@@ -94,7 +131,7 @@ forgegraph render voltage.yaml
|
|
|
94
131
|
|
|
95
132
|
## Packs and configs
|
|
96
133
|
|
|
97
|
-
Every named theme, format, GraphSpec, layout and schedule comes from a **pack**, a folder or pip package of specs, and is named `pack/name`.
|
|
134
|
+
Every named theme, format, GraphSpec, layout and schedule comes from a **pack**, a folder or pip package of specs, and is named `pack/name`. ForgeGraph's built-in pack, `forgegraph_default`, is stored in src/forgegraph/packs: its theme, `light_theme`, its formats, `compact_format` for single graphs and `wide_format` for layouts, and a layout and a schedule to extend.
|
|
98
135
|
|
|
99
136
|
A **config** lists the packs that may be used:
|
|
100
137
|
|
|
@@ -102,11 +139,15 @@ A **config** lists the packs that may be used:
|
|
|
102
139
|
- A folder config, `forgegraph.toml`, applies to the files in its folder and every folder below it. A file may use only the packs it lists.
|
|
103
140
|
- A pack that a folder config lists but the main config doesn't still works, but it's non-standard: graphs drawn with it are watermarked, and ForgeGraph's commands say so. That way you can make and try a pack without changing an organization's main config.
|
|
104
141
|
|
|
142
|
+
To write a pack, start from the example pack in [examples/packs/acme](https://github.com/sskaye/forgegraph/blob/main/examples/packs/acme); `forgegraph schema theme`, `format`, `pack` and `config` list every parameter.
|
|
143
|
+
|
|
144
|
+
On macOS, a scheduled render that writes into a cloud-synced folder needs Full Disk Access.
|
|
145
|
+
|
|
105
146
|
## Commands
|
|
106
147
|
|
|
107
148
|
- `forgegraph render <graphspec or layout>`: draw and save, and report lint.
|
|
108
149
|
- `forgegraph explain <graphspec or layout>`: every value it's drawn with, and which file set it.
|
|
109
|
-
- `forgegraph catalog`: the packs, graph types, layer types, themes, formats and reference notes available here.
|
|
150
|
+
- `forgegraph catalog`: the packs, graph types, layer types, themes, formats, GraphSpecs, layouts, schedules and reference notes available here.
|
|
110
151
|
- `forgegraph schema graphspec --graph-type <type> --theme <theme> --format <format>`: every parameter a GraphSpec can set.
|
|
111
152
|
- `forgegraph schema <kind>`: every parameter of a theme, format, layer, layout, schedule, pack or config.
|
|
112
153
|
- `forgegraph pack-notes`: the reference notes of the packs available here.
|
|
@@ -118,48 +159,42 @@ Every command takes `--help`, and `--json` for agents.
|
|
|
118
159
|
|
|
119
160
|
## Catalogs
|
|
120
161
|
|
|
121
|
-
|
|
162
|
+
The built-in pack has a catalog: a page with a card for each parameter, showing what changing it does. Download it and open it in a browser.
|
|
122
163
|
|
|
123
|
-
-
|
|
124
|
-
- forgegraph_base_2: its own theme and format, and the same graph types and layer types drawn in them.
|
|
164
|
+
- [forgegraph_default](https://github.com/sskaye/forgegraph/blob/main/catalog/forgegraph_default.html): its theme and formats, and ForgeGraph's graph types and layer types drawn in them.
|
|
125
165
|
|
|
126
166
|
## Your graphs are yours
|
|
127
167
|
|
|
128
|
-
ForgeGraph is [MIT-licensed](LICENSE). Graphs and other output you make with it are yours: no attribution or licence terms apply to them. See TRADEMARKS.md for use of the name.
|
|
168
|
+
ForgeGraph is [MIT-licensed](https://github.com/sskaye/forgegraph/blob/main/LICENSE). Graphs and other output you make with it are yours: no attribution or licence terms apply to them. See [TRADEMARKS.md](https://github.com/sskaye/forgegraph/blob/main/TRADEMARKS.md) for use of the name.
|
|
129
169
|
|
|
130
170
|
## Documentation
|
|
131
171
|
|
|
132
|
-
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
- [
|
|
136
|
-
-
|
|
172
|
+
- [Specifications](https://github.com/sskaye/forgegraph/blob/main/docs/specifications): the file that defines each kind of spec, every parameter with its default, range and description.
|
|
173
|
+
- [Built-in pack](https://github.com/sskaye/forgegraph/blob/main/docs/packs/forgegraph_default): forgegraph_default's specs.
|
|
174
|
+
- [Changelog](https://github.com/sskaye/forgegraph/blob/main/CHANGELOG.md).
|
|
175
|
+
- [Contributing](https://github.com/sskaye/forgegraph/blob/main/CONTRIBUTING.md): working on ForgeGraph itself.
|
|
176
|
+
- Design record, in [docs/design](https://github.com/sskaye/forgegraph/blob/main/docs/design):
|
|
177
|
+
- [Architecture](https://github.com/sskaye/forgegraph/blob/main/docs/design/architecture.md): how ForgeGraph is designed, and why.
|
|
178
|
+
- [To do](https://github.com/sskaye/forgegraph/blob/main/docs/design/todo.md): what's still planned.
|
|
137
179
|
|
|
138
180
|
## Contributing
|
|
139
181
|
|
|
140
|
-
Feature requests and bug reports go to [GitHub issues](https://github.com/sskaye/forgegraph/issues); the skill can file them for you. CONTRIBUTING.md covers working on ForgeGraph itself
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
uv sync && uv run pre-commit install
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
uv run pytest --full && uv run ruff check . && uv run pyright
|
|
148
|
-
```
|
|
182
|
+
Feature requests and bug reports go to [GitHub issues](https://github.com/sskaye/forgegraph/issues); the skill can file them for you. [CONTRIBUTING.md](https://github.com/sskaye/forgegraph/blob/main/CONTRIBUTING.md) covers working on ForgeGraph itself: setup, the checks to run, and regenerating the catalogs.
|
|
149
183
|
|
|
150
184
|
## Repository map
|
|
151
185
|
|
|
152
186
|
- **src/forgegraph/**: the package.
|
|
153
|
-
- `graph.py`: the Python API (`fg.xy`, `fg.render`, `fg.graphspec`, `fg.load`) and the `Graph` object; `canvas.py`: the themed canvas.
|
|
187
|
+
- `graph.py`: the Python API (`fg.xy`, `fg.render`, `fg.graphspec`, `fg.load`) and the `Graph` object; `canvas.py`: `fg.blank`, the themed canvas; `drawn.py`: what they and layouts share once drawn; `data.py`: reading a GraphSpec's data.
|
|
154
188
|
- **cli/**: the `forgegraph` command.
|
|
155
189
|
- **spec/**: reading, checking and resolving specs, and the provenance record.
|
|
156
|
-
- **drawing/**: drawing, layout and lint. **layouts/**: layouts. **jobs/**: scheduled renders.
|
|
157
|
-
- **
|
|
158
|
-
- **
|
|
159
|
-
- **
|
|
190
|
+
- **drawing/**: drawing, layout and lint. **layouts/**: `fg.layout` and layouts. **jobs/**: scheduled renders.
|
|
191
|
+
- **specifications/**: the specification files, which define each kind of spec, and the graph types' and layer types' catalog files.
|
|
192
|
+
- **packs/**: packs and configs, and the built-in pack `forgegraph_default`. **fonts/**: bundled fonts and their licences.
|
|
193
|
+
- **catalog_build/**: the catalog builder.
|
|
194
|
+
- **skill/forgegraph/**: the agent skill. `forgemark.py`: Forgemark's review-comment format, and its pinned tool.
|
|
160
195
|
- **catalog/**: the generated catalog pages.
|
|
161
|
-
- **examples/**: sample data
|
|
196
|
+
- **examples/**: sample data; `packs/acme`, an example pack in a deliberately different style; and `layouts/`, a paper figure and a dashboard.
|
|
162
197
|
- **evals/skill/**: the skill's eval cases, run by `scripts/run_skill_evals.py`.
|
|
163
198
|
- **tests/**, **scripts/**: tests, and build and maintenance scripts.
|
|
164
|
-
- **docs/**: the
|
|
199
|
+
- **docs/**: the specifications' and packs' pages, the design record and the visual changelogs. **review/**: each build phase's review pages.
|
|
165
200
|
|
|
@@ -1,31 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: forgegraph
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: Consistent, high-quality graphs from pandas DataFrames, for people and AI agents. Early development.
|
|
5
|
-
Project-URL: Repository, https://github.com/sskaye/forgegraph
|
|
6
|
-
Author: Steven Kaye
|
|
7
|
-
License-Expression: MIT
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
Classifier: Development Status :: 1 - Planning
|
|
10
|
-
Classifier: Intended Audience :: Science/Research
|
|
11
|
-
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
-
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
16
|
-
Requires-Python: >=3.12
|
|
17
|
-
Requires-Dist: matplotlib>=3.9
|
|
18
|
-
Requires-Dist: packaging>=23
|
|
19
|
-
Requires-Dist: pandas>=2.2
|
|
20
|
-
Requires-Dist: pyarrow>=17
|
|
21
|
-
Requires-Dist: pydantic>=2.7
|
|
22
|
-
Requires-Dist: ruamel-yaml>=0.18
|
|
23
|
-
Requires-Dist: typer>=0.12
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
|
|
26
1
|
# ForgeGraph
|
|
27
2
|
|
|
28
|
-
Fast, consistent, publication-quality graphs from pandas DataFrames,
|
|
3
|
+
Fast, consistent, publication-quality graphs from pandas DataFrames, usable by people and AI agents.
|
|
29
4
|
|
|
30
5
|
You describe a graph in a **GraphSpec**. ForgeGraph draws it in a house style set by a **theme** and a **format**. It checks what it drew, and records how the graph was made inside the saved file. An agent skill lets agents make and revise graphs the same way.
|
|
31
6
|
|
|
@@ -43,7 +18,7 @@ You describe a graph in a **GraphSpec**. ForgeGraph draws it in a house style se
|
|
|
43
18
|
- **Configs:** control which packs may be used, per user or folder. Used to enforce use of style pack(s) and watermark non-standard graphs.
|
|
44
19
|
- **Lint:** Graphs are linted on rendering, with warnings for issues including overlapping or clipped text, a key covering data, or fonts too small.
|
|
45
20
|
|
|
46
|
-
**Status:** 0.x. `xy` graph type (lines, markers, & bars), reference lines, error bars, and notes layers, initial style packs. More graph types
|
|
21
|
+
**Status:** 0.x. `xy` graph type (lines, markers, & bars), reference lines, error bars, and notes layers, initial style packs. More graph types are planned. If there’s specific ones you want, [open an issue](https://github.com/sskaye/forgegraph/issues).
|
|
47
22
|
|
|
48
23
|
## Install
|
|
49
24
|
|
|
@@ -84,6 +59,16 @@ g = fg.xy(runs, x="hours", y="voltage", color="cell", title="Cell voltage")
|
|
|
84
59
|
g.save("voltage") # voltage.png, with its GraphSpec inside
|
|
85
60
|
```
|
|
86
61
|
|
|
62
|
+
The Python API (each function has a docstring):
|
|
63
|
+
|
|
64
|
+
- `fg.xy(df, x, y, ...)`: draw y against x from a DataFrame.
|
|
65
|
+
- `fg.render(spec, data=None)`: draw a GraphSpec, given as a file or a document.
|
|
66
|
+
- `fg.graphspec(name, graph_type, ...)`: write a GraphSpec document.
|
|
67
|
+
- `fg.layout(spec, data=None)`: draw a layout.
|
|
68
|
+
- `fg.load(path)`: a saved graph's record; its GraphSpec is under `"graphspec"`.
|
|
69
|
+
- `fg.blank(theme, format)`: a themed canvas for drawing with matplotlib what no graph type can; what's drawn on it is watermarked.
|
|
70
|
+
- A `Graph` has `.save(path)`, `.figure` and `.axes` (matplotlib's), `.issues` (the lint) and `.check()`.
|
|
71
|
+
|
|
87
72
|
From the command line, with the DataFrame saved as runs.parquet and a GraphSpec, voltage.yaml:
|
|
88
73
|
|
|
89
74
|
```yaml
|
|
@@ -91,12 +76,11 @@ name: voltage
|
|
|
91
76
|
version: 0
|
|
92
77
|
description: Cell voltage over a test, one line per cell.
|
|
93
78
|
extends: None
|
|
94
|
-
|
|
95
|
-
variable_parameters:
|
|
79
|
+
parameters: !var
|
|
96
80
|
specifications:
|
|
97
81
|
graph_type: xy
|
|
98
|
-
theme:
|
|
99
|
-
format:
|
|
82
|
+
theme: forgegraph_default/light_theme
|
|
83
|
+
format: forgegraph_default/compact_format
|
|
100
84
|
text:
|
|
101
85
|
title: Cell voltage
|
|
102
86
|
data:
|
|
@@ -106,11 +90,9 @@ variable_parameters:
|
|
|
106
90
|
x:
|
|
107
91
|
data:
|
|
108
92
|
column: hours
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
encoding:
|
|
113
|
-
color: cell
|
|
93
|
+
series:
|
|
94
|
+
voltage:
|
|
95
|
+
color: cell
|
|
114
96
|
```
|
|
115
97
|
|
|
116
98
|
```bash
|
|
@@ -119,7 +101,7 @@ forgegraph render voltage.yaml
|
|
|
119
101
|
|
|
120
102
|
## Packs and configs
|
|
121
103
|
|
|
122
|
-
Every named theme, format, GraphSpec, layout and schedule comes from a **pack**, a folder or pip package of specs, and is named `pack/name`.
|
|
104
|
+
Every named theme, format, GraphSpec, layout and schedule comes from a **pack**, a folder or pip package of specs, and is named `pack/name`. ForgeGraph's built-in pack, `forgegraph_default`, is stored in src/forgegraph/packs: its theme, `light_theme`, its formats, `compact_format` for single graphs and `wide_format` for layouts, and a layout and a schedule to extend.
|
|
123
105
|
|
|
124
106
|
A **config** lists the packs that may be used:
|
|
125
107
|
|
|
@@ -127,11 +109,15 @@ A **config** lists the packs that may be used:
|
|
|
127
109
|
- A folder config, `forgegraph.toml`, applies to the files in its folder and every folder below it. A file may use only the packs it lists.
|
|
128
110
|
- A pack that a folder config lists but the main config doesn't still works, but it's non-standard: graphs drawn with it are watermarked, and ForgeGraph's commands say so. That way you can make and try a pack without changing an organization's main config.
|
|
129
111
|
|
|
112
|
+
To write a pack, start from the example pack in [examples/packs/acme](https://github.com/sskaye/forgegraph/blob/main/examples/packs/acme); `forgegraph schema theme`, `format`, `pack` and `config` list every parameter.
|
|
113
|
+
|
|
114
|
+
On macOS, a scheduled render that writes into a cloud-synced folder needs Full Disk Access.
|
|
115
|
+
|
|
130
116
|
## Commands
|
|
131
117
|
|
|
132
118
|
- `forgegraph render <graphspec or layout>`: draw and save, and report lint.
|
|
133
119
|
- `forgegraph explain <graphspec or layout>`: every value it's drawn with, and which file set it.
|
|
134
|
-
- `forgegraph catalog`: the packs, graph types, layer types, themes, formats and reference notes available here.
|
|
120
|
+
- `forgegraph catalog`: the packs, graph types, layer types, themes, formats, GraphSpecs, layouts, schedules and reference notes available here.
|
|
135
121
|
- `forgegraph schema graphspec --graph-type <type> --theme <theme> --format <format>`: every parameter a GraphSpec can set.
|
|
136
122
|
- `forgegraph schema <kind>`: every parameter of a theme, format, layer, layout, schedule, pack or config.
|
|
137
123
|
- `forgegraph pack-notes`: the reference notes of the packs available here.
|
|
@@ -143,48 +129,42 @@ Every command takes `--help`, and `--json` for agents.
|
|
|
143
129
|
|
|
144
130
|
## Catalogs
|
|
145
131
|
|
|
146
|
-
|
|
132
|
+
The built-in pack has a catalog: a page with a card for each parameter, showing what changing it does. Download it and open it in a browser.
|
|
147
133
|
|
|
148
|
-
-
|
|
149
|
-
- forgegraph_base_2: its own theme and format, and the same graph types and layer types drawn in them.
|
|
134
|
+
- [forgegraph_default](https://github.com/sskaye/forgegraph/blob/main/catalog/forgegraph_default.html): its theme and formats, and ForgeGraph's graph types and layer types drawn in them.
|
|
150
135
|
|
|
151
136
|
## Your graphs are yours
|
|
152
137
|
|
|
153
|
-
ForgeGraph is [MIT-licensed](LICENSE). Graphs and other output you make with it are yours: no attribution or licence terms apply to them. See TRADEMARKS.md for use of the name.
|
|
138
|
+
ForgeGraph is [MIT-licensed](https://github.com/sskaye/forgegraph/blob/main/LICENSE). Graphs and other output you make with it are yours: no attribution or licence terms apply to them. See [TRADEMARKS.md](https://github.com/sskaye/forgegraph/blob/main/TRADEMARKS.md) for use of the name.
|
|
154
139
|
|
|
155
140
|
## Documentation
|
|
156
141
|
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
-
|
|
160
|
-
- [
|
|
161
|
-
-
|
|
142
|
+
- [Specifications](https://github.com/sskaye/forgegraph/blob/main/docs/specifications): the file that defines each kind of spec, every parameter with its default, range and description.
|
|
143
|
+
- [Built-in pack](https://github.com/sskaye/forgegraph/blob/main/docs/packs/forgegraph_default): forgegraph_default's specs.
|
|
144
|
+
- [Changelog](https://github.com/sskaye/forgegraph/blob/main/CHANGELOG.md).
|
|
145
|
+
- [Contributing](https://github.com/sskaye/forgegraph/blob/main/CONTRIBUTING.md): working on ForgeGraph itself.
|
|
146
|
+
- Design record, in [docs/design](https://github.com/sskaye/forgegraph/blob/main/docs/design):
|
|
147
|
+
- [Architecture](https://github.com/sskaye/forgegraph/blob/main/docs/design/architecture.md): how ForgeGraph is designed, and why.
|
|
148
|
+
- [To do](https://github.com/sskaye/forgegraph/blob/main/docs/design/todo.md): what's still planned.
|
|
162
149
|
|
|
163
150
|
## Contributing
|
|
164
151
|
|
|
165
|
-
Feature requests and bug reports go to [GitHub issues](https://github.com/sskaye/forgegraph/issues); the skill can file them for you. CONTRIBUTING.md covers working on ForgeGraph itself
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
uv sync && uv run pre-commit install
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
uv run pytest --full && uv run ruff check . && uv run pyright
|
|
173
|
-
```
|
|
152
|
+
Feature requests and bug reports go to [GitHub issues](https://github.com/sskaye/forgegraph/issues); the skill can file them for you. [CONTRIBUTING.md](https://github.com/sskaye/forgegraph/blob/main/CONTRIBUTING.md) covers working on ForgeGraph itself: setup, the checks to run, and regenerating the catalogs.
|
|
174
153
|
|
|
175
154
|
## Repository map
|
|
176
155
|
|
|
177
156
|
- **src/forgegraph/**: the package.
|
|
178
|
-
- `graph.py`: the Python API (`fg.xy`, `fg.render`, `fg.graphspec`, `fg.load`) and the `Graph` object; `canvas.py`: the themed canvas.
|
|
157
|
+
- `graph.py`: the Python API (`fg.xy`, `fg.render`, `fg.graphspec`, `fg.load`) and the `Graph` object; `canvas.py`: `fg.blank`, the themed canvas; `drawn.py`: what they and layouts share once drawn; `data.py`: reading a GraphSpec's data.
|
|
179
158
|
- **cli/**: the `forgegraph` command.
|
|
180
159
|
- **spec/**: reading, checking and resolving specs, and the provenance record.
|
|
181
|
-
- **drawing/**: drawing, layout and lint. **layouts/**: layouts. **jobs/**: scheduled renders.
|
|
182
|
-
- **
|
|
183
|
-
- **
|
|
184
|
-
- **
|
|
160
|
+
- **drawing/**: drawing, layout and lint. **layouts/**: `fg.layout` and layouts. **jobs/**: scheduled renders.
|
|
161
|
+
- **specifications/**: the specification files, which define each kind of spec, and the graph types' and layer types' catalog files.
|
|
162
|
+
- **packs/**: packs and configs, and the built-in pack `forgegraph_default`. **fonts/**: bundled fonts and their licences.
|
|
163
|
+
- **catalog_build/**: the catalog builder.
|
|
164
|
+
- **skill/forgegraph/**: the agent skill. `forgemark.py`: Forgemark's review-comment format, and its pinned tool.
|
|
185
165
|
- **catalog/**: the generated catalog pages.
|
|
186
|
-
- **examples/**: sample data
|
|
166
|
+
- **examples/**: sample data; `packs/acme`, an example pack in a deliberately different style; and `layouts/`, a paper figure and a dashboard.
|
|
187
167
|
- **evals/skill/**: the skill's eval cases, run by `scripts/run_skill_evals.py`.
|
|
188
168
|
- **tests/**, **scripts/**: tests, and build and maintenance scripts.
|
|
189
|
-
- **docs/**: the
|
|
169
|
+
- **docs/**: the specifications' and packs' pages, the design record and the visual changelogs. **review/**: each build phase's review pages.
|
|
190
170
|
|