Skip to content
Snippets Groups Projects
Commit fd5fe608 authored by leufen1's avatar leufen1
Browse files

new method to calculate seasonal diurnal anomalies

parent 24808a64
No related branches found
No related tags found
5 merge requests!319add all changes of dev into release v1.4.0 branch,!318Resolve "release v1.4.0",!317enabled window_lead_time=1,!295Resolve "data handler FIR filter",!259Draft: Resolve "WRF-Datahandler should inherit from SingleStationDatahandler"
Pipeline #68615 passed
...@@ -85,7 +85,10 @@ class ClimateFIRFilter: ...@@ -85,7 +85,10 @@ class ClimateFIRFilter:
sampling = {1: "1d", 24: "1H"}.get(int(fs)) sampling = {1: "1d", 24: "1H"}.get(int(fs))
logging.info(f"{plot_name}: create diurnal_anomalies") logging.info(f"{plot_name}: create diurnal_anomalies")
if apriori_diurnal is True and sampling == "1H": if apriori_diurnal is True and sampling == "1H":
diurnal_anomalies = self.create_hourly_mean(data, sel_opts=sel_opts, sampling=sampling, time_dim=time_dim, # diurnal_anomalies = self.create_hourly_mean(data, sel_opts=sel_opts, sampling=sampling, time_dim=time_dim,
# as_anomaly=True)
diurnal_anomalies = self.create_seasonal_hourly_mean(data, sel_opts=sel_opts, sampling=sampling,
time_dim=time_dim,
as_anomaly=True) as_anomaly=True)
else: else:
diurnal_anomalies = 0 diurnal_anomalies = 0
...@@ -140,7 +143,10 @@ class ClimateFIRFilter: ...@@ -140,7 +143,10 @@ class ClimateFIRFilter:
if len(apriori_list) <= i + 1: if len(apriori_list) <= i + 1:
logging.info(f"{plot_name}: create diurnal_anomalies") logging.info(f"{plot_name}: create diurnal_anomalies")
if apriori_diurnal is True and sampling == "1H": if apriori_diurnal is True and sampling == "1H":
diurnal_anomalies = self.create_hourly_mean(input_data.sel({new_dim: 0}, drop=True), # diurnal_anomalies = self.create_hourly_mean(input_data.sel({new_dim: 0}, drop=True),
# sel_opts=sel_opts, sampling=sampling,
# time_dim=time_dim, as_anomaly=True)
diurnal_anomalies = self.create_seasonal_hourly_mean(input_data.sel({new_dim: 0}, drop=True),
sel_opts=sel_opts, sampling=sampling, sel_opts=sel_opts, sampling=sampling,
time_dim=time_dim, as_anomaly=True) time_dim=time_dim, as_anomaly=True)
else: else:
...@@ -242,6 +248,43 @@ class ClimateFIRFilter: ...@@ -242,6 +248,43 @@ class ClimateFIRFilter:
hourly.loc[{f"{time_dim}": loc}] = hourly_mean.sel(hour=hour) hourly.loc[{f"{time_dim}": loc}] = hourly_mean.sel(hour=hour)
return hourly return hourly
def create_seasonal_hourly_mean(self, data, sel_opts=None, sampling="1H", time_dim="datetime", as_anomaly=True):
"""Calculate hourly statistics. Either the absolute value or the anomaly (as_anomaly=True)."""
# can only be used for hourly sampling rate
assert sampling == "1H"
# apply selection if given (only use subset for seasonal hourly means)
if sel_opts is not None:
data = data.sel(**sel_opts)
# create unity xarray in monthly resolution with sampling point in mid of each month
monthly = self.create_unity_array(data, time_dim) * np.nan
seasonal_hourly_means = {}
for month in data.groupby(f"{time_dim}.month").groups.keys():
# select each month
single_month_data = data.sel({time_dim: (data[f"{time_dim}.month"] == month)})
hourly_mean = single_month_data.groupby(f"{time_dim}.hour").mean()
if as_anomaly is True:
hourly_mean = hourly_mean - hourly_mean.mean("hour")
seasonal_hourly_means[month] = hourly_mean
seasonal_coll = []
for hour in data.groupby(f"{time_dim}.hour").groups.keys():
h_coll = monthly.__deepcopy__()
for month in seasonal_hourly_means.keys():
hourly_mean_single_month = seasonal_hourly_means[month].sel(hour=hour, drop=True)
h_coll = xr.where((h_coll[f"{time_dim}.month"] == month),
hourly_mean_single_month,
h_coll)
h_coll = h_coll.resample({time_dim: sampling}).interpolate()
h_coll = h_coll.sel({time_dim: (h_coll[f"{time_dim}.hour"] == hour)})
seasonal_coll.append(h_coll)
hourly = xr.concat(seasonal_coll, time_dim).sortby(time_dim).resample({time_dim: sampling}).interpolate()
return hourly
@staticmethod @staticmethod
def extend_apriori(data, apriori, time_dim, sampling="1d"): def extend_apriori(data, apriori, time_dim, sampling="1d"):
""" """
...@@ -721,7 +764,7 @@ class ClimateFIRFilter: ...@@ -721,7 +764,7 @@ class ClimateFIRFilter:
rc_params = {'axes.labelsize': 'large', rc_params = {'axes.labelsize': 'large',
'xtick.labelsize': 'large', 'xtick.labelsize': 'large',
'ytick.labelsize': 'large', 'ytick.labelsize': 'large',
'legend.fontsize': 'large', 'legend.fontsize': 'medium',
'axes.titlesize': 'large', 'axes.titlesize': 'large',
} }
plt.rcParams.update(rc_params) plt.rcParams.update(rc_params)
...@@ -831,7 +874,7 @@ class ClimateFIRFilter: ...@@ -831,7 +874,7 @@ class ClimateFIRFilter:
label="clim filter residuum", linewidth=2) label="clim filter residuum", linewidth=2)
ax.set_xlim((ax_start, ax_end)) ax.set_xlim((ax_start, ax_end))
plt.title(f"Residuum of ClimFilter ({str(var)})") plt.title(f"Residuum of ClimFilter ({str(var)})")
plt.legend() plt.legend(loc="upper left")
fig.autofmt_xdate() fig.autofmt_xdate()
plt.tight_layout() plt.tight_layout()
plot_name = os.path.join(plot_folder, plot_name = os.path.join(plot_folder,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment