forgegraph 0.6.1__tar.gz → 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.
- {forgegraph-0.6.1 → forgegraph-0.8.0}/CHANGELOG.md +48 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/PKG-INFO +1 -1
- forgegraph-0.6.1/src/forgegraph/skill/forgegraph/examples/figure.schedule.yaml → forgegraph-0.8.0/docs/examples/cells.schedule.yaml +3 -3
- forgegraph-0.8.0/docs/examples/passenger_toggles.yaml +48 -0
- forgegraph-0.8.0/docs/examples/penguin_measures.yaml +38 -0
- forgegraph-0.8.0/docs/examples/plate_spectra.yaml +32 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/graphspecs/graphspec_example.md +11 -11
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/pack.md +2 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/themes/light_theme.md +7 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/gallery.md +12 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/graphs.md +2 -2
- forgegraph-0.8.0/docs/site/guides/layers.md +92 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/layouts.md +5 -3
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/schedules.md +4 -4
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/series.md +4 -4
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/help/troubleshooting.md +11 -3
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/catalogs/graphtype_xy.md +2 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/catalogs/layer_reference.md +4 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/graphspec_example.md +25 -13
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/graphtype_xy.md +8 -7
- forgegraph-0.8.0/docs/specifications/layer_choice.md +15 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/layer_reference.md +5 -4
- forgegraph-0.8.0/docs/specifications/layer_toggle.md +14 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/pack.md +2 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/styles.md +1 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/theme.md +6 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/README.md +1 -0
- forgegraph-0.8.0/examples/sample-data/plate_spectra.csv +4561 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/pyproject.toml +1 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/build_example_data.py +3 -4
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/build_sample_data.py +26 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/docs_site.py +10 -5
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/run_skill_evals.py +16 -1
- forgegraph-0.8.0/scripts/skill_examples.py +132 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/catalog_build/build.py +3 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/catalog_build/cards.py +11 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/axes.py +33 -9
- forgegraph-0.8.0/src/forgegraph/drawing/equation.py +231 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/figure.py +12 -10
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/key.py +67 -15
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/labels.py +285 -35
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/layers.py +346 -61
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/layout.py +68 -11
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/limits.py +21 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/lint.py +4 -3
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/marks.py +108 -2
- forgegraph-0.8.0/src/forgegraph/drawing/owners.py +72 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/page.py +422 -35
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/readout.py +112 -16
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/spacing.py +41 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/style.py +17 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/ticks.py +17 -6
- forgegraph-0.8.0/src/forgegraph/drawing/toggles.py +104 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/xy.py +185 -44
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/graph.py +251 -22
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/layouts/__init__.py +264 -25
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/graphspecs/graphspec_example.yaml +11 -11
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/pack.yaml +2 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/themes/light_theme.yaml +7 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/skill/forgegraph/SKILL.md +10 -7
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/air_passengers_by_month.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/cell_durability.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/cell_polarization.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/cells.layout.yaml +26 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/cells.schedule.yaml +12 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/co2.yaml +28 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/co2_monthly.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/dose_response.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/dose_response.yaml +33 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/durability.yaml +26 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/economics.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/passenger_toggles.yaml +48 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/penguin_measures.yaml +38 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/penguins.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/plate_spectra.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/plate_spectra.yaml +32 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/polarization.yaml +24 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/savings.yaml +58 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/tips.parquet +0 -0
- forgegraph-0.8.0/src/forgegraph/skill/forgegraph/examples/tips_stacked.yaml +42 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/skill/forgegraph/references/themes_formats_configs.md +1 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/layers.py +35 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/parameters.py +24 -2
- forgegraph-0.8.0/src/forgegraph/spec/toggles.py +97 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/validate.py +9 -2
- forgegraph-0.8.0/src/forgegraph/spec/views.py +131 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/catalogs/graphtype_xy.yaml +1 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/catalogs/layer_reference.yaml +3 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/graphspec_example.yaml +24 -12
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/graphtype_xy.yaml +7 -7
- forgegraph-0.8.0/src/forgegraph/specifications/layer_choice.yaml +10 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/layer_reference.yaml +5 -4
- forgegraph-0.8.0/src/forgegraph/specifications/layer_toggle.yaml +9 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/pack.yaml +2 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/styles.yaml +1 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/theme.yaml +5 -2
- forgegraph-0.8.0/tests/baselines/precipitation_loglog.png +0 -0
- forgegraph-0.8.0/tests/baselines/replicates.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_axes.py +104 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_catalog_files.py +5 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_cli.py +2 -2
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_docs_site.py +2 -0
- forgegraph-0.8.0/tests/test_key_position.py +353 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_layers.py +313 -8
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_layout.py +17 -3
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_marks.py +146 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_perturbation.py +2 -1
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_readout.py +162 -3
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_render.py +88 -9
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_series.py +107 -0
- forgegraph-0.8.0/tests/test_skill_examples.py +26 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_specs.py +5 -1
- forgegraph-0.8.0/tests/test_toggles.py +282 -0
- forgegraph-0.8.0/tests/test_views.py +255 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/uv.lock +1 -1
- forgegraph-0.6.1/docs/site/guides/layers.md +0 -57
- forgegraph-0.6.1/src/forgegraph/skill/forgegraph/examples/bars.yaml +0 -32
- forgegraph-0.6.1/src/forgegraph/skill/forgegraph/examples/figure.layout.yaml +0 -16
- forgegraph-0.6.1/src/forgegraph/skill/forgegraph/examples/layers.yaml +0 -36
- forgegraph-0.6.1/src/forgegraph/skill/forgegraph/examples/xy.parquet +0 -0
- forgegraph-0.6.1/src/forgegraph/skill/forgegraph/examples/xy.yaml +0 -22
- forgegraph-0.6.1/tests/baselines/precipitation_loglog.png +0 -0
- forgegraph-0.6.1/tests/baselines/replicates.png +0 -0
- forgegraph-0.6.1/tests/test_key_position.py +0 -83
- {forgegraph-0.6.1 → forgegraph-0.8.0}/.gitignore +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/.pre-commit-config.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/CITATION.cff +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/CONTRIBUTING.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/LICENSE +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/README.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/SECURITY.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/TRADEMARKS.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/design/architecture.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/design/initial-specification.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/acme_polarization.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/assay_summary.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/cells.layout.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/co2.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/dose_response.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/durability.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/lab_polarization.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/packs/lab/formats/poster.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/packs/lab/pack.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/packs/lab/themes/lab_theme.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/penguins.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/polarization.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/savings.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/tips_side_by_side.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/examples/tips_stacked.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/acme/formats/slide.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/acme/graphspecs/polarization-curve.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/acme/layouts/dashboard.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/acme/pack.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/acme/schedules/workday.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/acme/themes/acme.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/catalogs/formats/compact_format.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/catalogs/formats/wide_format.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/catalogs/themes/light_theme.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/formats/compact_format.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/formats/wide_format.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/layouts/layout.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/schedules/schedule.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/get-started/installation.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/get-started/quickstart.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/get-started/skill.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/configs.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/provenance.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/guides/themes-formats-packs.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/index.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/reference/python-api.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/release-notes.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/site/stylesheets/extra.css +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/catalogs/layer_error_bar.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/catalogs/layer_note.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/config.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/format.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/layer_error_bar.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/layer_note.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/layout_example.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/provenance.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/docs/specifications/schedule.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/README.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/forgegraph.toml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/lab_throughput.layout.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/lab_throughput.layout.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/lost_runs.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/lost_runs.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/ops/formats/dashboard.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/ops/formats/dashboard.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/ops/pack.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/prep_lab_dashboard.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/run_time.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/run_time.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/runs_gc_ms_01.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/runs_hplc_01.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/runs_hplc_02.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/runs_icp_oes_01.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/samples_weekly.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/throughput_weekly.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/weekly_gc_ms_01.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/weekly_hplc_01.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/weekly_hplc_02.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/weekly_icp_oes_01.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/weekly_runs.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/dashboard/weekly_samples.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/cell_durability.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/cell_performance.layout.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/cell_performance.layout.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/cell_polarization.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/forgegraph.toml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/hfr_time.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/journal/formats/journal-double.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/journal/formats/journal-double.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/journal/pack.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/polarization.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/prep_cells.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/layouts/paper/voltage_time.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/formats/slide.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/graphspecs/polarization-curve.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/layouts/dashboard.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/pack.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/references/house.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/schedules/workday.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/packs/acme/themes/acme.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/air_passengers.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/air_passengers_by_month.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/anscombe.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/assay_summary.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/cell_durability.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/cell_polarization.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/co2_monthly.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/diamonds.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/dose_response.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/economics.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/enzyme_kinetics.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/fmri.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/gapminder.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/geyser.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/growth.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/iris.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/lab_export.xlsx +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/lab_runs.xlsx +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/penguins.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/seaice.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/sensor_log_eu.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/stocks.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/tips.csv +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/examples/sample-data/weather.xlsx +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/mkdocs.yml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/build_recreations.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/check_denylist.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/forgemark.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/mirror_specs.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/report_skill_evals.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/smoke_installed.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/scripts/visual_changelog.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/__main__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/canvas.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/catalog_build/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/catalog_build/examples.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/catalog_build/files.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/catalog_build/page.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/cli/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/cli/catalog.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/cli/graphs.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/cli/jobs.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/cli/schema.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/cli/skill.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/data.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/colorbar.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/dates.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/errors.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/export.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/markup.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawing/text.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/drawn.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/IBMPlexSerif-Bold.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/IBMPlexSerif-Light.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/IBMPlexSerif-Medium.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/IBMPlexSerif-Regular.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/IBMPlexSerif-SemiBold.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/OFL-IBMPlexSerif.txt +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/OFL-Roboto.txt +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/OFL-SourceSans3.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/Roboto-Bold.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/Roboto-Italic.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/Roboto-Light.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/Roboto-Medium.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/Roboto-Regular.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/Roboto-SemiBold.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/SourceSans3-Bold.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/SourceSans3-It.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/SourceSans3-Light.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/SourceSans3-Medium.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/SourceSans3-Regular.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/SourceSans3-Semibold.ttf +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/fonts/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/forgemark.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/jobs/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/jobs/run.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/jobs/status.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/layouts/separators.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/catalogs/formats/compact_format.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/catalogs/formats/wide_format.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/catalogs/themes/light_theme.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/formats/compact_format.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/formats/wide_format.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/graphspecs/dated.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/graphspecs/fanned.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/graphspecs/polarization.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/graphspecs/reinforced.parquet +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/layouts/layout.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/packs/forgegraph_default/schedules/schedule.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/skill/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/skill/forgegraph/references/requests.md +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/__init__.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/access.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/common.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/explain.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/layout.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/loaded.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/provenance.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/registry.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/resolve.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/schedule.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/series.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/spec/tags.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/catalogs/layer_error_bar.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/catalogs/layer_note.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/config.toml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/format.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/layer_error_bar.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/layer_note.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/layout_example.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/provenance.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/src/forgegraph/specifications/schedule.yaml +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/crowded_runs.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/flow_sweep_wide.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/fuel_by_size.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/layout_anode_layers.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/layout_screening_and_rate.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/polarization.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/polarization_narrow.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/screening_scatter.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/baselines/separator_colorbar.png +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/conftest.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/fixtures/catalog_comments.html +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/pack_helpers.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/recreations.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/render_helpers.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/spec_mirror.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_blank.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_catalog.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_catalog_inputs.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_catalog_page.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_dates.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_denylist.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_jobs.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_labels.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_lint.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_markup.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_packaging.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_packs.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_regression.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_schedule.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_smoke.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_spec_comments.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_spec_mirrors.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_styles.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_tags.py +0 -0
- {forgegraph-0.6.1 → forgegraph-0.8.0}/tests/test_text.py +0 -0
|
@@ -2,6 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
ForgeGraph follows [semantic versioning](https://semver.org). Before 1.0, a minor version may change how graphs look or how specs are written.
|
|
4
4
|
|
|
5
|
+
## 0.8.0 (2026-11-07)
|
|
6
|
+
|
|
7
|
+
### New Features
|
|
8
|
+
|
|
9
|
+
- **Controls on the HTML page.** Two new layers add controls to a graph's web page. A `choice` layer lists views, such as other columns for a series or a log axis, and readers switch between them with a dropdown or radio buttons. A `toggle` layer adds checkboxes that show or hide series and layers; a series named in a key gets its checkbox in the key. Every view is drawn ahead of time, so the page needs no server, and the graph keeps its size and position as you switch. The controls go to the right of the graph, or above or below it, and the theme sets their text. In a layout, controls of the same name in different panels work together. Saved images show the first view, without the items hidden at first.
|
|
10
|
+
- **Axis limits that leave out outliers.** An axis's `min` or `max` can be `3IQR`, which ends the axis 3 interquartile ranges beyond the quartile, so a few extreme values don't squash the rest of the data.
|
|
11
|
+
- **Geometric statistics.** `geom_mean`, `geom_stddev` and `geom_ci` work wherever the other statistics do: combining points, error bars and reference lines. They suit values that vary by a factor, such as concentrations, and their error bars are longer above the point than below it.
|
|
12
|
+
- **Star and asterisk markers.**
|
|
13
|
+
- **Long titles can wrap.** A theme's `title.max_wrap` lets a title run onto more lines. By default a title doesn't wrap, and one that's too long now gives an error that names it.
|
|
14
|
+
- **Named parts in SVG files.** In an SVG, each series' and layer's parts have ids that start with its name, such as `fg-series-Voltage-1`, so a web page can find them.
|
|
15
|
+
|
|
16
|
+
### Changes
|
|
17
|
+
|
|
18
|
+
- **Fewer tick labels when they'd run together.** Automatic ticks on a number axis now space out until their labels fit.
|
|
19
|
+
- **Ticks on an extended axis.** When an axis grows to make room for a key, note or label, its ticks carry on into the new part.
|
|
20
|
+
- **Keys and notes keep clear of reference lines and bands.** Keys, notes and reference labels no longer sit on a reference line, a band, or the edge of a large marker. The axis grows to make room, or the error says what's in the way. Some graphs will place their key differently.
|
|
21
|
+
- **Reference lines past a set limit.** A reference line or band beyond an axis limit you've set is now left out, and lint says so, rather than stopping the graph.
|
|
22
|
+
- **Clearer label errors.** When a reference label at `position: auto` has no room, the error says what's in the way at each place it tried.
|
|
23
|
+
- **The agent skill** knows about the new controls, and its examples are now the ones in the documentation.
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
- Points and bars beyond a set axis limit still had a hover box on the HTML page. Only what's drawn inside the plot has one now.
|
|
28
|
+
- Cross and plus markers were drawn in black instead of their series' color.
|
|
29
|
+
- After an axis grew to fit a key, a new top tick label could run off the figure.
|
|
30
|
+
|
|
31
|
+
## 0.7.0 (2026-11-02)
|
|
32
|
+
|
|
33
|
+
### New Features
|
|
34
|
+
|
|
35
|
+
- **Heat maps.** `marker.shape: grid_cell` makes each point fill its place in a grid, so an xy graph colored by a column of numbers becomes a heat map. The cells fit at any format, and an HTML page shows a cell's values when you point at it. There's an example in the gallery and in the skill.
|
|
36
|
+
- **Reference lines from an equation.** A reference line can now be an equation instead of a value, such as `equation: x` for a y = x line on a parity plot, or `2x^2 - 3x + 1` for a curve. Two equations, such as `x - 10` and `x + 10`, make a tolerance band.
|
|
37
|
+
- **No tick labels.** `tick.algorithm: none` draws no ticks or tick labels on an axis, for when there are too many names to fit and readers can point at a point to see its name.
|
|
38
|
+
- **Tab bars stay in view.** On a layout's HTML page, the tabs now stay at the top of the window as you scroll, and switching tabs keeps your place on the page.
|
|
39
|
+
|
|
40
|
+
### Changes
|
|
41
|
+
|
|
42
|
+
- **More in the hover box.** On a graph of more than one series, the hover box now always names the series. It also shows each column a series is split by, so splitting a scatter by its sample's name shows that name on each point.
|
|
43
|
+
- **More room for keys.** A reference line's label at `position: auto` now goes after the keys and keeps clear of them, so keys and labels may sit in different places than before. A second key can go under or beside the first, and the y-axis can grow by up to `axis.max_extension` to make room for a key. Some graphs that couldn't fit a key now draw, with a longer y-axis.
|
|
44
|
+
- **Clearer key errors.** When a key doesn't fit, the error now says what's in the way at each position.
|
|
45
|
+
|
|
46
|
+
### Bug Fixes
|
|
47
|
+
|
|
48
|
+
- Coloring by the column on a categorical axis gave every point the first color and labelled the groups 0.0, 1.0 and 2.0. Each category now gets its own color, and the same goes for marker shapes and line styles. The axis already names the groups, so with `legend.method: auto` they aren't named again.
|
|
49
|
+
- A categorical axis with exactly two categories had no tick labels. It now has one for each category.
|
|
50
|
+
- An aggregated series colored by a column of numbers crashed with a message from matplotlib. If the rows behind a point share one value, the point now takes that color. If they don't, it's an error that says which column to change.
|
|
51
|
+
- The hover box on an integer axis showed `2.0` where it now shows `2`.
|
|
52
|
+
|
|
5
53
|
## 0.6.1 (2026-10-31)
|
|
6
54
|
|
|
7
55
|
### Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: forgegraph
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Fast, consistent, publication-quality graphs from pandas DataFrames, usable by people and AI agents.
|
|
5
5
|
Project-URL: Repository, https://github.com/sskaye/forgegraph
|
|
6
6
|
Project-URL: Issues, https://github.com/sskaye/forgegraph/issues
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: cells
|
|
2
2
|
version: 0
|
|
3
|
-
description: The
|
|
3
|
+
description: The cells layout, rendered every weekday at 06:00.
|
|
4
4
|
extends: forgegraph_default/schedule
|
|
5
5
|
|
|
6
6
|
parameters: # !var: a schedule that extends it may change it; !fix: it may not; on a category, all in it. Each parameter is tagged here or in the schedule it extends.
|
|
7
7
|
targets:
|
|
8
|
-
files: [
|
|
8
|
+
files: [cells.layout.yaml]
|
|
9
9
|
cadence:
|
|
10
10
|
interval:
|
|
11
11
|
unit: week
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: passenger_toggles
|
|
2
|
+
version: 0
|
|
3
|
+
description: Airline passengers in March, July and November of each year, each month and July's mean shown or hidden on the HTML page.
|
|
4
|
+
extends: None
|
|
5
|
+
parameters: !var
|
|
6
|
+
specifications:
|
|
7
|
+
graph_type: xy
|
|
8
|
+
theme: forgegraph_default/light_theme
|
|
9
|
+
format: forgegraph_default/compact_format
|
|
10
|
+
text:
|
|
11
|
+
title: Airline passengers by month
|
|
12
|
+
data:
|
|
13
|
+
file: air_passengers_by_month.parquet
|
|
14
|
+
preprocessing: examples/sample-data/air_passengers_by_month.csv, unchanged
|
|
15
|
+
axis:
|
|
16
|
+
x:
|
|
17
|
+
data:
|
|
18
|
+
column: Year
|
|
19
|
+
title: None
|
|
20
|
+
y:
|
|
21
|
+
title: Passengers (thousands)
|
|
22
|
+
series:
|
|
23
|
+
July:
|
|
24
|
+
column: Jul
|
|
25
|
+
March:
|
|
26
|
+
column: Mar
|
|
27
|
+
November:
|
|
28
|
+
column: Nov
|
|
29
|
+
legend:
|
|
30
|
+
method: direct
|
|
31
|
+
key:
|
|
32
|
+
title:
|
|
33
|
+
text: None
|
|
34
|
+
layers:
|
|
35
|
+
mean:
|
|
36
|
+
type: reference
|
|
37
|
+
axis: y
|
|
38
|
+
line_1:
|
|
39
|
+
value: Jul
|
|
40
|
+
aggregation:
|
|
41
|
+
function: mean
|
|
42
|
+
label:
|
|
43
|
+
text: aggregation_value
|
|
44
|
+
show:
|
|
45
|
+
type: toggle
|
|
46
|
+
label: Show
|
|
47
|
+
items: [series, mean]
|
|
48
|
+
hidden: [mean]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: penguin_measures
|
|
2
|
+
version: 0
|
|
3
|
+
description: A penguin measurement against bill length for three species, the measurement chosen on the HTML page.
|
|
4
|
+
extends: None
|
|
5
|
+
parameters: !var
|
|
6
|
+
specifications:
|
|
7
|
+
graph_type: xy
|
|
8
|
+
theme: forgegraph_default/light_theme
|
|
9
|
+
format: forgegraph_default/compact_format
|
|
10
|
+
text:
|
|
11
|
+
title: Penguin measurements
|
|
12
|
+
data:
|
|
13
|
+
file: penguins.parquet
|
|
14
|
+
preprocessing: examples/sample-data/penguins.csv, unchanged
|
|
15
|
+
axis:
|
|
16
|
+
x:
|
|
17
|
+
data:
|
|
18
|
+
column: bill_length_mm
|
|
19
|
+
title: Bill length (mm)
|
|
20
|
+
y:
|
|
21
|
+
title: Bill depth (mm)
|
|
22
|
+
series:
|
|
23
|
+
measure:
|
|
24
|
+
column: bill_depth_mm
|
|
25
|
+
color: species
|
|
26
|
+
line:
|
|
27
|
+
show: false
|
|
28
|
+
marker:
|
|
29
|
+
shape: species
|
|
30
|
+
size: 0.3
|
|
31
|
+
layers:
|
|
32
|
+
measure:
|
|
33
|
+
type: choice
|
|
34
|
+
label: Measurement
|
|
35
|
+
views:
|
|
36
|
+
Bill depth: {}
|
|
37
|
+
Flipper length: {series.measure.column: flipper_length_mm, axis.y.title: Flipper length (mm)}
|
|
38
|
+
Body mass: {series.measure.column: body_mass_g, axis.y.title: Body mass (g)}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: plate_spectra
|
|
2
|
+
version: 0
|
|
3
|
+
description: A heat map of a plate's spectra, one row for each sample, colored by absorbance.
|
|
4
|
+
extends: None
|
|
5
|
+
parameters: !var
|
|
6
|
+
specifications:
|
|
7
|
+
graph_type: xy
|
|
8
|
+
theme: forgegraph_default/light_theme
|
|
9
|
+
format: forgegraph_default/compact_format
|
|
10
|
+
text:
|
|
11
|
+
title: A plate of UV-Vis spectra
|
|
12
|
+
data:
|
|
13
|
+
file: plate_spectra.parquet
|
|
14
|
+
preprocessing: examples/sample-data/plate_spectra.csv
|
|
15
|
+
arrangement:
|
|
16
|
+
base_axis: y
|
|
17
|
+
axis:
|
|
18
|
+
x:
|
|
19
|
+
title: Wavelength (nm)
|
|
20
|
+
y:
|
|
21
|
+
data:
|
|
22
|
+
column: Sample
|
|
23
|
+
type: categorical
|
|
24
|
+
title: Sample
|
|
25
|
+
series:
|
|
26
|
+
Wavelength (nm):
|
|
27
|
+
color: Normalized absorbance
|
|
28
|
+
color_scale: continuous
|
|
29
|
+
marker:
|
|
30
|
+
shape: grid_cell
|
|
31
|
+
line:
|
|
32
|
+
show: false
|
{forgegraph-0.6.1 → forgegraph-0.8.0}/docs/packs/forgegraph_default/graphspecs/graphspec_example.md
RENAMED
|
@@ -27,10 +27,10 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
27
27
|
direction: ascending *# \[ascending, descending\]; The direction of the category order.*\
|
|
28
28
|
title: column_name *# \[None, column_name, text\]; The axis title. column_name uses the name of data.column if it's the base_axis or the series' column if it's not. With several series, use text or None.*\
|
|
29
29
|
scale: linear *# \[linear, log\]; The axis scale.*\
|
|
30
|
-
min: None *# \[None, float, date\]; The axis minimum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the lowest value minus plot_area.gap × the data's range.*\
|
|
31
|
-
max: None *# \[None, float, date\]; The axis maximum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the highest value plus plot_area.gap × the data's range.*\
|
|
30
|
+
min: None *# \[None, float, date, IQR rule\]; The axis minimum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the lowest value minus plot_area.gap × the data's range. 3IQR moves it in to the lower quartile minus 3 × the interquartile range.*\
|
|
31
|
+
max: None *# \[None, float, date, IQR rule\]; The axis maximum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the highest value plus plot_area.gap × the data's range. 3IQR moves it in to the upper quartile plus 3 × the interquartile range.*\
|
|
32
32
|
tick:\
|
|
33
|
-
algorithm: auto *# \[auto, all, manual\]; How the ticks are placed. auto uses the theme's algorithm, or on dates, the boundaries of one calendar unit. all places a tick at every value. manual places one every tick.step.*\
|
|
33
|
+
algorithm: auto *# \[auto, all, manual, none\]; How the ticks are placed. auto uses the theme's algorithm, or on dates, the boundaries of one calendar unit. all places a tick at every value. manual places one every tick.step. none draws no ticks or tick labels.*\
|
|
34
34
|
step: None *# \[None, float > 0, text\]; The distance between ticks when algorithm is manual, e.g. 5 or "2 week". On a log axis, it's a factor.*\
|
|
35
35
|
label:\
|
|
36
36
|
format: auto *# \[auto, format\]; The tick label format. auto chooses one from the values, and for dates, from the tick unit.*\
|
|
@@ -43,10 +43,10 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
43
43
|
direction: ascending *# \[ascending, descending\]; The direction of the category order.*\
|
|
44
44
|
title: column_name *# \[None, column_name, text\]; The axis title. column_name uses the name of data.column if it's the base_axis or the series' column if it's not. With several series, use text or None.*\
|
|
45
45
|
scale: linear *# \[linear, log\]; The axis scale.*\
|
|
46
|
-
min: None *# \[None, float, date\]; The axis minimum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the lowest value minus plot_area.gap × the data's range.*\
|
|
47
|
-
max: None *# \[None, float, date\]; The axis maximum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the highest value plus plot_area.gap × the data's range.*\
|
|
46
|
+
min: None *# \[None, float, date, IQR rule\]; The axis minimum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the lowest value minus plot_area.gap × the data's range. 3IQR moves it in to the lower quartile minus 3 × the interquartile range.*\
|
|
47
|
+
max: None *# \[None, float, date, IQR rule\]; The axis maximum. On a datetime axis, it's a date, e.g. 2025-08-25 or "2025-08-25T06:00". If None, it's the highest value plus plot_area.gap × the data's range. 3IQR moves it in to the upper quartile plus 3 × the interquartile range.*\
|
|
48
48
|
tick:\
|
|
49
|
-
algorithm: auto *# \[auto, all, manual\]; How the ticks are placed. auto uses the theme's algorithm, or on dates, the boundaries of one calendar unit. all places a tick at every value. manual places one every tick.step.*\
|
|
49
|
+
algorithm: auto *# \[auto, all, manual, none\]; How the ticks are placed. auto uses the theme's algorithm, or on dates, the boundaries of one calendar unit. all places a tick at every value. manual places one every tick.step. none draws no ticks or tick labels.*\
|
|
50
50
|
step: None *# \[None, float > 0, text\]; The distance between ticks when algorithm is manual, e.g. 5 or "2 week". On a log axis, it's a factor.*\
|
|
51
51
|
label:\
|
|
52
52
|
format: auto *# \[auto, format\]; The tick label format. auto chooses one from the values, and for dates, from the tick unit.*\
|
|
@@ -60,7 +60,7 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
60
60
|
"Cell Voltage (V)":\
|
|
61
61
|
column: name *# \[name, column\]; The column of values the series draws along the axis that isn't arrangement.base_axis. name uses the column with the series' name.*\
|
|
62
62
|
aggregation: *# \[aggregation style\]; How rows at the same location are combined into one point. If its function is None, each row is drawn.*\
|
|
63
|
-
split: \[Cell, Run\] *# \[None, columns\]; Columns whose values split the series into separate lines, e.g. replicates.*\
|
|
63
|
+
split: \[Cell, Run\] *# \[None, columns\]; Columns whose values split the series into separate lines, e.g. replicates. An html page's readout shows each one.*\
|
|
64
64
|
order: sorted *# \[sorted, data\]; The order of the series' groups: sorted, or data for the order in which they first appear.*\
|
|
65
65
|
color: Cell *# \[series, hex color, column\]; The series' color. series takes the next palette color, and a column gives each of its values its own.*\
|
|
66
66
|
color_scale: auto *# \[auto, categorical, continuous\]; For a color column: categorical uses the palette, continuous a color scale and color bar, and auto continuous for numbers.*\
|
|
@@ -73,7 +73,7 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
73
73
|
missing_values: drop *# \[drop, gap\]; What happens to rows missing x or y. drop joins the line across them, and gap breaks the line. Lint counts both in dropped-rows.*\
|
|
74
74
|
marker:\
|
|
75
75
|
show: true *# \[true, false\]; Whether to draw markers.*\
|
|
76
|
-
shape: first *# \[first, series, circle, square, triangle_up, triangle_down, diamond, cross, plus, column\]; The marker shape. first is the theme's first marker shape, series takes the next one, and a column gives each of its values its own.*\
|
|
76
|
+
shape: first *# \[first, series, circle, square, triangle_up, triangle_down, diamond, cross, plus, star, asterisk, grid_cell, column\]; The marker shape. first is the theme's first marker shape, series takes the next one, and a column gives each of its values its own. grid_cell fills the grid the points lie on, for a heat map.*\
|
|
77
77
|
fill: first *# \[first, series, filled, open, column\]; The marker fill. first is the theme's first marker fill, series takes the next one, and a column gives each of its values its own.*\
|
|
78
78
|
size: 0.5 *# \[float > 0\]; The marker size, × base size.*\
|
|
79
79
|
bar:\
|
|
@@ -91,7 +91,7 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
91
91
|
legend:\
|
|
92
92
|
method: auto *# \[auto, direct, key, none\]; How this graph names its series: one of the theme's legend.methods.*\
|
|
93
93
|
key:\
|
|
94
|
-
positions: \[top_right, top_left, bottom_right, bottom_left\] *# \[top_left, top_center, top_right, bottom_left, bottom_center, bottom_right, right_top, right_center, right_bottom\]; The positions to try, in order. The key goes in the first one where it doesn't overlap the data.*\
|
|
94
|
+
positions: \[top_right, top_left, bottom_right, bottom_left\] *# \[top_left, top_center, top_right, bottom_left, bottom_center, bottom_right, right_top, right_center, right_bottom\]; The positions to try, in order. The key goes in the first one where it doesn't overlap the data. If there's none inside the plot, it goes beside a key there, or the y-axis is extended.*\
|
|
95
95
|
inside: true *# \[true, false\]; Whether the key is inside the plot area. If false, top positions are above the plot area, bottom positions are below the x-axis title, and right positions are to its right.*\
|
|
96
96
|
title:\
|
|
97
97
|
text: column_name *# \[None, column_name, text\]; The title of every key. column_name uses the name of each key's column. Other text is allowed only when there is one key. If None, there is no title.*\
|
|
@@ -106,11 +106,11 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
106
106
|
layers: *# The layers drawn on the graph, in this order, each under a name the GraphSpec chooses. A layer may set the look its theme marks !var.*\
|
|
107
107
|
target:\
|
|
108
108
|
type: reference *# \[layer type\]; The layer's type: one of the graph type's layer.types.*\
|
|
109
|
-
axis: y *# \[x, y\]; The axis the values are on. y draws horizontal lines.*\
|
|
109
|
+
axis: y *# \[x, y\]; The axis the values are on. y draws horizontal lines, and an equation then gives y in terms of x.*\
|
|
110
110
|
line_1:\
|
|
111
111
|
value: 1.2 *# \[None, float, date, column\]; A number, a date, or a column.*\
|
|
112
112
|
label:\
|
|
113
|
-
text: Target 1.2 V *# \[None, aggregation, value, aggregation_value, text\]; aggregation writes e.g. Mean, value e.g. 14.9, and aggregation_value e.g. Mean: 14.9. Other text is written as given.*\
|
|
113
|
+
text: Target 1.2 V *# \[None, aggregation, value, aggregation_value, text\]; aggregation writes e.g. Mean, value e.g. 14.9, and aggregation_value e.g. Mean: 14.9. With an equation, value writes e.g. y = 2x. Other text is written as given.*\
|
|
114
114
|
conditions:\
|
|
115
115
|
type: note *# \[layer type\]; The layer's type: one of the graph type's layer.types.*\
|
|
116
116
|
text: "60 °C, 1 atm, H₂/air" *# \[text\]; The note's text, in label markup. A line break starts a new line.*
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This page mirrors src/forgegraph/packs/forgegraph_default/pack.yaml, which is the specification. A test fails if they ever differ.
|
|
4
4
|
|
|
5
5
|
name: forgegraph_default *# \[text\]; The pack's name, which its specs' names start with (pack/name); a pip pack's must match its entry point.*\
|
|
6
|
-
version: 0.
|
|
6
|
+
version: 0.8.0 *# \[text\]; The pack's release version.*\
|
|
7
7
|
description: ForgeGraph's built-in default pack. So it’s always possible to create a graph. *# \[text\]; One line, describing what the pack is.*\
|
|
8
8
|
issues: https://github.com/sskaye/forgegraph/issues *# \[text\]; Where to file feature requests and bug reports about the pack.*\
|
|
9
|
-
requires: ">=0.
|
|
9
|
+
requires: ">=0.8, <0.9" *# \[None, version specifier\]; The ForgeGraph version required for the pack. pip format, e.g. ">=0.6, <1". If None, it works with any version.*
|
|
@@ -27,6 +27,7 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
27
27
|
size: 1.05 *# \[float > 0\]; The size, × base size.*\
|
|
28
28
|
weight: semibold *# \[light, regular, medium, semibold, bold\]; The weight.*\
|
|
29
29
|
gap: 0.41 *# \[float ≥ 0\]; The gap between the text and whatever is around it, × base size.*\
|
|
30
|
+
max_wrap: 0 *# \[int ≥ 0\]; The number of times the title may wrap onto a new line to fit above the plot. If 0, it never wraps.*\
|
|
30
31
|
axis:\
|
|
31
32
|
title: *# \[text style\]; The axis titles.*\
|
|
32
33
|
size: 1.05 *# \[float > 0\]; The size, × base size.*\
|
|
@@ -46,7 +47,7 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
46
47
|
count: 0 *# \[int ≥ 0\]; The number of minor ticks between major ticks. If 0, there are none.*\
|
|
47
48
|
length: 0.15 *# \[float ≥ 0\]; The minor tick length, × base size.*\
|
|
48
49
|
width: 0.05 *# \[float ≥ 0\]; The width, × base size. If 0, no line is drawn.*\
|
|
49
|
-
max_extension: 0.15 *# \[0-1\]; The most an axis may be extended to fit direct labels, notes and line labels inside the plot area, × its range. If 0, it's never extended.*\
|
|
50
|
+
max_extension: 0.15 *# \[0-1\]; The most an axis may be extended to fit direct labels, keys, notes and line labels inside the plot area, × its range. If 0, it's never extended.*\
|
|
50
51
|
plot_area:\
|
|
51
52
|
border: *# \[line style\]; The plot area's border.*\
|
|
52
53
|
width: 0.08 *# \[float ≥ 0\]; The width, × base size. If 0, no line is drawn.*\
|
|
@@ -67,7 +68,7 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
67
68
|
width: 0.15 *# \[float ≥ 0\]; The width, × base size. If 0, no line is drawn.*\
|
|
68
69
|
styles: !fix \[solid, dashed, dotted, dashdot\] *# \[solid, dashed, dotted, dashdot\]; The line styles given to the series, or to the values of a series' line.style column.*\
|
|
69
70
|
marker:\
|
|
70
|
-
shapes: !fix \[circle, square, triangle_up, diamond, triangle_down, cross\] *# \[circle, square, triangle_up, triangle_down, diamond, cross, plus\]; The marker shapes given to the series, or to the values of a series' marker.shape column.*\
|
|
71
|
+
shapes: !fix \[circle, square, triangle_up, diamond, triangle_down, cross\] *# \[circle, square, triangle_up, triangle_down, diamond, cross, plus, star, asterisk\]; The marker shapes given to the series, or to the values of a series' marker.shape column.*\
|
|
71
72
|
fills: !fix \[filled, open\] *# \[filled, open\]; The marker fills given to the series, or to the values of a series' marker.fill column. open draws only the outline.*\
|
|
72
73
|
size: 0.5 *# \[float > 0\]; The marker size, × base size.*\
|
|
73
74
|
edge: *# \[line style\]; The outline of filled markers. Open markers are outlined at its width, in their series' color.*\
|
|
@@ -139,6 +140,10 @@ parameters: !var *# !var/!fix sets whether a GraphSpec may ch
|
|
|
139
140
|
size: 0.8 *# \[float > 0\]; The size, × base size.*\
|
|
140
141
|
color: "#404040" *# \[hex color\]; The color.*\
|
|
141
142
|
gap: 0.5 *# \[float ≥ 0\]; The gap between the text and whatever is around it, × base size.*\
|
|
143
|
+
choice: *# \[text style\]; A choice layer's label and its views' names on an HTML page. Its gap is between the label and the control.*\
|
|
144
|
+
alignment: left *# \[left, center, right\]; The text alignment.*\
|
|
145
|
+
toggle: *# \[text style\]; A toggle layer's label and its items' names on an HTML page. Its gap is between the label and the checkboxes.*\
|
|
146
|
+
alignment: left *# \[left, center, right\]; The text alignment.*\
|
|
142
147
|
watermark: *# \[text style\]; The watermark drawn on non-standard graphs.*\
|
|
143
148
|
weight: bold *# \[light, regular, medium, semibold, bold\]; The weight.*\
|
|
144
149
|
color: "#CC0000" *# \[hex color\]; The color.*\
|
|
@@ -14,6 +14,18 @@ Polarization curves of three fuel cells, one line for each cell, named beside it
|
|
|
14
14
|
--8<-- "docs/examples/polarization.yaml"
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## A heat map
|
|
18
|
+
|
|
19
|
+
A plate of 60 UV-Vis spectra, one row for each sample, colored by absorbance. It's an xy graph whose markers fill the grid its points lie on, with `marker.shape: grid_cell`. Pointing at a cell on an HTML page shows its wavelength, sample and absorbance. Data: plate_spectra.csv.
|
|
20
|
+
|
|
21
|
+
{ width="480" }
|
|
22
|
+
|
|
23
|
+
??? example "GraphSpec"
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
--8<-- "docs/examples/plate_spectra.yaml"
|
|
27
|
+
```
|
|
28
|
+
|
|
17
29
|
## Lines over time
|
|
18
30
|
|
|
19
31
|
Each cell's voltage over a 200-hour durability test, as lines without markers. Data: cell_durability.csv.
|
|
@@ -16,7 +16,7 @@ These are the polarization curves of three fuel cells, from `cell_polarization.c
|
|
|
16
16
|
- **extends** is the GraphSpec this one builds on. With `None`, the file lists every parameter it sets, and `!var` on `parameters` lets a GraphSpec that extends it change any of them (see [Building on a GraphSpec](#building-on-a-graphspec)).
|
|
17
17
|
- **specifications** names the graph type, the theme and the format. The theme sets the look and the format sets the size and the file types. Both come from a [pack](themes-formats-packs.md), and are named `pack/name`.
|
|
18
18
|
- **data.file** is the Parquet file holding the DataFrame, as a path from the GraphSpec's folder. `data.preprocessing` says where the code that made it is; it's recorded in the saved files and never read.
|
|
19
|
-
- **axis.x.data.column** is the column along the x-axis. Each axis can also set its `title`, `scale` (`linear` or `log`), `min` and `max`, its ticks and their label format.
|
|
19
|
+
- **axis.x.data.column** is the column along the x-axis. Each axis can also set its `title`, `scale` (`linear` or `log`), `min` and `max`, its ticks and their label format. `max: 3IQR` keeps a few far outliers from squashing the data: the axis stops at the upper quartile plus 3 × the interquartile range, where that's nearer than it would be, and lint counts the points beyond it.
|
|
20
20
|
- **series** lists what's drawn against it, each under its name. A series draws the column with its name unless it sets `column`, and `color: cell` gives each cell its own color. The [Series guide](series.md) covers the rest.
|
|
21
21
|
|
|
22
22
|
Titles are written in label markup: `^2` or `^{...}` makes a superscript and `_{...}` a subscript, so `A/cm^2` draws as A/cm². A column's name is always drawn as it's written.
|
|
@@ -29,7 +29,7 @@ Every parameter, with its default, the values it allows and its description, is
|
|
|
29
29
|
forgegraph render polarization.yaml
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
`render` saves the graph in each file type its format lists, beside the GraphSpec, and reports the lint. `--out` saves it elsewhere, and a suffix there picks one file type: `--out curves.svg`.
|
|
32
|
+
`render` saves the graph in each file type its format lists, beside the GraphSpec, and reports the lint. `--out` saves it elsewhere, and a suffix there picks one file type: `--out curves.svg`. In an SVG, each part of a series or a layer has an id that names it, such as `fg-series-Cell_A-1` for a series' line or `fg-layer-target-1` for a reference line, so a page can style or hide a whole series by the start of its ids.
|
|
33
33
|
|
|
34
34
|
The format's file types, size and resolution can be set in the GraphSpec too, where the format allows it. The built-in formats allow all of them:
|
|
35
35
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Layers
|
|
2
|
+
|
|
3
|
+
Layers are drawn over a graph: reference lines and bands, error bars, and notes. Choice and toggle layers add controls to the graph's HTML page instead. A GraphSpec lists its layers under `layers`, each under a name it chooses, with its `type`. They're drawn in the order they're listed. The [layer specifications](../reference/specifications/layer_reference.md) list every parameter.
|
|
4
|
+
|
|
5
|
+
## Reference lines and bands
|
|
6
|
+
|
|
7
|
+
A `reference` layer draws a line across the plot at a value: horizontal with `axis: y`, vertical with `axis: x`. `line_1.value` is a number, a date, or a column, and a column's rows are combined by `line_1.aggregation`, so a line can sit at the data's mean, median, a percentile and so on. `offset` adds a distance to that, such as three standard deviations.
|
|
8
|
+
|
|
9
|
+
A line can also be an equation, in place of a value, such as `equation: x` for a line of y = x on a parity plot. With `axis: y`, an equation gives y in terms of x, and with `axis: x`, x in terms of y. It may use numbers, that letter, `+`, `-`, `*`, `/`, `^` and parentheses, as in `2x^2 - 3x + 1`, and it may be a curve. The line runs across the plot without widening an axis, and its label lies along it. `label.text: value` writes the equation, as in y = 2x. A label that can't find a clear place beside the data can go beyond the plot, with `label.inside: false`.
|
|
10
|
+
|
|
11
|
+
A second line, `line_2`, makes the layer a band, filled between the two lines, which can be equations: `x - 10` and `x + 10` make a tolerance band around y = x. The savings rate has a band one standard deviation either side of its mean, drawn without its lines, and a second layer with a line at the mean:
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
--8<-- "docs/examples/savings.yaml"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
{ width="480" }
|
|
18
|
+
|
|
19
|
+
- **label.text** writes the line's label: `aggregation` writes, for example, Mean, `value` writes 14.9, `aggregation_value` writes Mean: 14.9, and other text is written as it's given. `label.position` and `label.inside` place it; here it's outside the plot, at the line's end.
|
|
20
|
+
- **per_series: true** draws the layer for every series with matching color, marker shape, marker fill and line style, in its color and from its rows, instead of once for all the data.
|
|
21
|
+
- **scope: each** makes a line that follows the data, instead of a straight line over all the rows.
|
|
22
|
+
|
|
23
|
+
## Error bars
|
|
24
|
+
|
|
25
|
+
An `error_bar` layer draws a bar on each point or bar, along `axis` (y by default). Its distances below and above each value come from `value.lower` and `value.upper`:
|
|
26
|
+
|
|
27
|
+
- **data_column**, the default, takes them from the rows each point stands for, as `value.aggregation` says: their standard deviation by default, or their standard error, confidence interval and so on. The series must then be aggregated, so each point stands for several rows.
|
|
28
|
+
- **A number** is the same distance for every point.
|
|
29
|
+
- **A column** gives each point its own, with `value.aggregation.function: None` to use the column's values as they are.
|
|
30
|
+
|
|
31
|
+
The mean tip on each day, with the 95 % confidence interval of each mean:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
--8<-- "docs/examples/tips_side_by_side.yaml"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
{ width="480" }
|
|
38
|
+
|
|
39
|
+
When the data already holds the spread, the error bars read it from its column:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
--8<-- "docs/examples/assay_summary.yaml"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
{ width="480" }
|
|
46
|
+
|
|
47
|
+
## Notes
|
|
48
|
+
|
|
49
|
+
A `note` layer writes a block of text in or around the plot. Its `text` is written in label markup, and a line break starts a new line. `position: auto` puts it at the first clear place inside the plot area; `inside: false` puts it outside, at the `position` given.
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
--8<-- "docs/examples/dose_response.yaml"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
{ width="480" }
|
|
56
|
+
|
|
57
|
+
## Views
|
|
58
|
+
|
|
59
|
+
A `choice` layer draws nothing on the graph. It lists views, and the graph's HTML page gets a control that switches between them. Each view is a set of the GraphSpec's parameters and their values, under the name the control shows, such as another column for a series and its axis title; `{}` changes nothing. ForgeGraph draws every view ahead of time, so the page needs no server. A png, pdf or svg file shows the first view. Every view has the same figure size and plot box, so the graph stays put as the views switch.
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
--8<-- "docs/examples/penguin_measures.yaml"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
[Open its HTML page](../pages/penguin_measures.html) to choose the measurement.
|
|
66
|
+
|
|
67
|
+
- **control** shows the views' names as a `dropdown`, or as `radio` buttons, and **label** is the text before it.
|
|
68
|
+
- **position** puts the control to the figure's `right` (the default), with the label above it, or at its `top` or `bottom`, with the label before it. On a narrow window, the right side moves below the figure.
|
|
69
|
+
- A view can't change the data, the specifications, output or provenance. Each view is checked as the GraphSpec it makes, so a view can set a parameter only where the GraphSpec could.
|
|
70
|
+
- Two choice layers, such as one for each axis, draw every combination of their views: four views each make 16 images. The page's size, and the time it takes to draw, grow with the number of images. Two choice layers can't set the same parameter.
|
|
71
|
+
- In a layout, choice layers of the same name in several tiles share one control, which switches every tile that has it. Their views need the same names, in the same order, and the same position.
|
|
72
|
+
|
|
73
|
+
## Toggles
|
|
74
|
+
|
|
75
|
+
A `toggle` layer adds a checkbox to the graph's HTML page for each of its `items`, which shows the item when it's checked: `series` for every series, `layers` for every layer, or series and layers by name. `hidden` lists those hidden when the page opens, and png, pdf and svg files leave them out too.
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
--8<-- "docs/examples/passenger_toggles.yaml"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
[Open its HTML page](../pages/passenger_toggles.html) to show July's mean, or hide a month.
|
|
82
|
+
|
|
83
|
+
- **label** is the text before the checkboxes, and **position** puts them to the figure's `right`, one under another, or in a row at its `top` or `bottom`.
|
|
84
|
+
- A series named in a key gets its checkbox in the key, before its sample, on the page only: png, pdf and svg files are drawn without the room for it.
|
|
85
|
+
- The graph is drawn once, with everything shown, so the axes don't change when an item is hidden, and the key keeps its entries.
|
|
86
|
+
- A hidden series loses its lines, markers, bars, error bars, value labels, direct label and readouts. A hidden layer loses its lines, fill and label.
|
|
87
|
+
- The page cuts the figure into images laid over each other, in the order the figure draws them, so it grows with the number of items. With choice layers, each view has its own.
|
|
88
|
+
- A GraphSpec has at most one toggle layer. In a layout, the items of the same name in tiles with toggle layers share one checkbox, so they start hidden in every tile or in none, and the toggle layers share one list, so they need the same position.
|
|
89
|
+
|
|
90
|
+
## The layers' look
|
|
91
|
+
|
|
92
|
+
Each layer's lines, labels, fill and text take their look from the theme's `layer` category: a choice or toggle layer's text from `layer.choice` and `layer.toggle`. A layer may set the parts its theme marks `!var`, such as `line_1.line.style: None` above, which draws a band without its edges.
|
|
@@ -56,11 +56,13 @@ Tabs that hold tabs look like this, with a tab bar for each level on the HTML pa
|
|
|
56
56
|
|
|
57
57
|
## The HTML page
|
|
58
58
|
|
|
59
|
-
A layout's HTML page, or a GraphSpec's, shows each figure as an image that shrinks to fit a narrow window. On a layout of several tabs, the tab names sit above the figures, in `tab_bar.label`'s look, with `tab_bar.line` under them; by default, they follow the first tile's theme. The tabs work where the page's scripts don't run. Where they run, each tab also has its own link, such as `#by-instrument`.
|
|
59
|
+
A layout's HTML page, or a GraphSpec's, shows each figure as an image that shrinks to fit a narrow window. On a layout of several tabs, the tab names sit above the figures, in `tab_bar.label`'s look, with `tab_bar.line` under them; by default, they follow the first tile's theme. The tabs work where the page's scripts don't run. Where they run, each tab also has its own link, such as `#by-instrument`. The tab names stay at the top of the window as the page scrolls, and switching tabs leaves the page where it is, so the same tile stays in view. A tile's [choice](layers.md#views) and [toggle](layers.md#toggles) layers add their controls under the tab names, and a control shows only on the tabs that use it.
|
|
60
60
|
|
|
61
61
|
**Readouts.** Pointing at a data point on the page, or tapping it, shows its values in a box above it, with a ring around the point:
|
|
62
62
|
|
|
63
63
|
- each axis's title and the point's value, with its error bar and the error bar's aggregation where it has one, as in `8.0 ± 0.4 (95%CI)`;
|
|
64
|
-
- then the series' color, marker shape and line style, each where it varies, as the key's title and the point's group
|
|
64
|
+
- then the series' color, marker shape and line style, each where it varies, as the key's title and the point's group;
|
|
65
|
+
- then, with more than one series, the series' name;
|
|
66
|
+
- then each column the series is split by, with the point's value. To name each point of a scatter, split the series by the column that holds its name, as in `split: measurement_id`.
|
|
65
67
|
|
|
66
|
-
Markers, a line's points and bars respond; empty space, reference lines and notes don't. A number with an error bar is rounded to the error's last digit; one without has a decimal more than the tick labels. The page carries each figure's points and the font the readouts are written in, so it's larger than the image alone.
|
|
68
|
+
Markers, a line's points and bars respond; empty space, reference lines and notes don't. A number with an error bar is rounded to the error's last digit; one without has a decimal more than the tick labels, except on an integer base axis, whose values are whole. The page carries each figure's points and the font the readouts are written in, so it's larger than the image alone.
|
|
@@ -4,10 +4,10 @@ A **schedule** re-renders GraphSpecs and layouts on a cadence, so a dashboard ke
|
|
|
4
4
|
|
|
5
5
|
## A schedule file
|
|
6
6
|
|
|
7
|
-
This one,
|
|
7
|
+
This one, which the agent skill also uses as its example, renders a layout every weekday at 06:00:
|
|
8
8
|
|
|
9
9
|
```yaml
|
|
10
|
-
--8<-- "
|
|
10
|
+
--8<-- "docs/examples/cells.schedule.yaml"
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
- **targets.files** are the GraphSpec and layout files rendered on each run, as paths from the schedule's folder. `targets.output_folder` saves their outputs elsewhere; by default, each is saved beside its file.
|
|
@@ -20,7 +20,7 @@ A schedule usually extends the built-in pack's `schedule`, or a pack's own, such
|
|
|
20
20
|
## Running it
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
forgegraph job run
|
|
23
|
+
forgegraph job run cells.schedule.yaml
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
`job run` runs the schedule once: it renders every target, writes the status file, and runs on_failure or on_success. A target that fails is recorded, and the others still render; the command exits with 1 if any failed.
|
|
@@ -28,7 +28,7 @@ forgegraph job run figure.schedule.yaml
|
|
|
28
28
|
ForgeGraph doesn't schedule the command itself. Whatever schedules commands where you work runs it at the schedule's times: cron, launchd, systemd, Task Scheduler, a GitHub Actions workflow, or an agent's scheduled task. For the schedule above, a cron line is:
|
|
29
29
|
|
|
30
30
|
```text
|
|
31
|
-
0 6 * * 1-5 forgegraph job run /path/to/
|
|
31
|
+
0 6 * * 1-5 forgegraph job run /path/to/cells.schedule.yaml
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Each run renders the data files as they are; keeping them current is up to you. On macOS, a background job that writes into a cloud-synced folder needs Full Disk Access.
|
|
@@ -20,7 +20,7 @@ Each series chooses its marks: `line.show`, `marker.show` and `bar.show`. By def
|
|
|
20
20
|
|
|
21
21
|
- **Lines** join the points in order of x, or in the order of the rows with `line.connect_order: data`. `line.interpolate` draws them straight, in steps, or as a smooth curve.
|
|
22
22
|
- **Missing values:** with `line.missing_values: drop`, a line joins across a row missing its x or y; with `gap`, the line breaks there. Either way, the lint counts the rows left out.
|
|
23
|
-
- **Markers** take the theme's shapes and fills, and `marker.size` sets their size.
|
|
23
|
+
- **Markers** take the theme's shapes and fills, and `marker.size` sets their size. `marker.shape: grid_cell` instead fills the grid the points lie on, which makes a heat map: see the [gallery](../gallery.md#a-heat-map).
|
|
24
24
|
- **Bars** stand on the x-axis, from 0, or from 1 on a log axis, and `bar.width` sets how much of the space between neighboring bars they fill.
|
|
25
25
|
|
|
26
26
|
The durability test draws lines without markers:
|
|
@@ -41,13 +41,13 @@ A series' rows can be split into groups by a column. Each of `color`, `line.styl
|
|
|
41
41
|
|
|
42
42
|
{ width="480" }
|
|
43
43
|
|
|
44
|
-
- **split** specifies how rows should be grouped for aggregation or line paths. This can be used to, for example, prevent averaging of data from replicates or draw independent lines for multiple runs under the same conditions.
|
|
44
|
+
- **split** specifies how rows should be grouped for aggregation or line paths. This can be used to, for example, prevent averaging of data from replicates or draw independent lines for multiple runs under the same conditions. On an HTML page, a point's readout shows its value of each column it's split by.
|
|
45
45
|
- **order** puts the groups in sorted order, or with `data`, in the order they first appear.
|
|
46
46
|
- **A numeric color column** draws on a color scale, with a color bar beside the plot. `color_scale: categorical` gives each number a palette color instead.
|
|
47
47
|
|
|
48
48
|
## Combining rows
|
|
49
49
|
|
|
50
|
-
`aggregation` combines the rows at each x into one point: their mean, median, sum, minimum, maximum, a percentile, standard deviation, standard error, or half the 95 % confidence interval of the mean (`ci`). `multiplier` scales the result, and `percentile` sets which percentile.
|
|
50
|
+
`aggregation` combines the rows at each x into one point: their mean, median, sum, minimum, maximum, a percentile, standard deviation, standard error, or half the 95 % confidence interval of the mean (`ci`). `multiplier` scales the result, and `percentile` sets which percentile. For positive values that vary by a factor, such as ratios or concentrations, `geom_mean` is the geometric mean, worked on the values' logs. `geom_stddev` and `geom_ci` are the geometric standard deviation and the 95 % confidence interval of the geometric mean: as a reference line's offset or an error bar, they multiply and divide, so an error bar's two sides differ.
|
|
51
51
|
|
|
52
52
|
```yaml
|
|
53
53
|
aggregation:
|
|
@@ -85,7 +85,7 @@ A categorical axis keeps the order of its categories in the data, or sorts them
|
|
|
85
85
|
`legend.method` chooses how a graph names its series, from the methods its theme allows:
|
|
86
86
|
|
|
87
87
|
- **direct:** each name beside its own series, touching no line, marker or other name.
|
|
88
|
-
- **key:** a key at the first of `legend.key.positions` that covers no data. With `legend.key.inside: false`, the key is outside the plot area.
|
|
88
|
+
- **key:** a key at the first of `legend.key.positions` that covers no data. If there's none, a second key goes under or beside the first, and otherwise the y-axis is extended by up to `axis.max_extension` to make room. With `legend.key.inside: false`, the key is outside the plot area.
|
|
89
89
|
- **none:** no names, where the theme allows it. The built-in theme doesn't.
|
|
90
90
|
- **auto**, the default, tries the theme's methods in order and uses the first that fits.
|
|
91
91
|
|
|
@@ -10,7 +10,7 @@ Every render lints the graph it drew and lists any issues, each under the name o
|
|
|
10
10
|
|
|
11
11
|
Two texts' letters overlap, such as neighboring tick labels or a title and a key.
|
|
12
12
|
|
|
13
|
-
Make room: fewer ticks (`tick.algorithm: manual` with a larger `tick.step`), a shorter label or tick label format, a wider format (`figure.width`), or rotated x tick labels, where the theme lets a GraphSpec set `axis.tick.label.x_rotation`.
|
|
13
|
+
Make room: fewer ticks (`tick.algorithm: manual` with a larger `tick.step`), no tick labels at all (`tick.algorithm: none`, where readers identify a point from its readout on an HTML page), a shorter label or tick label format, a wider format (`figure.width`), or rotated x tick labels, where the theme lets a GraphSpec set `axis.tick.label.x_rotation`.
|
|
14
14
|
|
|
15
15
|
### clipped-text
|
|
16
16
|
|
|
@@ -22,7 +22,7 @@ Shorten the text, place it inside the plot, or widen the format.
|
|
|
22
22
|
|
|
23
23
|
A key covers a line or marker.
|
|
24
24
|
|
|
25
|
-
List other positions in `legend.key.positions`, put the key outside the plot with `legend.key.inside: false`, or name the series directly with `legend.method: direct`.
|
|
25
|
+
The error says what's in the way at each position. List other positions in `legend.key.positions`, let the axis extend further with a larger `axis.max_extension`, move a reference line's label by leaving its `position` at `auto`, put the key outside the plot with `legend.key.inside: false`, or name the series directly with `legend.method: direct`.
|
|
26
26
|
|
|
27
27
|
### too-many-groups
|
|
28
28
|
|
|
@@ -38,7 +38,7 @@ Use a linear scale, or leave those values out.
|
|
|
38
38
|
|
|
39
39
|
### outside-limits
|
|
40
40
|
|
|
41
|
-
Points lie beyond an axis's fixed `min` or `max`, so they aren't drawn.
|
|
41
|
+
Points, or a reference line or part of a band, lie beyond an axis's fixed `min` or `max`, so they aren't drawn.
|
|
42
42
|
|
|
43
43
|
Widen the limits, or set them to None so the axis fits the data.
|
|
44
44
|
|
|
@@ -116,6 +116,14 @@ titel: unknown category; did you mean 'title'?
|
|
|
116
116
|
|
|
117
117
|
A misspelled or misplaced parameter, with the nearest one ForgeGraph knows. The [specifications](../reference/specifications/index.md) list every parameter in its place.
|
|
118
118
|
|
|
119
|
+
### A title too long for the figure
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
text.title: too long for the figure: the title is 631 pt wide, and the figure 419 pt; ...
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Shorten the title, put line breaks in it, or let a theme wrap it: `title.max_wrap` is how many more lines a title may take. It's 0, no wrapping, in the built-in theme.
|
|
126
|
+
|
|
119
127
|
### No way to name the series
|
|
120
128
|
|
|
121
129
|
```text
|
|
@@ -11,7 +11,6 @@ baseline: forgegraph_default/graphspec_example *# \[graphspec
|
|
|
11
11
|
baselines: *# Generic scenarios, each the baseline with one or more changes, numbered in the order they're first used. Every parameter gets one card, chosen by a rule: the first candidate value that changes the drawing, on the baseline or on the first of these scenarios where it does. The page shows the cards of the variable parameters. If there are no scenarios, this is None.*\
|
|
12
12
|
key_shown: {legend.method: key} *# \[parameters and their values, or non-standard\]; Series named in a key, so the key's parameters act.*\
|
|
13
13
|
colored_by_temperature: {series.color: "Temperature (°C)"} *# \[parameters and their values, or non-standard\]; A numeric color column, so a color bar is drawn.*\
|
|
14
|
-
colored_by_run: {series.color: Run} *# \[parameters and their values, or non-standard\]; Colored by run, a column of numbers, so auto draws a color scale.*\
|
|
15
14
|
temperatures: *# \[parameters and their values, or non-standard\]; Each cell's peak power density at each temperature it ran at.*\
|
|
16
15
|
axis.x.data.column: "Temperature (°C)"\
|
|
17
16
|
series: {"Power Density (mW/cm²)": {color: Cell, split: None, aggregation: {function: max}}}\
|
|
@@ -52,4 +51,5 @@ baselines: *# Generic scenarios, each the baseline with one o
|
|
|
52
51
|
axis.y.data.column: Cell\
|
|
53
52
|
axis.x.data.column: None\
|
|
54
53
|
series: {"Temperature (°C)": {color: series, split: None, aggregation: {function: max}, line: {show: false}}}\
|
|
55
|
-
dated: {data.file: dated.parquet, axis.x.data.column: Date} *# \[parameters and their values, or non-standard\]; Daily dates on x
|
|
54
|
+
dated: {data.file: dated.parquet, axis.x.data.column: Date} *# \[parameters and their values, or non-standard\]; Daily dates on x.*\
|
|
55
|
+
temperature_key_outside: {series.color: "Temperature (°C)", legend.key.inside: false} *# \[parameters and their values, or non-standard\]; A numeric color column with any key outside the plot area, so a key of each temperature fits.*
|