# noqa: D100from__future__importannotationsimportcf_xarray# noqa: F401, pylint: disable=unused-importimportnumpyasnpimportxarrayfromxclim.core.unitsimportconvert_units_to,declare_units# Frequencies : YS: year start, QS-DEC: seasons starting in december, MS: month start# See https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html# -------------------------------------------------- ## ATTENTION: ASSUME ALL INDICES WRONG UNTIL TESTED ! ## -------------------------------------------------- #__all__=["jetstream_metric_woollings",]
[docs]@declare_units(ua="[speed]")defjetstream_metric_woollings(ua:xarray.DataArray,)->tuple[xarray.DataArray,xarray.DataArray]:"""Strength and latitude of jetstream. Identify latitude and strength of maximum smoothed zonal wind speed in the region from 15 to 75°N and -60 to 0°E, using the formula outlined in :cite:p:`woollings_variability_2010`. Wind is smoothened using a Lanczos filter approach. Warnings -------- This metric expects eastward wind component (u) to be on a regular grid (i.e. Plate Carree, 1D lat and lon) Parameters ---------- ua : xarray.DataArray Eastward wind component (u) at between 750 and 950 hPa. Returns ------- (xarray.DataArray, xarray.DataArray) Daily time series of latitude of jetstream and daily time series of strength of jetstream. References ---------- :cite:cts:`woollings_variability_2010` """# Select longitudes in the -60 to 0°E rangelon=ua.cf["longitude"]ilon=(lon>=300)*(lon<=360)+(lon>=-60)*(lon<=0)ifnotilon.any():raiseValueError("Make sure the grid includes longitude values in a range between -60 and 0°E.")# Select latitudes in the 15 to 75°N rangelat=ua.cf["latitude"]ilat=(lat>=15)*(lat<=75)ifnotilat.any():raiseValueError("Make sure the grid includes latitude values in a range between 15 and 75°N.")# Select levels between 750 and 950 hPapmin=convert_units_to("750 hPa",ua.cf["vertical"])pmax=convert_units_to("950 hPa",ua.cf["vertical"])p=ua.cf["vertical"]ip=(p>=pmin)*(p<=pmax)ifnotip.any():raiseValueError("Make sure the grid includes pressure values in a range between 750 and 950 hPa.")ua=ua.cf.sel(vertical=ip,latitude=ilat,longitude=ilon,)zonal_mean=ua.cf.mean(["vertical","longitude"])# apply Lanczos filter - parameters are hard-coded following those used in Woollings (2010)filter_freq=10window_size=61cutoff=1/filter_freqifua.time.size<=filter_freqorua.time.size<=window_size:raiseValueError(f"Time series is too short to apply 61-day Lanczos filter (got a length of {ua.time.size})")# compute low-pass filter weightslanczos_weights=_compute_low_pass_filter_weights(window_size=window_size,cutoff=cutoff)# apply the filterua_lf=(zonal_mean.rolling(time=window_size,center=True).construct("window").dot(lanczos_weights))# Get latitude & eastward wind component unitslat_name=ua.cf["latitude"].namelat_units=ua.cf["latitude"].unitsua_units=ua.unitsjetlat=ua_lf.cf.idxmax(lat_name).rename("jetlat").assign_attrs(units=lat_units)jetstr=ua_lf.cf.max(lat_name).rename("jetstr").assign_attrs(units=ua_units)returnjetlat,jetstr