Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 26 additions & 6 deletions pepsico/app_calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ def seasonal_data(monthly_data, start_month, end_month, start_year=None, end_yea


def seasonal_wwc(
labelled_season_data, variable, frost_threshold, wet_threshold
labelled_season_data, variable, frost_threshold, wet_threshold, hot_threshold,
warm_nights_spell,
):
# Boolean variables need the additional where to return NaNs from False/0 to Nans
# and the sum parameters for entirely NaNs seasons to remain NaNs and not turn to
Expand All @@ -128,7 +129,7 @@ def seasonal_wwc(
data_ds = labelled_season_data.groupby(
labelled_season_data["seasons_starts"]
).mean()
wwc_units = "˚C"
wwc_units = "˚C"
# It takes several 10s of minutes to get empirical quantiles maps
if variable in ["Tmax_90", "Tmin_10"]:
quantile = 0.1 if variable == "Tmin_10" else 0.9
Expand Down Expand Up @@ -162,6 +163,17 @@ def seasonal_wwc(
.sum(skipna=True, min_count=1)
)
wwc_units = "days"
if variable == "warm_nights":
data_ds = (
(labelled_season_data > hot_threshold)
.where(~np.isnan(labelled_season_data))
.groupby(labelled_season_data["seasons_starts"])
.map(
count_days_in_spells, "T", min_spell_length=warm_nights_spell,
skipna=True, min_count=1,
)
)
wwc_units = "days"
# This is all a bit tedious but I didn't figure out another way to keep
# seasons_ends and renaming time dim T
# Can revisit later if this code has a future
Expand Down Expand Up @@ -441,7 +453,9 @@ def _cumsum_flagged_diff(flagged_data, dim):
).bfill(dim).diff(dim)
return cfd

def count_days_in_spells(flagged_data, dim, min_spell_length=1):
def count_days_in_spells(
flagged_data, dim, min_spell_length=1, skipna=None, min_count=None,
):
""" Counts number of days in spells.

Parameters
Expand All @@ -466,9 +480,15 @@ def count_days_in_spells(flagged_data, dim, min_spell_length=1):
--------
"""

return _cumsum_flagged_diff(flagged_data, dim).where(
lambda x : x >= min_spell_length
).sum(dim=dim)
return (
_cumsum_flagged_diff(flagged_data, dim)
# Nullify the spells that are too short to be counted
.where(lambda x : x >= min_spell_length, 0)
# Return NaNs to NaNs
.where(~np.isnan(flagged_data))
# Include sum's skipna and min_count to properly deal with 0s vs NaNs
.sum(dim=dim, skipna=skipna, min_count=min_count)
)

def length_of_longest_spell(flagged_data, dim):
""" Length of longest spells.
Expand Down
34 changes: 31 additions & 3 deletions pepsico/proj_wwc/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def app_layout():
Block("WWC statistics", Select(
id="variable",
options=[
# "warm_nights",
"warm_nights",
# "rain_events",
"mean_Tmax",
"mean_Tmin",
Expand All @@ -56,7 +56,7 @@ def app_layout():
# "dry_spells_median_length",
],
labels=[
# "Warm Nights",
"Warm Nights",
# "Count of Rain Events",
"Mean Max Temperature",
"Mean Min Temperature",
Expand Down Expand Up @@ -96,7 +96,27 @@ def app_layout():
width="5em",
debounce=False,
),
"mm",
"mm; ",
"Hot/Cold day > / <=",
Number(
id="hot",
default=25,
min=-99,
max=999,
width="5em",
debounce=False,
),
"˚C; ",
"Warm Nights Spell >=",
Number(
id="wms",
default=5,
min=0,
max=99,
width="5em",
debounce=False,
),
"days",
),
Block("Season",
Number(
Expand Down Expand Up @@ -206,6 +226,14 @@ def app_layout():
Obtained through parametric Normal distributions.
"""
]),
html.P([
html.B("Warm Nights (warm_nights):"),"""
Number of days in a season in a warm night spell. A warm night
spell is defined as a user-defined minimum consecutive number of
warm nights. A warm night is defined as days where minimum
temperature is greater than a user-defined thredhold.
"""
]),
),

