{"id":50257175,"url":"https://github.com/thchilly/subselect","last_synced_at":"2026-05-27T07:03:44.551Z","repository":{"id":355439484,"uuid":"1227961196","full_name":"thchilly/subselect","owner":"thchilly","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-03T15:41:46.000Z","size":71749,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-03T17:30:28.037Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thchilly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-03T12:04:13.000Z","updated_at":"2026-05-03T15:41:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thchilly/subselect","commit_stats":null,"previous_names":["thchilly/subselect"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/thchilly/subselect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thchilly%2Fsubselect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thchilly%2Fsubselect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thchilly%2Fsubselect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thchilly%2Fsubselect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thchilly","download_url":"https://codeload.github.com/thchilly/subselect/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thchilly%2Fsubselect/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33554782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-27T07:03:42.505Z","updated_at":"2026-05-27T07:03:44.541Z","avatar_url":"https://github.com/thchilly.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# subselect\n\n`subselect` picks a small, representative subset of CMIP6 climate models for\ncountry-scale impact assessments. Given a country and a target subset size *k*,\nthe framework recommends *k* models that jointly satisfy three criteria:\n\n1. **Historical fidelity** — the subset reproduces observed climate well\n   over the country.\n2. **Future-response spread coverage** — the subset stays representative of\n   the *full* CMIP6 spread of projected end-of-century changes.\n3. **Model independence** — the subset avoids redundant models that share\n   land/ocean/atmosphere components or institutional lineage.\n\nThe methodology was first published as a Greece-only study in April 2026\n(`subselection_paper/`); this package generalises that pipeline to any\ncountry with a GADM polygon and produces the same figure set automatically.\n\n---\n\n## Installation\n\n`subselect` targets Python ≥ 3.11. The authoritative dependency pin source is\n`environment.yml`; bootstrap the conda environment and install the package\nin editable mode:\n\n```bash\nconda env create -f environment.yml\nconda activate subselect\npip install -e .\n```\n\nA pure-pip install also works inside an existing scientific-Python environment\nthat satisfies the lower bounds in `pyproject.toml`:\n\n```bash\npip install -e .\n```\n\n---\n\n## Quick start\n\n```bash\n# First country: builds the global cache (one-time, ~5–7 min) plus the\n# per-country derivations (~1–2 min). Renders the full figure set under\n# results/greece/figures/.\npython -m subselect greece\n\n# Second and subsequent countries: ~30–60 s on a warm global cache.\npython -m subselect sweden\n\n# Re-running the same country: \u003c30 s when nothing has changed.\npython -m subselect sweden\n```\n\nThe CLI also accepts:\n\n- `--global-only` — populate `cache/_global/` without rendering for any country\n- `--no-figures` — run the L1 compute pipeline only\n- `--no-bias-maps` — skip the bias-map figures (useful for fast smoke tests)\n- `--include-seasonal-bias` — render DJF/MAM/JJA/SON bias maps in addition to annual\n- `--only performance,spread,country_profile` — restrict to a figure-group subset\n- `--force {all,country,global}` — bypass the corresponding cache and recompute\n- `--output-dir \u003cpath\u003e` — write figures somewhere other than the default\n\nThe Python API matches the CLI:\n\n```python\nfrom subselect.compute import compute\nfrom subselect.render import render\n\nstate = compute(\"greece\")          # L1: build state, populate caches\npaths = render(state)              # L2: write figure set\n```\n\n---\n\n## How it works\n\nThe pipeline is a clean two-layer architecture with a two-scope cache:\n\n- **L1 — `subselect.compute.compute(country)`** produces every artefact\n  needed for the figure set (HPS metrics, σ\\_obs, monthly climatologies,\n  change signals, annual time series, warming-level crossings, future\n  anomalies, country-profile signals, bias-map fields). Returns a typed\n  `SubselectState`.\n- **L2 — `subselect.render.render(state)`** consumes a `SubselectState`\n  and writes the figure set under `results/\u003ccountry\u003e/figures/{performance,\n  spread, country_profile}/`.\n- **Cache — `cache/_global/`** holds country-independent artefacts (per-(model,\n  variable) climatologies and annual fields, native-grid σ maps), built once\n  and reused across countries; **`cache/\u003ccountry\u003e/`** holds country-mean\n  reductions and country-specific tables.\n\nAdding a new country requires only that the country has a row in\n`Data/country_codes/country_codes.json` and a polygon in the GADM 4.1\nGeoPackage at `Data/shapefiles/gadm/gadm_410-levels.gpkg`. The first call\npopulates the global cache; subsequent country calls reuse it.\n\n---\n\n## Output\n\n`python -m subselect \u003ccountry\u003e` writes:\n\n```\nresults/\u003ccountry\u003e/figures/\n├── performance/\n│   ├── \u003ccountry\u003e_HPS_rankings_annual_and_seasons.png\n│   ├── \u003ccountry\u003e_tas_seasonal_performance.png\n│   ├── \u003ccountry\u003e_pr_seasonal_performance.png\n│   ├── \u003ccountry\u003e_psl_seasonal_performance.png\n│   ├── \u003ccountry\u003e_tasmax_seasonal_performance.png\n│   ├── \u003ccountry\u003e_composite_taylor.png\n│   └── \u003ccountry\u003e_\u003cvar\u003e_annual_bias.png            (one per variable)\n├── spread/\n│   ├── \u003ccountry\u003e_annual_spread.png\n│   └── \u003ccountry\u003e_seasonal_spread.png\n└── country_profile/\n    ├── \u003ccountry\u003e_WL_table.png\n    ├── \u003ccountry\u003e_gwls_boxplot.png\n    ├── \u003ccountry\u003e_tas_anomalies_table.png\n    ├── \u003ccountry\u003e_tas_change.png\n    ├── \u003ccountry\u003e_tas_change_spaghetti.png\n    ├── \u003ccountry\u003e_pr_percent_anomalies_table.png\n    ├── \u003ccountry\u003e_pr_percent_change_ratio.png\n    └── \u003ccountry\u003e_pr_percent_change_spaghetti.png\n```\n\n---\n\n## Methodology\n\n`subselect` evaluates models along three orthogonal dimensions:\n\n- **Historical Performance Score (HPS).** Per-(variable, season) Taylor Skill\n  Score and Bias-Variability Score on `{tas, pr, psl}`, harmonic-mean-combined\n  and min-max normalised across the 35-model ensemble. Reference dataset:\n  W5E5; evaluation window: 1995–2014.\n- **Future spread.** End-of-century (2081–2100 vs. 1850–1899) Δtas, Δpr, and\n  Δtasmax under SSP5-8.5; rendered as quadrant scatter coloured by HPS rank.\n- **Model independence.** Two complementary methods (feature-space k-means\n  on regional climatology, and pairwise-RMSE genealogy clustering) score\n  the redundancy of a candidate subset.\n\nThe full methodology — definitions, equations, regression-test\ncontracts, design decisions — is logged in\n`documentation/methods.tex` (build with `pdflatex methods.tex`).\n\nThe framework is inspired by ClimSIPS (Merrifield, Brunner, Lorenz, Humphrey,\nKnutti, 2023; doi:10.5194/egusphere-2022-1520). Its contribution beyond\nClimSIPS is **explicit country-scale customisation** and **transparent\ndiagnostics for any user choice**.\n\n---\n\n## Citation\n\nA peer-reviewed paper on the Greece-only application was published in April\n2026; cite it as:\n\n```bibtex\n@article{tsilimigkras2026subselection,\n  author  = {Tsilimigkras, A. and Lazaridis, M. and Voulgarakis, A. and others},\n  title   = {Climate projections for {Greece}: Defining a regional sub-ensemble from the {CMIP6} landscape},\n  journal = {Theoretical and Applied Climatology},\n  volume  = {157},\n  pages   = {123},\n  year    = {2026},\n  doi     = {10.1007/s00704-026-06029-w},\n  url     = {https://doi.org/10.1007/s00704-026-06029-w},\n}\n```\n\n---\n\n## Contributing\n\nIssues and pull requests are welcome at\n\u003chttps://github.com/thchilly/subselect\u003e. New countries, methodology\nextensions, and figure-style options are all in scope; behaviour-changing\nedits should reproduce the pinned regression test\n(`pytest -m regression`) within the documented tolerance ladder.\n\n---\n\n## License\n\nMIT. See the `license` field in `pyproject.toml` for the package metadata.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthchilly%2Fsubselect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthchilly%2Fsubselect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthchilly%2Fsubselect/lists"}