Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ClimaticIndicator model #286

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
47cfc22
Added model for climaticindicator
ricardogsilva Oct 29, 2024
4279846
Added database operations for crud'ing a climatic indicator
ricardogsilva Oct 29, 2024
c8a0db5
Added initial bootstrap values for climatic indicators
ricardogsilva Oct 29, 2024
9970675
Added new v3 of API with climatic indicator path operations
ricardogsilva Oct 29, 2024
ca40233
Added 1:m relationship between climaticindicator and coverageconfigur…
ricardogsilva Oct 29, 2024
248d900
Added bootstrapping-stuff for all climatic indicators and related all…
ricardogsilva Oct 29, 2024
f3c5a89
Added climatic indicator as the source of a coverage configuration's …
ricardogsilva Oct 31, 2024
90f44c7
Refactoring forecast coverage menu generation (wip)
ricardogsilva Oct 31, 2024
d2ea35c
Refactored forecast coverage menu generation
ricardogsilva Nov 4, 2024
a80609c
Refactored data download link generation and time series translations…
ricardogsilva Nov 5, 2024
94f35b5
Refactoring in order to integrate climatic indicator (wip)
ricardogsilva Nov 5, 2024
1bfe029
Commented out bootstrap cov conf properties that are now in climatic …
Nov 7, 2024
ff3c18a
Removed filtering cov conf by display name
Nov 7, 2024
023c8bf
Fixing failing tests (wip)
ricardogsilva Nov 7, 2024
a9dfc68
Fixed tests
ricardogsilva Nov 8, 2024
fd0cf77
Dropping variable table, which now becomes redundant (WIP)
ricardogsilva Nov 8, 2024
ccfb8f9
Continue work to replace Variable with ClimaticIndicator (wip)
ricardogsilva Nov 11, 2024
638fc2b
Replacing variable with climatic_indicator (wip)
ricardogsilva Nov 14, 2024
cde3c28
Fixing tests
ricardogsilva Nov 15, 2024
cbd68d1
Introducing observation refreshes things
ricardogsilva Dec 13, 2024
ad10cd1
Adding support for ARPAFVG observation data
ricardogsilva Dec 16, 2024
5797509
Update poetry lock file
ricardogsilva Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,24 @@ this can also be modified if needed. The system recognizes the following environ

### Operations

##### Translations

```shell
# look for new translatable strings in the codebase
docker exec -ti arpav-ppcv-webapp-1 poetry run arpav-ppcv translations extract

# update existing catalogs with the new strings found in the previous step
docker exec -ti arpav-ppcv-webapp-1 poetry run arpav-ppcv translations update
```

Now use your favorite editor to translate the strings.

Finally, compile the translations files:

```shell
docker exec -ti arpav-ppcv-webapp-1 poetry run arpav-ppcv translations compile
```

##### Accessing the CLI

The CLI is named `arpav-ppcv`. When running under docker compose, it can be used with the following incantation:
Expand Down
160 changes: 115 additions & 45 deletions arpav_ppcv/bootstrapper/cliapp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
from pathlib import Path
from typing import Annotated
from typing import Annotated, Optional

import geojson_pydantic
import sqlmodel
Expand Down Expand Up @@ -45,19 +45,42 @@
tr as tr_historical,
txd as txd_historical,
)
from .variables import generate_variable_configurations
from .climaticindicators import (
cdd as cdd_climatic_indicators,
cdds as cdds_climatic_indicators,
fd as fd_climatic_indicators,
hdds as hdds_climatic_indicators,
hwdi as hwdi_climatic_indicators,
pr as pr_climatic_indicators,
r95ptot as r95ptot_climatic_indicators,
snwdays as snwdays_climatic_indicators,
su30 as su30_climatic_indicators,
tas as tas_climatic_indicators,
tasmax as tasmax_climatic_indicators,
tasmin as tasmin_climatic_indicators,
tr as tr_climatic_indicators,
)

from .configurationparameters import generate_configuration_parameters

app = typer.Typer()