lou.map(GLOBAL_CONFIG["zoom"]),
Expand Down
54 changes: 37 additions & 17 deletions pepsico/proj_wwc/maproom.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ def select_var(variable):
"Tmin_10",
"frost_season_length",
"frost_days",
"warm_nights",
]:
data_var = "tasmin"
if variable in [
# "warm_nights",
"mean_Tmax",
"Tmax_90",
# "heatwave_duration",
Expand All @@ -115,7 +115,7 @@ def local_data(
lat, lng, region,
model, variable,
start_day, start_month, end_day, end_month,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
model = [model] if model != "Multi-Model-Average" else [
"GFDL-ESM4", "IPSL-CM6A-LR", "MPI-ESM1-2-HR","MRI-ESM2-0", "UKESM1-0-LL"
Expand Down Expand Up @@ -160,7 +160,8 @@ def local_data(
ac.daily_tobegroupedby_season(
data_ds, start_day, start_month, end_day, end_month,
),
variable, frost_threshold, wet_threshold,
variable, frost_threshold, wet_threshold, hot_threshold,
warm_nights_spell,
)
return data_ds, error_msg

Expand Down Expand Up @@ -226,12 +227,14 @@ def invalid_button(lat, lng, lat_min, lng_min, lat_max, lng_max):
State("end_month", "value"),
State("frost", "value"),
State("wet", "value"),
State("hot", "value"),
State("wms", "value"),
prevent_initial_call=True,
)
def send_data_as_csv(
n_clicks, marker_pos, region, variable,
start_day, start_month, end_day, end_month,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
lat = marker_pos[0]
lng = marker_pos[1]
Expand All @@ -241,11 +244,13 @@ def send_data_as_csv(
end_month = ac.strftimeb2int(end_month)
frost_threshold = float(frost_threshold)
wet_threshold = float(wet_threshold)
hot_threshold = float(hot_threshold)
warm_nights_spell = int(warm_nights_spell)
model = "Multi-Model-Average"
data_ds, error_msg = local_data(
lat, lng, region, model, variable,
start_day, start_month, end_day, end_month,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
)
if error_msg == None :
lng_units = "E" if (lng >= 0) else "W"
Expand Down Expand Up @@ -279,12 +284,14 @@ def send_data_as_csv(
State("end_year_ref", "value"),
State("frost", "value"),
State("wet", "value"),
State("hot", "value"),
State("wms", "value"),
)
def local_plots(
marker_pos, region, n_clicks, model, variable,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
lat = marker_pos[0]
lng = marker_pos[1]
Expand All @@ -294,10 +301,12 @@ def local_plots(
end_month = ac.strftimeb2int(end_month)
frost_threshold = float(frost_threshold)
wet_threshold = float(wet_threshold)
hot_threshold = float(hot_threshold)
warm_nights_spell = int(warm_nights_spell)
data_ds, error_msg = local_data(
lat, lng, region, model, variable,
start_day, start_month, end_day, end_month,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
)
if error_msg != None :
local_graph = pingrid.error_fig(error_msg)
Expand Down Expand Up @@ -458,7 +467,7 @@ def seasonal_change(
scenario, model, variable, region,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
model = [model] if model != "Multi-Model-Average" else [
"GFDL-ESM4", "IPSL-CM6A-LR", "MPI-ESM1-2-HR","MRI-ESM2-0", "UKESM1-0-LL"
Expand All @@ -475,7 +484,8 @@ def seasonal_change(
).to_dataset(),
start_day, start_month, end_day, end_month,
),
variable, frost_threshold, wet_threshold,
variable, frost_threshold, wet_threshold, hot_threshold,
warm_nights_spell,
).mean(dim="T", keep_attrs=True) for m in model
], "M").mean("M", keep_attrs=True)
data = xr.concat([
Expand All @@ -489,7 +499,8 @@ def seasonal_change(
).to_dataset(),
start_day, start_month, end_day, end_month,
),
variable, frost_threshold, wet_threshold,
variable, frost_threshold, wet_threshold, hot_threshold,
warm_nights_spell,
).mean(dim="T", keep_attrs=True) for m in model
], "M").mean("M", keep_attrs=True)
#Tedious way to make a subtraction only to keep attributes (units)
Expand Down Expand Up @@ -531,24 +542,28 @@ def map_attributes(data, variable):
State("end_year_ref", "value"),
State("frost", "value"),
State("wet", "value"),
State("hot", "value"),
State("wms", "value"),
)
def draw_colorbar(
region, n_clicks, scenario, model, variable,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
start_day = int(start_day)
end_day = int(end_day)
start_month = ac.strftimeb2int(start_month)
end_month = ac.strftimeb2int(end_month)
frost_threshold = float(frost_threshold)
wet_threshold = float(wet_threshold)
hot_threshold = float(hot_threshold)
warm_nights_spell = int(warm_nights_spell)
data = seasonal_change(
scenario, model, variable, region,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
)
colorbar, min, max = map_attributes(data, variable)
return (
Expand All @@ -575,20 +590,23 @@ def draw_colorbar(
State("end_year_ref", "value"),
State("frost", "value"),
State("wet", "value"),
State("hot", "value"),
State("wms", "value"),
)
def make_map(
region, n_clicks, scenario, model, variable,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
try:
send_alarm = False
url_str = (
f"{TILE_PFX}/{{z}}/{{x}}/{{y}}/{region}/{scenario}/{model}/"
f"{variable}/{start_day}/{end_day}/{start_month}/{end_month}/"
f"{start_year}/{end_year}/{start_year_ref}/{end_year_ref}/"
f"{frost_threshold}/{wet_threshold}"
f"{frost_threshold}/{wet_threshold}/{hot_threshold}/"
f"{warm_nights_spell}"
)
except:
url_str= ""
Expand All @@ -605,27 +623,29 @@ def make_map(
f"{TILE_PFX}/<int:tz>/<int:tx>/<int:ty>/<region>/<scenario>/<model>/"
f"<variable>/<start_day>/<end_day>/<start_month>/<end_month>/"
f"<start_year>/<end_year>/<start_year_ref>/<end_year_ref>/"
f"<frost_threshold>/<wet_threshold>/"
f"<frost_threshold>/<wet_threshold>/<hot_threshold>/<warm_nights_spell>"
),
endpoint=f"{config['core_path']}"
)
def fcst_tiles(tz, tx, ty,
region, scenario, model, variable,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
):
start_day = int(start_day)
end_day = int(end_day)
start_month = ac.strftimeb2int(start_month)
end_month = ac.strftimeb2int(end_month)
frost_threshold = float(frost_threshold)
wet_threshold = float(wet_threshold)
hot_threshold = float(hot_threshold)
warm_nights_spell = int(warm_nights_spell)
data = seasonal_change(
scenario, model, variable, region,
start_day, end_day, start_month, end_month,
start_year, end_year, start_year_ref, end_year_ref,
frost_threshold, wet_threshold,
frost_threshold, wet_threshold, hot_threshold, warm_nights_spell,
)
(
data[select_var(variable)].attrs["colormap"],
Expand Down