Skip to content

Commit aac2702

Browse files
authored
Scores by Region (#75)
* add region averages * add regions to config * Add regions to verification module, scripts, and rules * add stratification to forecaster config and fix typo * fix dict indexing * fix append error * read lon/lat from obs dataset * Add inner verification domain * Add missing dependency * add plots by region * Add regions to dashboard * Fix dashboard * Add region name and initializations to plot title (and remove header div) * Add support for multiple regions * Fix legend
1 parent e7f12b2 commit aac2702

File tree

17 files changed

+480
-63
lines changed

17 files changed

+480
-63
lines changed

config/forecasters-co1e.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ analysis:
2929
label: COSMO KENDA
3030
analysis_zarr: /scratch/mch/fzanetta/data/anemoi/datasets/mch-co1e-an-archive-0p01-2019-2024-1h-v1-pl13.zarr
3131

32+
stratification:
33+
regions:
34+
- jura
35+
- mittelland
36+
- voralpen
37+
- alpennordhang
38+
- innerealpentaeler
39+
- alpensuedseite
40+
root: /scratch/mch/bhendj/regions/Prognoseregionen_LV95_20220517
41+
3242
locations:
3343
output_root: output/
3444
mlflow_uri:

config/forecasters.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ analysis:
2424
label: COSMO KENDA
2525
analysis_zarr: /scratch/mch/fzanetta/data/anemoi/datasets/mch-co2-an-archive-0p02-2015-2020-6h-v3-pl13.zarr
2626

27+
stratification:
28+
regions:
29+
- jura
30+
- mittelland
31+
- voralpen
32+
- alpennordhang
33+
- innerealpentaeler
34+
- alpensuedseite
35+
root: /scratch/mch/bhendj/regions/Prognoseregionen_LV95_20220517
36+
2737
locations:
2838
output_root: output/
2939
mlflow_uri:

config/interpolators.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ analysis:
4848
label: COSMO KENDA
4949
analysis_zarr: /scratch/mch/fzanetta/data/anemoi/datasets/mch-co2-an-archive-0p02-2015-2020-1h-v3-pl13.zarr
5050

51+
stratification:
52+
regions:
53+
- jura
54+
- mittelland
55+
- voralpen
56+
- alpennordhang
57+
- innerealpentaeler
58+
- alpensuedseite
59+
root: /scratch/mch/bhendj/regions/Prognoseregionen_LV95_20220517
60+
5161
locations:
5262
output_root: output/
5363
mlflow_uri:

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ dependencies = [
1818
"pydantic>=2.11.7",
1919
"toml>=0.10.2",
2020
"netcdf4>=1.7.2",
21+
"shapely>=2.1.2",
22+
"cartopy>=0.25.0",
23+
"pyproj>=3.7.2",
2124
]
2225

2326
[project.optional-dependencies]

resources/report/dashboard/script.js

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ document.querySelectorAll(".tab-link").forEach(button => {
1212
// Initialize selection widgets
1313
const choicesInstances = {};
1414

15+
choicesInstances["region-select"] = new Choices("#region-select", {
16+
searchEnabled: false,
17+
removeItemButton: true,
18+
shouldSort: false,
19+
itemSelectText: "",
20+
placeholder: false
21+
});
22+
document.getElementById("region-select").addEventListener("change", updateChart);
23+
24+
1525
choicesInstances["source-select"] = new Choices("#source-select", {
1626
searchEnabled: false,
1727
removeItemButton: true,
@@ -41,57 +51,74 @@ document.getElementById("param-select").addEventListener("change", updateChart);
4151

4252
// Get the data (embedded in the HTML)
4353
data = JSON.parse(document.getElementById("verif-data").textContent)
54+
header = document.getElementById("header-text").textContent.trim()
4455

4556
// Define base spec
4657
var spec = {
4758
"data": { "values": data },
48-
"params": [
49-
{
50-
"name": "xZoom",
51-
"select": {
52-
"type": "interval",
53-
"encodings": ["x"],
54-
"zoom": "wheel![!event.shiftKey]"
55-
},
56-
"bind": "scales"
57-
}
58-
],
59+
"config": {
60+
"scale": { "continuousPadding": 1 }
61+
},
5962
"facet": {
60-
"column": { "field": "param" },
61-
"row": { "field": "metric" }
63+
"row": { "field": "metric", "type": "nominal", "title": null },
64+
"column": { "field": "param", "type": "nominal" , "title": null },
65+
},
66+
"resolve": {
67+
"scale": {
68+
"x": "shared",
69+
"y": "independent"
70+
},
6271
},
6372
"spec": {
64-
"mark": "line",
73+
"params": [
74+
{
75+
"name": "xZoom",
76+
"select": {
77+
"type": "interval",
78+
"encodings": ["x"],
79+
"zoom": "wheel![!event.shiftKey]"
80+
},
81+
"bind": "scales"
82+
}
83+
],
84+
"mark": {"type": "line", "point": { "size": 50 } },
6585
"width": 300,
6686
"height": 200,
6787
"encoding": {
6888
"x": {
6989
"field": "lead_time",
70-
"type": "quantitative",
71-
"axis": { "labels": true, "ticks": true },
90+
"type": "quantitative"
7291
},
7392
"y": {
7493
"field": "value",
75-
"type": "quantitative",
76-
"scale": { "zero": false }
94+
"type": "quantitative" ,
95+
"scale": { "zero": false }
7796
},
7897
"color": {
7998
"field": "source",
80-
"legend": { "orient": "top", "labelLimit": 1000, "symbolSize": 1000 }
81-
}
99+
"type": "nominal",
100+
"legend": { "orient": "top", "title": "Data Source", "offset": 0, "padding": 10 }
101+
},
102+
"shape": {
103+
"field": "region",
104+
"type": "nominal",
105+
"legend": { "orient": "top", "title": "Region", "offset": 0, "padding": 10 }
106+
},
107+
"strokeDash": {
108+
"field": "region",
109+
"type": "nominal",
110+
"legend": null
111+
},
112+
"tooltip": [
113+
{ "field": "region", "type": "nominal", "title": "Region" },
114+
{ "field": "source", "type": "nominal", "title": "Source" },
115+
{ "field": "param", "type": "nominal", "title": "Parameter" },
116+
{ "field": "metric", "type": "nominal", "title": "Metric" },
117+
{ "field": "lead_time", "type": "quantitative", "title": "Lead Time (h)" },
118+
{ "field": "value", "type": "quantitative", "title": "Value" }
119+
]
82120
},
83-
"transform": [
84-
{
85-
"filter": { "param": "xZoom" }
86-
}
87-
]
88121
},
89-
"resolve": {
90-
"scale": {
91-
"x": "shared",
92-
"y": "independent"
93-
}
94-
}
95122
};
96123

97124

@@ -102,13 +129,18 @@ function getSelectedValues(id) {
102129
}
103130

104131
function updateChart() {
132+
const selectedRegions = getSelectedValues("region-select");
105133
const selectedSources = getSelectedValues("source-select");
106134
const selectedparams = getSelectedValues("param-select");
107135
const selectedMetrics = getSelectedValues("metric-select");
108136

109137
const newSpec = JSON.parse(JSON.stringify(spec));
110138
const filters = [];
111139

140+
newSpec.title = "Verification using " + header;
141+
if (selectedRegions.length > 0) {
142+
filters.push({ field: "region", oneOf: selectedRegions });
143+
}
112144
if (selectedSources.length > 0) {
113145
filters.push({ field: "source", oneOf: selectedSources });
114146
}

resources/report/dashboard/template.html.jinja2

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,15 @@
101101

102102
<!-- First tab -->
103103
<div id="tab1" class="tab-content active">
104-
<div class="header">
105-
<p>
106-
{{header_text}}
107-
</p>
108-
</div>
109104
<div class="controls">
105+
<div class="control-group">
106+
<label>Region</label>
107+
<select id="region-select" multiple>
108+
{% for region in regions %}
109+
<option value="{{region}}"{% if region == 'all' %} selected{% endif %}>{{region}}</option>
110+
{% endfor %}
111+
</select>
112+
</div>
110113
<div class="control-group">
111114
<label>Source(s)</label>
112115
<select id="source-select" multiple>
@@ -144,6 +147,10 @@
144147
{{ verif_data | safe | indent(8, false)}}
145148
</script>
146149

150+
<script id="header-text" type="text">
151+
{{ header_text }}
152+
</script>
153+
147154
<script>
148155
{{ js_src | indent(8, true) }}
149156
</script>

src/evalml/config.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,19 @@ class Locations(BaseModel):
205205
)
206206

207207

208+
class Stratification(BaseModel):
209+
"""Stratification settings for the analysis."""
210+
211+
regions: List[str] = Field(
212+
...,
213+
description="List of region names for stratification.",
214+
)
215+
root: str = Field(
216+
...,
217+
description="Root directory where the region shapefiles are stored.",
218+
)
219+
220+
208221
class DefaultResources(BaseModel):
209222
"""Default resource settings for job execution."""
210223

@@ -276,6 +289,7 @@ class ConfigModel(BaseModel):
276289
description="Dictionary of baselines to include in the verification.",
277290
)
278291
analysis: AnalysisConfig
292+
stratification: Stratification
279293
locations: Locations
280294
profile: Profile
281295

0 commit comments

Comments
 (0)