def normalize(array, window=11, normalize_variance=True):
"""
Arguments:
array (np.array): 2D array (time, member)
window (int): Window length to compute climatology
normalize_variance (bool): Adjust variance
Returns:
np.array: Array of normalized values (same size as input array)
"""
N = array.shape[1]
"""
Remove climatology so we can look at annomalies. Use separate obs and fcst climatology
otherwise the fcst variance is higher because obs gets the advantage of using its own
climatology.
"""
clim = climatology(array, window, use_future_years=True)
values = copy.deepcopy(array)
for i in range(0, N):
values[:, i] = (values[:, i] - clim)
if normalize_variance and array.shape[1] > 2:
"""
This removes any seasonally varying variance, which can cause the 1-year variance to be
larger than the 1/2 year variance, because the 1/2 year variance samples the summer months
more often than the winter months, because of the windowing approach. Also, this
normalization does not guarantee that the std of the whole timeseries is 1, therefore in
the plot, don't expect the first point to be 1.
The timeseries is scaled up again to match the average anomaly variance in the timeseries.
"""
std = np.nanstd(array, axis=1)
if np.min(std) == 0:
warning("Standard deviation of 0 at one or more days. Not normalizing variance")
else:
meanstd = np.nanmean(std)
for i in range(0, N):
values[:, i] = values[:, i] / std * meanstd
return values
评论列表
文章目录