From 1f4ed2e33c51362a0942bd04da3ee9c1174126a1 Mon Sep 17 00:00:00 2001 From: dgilford Date: Tue, 13 Jan 2026 17:01:08 +0000 Subject: [PATCH] Auto update doc strings --- run_sample.py | 35 +++- src/tcpyPI/pi.py | 261 ++++++++++++++++++------------ src/tcpyPI/utilities.py | 343 +++++++++++++++++++++++++--------------- 3 files changed, 405 insertions(+), 234 deletions(-) diff --git a/run_sample.py b/run_sample.py index 1fce2b3..6404882 100644 --- a/run_sample.py +++ b/run_sample.py @@ -20,7 +20,23 @@ def run_sample_dataset(fn, dim='p',CKCD=0.9): - """ This function calculates PI over the sample dataset using xarray """ + """Calculate potential intensity over the sample dataset with xarray. + + Parameters + ---------- + fn : str + Path to the input dataset (e.g., `data/sample_data.nc`). + dim : str, default="p" + Name of the vertical pressure coordinate in `fn`. + CKCD : float, default=0.9 + Ratio of exchange coefficients (Ck/Cd). + + Returns + ------- + xarray.Dataset + Dataset containing PI outputs (`vmax`, `pmin`, `ifl`, `t0`, `otl`) and the + state variables used in the calculation. + """ # open the sample data file ds = xr.open_dataset(fn) @@ -65,7 +81,20 @@ def run_sample_dataset(fn, dim='p',CKCD=0.9): return out_ds def run_sample_analyses(ds,CKCD=0.9): - """ This function performs PI analyses over the sample dataset using xarray """ + """Compute analysis diagnostics (including log decomposition) on PI outputs. + + Parameters + ---------- + ds : xarray.Dataset + Output from :func:`run_sample_dataset`. + CKCD : float, default=0.9 + Ratio of exchange coefficients (Ck/Cd). + + Returns + ------- + xarray.Dataset + Dataset of diagnostics: `eff`, `diseq`, `lnpi`, `lneff`, `lndiseq`, `lnCKCD`. + """ # calculate PI analyses over the whole data set using the xarray universal function efficiency = xr.apply_ufunc( @@ -147,4 +176,4 @@ def run_sample_analyses(ds,CKCD=0.9): ds3.to_netcdf(datdir+'full_sample_output.nc') del ds, ds2 print('...PI analyses complete and saved') - print('pyPI sample run finished!') \ No newline at end of file + print('pyPI sample run finished!') diff --git a/src/tcpyPI/pi.py b/src/tcpyPI/pi.py index 48db444..0893dd1 100644 --- a/src/tcpyPI/pi.py +++ b/src/tcpyPI/pi.py @@ -55,38 +55,60 @@ def cape(TP,RP,PP,T,R,P,ascent_flag=0,ptop=50,miss_handle=1): Emanuel 1994 (E94) Equation 6.3.6 and TOB is the temperature at the level of neutral buoyancy ("LNB") for the displaced parcel. - Args: - TP (float): Parcel temperature (K) - RP (float): Parcel mixing ratio (gram/gram) - PP (float): Parcel pressure (hPa) - T (array): Environmental temperature profile (K) - R (array): Environmental mixing ratio profile (gram/gram) - P (array): Environmental pressure profile (hPa) - The arrays MUST be arranged so that the lowest index corresponds - to the lowest model level, with increasing index corresponding to - decreasing pressure. - ascent_flag (int, optional): Adjustable constant fraction for buoyancy of displaced parcels. - 0 = Reversible ascent (default) - 1 = Pseudo-adiabatic ascent. - ptop (float, optional): Pressure below which sounding is ignored (hPa). Defaults to 50. - miss_handle (int, optional): Flag for handling missing values. - 0 = ignore NaN (BE02 default) - NaN values in profile are ignored and PI is still calcuated. - 1 = return missing values (pyPI default) - given NaN values PI will be set to missing (with IFLAG=3) - NOTE: If any missing values are between the lowest valid level and ptop - then PI will automatically be set to missing (with IFLAG=3) - - Returns: - tuple: (CAPED, TOB, LNB, IFLAG) where: - - CAPED (float): Convective Available Potential Energy (J/kg) - - TOB (float): Temperature at level of neutral buoyancy (K) - - LNB (float): Level of neutral buoyancy pressure (hPa) - - IFLAG (int): Status flag where: - 1 = Success - 0 = Improper sounding/parcel - 2 = Did not converge - 3 = Missing values in input profile + Parameters + ---------- + TP : float + Parcel temperature (K). + RP : float + Parcel mixing ratio (gram/gram). + PP : float + Parcel pressure (hPa). + T : array + Environmental temperature profile (K). + R : array + Environmental mixing ratio profile (gram/gram). + P : array + Environmental pressure profile (hPa). + + The arrays MUST be arranged so that the lowest index corresponds to the + lowest model level, with increasing index corresponding to decreasing + pressure. + ascent_flag : int, default=0 + Adjustable constant fraction for buoyancy of displaced parcels. + + - ``0``: reversible ascent + - ``1``: pseudo-adiabatic ascent + ptop : float, default=50 + Pressure below which sounding is ignored (hPa). + miss_handle : int, default=1 + Flag for handling missing values. + + - ``0``: ignore NaN (BE02 default); NaNs in the profile are ignored and + CAPE may still be calculated. + - ``1``: return missing values (pyPI default); any NaNs set outputs to + missing with ``IFLAG=3``. + + NOTE: If any missing values are between the lowest valid level and `ptop`, + outputs are set to missing with ``IFLAG=3`` regardless of `miss_handle`. + + Returns + ------- + tuple + ``(CAPED, TOB, LNB, IFLAG)`` where: + + - CAPED : float + Convective available potential energy (J/kg). + - TOB : float + Temperature at level of neutral buoyancy (K). + - LNB : float + Level of neutral buoyancy pressure (hPa). + - IFLAG : int + Status flag: + + - ``1``: success + - ``0``: improper sounding/parcel + - ``2``: did not converge + - ``3``: missing values in input profile """ # # *** Handle missing values *** @@ -309,21 +331,34 @@ def solve_temperature_from_entropy(S, P, RP, T_initial): saturated entropy to find the temperature T that satisfies SG(T) = S for a target value of saturated entropy S. - Args: - S (float): Target saturated entropy (J/kg/K). - P (float): Ambient pressure (hPa). - RP (float): Parcel mixing ratio for the dry component (g/g). - T_initial (float): Initial guess for temperature (K). - - Returns: - tuple: (TG, RG, IFLAG) where: - TG (float): Temperature (K) satisfying SG(T) = S. - RG (float): Computed saturated mixing ratio (g/g). - IFLAG (int): Status flag where: - 1 = Success - 2 = Did not converge - - Examples: + Parameters + ---------- + S : float + Target saturated entropy (J/kg/K). + P : float + Ambient pressure (hPa). + RP : float + Parcel mixing ratio for the dry component (g/g). + T_initial : float + Initial guess for temperature (K). + + Returns + ------- + tuple + ``(TG, RG, IFLAG)`` where: + + - TG : float + Temperature (K) satisfying ``SG(T) = S``. + - RG : float + Computed saturated mixing ratio (g/g). + - IFLAG : int + Status flag: + + - ``1``: success + - ``2``: did not converge + + Examples + -------- >>> S = 4000 >>> P = 1000 >>> RP = 0.01 @@ -408,61 +443,83 @@ def pi(SSTC,MSL,P,TC,R,CKCD=0.9,ascent_flag=0,diss_flag=1,V_reduc=0.8,ptop=50,mi Thermodynamic and dynamic technical backgrounds (and calculations) are found in Bister and Emanuel (2002; BE02) and Emanuel's "Atmospheric Convection" (E94; 1994; ISBN: 978-0195066302). - Args: - SSTC (float): Sea surface temperature (C) - MSL (float): Mean sea level pressure (hPa) - P (array): Pressure levels (hPa) - TC (array): Temperature profile (C) - R (array): Mixing ratio profile (g/kg) - The arrays MUST be arranged so that the lowest index corresponds - to the lowest model level, with increasing index corresponding to - decreasing pressure. The temperature sounding should extend to at least - the tropopause and preferably to the lower stratosphere, however the - mixing ratios are not important above the boundary layer. Missing - mixing ratios can be replaced by zeros. - CKCD (float, optional): Ratio of C_k to C_D (unitless) - Defaults to 0.9 - The ratio of the exchange coefficients of enthalpy and momentum flux - (e.g. see Bister and Emanuel 1998, EQN. 17-18). More discussion - on CK/CD is found in Emanuel (2003). Default is 0.9 based - on e.g. Wing et al. (2015) - ascent_flag (int, optional): Adjustable constant fraction for buoyancy (unitless) - 0 = Reversible ascent (default) - 1 = Pseudo-adiabatic ascent - diss_flag (int, optional): Switch for dissipative heating - 1 = Allowed (default) - 0 = Disallowed - See Bister and Emanuel (1998) for inclusion of dissipative heating. - V_reduc (float, optional): Reduction factor from gradient winds to 10m winds (unitless) - Defaults to 0.8. - See Emanuel (2000) and Powell (1980). - ptop (float, optional): Pressure below which sounding is ignored (hPa). - Defaults to 50. - miss_handle (int, optional): Flag for handling missing values. - 0 = ignore NaN (BE02 default) - NaN values in profile are ignored and PI is still calculated - 1 = return missing values (pyPI default) - given NaN values PI will be set to missing (with IFL=3) - NOTE: If any missing values are between the lowest valid level and ptop - then PI will automatically be set to missing (with IFL=3) - - Returns: - tuple: (VMAX, PMIN, IFL, TO, OTL) where: - - VMAX (float): Maximum surface wind speed (m/s) - reduced to reflect surface drag via V_reduc - - PMIN (float): Minimum central pressure (hPa) - - IFL (int): Status flag where: - 1 = Success - 0 = No convergence - 2 = CAPE routine failed to converge - 3 = CAPE routine failed due to missing data - - TO (float): Outflow temperature (K) - - OTL (float): Outflow temperature level (hPa) - Defined as the level of neutral bouyancy - where the outflow temperature is found, i.e. where buoyancy is actually equal - to zero under the condition of an air parcel that is saturated at sea level pressure - - Example: + Parameters + ---------- + SSTC : float + Sea surface temperature (C). + MSL : float + Mean sea level pressure (hPa). + P : array + Pressure levels (hPa). + TC : array + Temperature profile (C). + R : array + Mixing ratio profile (g/kg). + + The arrays MUST be arranged so that the lowest index corresponds to the + lowest model level, with increasing index corresponding to decreasing + pressure. The temperature sounding should extend to at least the tropopause + and preferably to the lower stratosphere; mixing ratios are not important + above the boundary layer. Missing mixing ratios can be replaced by zeros. + CKCD : float, default=0.9 + Ratio of C_k to C_D (unitless). + + The ratio of the exchange coefficients of enthalpy and momentum flux + (e.g. see Bister and Emanuel 1998, EQN. 17-18). More discussion on Ck/Cd is + found in Emanuel (2003). Default is 0.9 based on e.g. Wing et al. (2015). + ascent_flag : int, default=0 + Adjustable constant fraction for buoyancy (unitless). + + - ``0``: reversible ascent + - ``1``: pseudo-adiabatic ascent + diss_flag : int, default=1 + Switch for dissipative heating. + + - ``1``: allowed + - ``0``: disallowed + + See Bister and Emanuel (1998) for inclusion of dissipative heating. + V_reduc : float, default=0.8 + Reduction factor from gradient winds to 10 m winds (unitless). + See Emanuel (2000) and Powell (1980). + ptop : float, default=50 + Pressure below which sounding is ignored (hPa). + miss_handle : int, default=1 + Flag for handling missing values. + + - ``0``: ignore NaN (BE02 default); NaN values in the profile are ignored + and PI may still be calculated. + - ``1``: return missing values (pyPI default); any NaNs set outputs to + missing with ``IFL=3``. + + NOTE: If any missing values are between the lowest valid level and `ptop`, + outputs are set to missing with ``IFL=3`` regardless of `miss_handle`. + + Returns + ------- + tuple + ``(VMAX, PMIN, IFL, TO, OTL)`` where: + + - VMAX : float + Maximum surface wind speed (m/s), reduced by `V_reduc`. + - PMIN : float + Minimum central pressure (hPa). + - IFL : int + Status flag: + + - ``1``: success + - ``0``: no convergence + - ``2``: CAPE routine failed to converge + - ``3``: CAPE routine failed due to missing data + - TO : float + Outflow temperature (K). + - OTL : float + Outflow temperature level (hPa), defined as the level of neutral buoyancy + where the outflow temperature is found (buoyancy equal to zero for a parcel + saturated at sea level pressure). + + Examples + -------- >>> SSTC = 30 >>> MSL = 1010 >>> level_data = np.array( diff --git a/src/tcpyPI/utilities.py b/src/tcpyPI/utilities.py index 686029c..44753a3 100644 --- a/src/tcpyPI/utilities.py +++ b/src/tcpyPI/utilities.py @@ -1,4 +1,4 @@ -"""Helper functions used throughout tcpyPI""" +"""Helper functions used throughout tcpyPI.""" # doctest: +ELLIPSIS import numpy as np @@ -10,14 +10,19 @@ def convert_lon_to180(lon360): """Convert longitudes from 0-360E to 180W-180E. - - Args: - lon360 (float): Longitude in 0-360E format - - Returns: - float: Longitude in 180W-180E format - - Examples: + + Parameters + ---------- + lon360 : float + Longitude in 0-360E format. + + Returns + ------- + float + Longitude in 180W-180E format. + + Examples + -------- >>> convert_lon_to180(0) 0 >>> convert_lon_to180(180) @@ -32,14 +37,19 @@ def convert_lon_to180(lon360): def convert_lon_to360(lon180): """Convert longitudes from 180W-180E to 0-360E. - - Args: - lon180 (float): Longitude in 180W-180E format - - Returns: - float: Longitude in 0-360E format - - Examples: + + Parameters + ---------- + lon180 : float + Longitude in 180W-180E format. + + Returns + ------- + float + Longitude in 0-360E format. + + Examples + -------- >>> convert_lon_to360(-1) 359 >>> convert_lon_to360(0) @@ -59,14 +69,19 @@ def convert_lon_to360(lon180): @njit() def T_ktoC(Tk): """Convert kelvin to degrees Celsius. - - Args: - Tk (float): Temperature in kelvin - - Returns: - float: Temperature in degrees Celsius - - Examples: + + Parameters + ---------- + Tk : float + Temperature in kelvin. + + Returns + ------- + float + Temperature in degrees Celsius. + + Examples + -------- >>> T_ktoC(273.15) 0.0 >>> T_ktoC(283.15) @@ -77,14 +92,19 @@ def T_ktoC(Tk): @njit() def T_Ctok(TC): """Convert degrees Celsius to kelvin. - - Args: - TC (float): Temperature in degrees Celsius - - Returns: - float: Temperature in kelvin - - Examples: + + Parameters + ---------- + TC : float + Temperature in degrees Celsius. + + Returns + ------- + float + Temperature in kelvin. + + Examples + -------- >>> T_Ctok(0) 273.15 >>> T_Ctok(10) @@ -97,14 +117,19 @@ def T_Ctok(TC): @njit() def es_cc(TC): """Calculate saturated water vapor pressure from Clausius-Clapeyron relation/August-Roche-Magnus formula. - - Args: - TC (float): Temperature in Celsius - - Returns: - float: Saturation vapor pressure in hPa - - Examples: + + Parameters + ---------- + TC : float + Temperature in degrees Celsius. + + Returns + ------- + float + Saturation vapor pressure in hPa. + + Examples + -------- >>> es_cc(20) 23.369... >>> es_cc(0) @@ -115,14 +140,19 @@ def es_cc(TC): @njit() def Lv(TC): """Calculate latent heat of vaporization as a function of temperature. - - Args: - TC (float): Temperature in Celsius - - Returns: - float: Latent heat of vaporization in J/kg - - Examples: + + Parameters + ---------- + TC : float + Temperature in degrees Celsius. + + Returns + ------- + float + Latent heat of vaporization in J/kg. + + Examples + -------- >>> Lv(0) 2501000.0 >>> Lv(20) @@ -133,15 +163,21 @@ def Lv(TC): @njit() def ev(R,P): """Calculate parcel vapor pressure. - - Args: - R (float): Mixing ratio in gram/gram - P (float): Pressure in hPa - - Returns: - float: Vapor pressure in hPa - - Examples: + + Parameters + ---------- + R : float + Mixing ratio in gram/gram. + P : float + Pressure in hPa. + + Returns + ------- + float + Vapor pressure in hPa. + + Examples + -------- >>> ev(0.01, 1000) 15.823... >>> ev(0.02, 1000) @@ -152,15 +188,21 @@ def ev(R,P): @njit() def rv(E,P): """Calculate parcel mixing ratio. - - Args: - E (float): Vapor pressure in hPa - P (float): Pressure in hPa - - Returns: - float: Mixing ratio in gram/gram - - Examples: + + Parameters + ---------- + E : float + Vapor pressure in hPa. + P : float + Pressure in hPa. + + Returns + ------- + float + Mixing ratio in gram/gram. + + Examples + -------- >>> rv(15.942, 1000) 0.010076... >>> rv(31.250, 1000) @@ -171,16 +213,23 @@ def rv(E,P): @njit() def entropy_S(T,R,P): """Calculate total specific entropy per unit mass of dry air (E94, EQN. 4.5.9). - - Args: - T (float): Temperature in kelvin - R (float): Mixing ratio in gram/gram - P (float): Pressure in hPa - - Returns: - float: Specific entropy - - Examples: + + Parameters + ---------- + T : float + Temperature in kelvin. + R : float + Mixing ratio in gram/gram. + P : float + Pressure in hPa. + + Returns + ------- + float + Specific entropy per unit mass of dry air. + + Examples + -------- >>> entropy_S(300, 0.01, 1000) 3987.17... >>> entropy_S(290, 0.005, 900) @@ -196,16 +245,23 @@ def entropy_S(T,R,P): @njit() def Trho(T,RT,R): """Calculate density temperature in K. - - Args: - T (float): Temperature in kelvin - RT (float): Total water content mixing ratio in gram/gram - R (float): Parcel water vapor mixing ratio in gram/gram - - Returns: - float: Density temperature in kelvin - - Examples: + + Parameters + ---------- + T : float + Temperature in kelvin. + RT : float + Total water content mixing ratio in gram/gram. + R : float + Parcel water vapor mixing ratio in gram/gram. + + Returns + ------- + float + Density temperature in kelvin. + + Examples + -------- >>> Trho(300, 0.02, 0.01) 298.84... >>> Trho(290, 0.01, 0.005) @@ -216,16 +272,23 @@ def Trho(T,RT,R): @njit() def e_pLCL(TP,RH,PP): """Calculate empirical lifting condensation level pressure (pLCL). - - Args: - TP (float): Parcel temperature in kelvin - RH (float): Relative humidity (0-1) - PP (float): Parcel pressure in hPa - - Returns: - float: LCL pressure in hPa - - Examples: + + Parameters + ---------- + TP : float + Parcel temperature in kelvin. + RH : float + Relative humidity (0-1). + PP : float + Parcel pressure in hPa. + + Returns + ------- + float + LCL pressure in hPa. + + Examples + -------- >>> e_pLCL(300, 0.8, 1000) 948.70... >>> e_pLCL(290, 0.7, 900) @@ -238,15 +301,21 @@ def e_pLCL(TP,RH,PP): @njit() def pi_efficiency(sstk,t0): """Calculate TC efficiency. - - Args: - sstk (float): Sea surface temperature in kelvin - t0 (float): Outflow temperature in kelvin - - Returns: - float: TC efficiency - - Examples: + + Parameters + ---------- + sstk : float + Sea surface temperature in kelvin. + t0 : float + Outflow temperature in kelvin. + + Returns + ------- + float + TC efficiency (unitless). + + Examples + -------- >>> pi_efficiency(300, 200) 0.5 >>> pi_efficiency(295, 210) @@ -258,17 +327,25 @@ def pi_efficiency(sstk,t0): @njit() def pi_diseq_resid(pi,sstk,t0,CKCD=0.9): """Calculate TC air-sea thermodynamic disequilibrium as a residual from Bister and Emanuel (1998; BE98) EQN. 21. - - Args: - pi (float): Potential intensity in m/s - sstk (float): Sea surface temperature in kelvin - t0 (float): Outflow temperature in kelvin - CKCD (float, optional): Ratio of exchange coefficients. Defaults to 0.9. - - Returns: - float: Disequilibrium - - Examples: + + Parameters + ---------- + pi : float + Potential intensity in m/s. + sstk : float + Sea surface temperature in kelvin. + t0 : float + Outflow temperature in kelvin. + CKCD : float, default=0.9 + Ratio of exchange coefficients (Ck/Cd). + + Returns + ------- + float + Thermodynamic disequilibrium (J/kg). + + Examples + -------- >>> pi_diseq_resid(70, 300, 200, 0.9) 10888.88... >>> pi_diseq_resid(50, 295, 210, 0.9) @@ -281,17 +358,25 @@ def pi_diseq_resid(pi,sstk,t0,CKCD=0.9): @njit() def decompose_pi(pi,sstk,t0,CKCD=0.9): """Perform decomposition of TC PI terms from Wing et al. (2015), EQN. 2. - - Args: - pi (float): Potential intensity in m/s - sstk (float): Sea surface temperature in kelvin - t0 (float): Outflow temperature in kelvin - CKCD (float, optional): Ratio of exchange coefficients. Defaults to 0.9. - - Returns: - tuple: (lnpi, lneff, lndiseq, lnCKCD) - - Examples: + + Parameters + ---------- + pi : float + Potential intensity in m/s. + sstk : float + Sea surface temperature in kelvin. + t0 : float + Outflow temperature in kelvin. + CKCD : float, default=0.9 + Ratio of exchange coefficients (Ck/Cd). + + Returns + ------- + tuple + ``(lnpi, lneff, lndiseq, lnCKCD)`` where ``lnpi = ln(pi^2)``. + + Examples + -------- >>> decompose_pi(70, 300, 200, 0.9) (8.496..., -0.693..., 9.295..., -0.105...) >>> decompose_pi(50, 295, 210, 0.9) @@ -326,4 +411,4 @@ def decompose_pi(pi,sstk,t0,CKCD=0.9): else: return(np.nan,lneff,np.nan,lnCKCD) else: - return(np.nan,np.nan,np.nan,lnCKCD) \ No newline at end of file + return(np.nan,np.nan,np.nan,lnCKCD)