gtviz 0.3.3__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.
- gtviz-0.3.3/.github/workflows/bless_basslines.yml +23 -0
- gtviz-0.3.3/.github/workflows/ci.yml +148 -0
- gtviz-0.3.3/.github/workflows/docs.yml +25 -0
- gtviz-0.3.3/.github/workflows/pipeline.yml +89 -0
- gtviz-0.3.3/.github/workflows/release.yml +62 -0
- gtviz-0.3.3/.gitignore +11 -0
- gtviz-0.3.3/.readthedocs.yaml +20 -0
- gtviz-0.3.3/CHANGELOG.md +56 -0
- gtviz-0.3.3/LICENSE +21 -0
- gtviz-0.3.3/PKG-INFO +94 -0
- gtviz-0.3.3/README.md +54 -0
- gtviz-0.3.3/docs/api/charts.md +55 -0
- gtviz-0.3.3/docs/api/io.md +6 -0
- gtviz-0.3.3/docs/api/maps.md +9 -0
- gtviz-0.3.3/docs/api/pipeline.md +18 -0
- gtviz-0.3.3/docs/api/stats.md +24 -0
- gtviz-0.3.3/docs/api/tables.md +9 -0
- gtviz-0.3.3/docs/api/theme_config.md +9 -0
- gtviz-0.3.3/docs/conf.py +43 -0
- gtviz-0.3.3/docs/gallery.md +86 -0
- gtviz-0.3.3/docs/guides/charts_tour.md +113 -0
- gtviz-0.3.3/docs/guides/ci_images.md +70 -0
- gtviz-0.3.3/docs/guides/design_defaults.md +61 -0
- gtviz-0.3.3/docs/guides/exporting.md +69 -0
- gtviz-0.3.3/docs/guides/getting_started.md +113 -0
- gtviz-0.3.3/docs/guides/maps.md +52 -0
- gtviz-0.3.3/docs/guides/migration.md +86 -0
- gtviz-0.3.3/docs/guides/pipeline.md +106 -0
- gtviz-0.3.3/docs/guides/publishing.md +76 -0
- gtviz-0.3.3/docs/guides/tables.md +93 -0
- gtviz-0.3.3/docs/guides/theming.md +48 -0
- gtviz-0.3.3/docs/index.md +68 -0
- gtviz-0.3.3/examples/generate_gallery.py +165 -0
- gtviz-0.3.3/pyproject.toml +80 -0
- gtviz-0.3.3/src/gtviz/__init__.py +53 -0
- gtviz-0.3.3/src/gtviz/_mpl.py +24 -0
- gtviz-0.3.3/src/gtviz/charts/__init__.py +24 -0
- gtviz-0.3.3/src/gtviz/charts/bars.py +98 -0
- gtviz-0.3.3/src/gtviz/charts/donut.py +46 -0
- gtviz-0.3.3/src/gtviz/charts/dots.py +257 -0
- gtviz-0.3.3/src/gtviz/charts/funnel.py +70 -0
- gtviz-0.3.3/src/gtviz/charts/heatmap.py +68 -0
- gtviz-0.3.3/src/gtviz/charts/likert.py +99 -0
- gtviz-0.3.3/src/gtviz/charts/lines.py +187 -0
- gtviz-0.3.3/src/gtviz/charts/venn.py +159 -0
- gtviz-0.3.3/src/gtviz/charts/waffle.py +46 -0
- gtviz-0.3.3/src/gtviz/config.py +50 -0
- gtviz-0.3.3/src/gtviz/io.py +270 -0
- gtviz-0.3.3/src/gtviz/maps/__init__.py +6 -0
- gtviz-0.3.3/src/gtviz/maps/choropleth.py +106 -0
- gtviz-0.3.3/src/gtviz/maps/scalebar.py +77 -0
- gtviz-0.3.3/src/gtviz/pipeline/__init__.py +86 -0
- gtviz-0.3.3/src/gtviz/pipeline/base.py +114 -0
- gtviz-0.3.3/src/gtviz/pipeline/io.py +102 -0
- gtviz-0.3.3/src/gtviz/pipeline/steps.py +401 -0
- gtviz-0.3.3/src/gtviz/stats/__init__.py +16 -0
- gtviz-0.3.3/src/gtviz/stats/aggs.py +59 -0
- gtviz-0.3.3/src/gtviz/stats/change.py +72 -0
- gtviz-0.3.3/src/gtviz/stats/crosstabs.py +75 -0
- gtviz-0.3.3/src/gtviz/stats/likert.py +47 -0
- gtviz-0.3.3/src/gtviz/stats/summaries.py +81 -0
- gtviz-0.3.3/src/gtviz/stats/timeutils.py +60 -0
- gtviz-0.3.3/src/gtviz/tables/__init__.py +6 -0
- gtviz-0.3.3/src/gtviz/tables/compare.py +106 -0
- gtviz-0.3.3/src/gtviz/tables/html.py +202 -0
- gtviz-0.3.3/src/gtviz/theme.py +91 -0
- gtviz-0.3.3/tests/conftest.py +66 -0
- gtviz-0.3.3/tests/test_charts.py +145 -0
- gtviz-0.3.3/tests/test_io.py +49 -0
- gtviz-0.3.3/tests/test_maps.py +29 -0
- gtviz-0.3.3/tests/test_pipeline.py +199 -0
- gtviz-0.3.3/tests/test_stats.py +72 -0
- gtviz-0.3.3/tests/test_tables.py +60 -0
- gtviz-0.3.3/tools/compare_images.py +93 -0
- gtviz-0.3.3/tools/generate_report.py +281 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Bless baselines
|
|
2
|
+
on: workflow_dispatch # manual button in the Actions tab
|
|
3
|
+
|
|
4
|
+
permissions:
|
|
5
|
+
contents: write
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
bless:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: actions/setup-python@v5
|
|
13
|
+
with: { python-version: "3.12" }
|
|
14
|
+
- run: pip install -e .[dev]
|
|
15
|
+
- run: pytest -q
|
|
16
|
+
- run: python tools/compare_images.py --update
|
|
17
|
+
- name: Commit refreshed baselines
|
|
18
|
+
run: |
|
|
19
|
+
git config user.name "github-actions[bot]"
|
|
20
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
21
|
+
git add tests/baseline
|
|
22
|
+
git commit -m "Re-bless baselines on CI runner" || echo "no changes"
|
|
23
|
+
git push
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with: { python-version: "3.12" }
|
|
15
|
+
- run: pip install ruff
|
|
16
|
+
- name: Ruff (human-readable, fails the job)
|
|
17
|
+
run: ruff check src tests tools examples
|
|
18
|
+
- name: Ruff (JSON for the report; never fails)
|
|
19
|
+
if: always()
|
|
20
|
+
run: ruff check src tests tools examples --output-format=json > ruff.json || true
|
|
21
|
+
- name: Upload lint report input
|
|
22
|
+
if: always()
|
|
23
|
+
uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: report-lint
|
|
26
|
+
path: ruff.json
|
|
27
|
+
retention-days: 30
|
|
28
|
+
|
|
29
|
+
test:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: ${{ matrix.python-version }}
|
|
40
|
+
- run: pip install -e .[dev]
|
|
41
|
+
- name: Run tests (JUnit + coverage XML for the report)
|
|
42
|
+
run: >
|
|
43
|
+
pytest
|
|
44
|
+
--junitxml=junit-${{ matrix.python-version }}.xml
|
|
45
|
+
--cov=gtviz --cov-report=xml:coverage-${{ matrix.python-version }}.xml
|
|
46
|
+
--cov-report=term-missing
|
|
47
|
+
- name: Upload test + coverage report inputs
|
|
48
|
+
if: always()
|
|
49
|
+
uses: actions/upload-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
name: report-test-${{ matrix.python-version }}
|
|
52
|
+
path: |
|
|
53
|
+
junit-${{ matrix.python-version }}.xml
|
|
54
|
+
coverage-${{ matrix.python-version }}.xml
|
|
55
|
+
retention-days: 30
|
|
56
|
+
- name: Upload rendered chart images for HUMAN review
|
|
57
|
+
if: matrix.python-version == '3.12'
|
|
58
|
+
uses: actions/upload-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: test-images
|
|
61
|
+
path: tests/output/
|
|
62
|
+
retention-days: 30
|
|
63
|
+
- name: Upload coverage to Codecov
|
|
64
|
+
if: matrix.python-version == '3.12'
|
|
65
|
+
uses: codecov/codecov-action@v4
|
|
66
|
+
with:
|
|
67
|
+
files: coverage-3.12.xml
|
|
68
|
+
fail_ci_if_error: false
|
|
69
|
+
env:
|
|
70
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
71
|
+
|
|
72
|
+
visual-regression:
|
|
73
|
+
# HEADLESS image check: compares freshly rendered charts against
|
|
74
|
+
# committed baselines in tests/baseline/. To accept intentional visual
|
|
75
|
+
# changes, re-bless via the "Bless baselines" workflow.
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
needs: test
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
- uses: actions/setup-python@v5
|
|
81
|
+
with: { python-version: "3.12" }
|
|
82
|
+
- run: pip install -e .[dev]
|
|
83
|
+
- run: pytest -q
|
|
84
|
+
- name: Compare images against baselines
|
|
85
|
+
run: python tools/compare_images.py --threshold 3.0 | tee visual.txt
|
|
86
|
+
- name: Upload visual report input
|
|
87
|
+
if: always()
|
|
88
|
+
uses: actions/upload-artifact@v4
|
|
89
|
+
with:
|
|
90
|
+
name: report-visual
|
|
91
|
+
path: visual.txt
|
|
92
|
+
retention-days: 30
|
|
93
|
+
- name: Upload diff images on failure
|
|
94
|
+
if: failure()
|
|
95
|
+
uses: actions/upload-artifact@v4
|
|
96
|
+
with:
|
|
97
|
+
name: image-diffs
|
|
98
|
+
path: tests/output/*_diff.png
|
|
99
|
+
|
|
100
|
+
gallery:
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
needs: test
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/checkout@v4
|
|
105
|
+
- uses: actions/setup-python@v5
|
|
106
|
+
with: { python-version: "3.12" }
|
|
107
|
+
- run: pip install -e .[dev,waffle]
|
|
108
|
+
- name: Generate full gallery (PNG + SVG + HTML report + PDF)
|
|
109
|
+
run: python examples/generate_gallery.py
|
|
110
|
+
- uses: actions/upload-artifact@v4
|
|
111
|
+
with:
|
|
112
|
+
name: gallery
|
|
113
|
+
path: docs/_static/gallery/
|
|
114
|
+
|
|
115
|
+
report:
|
|
116
|
+
# Aggregates every job's machine-readable output into one Markdown report.
|
|
117
|
+
# Runs last, always (even if tests failed), so you always get a summary.
|
|
118
|
+
runs-on: ubuntu-latest
|
|
119
|
+
needs: [lint, test, visual-regression]
|
|
120
|
+
if: always()
|
|
121
|
+
steps:
|
|
122
|
+
- uses: actions/checkout@v4
|
|
123
|
+
- uses: actions/setup-python@v5
|
|
124
|
+
with: { python-version: "3.12" }
|
|
125
|
+
- name: Download all report inputs
|
|
126
|
+
uses: actions/download-artifact@v4
|
|
127
|
+
with:
|
|
128
|
+
path: report-inputs
|
|
129
|
+
pattern: report-*
|
|
130
|
+
merge-multiple: true
|
|
131
|
+
- name: Generate quality report
|
|
132
|
+
run: >
|
|
133
|
+
python tools/generate_report.py
|
|
134
|
+
--junit 'report-inputs/junit-*.xml'
|
|
135
|
+
--coverage report-inputs/coverage-3.12.xml
|
|
136
|
+
--ruff report-inputs/ruff.json
|
|
137
|
+
--visual report-inputs/visual.txt
|
|
138
|
+
--out quality-report.md
|
|
139
|
+
- name: Publish report to the run summary
|
|
140
|
+
if: always()
|
|
141
|
+
run: cat quality-report.md >> "$GITHUB_STEP_SUMMARY"
|
|
142
|
+
- name: Upload report as artifact
|
|
143
|
+
if: always()
|
|
144
|
+
uses: actions/upload-artifact@v4
|
|
145
|
+
with:
|
|
146
|
+
name: quality-report
|
|
147
|
+
path: quality-report.md
|
|
148
|
+
retention-days: 90
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-docs:
|
|
10
|
+
# Read the Docs builds the published site; this job catches Sphinx
|
|
11
|
+
# errors in PRs before they land.
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with: { python-version: "3.12" }
|
|
17
|
+
- run: pip install -e .[docs]
|
|
18
|
+
- name: Regenerate gallery images for docs
|
|
19
|
+
run: python examples/generate_gallery.py
|
|
20
|
+
- name: Build Sphinx docs (warnings are errors)
|
|
21
|
+
run: sphinx-build -W -b html docs docs/_build/html
|
|
22
|
+
- uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: docs-html
|
|
25
|
+
path: docs/_build/html
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
name: Pipeline
|
|
2
|
+
|
|
3
|
+
# Dedicated CI for the dataset-specific processing pipeline
|
|
4
|
+
# (gtviz.pipeline). Runs only when pipeline code changes, on its own cadence
|
|
5
|
+
# from the viz CI — pipeline steps encode survey-version logic that changes
|
|
6
|
+
# with each questionnaire wave, not with chart code.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths:
|
|
12
|
+
- "src/gtviz/pipeline/**"
|
|
13
|
+
- "tests/test_pipeline.py"
|
|
14
|
+
- ".github/workflows/pipeline.yml"
|
|
15
|
+
pull_request:
|
|
16
|
+
paths:
|
|
17
|
+
- "src/gtviz/pipeline/**"
|
|
18
|
+
- "tests/test_pipeline.py"
|
|
19
|
+
- ".github/workflows/pipeline.yml"
|
|
20
|
+
schedule:
|
|
21
|
+
# weekly regression run against latest deps (survey pipeline must not
|
|
22
|
+
# silently break between quarterly report cycles)
|
|
23
|
+
- cron: "0 6 * * 1"
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
pipeline-tests:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
|
|
29
|
+
strategy:
|
|
30
|
+
matrix:
|
|
31
|
+
python-version: ["3.10", "3.12"]
|
|
32
|
+
pandas: ["pandas>=2.0,<3", "pandas>=3"]
|
|
33
|
+
exclude:
|
|
34
|
+
- python-version: "3.10"
|
|
35
|
+
pandas: "pandas>=3"
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
- uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: ${{ matrix.python-version }}
|
|
41
|
+
- run: pip install -e .[dev] "${{ matrix.pandas }}" scikit-learn openpyxl
|
|
42
|
+
- name: Pipeline unit tests
|
|
43
|
+
run: pytest tests/test_pipeline.py -v --cov=gtviz.pipeline --cov-report=term-missing
|
|
44
|
+
- name: sklearn interoperability check
|
|
45
|
+
run: |
|
|
46
|
+
python - << 'PY'
|
|
47
|
+
import pandas as pd, numpy as np
|
|
48
|
+
from sklearn.pipeline import Pipeline as SkPipeline
|
|
49
|
+
from gtviz.pipeline import ScoreBelonging, CivicQuartile
|
|
50
|
+
rng = np.random.default_rng(0)
|
|
51
|
+
df = pd.DataFrame({q: rng.integers(0, 4, 50)
|
|
52
|
+
for q in ["Q31_r6_scale","Q31_r7_scale","Q31_r8_scale","Q31_r9_scale"]})
|
|
53
|
+
out = SkPipeline([("b", ScoreBelonging(answer_map=None)),
|
|
54
|
+
("q", CivicQuartile(source_col="belonging", out_col="bq"))]).fit_transform(df)
|
|
55
|
+
assert "bq" in out.columns
|
|
56
|
+
print("sklearn interop OK")
|
|
57
|
+
PY
|
|
58
|
+
|
|
59
|
+
batch-smoke:
|
|
60
|
+
# Headless batch run of the full default pipeline over synthetic data —
|
|
61
|
+
# proves `gtviz.pipeline.process()` end-to-end without production access.
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
needs: pipeline-tests
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
- uses: actions/setup-python@v5
|
|
67
|
+
with: { python-version: "3.12" }
|
|
68
|
+
- run: pip install -e .[dev]
|
|
69
|
+
- name: Full default_pipeline batch over synthetic frame
|
|
70
|
+
run: |
|
|
71
|
+
python - << 'PY'
|
|
72
|
+
import sys; sys.path.insert(0, "tests")
|
|
73
|
+
import pandas as pd
|
|
74
|
+
from test_pipeline import gp_frame, typology_ref, pew_ref # fixture fns
|
|
75
|
+
import gtviz.pipeline as pl
|
|
76
|
+
import numpy as np
|
|
77
|
+
# rebuild fixture data without pytest
|
|
78
|
+
import test_pipeline as tp
|
|
79
|
+
df = tp.gp_frame.__wrapped__()
|
|
80
|
+
out = pl.process(df,
|
|
81
|
+
typology=tp.typology_ref.__wrapped__(),
|
|
82
|
+
pew_decoder=tp.pew_ref.__wrapped__(),
|
|
83
|
+
verbose=True)
|
|
84
|
+
expected = {"activism_any","county_type","belonging","civic_intent",
|
|
85
|
+
"best_pew","civic_quartile"}
|
|
86
|
+
missing = expected - set(out.columns)
|
|
87
|
+
assert not missing, f"missing: {missing}"
|
|
88
|
+
print(f"batch OK: {len(out)} rows, {len(out.columns)} columns")
|
|
89
|
+
PY
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
target:
|
|
9
|
+
description: "Publish target"
|
|
10
|
+
type: choice
|
|
11
|
+
options: [testpypi, pypi]
|
|
12
|
+
default: testpypi
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with: { python-version: "3.12" }
|
|
21
|
+
- run: pip install build twine
|
|
22
|
+
- name: Verify tag matches package version
|
|
23
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
24
|
+
run: |
|
|
25
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
26
|
+
PKG=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
27
|
+
echo "tag=$TAG package=$PKG"
|
|
28
|
+
test "$TAG" = "$PKG" || { echo "::error::Tag v$TAG != package version $PKG"; exit 1; }
|
|
29
|
+
- run: python -m build
|
|
30
|
+
- run: twine check dist/*
|
|
31
|
+
- uses: actions/upload-artifact@v4
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
testpypi:
|
|
37
|
+
# Manual dry-run publish to Test PyPI (workflow_dispatch, target=testpypi).
|
|
38
|
+
needs: build
|
|
39
|
+
if: github.event_name == 'workflow_dispatch' && inputs.target == 'testpypi'
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment: testpypi
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/download-artifact@v4
|
|
46
|
+
with: { name: dist, path: dist }
|
|
47
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
48
|
+
with:
|
|
49
|
+
repository-url: https://test.pypi.org/legacy/
|
|
50
|
+
|
|
51
|
+
pypi:
|
|
52
|
+
# Real publish: on a v* tag, or manual dispatch with target=pypi.
|
|
53
|
+
needs: build
|
|
54
|
+
if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.target == 'pypi')
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
environment: pypi
|
|
57
|
+
permissions:
|
|
58
|
+
id-token: write # PyPI trusted publishing (OIDC), no API token needed
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/download-artifact@v4
|
|
61
|
+
with: { name: dist, path: dist }
|
|
62
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
gtviz-0.3.3/.gitignore
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
build:
|
|
4
|
+
os: ubuntu-24.04
|
|
5
|
+
tools:
|
|
6
|
+
python: "3.12"
|
|
7
|
+
jobs:
|
|
8
|
+
pre_build:
|
|
9
|
+
# regenerate gallery images so docs always show current output
|
|
10
|
+
- python examples/generate_gallery.py
|
|
11
|
+
|
|
12
|
+
python:
|
|
13
|
+
install:
|
|
14
|
+
- method: pip
|
|
15
|
+
path: .
|
|
16
|
+
extra_requirements: [docs]
|
|
17
|
+
|
|
18
|
+
sphinx:
|
|
19
|
+
configuration: docs/conf.py
|
|
20
|
+
fail_on_warning: false
|
gtviz-0.3.3/CHANGELOG.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.3 (2026-07-23)
|
|
4
|
+
- Fixed CI/CD and prepared for pypi
|
|
5
|
+
|
|
6
|
+
## 0.3.0 (2026-07-22)
|
|
7
|
+
|
|
8
|
+
- **Renamed package `gpviz` → `gtviz`** (imports, env var `GTVIZ_OUTPUT_DIR`,
|
|
9
|
+
docs URLs, `ax._gtviz_data`).
|
|
10
|
+
- **Brand-default restoration**: all chart styling audited line-by-line
|
|
11
|
+
against the production `gp_reports` code and ported verbatim as defaults
|
|
12
|
+
(dot marker/error/grid style, gray-first series palette, frameless
|
|
13
|
+
outside legends, no-box grouped dot plots, n= legend counts, 25-char
|
|
14
|
+
label wrapping, rolling-trend plain lines + (1,1) legend + optional gray
|
|
15
|
+
period shading, split-line palette, 4-point Likert palette + outside
|
|
16
|
+
legend + zero-width label suppression, venn 20pt/pad-30 titles, funnel
|
|
17
|
+
band geometry, donut without autopct, figure.dpi 300).
|
|
18
|
+
- `theme.use(profile, font=...)` for the brand font (Neutraface Text);
|
|
19
|
+
new palette tokens `split_series`, `likert4`, `stacked3`.
|
|
20
|
+
- New guide: *Design defaults & override policy* documenting every default,
|
|
21
|
+
its override kwarg, and the open default-vs-override decisions.
|
|
22
|
+
|
|
23
|
+
## 0.2.0 (2026-07-22)
|
|
24
|
+
|
|
25
|
+
- New `gtviz.pipeline` subpackage: sklearn-style dataset processing for the
|
|
26
|
+
GivingPulse survey. `read_pipeline()` (Delta/Spark loader with
|
|
27
|
+
year/quarter/week filters), `process()` / `default_pipeline()` batch
|
|
28
|
+
runner, and steps `AssignActivism`, `AssignCountyTypes`, `ScoreBelonging`,
|
|
29
|
+
`ScoreCivicIntent`, `AssignPew` (vectorized), `CivicQuartile`.
|
|
30
|
+
Steps implement the sklearn transformer contract (`get_params`,
|
|
31
|
+
`set_params`, `step__param` addressing, usable in `sklearn.pipeline`).
|
|
32
|
+
- Reference files (county typology, Pew decoder) are parameters accepting a
|
|
33
|
+
path or DataFrame — no hard-coded `/Volumes/...` paths.
|
|
34
|
+
- Dedicated `pipeline.yml` CI: path-filtered triggers, python x pandas
|
|
35
|
+
matrix, sklearn interop check, headless batch smoke run, weekly schedule.
|
|
36
|
+
|
|
37
|
+
## 0.1.0 (2026-07-22)
|
|
38
|
+
|
|
39
|
+
Initial public release: full refactor of the `gp_reports` visualization code.
|
|
40
|
+
|
|
41
|
+
- `charts`: dot_plot, grouped_dot_plot, trend_dot_plot, parallel_bars,
|
|
42
|
+
rolling_trend, split_line_plot, annotated_event_plot, venn,
|
|
43
|
+
venn_from_counts, weighted_heatmap, funnel, funnel_from_columns, donut,
|
|
44
|
+
likert_bars, waffle (extra).
|
|
45
|
+
- `tables`: HtmlTable (publication CSS table), compare_periods,
|
|
46
|
+
pivot_change_table.
|
|
47
|
+
- `maps`: choropleth_table (absolute/relative), scale_bar.
|
|
48
|
+
- `stats`: rolling_summary, period_change, compare_crosstab,
|
|
49
|
+
subgroup_summary, build_filter, chi_squared_matrix, normalize_likert,
|
|
50
|
+
decode_likert, named aggregators, time utilities.
|
|
51
|
+
- `io`: multi-format save (png/svg/pdf/jpg/webp/eps), HTML embedding,
|
|
52
|
+
ReportBuilder (standalone HTML + multi-page PDF).
|
|
53
|
+
- `theme`: "report" and "publication" profiles, palette tokens.
|
|
54
|
+
- CI: lint, test matrix (3.10–3.13) with image artifacts (human review),
|
|
55
|
+
baseline visual regression (headless), gallery build, docs build,
|
|
56
|
+
PyPI trusted-publishing release.
|
gtviz-0.3.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GivingPulse Analytics
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
gtviz-0.3.3/PKG-INFO
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gtviz
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Summary: Publication-quality survey data visualization: dot plots, comparison tables, venn diagrams, choropleth color tables, HTML/PDF/PNG/SVG export.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Giving-Tuesday/gtviz
|
|
6
|
+
Project-URL: Documentation, https://gtviz.readthedocs.io
|
|
7
|
+
Project-URL: Source, https://github.com/Giving-Tuesday/gtviz
|
|
8
|
+
Project-URL: Changelog, https://github.com/Giving-Tuesday/gtviz/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/Giving-Tuesday/gtviz/issues
|
|
10
|
+
Author: GivingPulse Analytics
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: matplotlib,reporting,survey,visualization
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: jinja2>=3.0
|
|
21
|
+
Requires-Dist: matplotlib-venn>=0.11
|
|
22
|
+
Requires-Dist: matplotlib>=3.7
|
|
23
|
+
Requires-Dist: numpy>=1.24
|
|
24
|
+
Requires-Dist: pandas>=2.0
|
|
25
|
+
Requires-Dist: scipy>=1.10
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pillow; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
31
|
+
Provides-Extra: docs
|
|
32
|
+
Requires-Dist: furo; extra == 'docs'
|
|
33
|
+
Requires-Dist: myst-parser; extra == 'docs'
|
|
34
|
+
Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
|
|
35
|
+
Requires-Dist: sphinx-copybutton; extra == 'docs'
|
|
36
|
+
Requires-Dist: sphinx>=7; extra == 'docs'
|
|
37
|
+
Provides-Extra: waffle
|
|
38
|
+
Requires-Dist: pywaffle>=1.1; extra == 'waffle'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# gtviz
|
|
42
|
+
|
|
43
|
+
[](https://pypi.org/project/gtviz/)
|
|
44
|
+
[](https://pypi.org/project/gtviz/)
|
|
45
|
+
[](https://github.com/Giving-Tuesday/gtviz/actions/workflows/ci.yml)
|
|
46
|
+
[](https://gtviz.readthedocs.io/en/latest/)
|
|
47
|
+
[](https://codecov.io/gh/Giving-Tuesday/gtviz)
|
|
48
|
+
[](https://github.com/astral-sh/ruff)
|
|
49
|
+
[](https://opensource.org/licenses/MIT)
|
|
50
|
+
|
|
51
|
+
Publication-quality survey data visualization, refactored from the GivingPulse
|
|
52
|
+
quarterly-report codebase into a clean, survey-agnostic library.
|
|
53
|
+
|
|
54
|
+
**Charts:** dot plots (single, grouped, trend), parallel bar panels, rolling trend
|
|
55
|
+
lines, venn diagrams (2/3 set, filtered or from pre-aggregated counts), weighted
|
|
56
|
+
heatmaps, funnels, donuts, diverging Likert bars.
|
|
57
|
+
**Tables:** publication CSS/HTML tables with zebra striping, high/low cell shading,
|
|
58
|
+
multi-index rollups; period-over-period comparison tables.
|
|
59
|
+
**Maps:** county/FIPS choropleth color tables (for SVG map filling) + scale-bar legends.
|
|
60
|
+
**Export:** PNG, SVG, PDF, standalone HTML reports (figures embedded as SVG),
|
|
61
|
+
suitable for websites or print reports.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import gtviz
|
|
65
|
+
gtviz.theme.use("report")
|
|
66
|
+
|
|
67
|
+
fig, ax = gtviz.dot_plot([62, 48, 31], ["Gave money", "Volunteered", "Gave items"],
|
|
68
|
+
error=[3, 3, 2], title="Generosity in Q2")
|
|
69
|
+
gtviz.io.save(fig, "generosity_q2", formats=("png", "svg", "pdf"))
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
pip install gtviz # core
|
|
76
|
+
pip install gtviz[waffle] # + waffle charts
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Docs
|
|
80
|
+
|
|
81
|
+
Full documentation, gallery, and migration guide from the original `gp_reports`
|
|
82
|
+
repo: https://gtviz.readthedocs.io
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
pip install -e .[dev,docs]
|
|
88
|
+
pytest # unit tests; writes chart images to tests/output/
|
|
89
|
+
python examples/generate_gallery.py # regenerate gallery images
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
CI runs lint + tests on every push and uploads rendered chart images as build
|
|
93
|
+
artifacts for **human review**; a **headless** job compares rendered images
|
|
94
|
+
against committed baselines in `tests/baseline/`. See `.github/workflows/`.
|
gtviz-0.3.3/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# gtviz
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/gtviz/)
|
|
4
|
+
[](https://pypi.org/project/gtviz/)
|
|
5
|
+
[](https://github.com/Giving-Tuesday/gtviz/actions/workflows/ci.yml)
|
|
6
|
+
[](https://gtviz.readthedocs.io/en/latest/)
|
|
7
|
+
[](https://codecov.io/gh/Giving-Tuesday/gtviz)
|
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
11
|
+
Publication-quality survey data visualization, refactored from the GivingPulse
|
|
12
|
+
quarterly-report codebase into a clean, survey-agnostic library.
|
|
13
|
+
|
|
14
|
+
**Charts:** dot plots (single, grouped, trend), parallel bar panels, rolling trend
|
|
15
|
+
lines, venn diagrams (2/3 set, filtered or from pre-aggregated counts), weighted
|
|
16
|
+
heatmaps, funnels, donuts, diverging Likert bars.
|
|
17
|
+
**Tables:** publication CSS/HTML tables with zebra striping, high/low cell shading,
|
|
18
|
+
multi-index rollups; period-over-period comparison tables.
|
|
19
|
+
**Maps:** county/FIPS choropleth color tables (for SVG map filling) + scale-bar legends.
|
|
20
|
+
**Export:** PNG, SVG, PDF, standalone HTML reports (figures embedded as SVG),
|
|
21
|
+
suitable for websites or print reports.
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
import gtviz
|
|
25
|
+
gtviz.theme.use("report")
|
|
26
|
+
|
|
27
|
+
fig, ax = gtviz.dot_plot([62, 48, 31], ["Gave money", "Volunteered", "Gave items"],
|
|
28
|
+
error=[3, 3, 2], title="Generosity in Q2")
|
|
29
|
+
gtviz.io.save(fig, "generosity_q2", formats=("png", "svg", "pdf"))
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
pip install gtviz # core
|
|
36
|
+
pip install gtviz[waffle] # + waffle charts
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Docs
|
|
40
|
+
|
|
41
|
+
Full documentation, gallery, and migration guide from the original `gp_reports`
|
|
42
|
+
repo: https://gtviz.readthedocs.io
|
|
43
|
+
|
|
44
|
+
## Development
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
pip install -e .[dev,docs]
|
|
48
|
+
pytest # unit tests; writes chart images to tests/output/
|
|
49
|
+
python examples/generate_gallery.py # regenerate gallery images
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
CI runs lint + tests on every push and uploads rendered chart images as build
|
|
53
|
+
artifacts for **human review**; a **headless** job compares rendered images
|
|
54
|
+
against committed baselines in `tests/baseline/`. See `.github/workflows/`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# gtviz.charts
|
|
2
|
+
|
|
3
|
+
All chart functions return `(fig, ax)`, accept an optional `ax=` for
|
|
4
|
+
composition, and never call `plt.show()`.
|
|
5
|
+
|
|
6
|
+
## Dot plots
|
|
7
|
+
|
|
8
|
+
```{eval-rst}
|
|
9
|
+
.. automodule:: gtviz.charts.dots
|
|
10
|
+
:members:
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Bar panels
|
|
14
|
+
|
|
15
|
+
```{eval-rst}
|
|
16
|
+
.. automodule:: gtviz.charts.bars
|
|
17
|
+
:members:
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Trend lines
|
|
21
|
+
|
|
22
|
+
```{eval-rst}
|
|
23
|
+
.. automodule:: gtviz.charts.lines
|
|
24
|
+
:members:
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Venn diagrams
|
|
28
|
+
|
|
29
|
+
```{eval-rst}
|
|
30
|
+
.. automodule:: gtviz.charts.venn
|
|
31
|
+
:members:
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Heatmaps
|
|
35
|
+
|
|
36
|
+
```{eval-rst}
|
|
37
|
+
.. automodule:: gtviz.charts.heatmap
|
|
38
|
+
:members:
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Funnel, donut, waffle, Likert
|
|
42
|
+
|
|
43
|
+
```{eval-rst}
|
|
44
|
+
.. automodule:: gtviz.charts.funnel
|
|
45
|
+
:members:
|
|
46
|
+
|
|
47
|
+
.. automodule:: gtviz.charts.donut
|
|
48
|
+
:members:
|
|
49
|
+
|
|
50
|
+
.. automodule:: gtviz.charts.likert
|
|
51
|
+
:members:
|
|
52
|
+
|
|
53
|
+
.. automodule:: gtviz.charts.waffle
|
|
54
|
+
:members:
|
|
55
|
+
```
|