@app.command("municipalities")
def bootstrap_municipalities(
ctx: typer.Context, municipalities_dataset: Path, force: bool = False
ctx: typer.Context,
municipalities_dataset: Annotated[
Path,
typer.Argument(
help=(
"Path to the municipalities geoJSON dataset. Example: "
"/home/appuser/app/data/municipalities-istat-2021.geojson"
)
),
],
force: bool = False,
) -> None:
"""Bootstrap Italian municipalities"""
# data_directory = Path(__file__).parents[2] / "data"
# municipalities_dataset = data_directory / "limits_IT_municipalities.geojson"
to_create = []

should_bootstrap = False
Expand Down Expand Up @@ -162,24 +185,69 @@ def bootstrap_station_variables(
print("Done!")


@app.command("observation-variables")
def bootstrap_observation_variables(
ctx: typer.Context,
@app.command("climatic-indicators")
def bootstrap_climatic_indicators(
ctx: typer.Context, name_filter: Optional[str] = None
):
"""Create initial observation variables."""
variables = generate_variable_configurations()
"""Create initial climatic indicators."""
climatic_indicators_to_generate = (
cdd_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
cdds_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
fd_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
hdds_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
hwdi_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
pr_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
r95ptot_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
snwdays_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
su30_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
tas_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
tasmax_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
tasmin_climatic_indicators.generate_climatic_indicators()
)
climatic_indicators_to_generate.extend(
tr_climatic_indicators.generate_climatic_indicators()
)
with sqlmodel.Session(ctx.obj["engine"]) as session:
for var_create in variables:
try:
db_variable = database.create_variable(session, var_create)
print(f"Created observation variable {db_variable.name!r}")
except IntegrityError as err:
print(
f"Could not create observation "
f"variable {var_create.name!r}: {err}"
)
session.rollback()
print("Done!")
for climatic_indicator_create in climatic_indicators_to_generate:
if name_filter is None or name_filter in climatic_indicator_create.name:
try:
db_climatic_indicator = database.create_climatic_indicator(
session, climatic_indicator_create
)
print(
f"Created climatic indicator {db_climatic_indicator.identifier!r}"
)
except IntegrityError as err:
print(
f"Could not create climatic indicator ("
f"{climatic_indicator_create.name!r}, "
f"{climatic_indicator_create.measure_type!r}, "
f"{climatic_indicator_create.aggregation_period!r}"
f"): {err}"
)
session.rollback()


@app.command("coverage-configuration-parameters")
Expand Down Expand Up @@ -210,81 +278,83 @@ def bootstrap_coverage_configurations(
):
"""Create initial coverage configurations."""
with sqlmodel.Session(ctx.obj["engine"]) as session:
all_vars = database.collect_all_variables(session)
all_conf_param_values = database.collect_all_configuration_parameter_values(
session
)
variables = {v.name: v for v in all_vars}
conf_param_values = {
(pv.configuration_parameter.name, pv.name): pv
for pv in all_conf_param_values
}
all_climatic_indicators = database.collect_all_climatic_indicators(session)
clim_indicator_ids = {i.identifier: i.id for i in all_climatic_indicators}
coverage_configurations = []
coverage_configurations.extend(
cdd_forecast.generate_configurations(conf_param_values)
cdd_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
cdds_forecast.generate_configurations(conf_param_values, variables)
cdds_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
fd_forecast.generate_configurations(conf_param_values, variables)
fd_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
hdds_forecast.generate_configurations(conf_param_values, variables)
hdds_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
hwdi_forecast.generate_configurations(conf_param_values)
hwdi_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
pr_forecast.generate_configurations(conf_param_values, variables)
pr_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
r95ptot_forecast.generate_configurations(conf_param_values)
r95ptot_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
snwdays_forecast.generate_configurations(conf_param_values)
snwdays_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
su30_forecast.generate_configurations(conf_param_values, variables)
su30_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tas_forecast.generate_configurations(conf_param_values, variables)
tas_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tasmax_forecast.generate_configurations(conf_param_values, variables)
tasmax_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tasmin_forecast.generate_configurations(conf_param_values, variables)
tasmin_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tr_forecast.generate_configurations(conf_param_values, variables)
tr_forecast.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
cdds_historical.generate_configurations(conf_param_values, variables)
cdds_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
fd_historical.generate_configurations(conf_param_values, variables)
fd_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
hdds_historical.generate_configurations(conf_param_values, variables)
hdds_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
prcptot_historical.generate_configurations(conf_param_values, variables)
prcptot_historical.generate_configurations(
conf_param_values, clim_indicator_ids
)
)
coverage_configurations.extend(
su30_historical.generate_configurations(conf_param_values, variables)
su30_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tdd_historical.generate_configurations(conf_param_values, variables)
tdd_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tnd_historical.generate_configurations(conf_param_values, variables)
tnd_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
tr_historical.generate_configurations(conf_param_values, variables)
tr_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)
coverage_configurations.extend(
txd_historical.generate_configurations(conf_param_values, variables)
txd_historical.generate_configurations(conf_param_values, clim_indicator_ids)
)

for cov_conf_create in coverage_configurations:
Expand Down
Empty file.
32 changes: 32 additions & 0 deletions arpav_ppcv/bootstrapper/climaticindicators/cdd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from ...schemas.static import (
AggregationPeriod,
MeasureType,
)
from ...schemas.climaticindicators import ClimaticIndicatorCreate


def generate_climatic_indicators() -> list[ClimaticIndicatorCreate]:
return [
ClimaticIndicatorCreate(
name="cdd",
measure_type=MeasureType.ANOMALY,
aggregation_period=AggregationPeriod.THIRTY_YEAR,
display_name_english="Consecutive dry days (CDD)",
display_name_italian="Giorni secchi (CDD)",
description_english=(
"Maximum number of consecutive dry days (daily precipitation "
"less than 1 mm)"
),
description_italian=(
"Numero massimo di giorni consecutivi asciutti "
"(precipitazione giornaliera inferiore a 1 mm)"
),
unit_english="days",
unit_italian="gg",
palette="uncert-stippled/div-BrBG-inv",
color_scale_min=-40,
color_scale_max=40,
data_precision=0,
sort_order=11,
),
]
76 changes: 76 additions & 0 deletions arpav_ppcv/bootstrapper/climaticindicators/cdds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from ...schemas.static import (
AggregationPeriod,
MeasureType,
)
from ...schemas.climaticindicators import ClimaticIndicatorCreate


def generate_climatic_indicators() -> list[ClimaticIndicatorCreate]:
return [
ClimaticIndicatorCreate(
name="cdds",
measure_type=MeasureType.ABSOLUTE,
aggregation_period=AggregationPeriod.ANNUAL,
display_name_english="Cooling degree days (CDDs)",
display_name_italian="Gradi giorno di raffrescamento (CDDs)",
description_english=(
"Sum of the average daily temperature minus 21°C if the "
"average daily temperature is larger than 24°C"
),
description_italian=(
"Somma della temperatura media giornaliera meno 21°C se la "
"temperatura media giornaliera è maggiore di 24°C"
),
unit_english="ºC",
unit_italian="ºC",
palette="default/seq-YlOrRd",
color_scale_min=0,
color_scale_max=1000,
data_precision=0,
sort_order=8,
),
ClimaticIndicatorCreate(
name="cdds",
measure_type=MeasureType.ABSOLUTE,
aggregation_period=AggregationPeriod.THIRTY_YEAR,
display_name_english="Cooling degree days (CDDs)",
display_name_italian="Gradi giorno di raffrescamento (CDDs)",
description_english=(
"Sum of the average daily temperature minus 21°C if the "
"average daily temperature is larger than 24°C"
),
description_italian=(
"Somma della temperatura media giornaliera meno 21°C se la "
"temperatura media giornaliera è maggiore di 24°C"
),
unit_english="ºC",
unit_italian="ºC",
palette="default/seq-YlOrRd",
color_scale_min=0,
color_scale_max=320,
data_precision=0,
sort_order=8,
),
ClimaticIndicatorCreate(
name="cdds",
measure_type=MeasureType.ANOMALY,
aggregation_period=AggregationPeriod.THIRTY_YEAR,
display_name_english="Cooling degree days (CDDs)",
display_name_italian="Gradi giorno di raffrescamento (CDDs)",
description_english=(
"Sum of the average daily temperature minus 21°C if the "
"average daily temperature is larger than 24°C"
),
description_italian=(
"Somma della temperatura media giornaliera meno 21°C se la "
"temperatura media giornaliera è maggiore di 24°C"
),
unit_english="ºC",
unit_italian="ºC",
palette="uncert-stippled/seq-YlOrRd",
color_scale_min=0,
color_scale_max=1000,
data_precision=0,
sort_order=8,
),
]
Loading
Loading