### Import Libraries for Thermofeel Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Imports all the necessary libraries for using the thermofeel notebook examples. Ensure all these libraries are installed in your environment. ```python #These are all the libraries you will need to use this notebook import matplotlib.pyplot as plt import cartopy.crs as ccrs import xarray as xr import pandas as pd import numpy as np import matplotlib.pyplot as plt import thermofeel as tf import metview as mv import cfgrib import eccodes import Magics as magics from Magics import macro as magics ``` -------------------------------- ### Install thermofeel Source: https://context7.com/ecmwf/thermofeel/llms.txt Install the thermofeel library using pip. This is the first step before importing and using the library. ```bash pip install thermofeel ``` -------------------------------- ### Install thermofeel with pip Source: https://github.com/ecmwf/thermofeel/blob/main/CONTRIBUTING.rst Use this command to install the thermofeel package from PyPI. Ensure you have pip installed. ```bash $ pip install thermofeel ``` -------------------------------- ### Initialize Seaborn for Correlation Heatmap Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Initializes the seaborn library for plotting, setting the style to 'whitegrid' and the context to 'paper' with a font scale of 0.9. This setup is typically used before creating visualizations like heatmaps. ```python #Using the seaborn library to plot a correlation heatmap import seaborn as sns sns.set_style("whitegrid") sns.set_context("paper", font_scale=0.9) ``` -------------------------------- ### Create Magics Plot for Apparent Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Generates a Magics plot for apparent temperature, allowing customization of the map area, coastlines, color levels, and legend. This example specifically crops the plot to the African continent. ```python #This is a simple magics plot example more detailed examples can be found: # https://github.com/ecmwf/notebook-examples #Select one of the datasets for a variable here we are using apparent temperature for step 12 data_grib = magics.mxarray(xarray_dataset = aptmpnds, xarray_variable_name = "aptmp") #area can be used to crop to any region of the world, not using this parameter returns the full area plot #here we are plotting for the African Continent area = magics.mmap(subpage_map_projection="cylindrical", subpage_lower_left_longitude=-20., subpage_lower_left_latitude=-50, subpage_upper_right_longitude=50, subpage_upper_right_latitude=50, ) coastlines = magics.mcoast() #This sets how you cut up the colour palette levels = [-40.,-27,-13,0,20,27,32,39,51,60,70] contour = magics.mcont( legend= "on", contour ="off", contour_label="off", contour_level_selection_type = "level_list", contour_level_list = levels, contour_shade = 'on', contour_shade_method = 'area_fill', contour_shade_colour_method = 'palette', contour_shade_palette_name = "m_green_purple_11") legend = magics.mlegend(legend_display_type = "continuous", legend_text_font_size = 0.4, legend_text_colour = '#000000') magics.plot(area,data_grib,contour,coastlines,legend) ``` -------------------------------- ### Full Pipeline: NWP Gridded Data to Multiple Indices Source: https://context7.com/ecmwf/thermofeel/llms.txt A complete end-to-end workflow computing MRT, UTCI, WBGT, and Humidex from NWP model output fields (numpy arrays representing global or regional grids). This pipeline demonstrates the integration of multiple thermofeel functions for comprehensive thermal comfort analysis. ```python import thermofeel import numpy as np # ── Simulated NWP output (1D arrays over a grid) ────────────────────────────── N = 5 # grid points t2_k = np.array([298.15, 303.15, 308.15, 288.15, 278.15]) # 2m temperature [K] td_k = np.array([290.15, 294.15, 298.15, 280.15, 268.15]) # 2m dew point [K] va = np.array([2.0, 3.0, 1.0, 8.0, 12.0]) # 10m wind speed [m/s] # Radiation fluxes [W m-2] (time-averaged over forecast step) ssrd = np.array([350.0, 400.0, 450.0, 200.0, 0.0]) ssr = np.array([280.0, 320.0, 360.0, 160.0, 0.0]) fdir = np.array([250.0, 300.0, 350.0, 120.0, 0.0]) strd = np.array([340.0, 350.0, 360.0, 310.0, 290.0]) strr = np.array([-25.0, -30.0, -35.0, -15.0, -5.0]) cossza = np.array([0.75, 0.80, 0.85, 0.50, 0.0]) # ── Step 1: Approximate dsrp from fdir and cossza ───────────────────────────── dsrp = thermofeel.approximate_dsrp(fdir, cossza, threshold=0.1) # ── Step 2: Mean Radiant Temperature ────────────────────────────────────────── mrt = thermofeel.calculate_mean_radiant_temperature(ssrd, ssr, dsrp, strd, fdir, strr, cossza) # ── Step 3: Relative humidity and vapour pressure ───────────────────────────── rh = thermofeel.calculate_relative_humidity_percent(t2_k, td_k) ehPa = thermofeel.calculate_saturation_vapour_pressure(t2_k) * rh / 100.0 # ── Step 4: Primary thermal indices ─────────────────────────────────────────── utci = thermofeel.calculate_utci(t2_k, va, mrt, ehPa=ehPa) wbgt = thermofeel.calculate_wbgt(t2_k, mrt, va, td_k) humidex = thermofeel.calculate_humidex(t2_k, td_k) at = thermofeel.calculate_apparent_temperature(t2_k, va, rh) wc = thermofeel.calculate_wind_chill(t2_k, va) # ── Step 5: Convert outputs to Celsius for reporting ────────────────────────── print("UTCI (°C):", np.round(thermofeel.kelvin_to_celsius(utci), 1)) print("WBGT (°C):", np.round(thermofeel.kelvin_to_celsius(wbgt), 1)) print("Humidx (°C):", np.round(thermofeel.kelvin_to_celsius(humidex), 1)) print("AT (°C):", np.round(thermofeel.kelvin_to_celsius(at), 1)) print("WChill (°C):", np.round(thermofeel.kelvin_to_celsius(wc), 1)) ``` -------------------------------- ### Load and Process GRIB Data to Pandas DataFrame Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Loads GRIB data, converts it to an xarray dataset, calculates the global area average, and then converts it to a pandas DataFrame. Prints the dataset and the head of the DataFrame. ```python #Create a dataframe from your dataset for the area average of the globe #reading in the same grib as above, but not limiting for one time step gribf = "Nov19thoutputr.grib" data_regular = mv.read(source=gribf,grid=[0.1,0.1]) #This converts our metview object to a xarray dataset dataset = data_regular.to_dataset() print(dataset) #meaning across the area of the globe dataset = dataset.mean(axis=1).mean(axis=1) #This converts out xarray dataset to a pandas dataframe df = dataset.to_dataframe() print(df.head()) ``` -------------------------------- ### Import thermofeel and numpy Source: https://context7.com/ecmwf/thermofeel/llms.txt Import the necessary libraries, thermofeel for calculations and numpy for array manipulation. All functions operate element-wise over numpy arrays. ```python import thermofeel import numpy as np ``` -------------------------------- ### Read and Convert GRIB Data Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Reads a GRIB file using Metview, interpolates it to a specified grid, and converts it to an xarray dataset. Select specific variables like relative humidity, apparent temperature, heat index, and UTCI from the dataset. ```python #Reading in a grib file that was created using a version of compute_utci.py # You could change this grib file to any that contains relative humidity, apparent temperature, heat index and utci. # the grid parameter interpolates the grid here we are using 0.1,0.1 ERA5 uses 0.25,0.25 #step allows you to select a step in time, leaving this parameter blank will select all steps in the grib file gribf = "Nov19thoutputr.grib" data_regular = mv.read(source=gribf,grid=[0.1,0.1],step=12) #This converts our metview object to a xarray dataset ds = data_regular.to_dataset() print(ds) #here we select certain variables from our dataset rhpn = ds['r2'][:] aptmpn = ds['aptmp'][:] hdn = ds['heatx'][:] utcin = ds['utci'][:] ``` -------------------------------- ### Calculate Saturation Vapour Pressure over Water Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/relativehumidity.md Computes saturation vapour pressure over water. The input is 2m air temperature in Kelvin, and the output is in hPa. ```python calculate_saturation_vapour_pressure(2m_temperature) ``` -------------------------------- ### Calculate Saturation Vapour Pressure (Multiphase) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes saturation vapour pressure over liquid water (phase=0) or ice (phase=1) using ECMWF IFS formulas. Use when your dataset contains sub-freezing temperatures requiring ice-phase vapour pressure. ```python import thermofeel import numpy as np t2_k = np.array([260.0, 270.0, 280.0, 290.0]) phase = np.array([1, 1, 0, 0]) # ice below ~273K, liquid above svp_mp = thermofeel.calculate_saturation_vapour_pressure_multiphase(t2_k, phase) print(svp_mp) # [ 1.96... 3.96... 10.02... 19.42...] hPa ``` -------------------------------- ### Calculate Wet Bulb Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/wbgt.md Calculates the wet bulb temperature in Kelvin using 2m temperature in Kelvin and relative humidity percentage. ```python calculate_wbt(2m_temperature, relative_humidity_percent) ``` -------------------------------- ### Create Cartopy Plot Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Sets up a basic Cartopy plot with coastlines and gridlines, and defines the extent to crop the map to a specific region, in this case, Europe. ```python #This is a simple cartopy plot example fig = plt.figure() ax = plt.axes(projection=ccrs.PlateCarree()) ax.coastlines() gl = ax.gridlines(crs=ccrs.PlateCarree(), linewidth=2, color='black', alpha=0.5, linestyle='--', draw_labels=True) ax.set_extent([-20,50,35,70]) # this is cropping the plot to Europe ``` -------------------------------- ### Calculate Normal Effective Temperature (Python) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Normal Effective Temperature (NET) based on Li & Chan (2006). NET represents the temperature in a standard environment that yields the same thermal sensation as the actual conditions at 1.2m wind height. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 298.15, 288.15]) # 30, 25, 15 °C va = np.array([1.0, 3.0, 6.0]) # 10m wind speed [m/s] rh = np.array([70.0, 50.0, 40.0]) # relative humidity [%] net_k = thermofeel.calculate_normal_effective_temperature(t2_k, va, rh) print(thermofeel.kelvin_to_celsius(net_k)) # [30.2... 22.8... 10.4...] °C ``` -------------------------------- ### Plotting Temperature Data with Colorbar Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Plots temperature data using pcolormesh and adds a horizontal colorbar. Sets vmin and vmax to limit the color bar extent. ```python filled_c=plt.pcolormesh(utcinds.longitude,utcinds.latitude,utcinds.utci-273.15, transform=ccrs.PlateCarree(),cmap="RdYlBu_r",vmin=-60,vmax=50) fig.colorbar(filled_c, orientation='horizontal') ``` -------------------------------- ### Calculate Simple WBGT Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/wbgt.md Use this function to calculate the WBGT using 2m temperature in Kelvin and relative humidity percentage. Returns WBGT in Kelvin. ```python calculate_wbgt_simple(2m_temperature, relative_humidity_percent) ``` -------------------------------- ### calculate_heat_index_simplified Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes the simplified Heat Index [K] using a Rothfusz regression valid for temperatures above 20°C. Below 20°C the 2m air temperature is returned unchanged. ```APIDOC ## calculate_heat_index_simplified Computes the simplified Heat Index [K] using a Rothfusz regression valid for temperatures above 20°C. Below 20°C the 2m air temperature is returned unchanged. ```python import thermofeel import numpy as np t2_k = np.array([298.15, 305.15, 313.15]) # 25, 32, 40 °C rh = np.array([50.0, 70.0, 90.0]) # relative humidity [%] hi_k = thermofeel.calculate_heat_index_simplified(t2_k, rh) print(thermofeel.kelvin_to_celsius(hi_k)) # [25.0... 37.9... 57.5...] °C ``` ``` -------------------------------- ### Calculate Non-saturation Vapour Pressure (hPa) Source: https://context7.com/ecmwf/thermofeel/llms.txt Returns the actual vapour pressure in hPa given 2m air temperature and relative humidity. Used as an intermediate variable in Apparent Temperature and WBGT Simple calculations. ```python import thermofeel import numpy as np t2_k = np.array([293.15, 303.15]) # 20 °C, 30 °C rh = np.array([60.0, 80.0]) # 60%, 80% ens = thermofeel.calculate_nonsaturation_vapour_pressure(t2_k, rh) print(ens) # [14.02... 33.94...] hPa ``` -------------------------------- ### Calculate Apparent Temperature Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Apparent Temperature (AT) [K], the perceived equivalent temperature accounting for humidity and wind but not radiation. Valid for shaded outdoor environments. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15, 298.15]) # 30, 35, 25 °C va = np.array([3.0, 1.0, 8.0]) # 10m wind speed [m/s] rh = np.array([60.0, 80.0, 30.0]) # relative humidity [%] at_k = thermofeel.calculate_apparent_temperature(t2_k, va, rh) print(thermofeel.kelvin_to_celsius(at_k)) # [31.7... 38.6... 18.0...] °C ``` -------------------------------- ### Scale Wind Speed to Target Height Source: https://context7.com/ecmwf/thermofeel/llms.txt Scales 10m wind speed to a target height below 10m using the logarithmic wind profile. Required for globe temperature and NET calculations. ```python import thermofeel import numpy as np va_10m = np.array([2.0, 5.0, 10.0]) # wind speed at 10m [m/s] va_1_1m = thermofeel.scale_windspeed(va_10m, h=1.1) # globe thermometer height va_1_2m = thermofeel.scale_windspeed(va_10m, h=1.2) # NET height print(va_1_1m) # [1.34... 3.36... 6.73...] print(va_1_2m) # [1.37... 3.44... 6.87...] ``` -------------------------------- ### calculate_saturation_vapour_pressure_multiphase Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes saturation vapour pressure over liquid water (phase=0) or ice (phase=1) using ECMWF IFS formulas. Use when your dataset contains sub-freezing temperatures requiring ice-phase vapour pressure. ```APIDOC ## `calculate_saturation_vapour_pressure_multiphase` Computes saturation vapour pressure over liquid water (phase=0) or ice (phase=1) using ECMWF IFS formulas. Use when your dataset contains sub-freezing temperatures requiring ice-phase vapour pressure. ```python import thermofeel import numpy as np t2_k = np.array([260.0, 270.0, 280.0, 290.0]) phase = np.array([1, 1, 0, 0]) # ice below ~273K, liquid above svp_mp = thermofeel.calculate_saturation_vapour_pressure_multiphase(t2_k, phase) print(svp_mp) # [ 1.96... 3.96... 10.02... 19.42...] hPa ``` ``` -------------------------------- ### Calculate Relative Humidity Percentage Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/relativehumidity.md Computes relative humidity percentage. The inputs are 2m temperature and 2m dew point temperature in Kelvin, and the output is in percentage. ```python calculate_relative_humidity_percent(2m_temperature, 2m_dew_point_temperature) ``` -------------------------------- ### Approximate Direct Solar Radiation at Surface Source: https://context7.com/ecmwf/thermofeel/llms.txt Approximates direct solar radiation at the surface (dsrp) from total sky direct solar radiation (fdir) and the cosine of the solar zenith angle. Use when dsrp is unavailable; introduces errors as cossza approaches 0. ```python import thermofeel import numpy as np fdir = np.array([500.0, 300.0, 100.0]) # W m-2 cossza = np.array([0.8, 0.5, 0.15]) # cosine of solar zenith angle dsrp = thermofeel.approximate_dsrp(fdir, cossza, threshold=0.1) print(dsrp) # [625. 600. 666.67] W m-2 (last value uses fdir directly; cossza > threshold) ``` -------------------------------- ### Calculate Simplified Heat Index Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes the simplified Heat Index [K] using a Rothfusz regression, valid for temperatures above 20°C. Below 20°C, the 2m air temperature is returned unchanged. ```python import thermofeel import numpy as np t2_k = np.array([298.15, 305.15, 313.15]) # 25, 32, 40 °C rh = np.array([50.0, 70.0, 90.0]) # relative humidity [%] hi_k = thermofeel.calculate_heat_index_simplified(t2_k, rh) print(thermofeel.kelvin_to_celsius(hi_k)) # [25.0... 37.9... 57.5...] °C ``` -------------------------------- ### Calculate Wind Chill Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/windchill.md Use this function to calculate the wind chill. It requires 2m air temperature in Kelvin and 10m wind speed in meters per second. The output is in Kelvin. ```python calculate_wind_chill(2m_temperature, 10m_wind_speed) ``` -------------------------------- ### calculate_wbt Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Wet Bulb Temperature (WBT) [K] from 2m temperature and relative humidity using the method described by Stull (2011). WBT is an intermediate variable used in the full WBGT computation. ```APIDOC ## calculate_wbt Computes Wet Bulb Temperature (WBT) [K] from 2m temperature and relative humidity using Stull (2011). WBT is an intermediate variable used within the full WBGT computation. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15]) # 30, 35 °C rh = np.array([60.0, 80.0]) # relative humidity [%] wbt_k = thermofeel.calculate_wbt(t2_k, rh) print(thermofeel.kelvin_to_celsius(wbt_k)) # [23.4... 31.2...] °C ``` ``` -------------------------------- ### Calculate Saturation Vapour Pressure (hPa) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes saturation vapour pressure over liquid water using the Hardy (1998) ITS-90 formula. Returns values in hPa. Used internally by UTCI and heat index calculations. ```python import thermofeel import numpy as np t2_k = np.array([273.15, 293.15, 303.15, 313.15]) # 0, 20, 30, 40 °C svp = thermofeel.calculate_saturation_vapour_pressure(t2_k) print(svp) # [ 6.11... 23.37... 42.43... 73.77...] hPa ``` -------------------------------- ### Calculate UTCI with Python Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/utci.md Use this snippet to calculate UTCI using 2m air temperature, 10m wind speed, mean radiant temperature, and optionally dew point temperature or water vapour pressure. Ensure inputs are numpy arrays. The output is in Kelvin. ```python rh_pc = calculate_relative_humidity_percent(2m_temperature, 2m_dew_point_temperature) ehPa = calculate_saturation_vapour_pressure(2m_temperature) * rh_pc / 100.0 utci = calculate_utci(2m_temperature, 10m_wind_speed, mean_radiant_temperature, 2m_dew_point_temperature=None, ehPa=None) ``` -------------------------------- ### Calculate Normal Effective Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/net.md Use this function to calculate the Normal Effective Temperature (NET). Ensure inputs are in Kelvin for temperature, m/s for wind speed, and percent for humidity. ```python calculate_net_effective_temperature(2m_temperature, 10m_wind_speed, relative_humidity_percent) ``` -------------------------------- ### calculate_saturation_vapour_pressure Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes saturation vapour pressure over liquid water using the Hardy (1998) ITS-90 formula. Returns values in hPa (equivalent to mBar). Used internally by UTCI and heat index calculations. ```APIDOC ## `calculate_saturation_vapour_pressure` Computes saturation vapour pressure over liquid water using the Hardy (1998) ITS-90 formula. Returns values in hPa (equivalent to mBar). Used internally by UTCI and heat index calculations. ```python import thermofeel import numpy as np t2_k = np.array([273.15, 293.15, 303.15, 313.15]) # 0, 20, 30, 40 °C svp = thermofeel.calculate_saturation_vapour_pressure(t2_k) print(svp) # [ 6.11... 23.37... 42.43... 73.77...] hPa ``` ``` -------------------------------- ### Calculate Adjusted Heat Index (Python) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes the adjusted Heat Index using NOAA/NWS methodology. It uses a simple formula for mild conditions and the full Rothfusz regression for hotter conditions, with additional corrections for specific temperature/humidity scenarios. ```python import thermofeel import numpy as np t2_k = np.array([300.15, 307.15, 315.15]) # 27, 34, 42 °C td_k = np.array([293.15, 298.15, 303.15]) # 20, 25, 30 °C hi_adj_k = thermofeel.calculate_heat_index_adjusted(t2_k, td_k) print(thermofeel.kelvin_to_celsius(hi_adj_k)) # [28.5... 40.8... 58.2...] °C ``` -------------------------------- ### Calculate Wet Bulb Temperature (Python) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Wet Bulb Temperature (WBT) from air temperature and relative humidity using Stull (2011). WBT is an intermediate variable used in the full WBGT computation. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15]) # 30, 35 °C rh = np.array([60.0, 80.0]) # relative humidity [%] wbt_k = thermofeel.calculate_wbt(t2_k, rh) print(thermofeel.kelvin_to_celsius(wbt_k)) # [23.4... 31.2...] °C ``` -------------------------------- ### calculate_apparent_temperature Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Apparent Temperature (AT) [K] — the perceived equivalent temperature accounting for humidity and wind but not radiation — following Steadman (1984) and the Australian Bureau of Meteorology approximation. Valid for shaded outdoor environments. ```APIDOC ## calculate_apparent_temperature Computes Apparent Temperature (AT) [K] — the perceived equivalent temperature accounting for humidity and wind but not radiation — following Steadman (1984) and the Australian Bureau of Meteorology approximation. Valid for shaded outdoor environments. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15, 298.15]) # 30, 35, 25 °C va = np.array([3.0, 1.0, 8.0]) # 10m wind speed [m/s] rh = np.array([60.0, 80.0, 30.0]) # relative humidity [%] at_k = thermofeel.calculate_apparent_temperature(t2_k, va, rh) print(thermofeel.kelvin_to_celsius(at_k)) # [31.7... 38.6... 18.0...] °C ``` ``` -------------------------------- ### Calculate Simplified Heat Index Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/heatindex.md Use this function to compute the simplified Heat Index. Requires 2m air temperature in Kelvin and relative humidity as a percentage. Input should be numpy arrays. Returns HI in Kelvin. ```python calculate_heat_index_simplified(2m_temperature, relative_humidity_percent) ``` -------------------------------- ### scale_windspeed Source: https://context7.com/ecmwf/thermofeel/llms.txt Scales 10m wind speed to a target height h (where h < 10m) using the logarithmic wind profile. This is required internally before globe temperature and NET calculations. ```APIDOC ## scale_windspeed Scales 10m wind speed to a target height `h` (where h < 10m) using the logarithmic wind profile (Bröde et al. 2012). Required internally before globe temperature and NET calculations. ```python import thermofeel import numpy as np va_10m = np.array([2.0, 5.0, 10.0]) # wind speed at 10m [m/s] va_1_1m = thermofeel.scale_windspeed(va_10m, h=1.1) # globe thermometer height va_1_2m = thermofeel.scale_windspeed(va_10m, h=1.2) # NET height print(va_1_1m) # [1.34... 3.36... 6.73...] print(va_1_2m) # [1.37... 3.44... 6.87...] ``` ``` -------------------------------- ### Create Scatter Matrix with Density Plots Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Generates a scatter matrix for selected variables from a pandas DataFrame. Uses density curves on the diagonal and specifies colors for the plots. Includes a commented-out line for saving the figure. ```python #Making a Scatter Matrix of our dataframe #This line plots a scatter matrix, with a density curve in the middle in a dark orchid colour pd.plotting.scatter_matrix(df[['t2m','r2','aptmp','heatx','utci']],color='darkorchid',diagonal='kde',density_kwds={'color':'darkorchid'}) #use the below line to save out a figure #plt.savefig("ScatterMatrix.png",dpi=300) ``` -------------------------------- ### Temperature Unit Converters Source: https://context7.com/ecmwf/thermofeel/llms.txt Utility functions for converting temperatures between Celsius, Kelvin, and Fahrenheit. All thermofeel functions require temperatures in Kelvin. ```python from thermofeel.helpers import ( celsius_to_kelvin, kelvin_to_celsius, kelvin_to_fahrenheit, fahrenheit_to_kelvin, ) t_c = np.array([0.0, 20.0, 37.0, 100.0]) t_k = celsius_to_kelvin(t_c) # array([273.15, 293.15, 310.15, 373.15]) t_back = kelvin_to_celsius(t_k) # array([ 0., 20., 37., 100.]) t_f = kelvin_to_fahrenheit(t_k) # array([ 32., 68., 98.6, 212.]) t_k2 = fahrenheit_to_kelvin(t_f) # array([273.15, 293.15, 310.15, 373.15]) ``` -------------------------------- ### Calculate Globe Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/wbgt.md Calculates the globe temperature in Kelvin. Requires 2m temperature, mean radiant temperature (both in Kelvin), and 10m wind speed in meters per second. ```python calculate_bgt(2m_temperature, mean_radiant_temperature, 10m_wind_speed) ``` -------------------------------- ### Calculate Relative Humidity (%) Source: https://context7.com/ecmwf/thermofeel/llms.txt Calculates relative humidity in percent using the Magnus formula from 2m air temperature and 2m dew point temperature in Kelvin. This is required for UTCI, WBGT, and other indices. ```python import thermofeel import numpy as np # 2m temperature and dew point in Kelvin t2_k = np.array([293.15, 303.15, 313.15]) # 20, 30, 40 °C td_k = np.array([283.15, 293.15, 293.15]) # 10, 20, 20 °C rh = thermofeel.calculate_relative_humidity_percent(t2_k, td_k) print(rh) # [52.08... 52.08... 30.38...] # relative humidity in % ``` -------------------------------- ### Calculate Adjusted Heat Index Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/heatindex.md Use this function to compute the adjusted Heat Index. Requires 2m air temperature and 2m dew point temperature in Kelvin. Input should be numpy arrays. Returns HI in Kelvin. ```python calculate_heat_index_adjusted(2m_temperature, 2m_dew_point_temperature) ``` -------------------------------- ### Calculate Simple WBGT (Python) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Wet Bulb Globe Temperature (WBGT Simple) using the ACSM (1984) approximation. This method is faster but less accurate than the full WBGT calculation and is suitable when only air temperature and relative humidity are available. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15, 313.15]) # 30, 35, 40 °C rh = np.array([50.0, 65.0, 80.0]) # relative humidity [%] wbgt_s_k = thermofeel.calculate_wbgt_simple(t2_k, rh) print(thermofeel.kelvin_to_celsius(wbgt_s_k)) # [24.3... 30.4... 37.4...] °C # 20–25: low risk | 25–31: moderate risk | ≥31: high risk ``` -------------------------------- ### calculate_wbgt_simple Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Wet Bulb Globe Temperature (WBGT Simple) [K] using the ACSM (1984) approximation. This method uses 2m temperature and relative humidity and is faster but less accurate than the full WBGT calculation, suitable when only T and RH are available. ```APIDOC ## calculate_wbgt_simple Computes Wet Bulb Globe Temperature (WBGT Simple) [K] using the ACSM (1984) approximation from 2m temperature and relative humidity. Faster but less accurate than the full WBGT; suitable when only T and RH are available. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15, 313.15]) # 30, 35, 40 °C rh = np.array([50.0, 65.0, 80.0]) # relative humidity [%] wbgt_s_k = thermofeel.calculate_wbgt_simple(t2_k, rh) print(thermofeel.kelvin_to_celsius(wbgt_s_k)) # [24.3... 30.4... 37.4...] °C # 20–25: low risk | 25–31: moderate risk | ≥31: high risk ``` ``` -------------------------------- ### Calculate Mean Radiant Temperature from Globe Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/mrt.md Calculates the Mean Global Radiant Temperature using 2m air temperature, 2m wet bulb temperature, and 10m wind speed. Temperatures should be in Kelvin and wind speed in meters per second. Expects numpy arrays as input and returns the mean global radiant temperature in Kelvin. ```APIDOC ## calculate_mrt_from_bgt ### Description Calculates the Mean Global Radiant Temperature from 2m air temperature, 2m wet bulb temperature, and 10m wind speed. ### Parameters - **2m_temperature** (numpy.ndarray) - 2m air temperature (Kelvin) - **2m_wet_bulb_globe_temperature** (numpy.ndarray) - 2m wet bulb temperature (Kelvin) - **10m_wind_speed** (numpy.ndarray) - 10m wind speed (m/s) ### Returns - **mrt** (numpy.ndarray) - Mean Global Radiant Temperature (Kelvin) ``` -------------------------------- ### calculate_relative_humidity_percent Source: https://context7.com/ecmwf/thermofeel/llms.txt Calculates relative humidity (%) from 2m air temperature and 2m dew point temperature using the Magnus formula. Required as an intermediate step for UTCI, WBGT, and several other indices. ```APIDOC ## `calculate_relative_humidity_percent` Calculates relative humidity (%) from 2m air temperature and 2m dew point temperature using the Magnus formula. Required as an intermediate step for UTCI, WBGT, and several other indices. ```python import thermofeel import numpy as np # 2m temperature and dew point in Kelvin t2_k = np.array([293.15, 303.15, 313.15]) # 20, 30, 40 °C td_k = np.array([283.15, 293.15, 293.15]) # 10, 20, 20 °C rh = thermofeel.calculate_relative_humidity_percent(t2_k, td_k) print(rh) # [52.08... 52.08... 30.38...] # relative humidity in % ``` ``` -------------------------------- ### Calculate Universal Thermal Climate Index (UTCI) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes the Universal Thermal Climate Index (UTCI) [K] using a 6th-order polynomial approximation. Accepts dew point temperature (td_k) or water vapour pressure (ehPa). UTCI is a primary index for outdoor heat stress assessment. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15]) # 30, 35 °C va = np.array([2.0, 0.5]) # 10m wind speed [m/s] mrt = np.array([315.0, 320.0]) # mean radiant temperature [K] td_k = np.array([293.15, 295.15]) # dew point temperature [K] # Using dew point utci_k = thermofeel.calculate_utci(t2_k, va, mrt, td_k=td_k) print(thermofeel.kelvin_to_celsius(utci_k)) # [37.8... 46.2...] °C → "Strong heat stress" / "Very strong heat stress" # Alternatively, supply water vapour pressure directly rh_pc = thermofeel.calculate_relative_humidity_percent(t2_k, td_k) ehPa = thermofeel.calculate_saturation_vapour_pressure(t2_k) * rh_pc / 100.0 utci_k2 = thermofeel.calculate_utci(t2_k, va, mrt, ehPa=ehPa) print(thermofeel.kelvin_to_celsius(utci_k2)) # [37.8... 46.2...] °C (identical result) # UTCI stress categories (°C): # > 46 Extreme heat stress | 38–46 Very strong | 32–38 Strong # 26–32 Moderate | 9–26 No stress | 0–9 Slight cold # 0 to -13 Moderate cold | -13 to -27 Strong cold | < -40 Extreme cold ``` -------------------------------- ### Calculate Apparent Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/apparenttemperature.md Use this function to calculate the apparent temperature. It requires 2m air temperature in Kelvin, 10m wind speed in meters per second, and relative humidity as a percentage. The function returns the apparent temperature in Kelvin. ```python calculate_apparent_temperature(2m_temperature, 10m_wind_speed, relative_humidity_percent) ``` -------------------------------- ### Temperature Unit Converters Source: https://context7.com/ecmwf/thermofeel/llms.txt Utility functions for converting temperatures between Celsius, Kelvin, and Fahrenheit. All thermofeel functions require temperatures in Kelvin. ```APIDOC ## Temperature Unit Converters Utility functions for converting between Celsius, Kelvin, and Fahrenheit. All thermofeel functions require temperatures in Kelvin; use these helpers when preprocessing data. ```python from thermofeel.helpers import ( celsius_to_kelvin, kelvin_to_celsius, kelvin_to_fahrenheit, fahrenheit_to_kelvin, ) t_c = np.array([0.0, 20.0, 37.0, 100.0]) t_k = celsius_to_kelvin(t_c) # array([273.15, 293.15, 310.15, 373.15]) t_back = kelvin_to_celsius(t_k) # array([ 0., 20., 37., 100.]) t_f = kelvin_to_fahrenheit(t_k) # array([ 32., 68., 98.6, 212.]) t_k2 = fahrenheit_to_kelvin(t_f) # array([273.15, 293.15, 310.15, 373.15]) ``` ``` -------------------------------- ### Calculate Mean Radiant Temperature with Radiation Variables Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/mrt.md Use this function when you have detailed surface solar and thermal radiation data, including downward surface solar radiation, net surface solar radiation, direct solar radiation, downward surface thermal radiation, direct solar radiation at the surface, net surface thermal radiation, and the cosine of the solar zenith angle. All radiation variables should be in W/m² and the cosine of the solar zenith angle should be dimensionless. Requires numpy arrays. ```python calculate_mean_radiant_temperature(ssrd, ssr, dsrp, strd, fdir, strr, cossza) ``` -------------------------------- ### Calculate Mean Radiant Temperature Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/mrt.md Calculates the Mean Radiant Temperature (MRT) using surface solar radiation downwards, surface net solar radiation, direct radiation from the Sun, surface thermal radiation downwards, total sky direct solar radiation at surface, surface net thermal radiation, and cosine of solar zenith angle. All radiation variables should be in W/m^2 and cosine of solar zenith angle is dimensionless. Expects numpy arrays as input and returns MRT in Kelvin. ```APIDOC ## calculate_mean_radiant_temperature ### Description Calculates the Mean Radiant Temperature (MRT) using various radiation variables. ### Parameters - **ssrd** (numpy.ndarray) - Surface solar radiation downwards (W/m^2) - **ssr** (numpy.ndarray) - Surface net solar radiation (W/m^2) - **dsrp** (numpy.ndarray) - Direct radiation from the Sun (W/m^2) - **strd** (numpy.ndarray) - Surface thermal radiation downwards (W/m^2) - **fdir** (numpy.ndarray) - Total sky direct solar radiation at surface (W/m^2) - **strr** (numpy.ndarray) - Surface net thermal radiation (W/m^2) - **cossza** (numpy.ndarray) - Cosine of solar zenith angle (dimensionless) ### Returns - **mrt** (numpy.ndarray) - Mean Radiant Temperature (Kelvin) ``` -------------------------------- ### calculate_normal_effective_temperature Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes Normal Effective Temperature (NET) [K] following Li & Chan (2006). NET indicates the temperature of a standard environment that would produce the same thermal sensation as the actual conditions at a 1.2m wind height. ```APIDOC ## calculate_normal_effective_temperature Computes Normal Effective Temperature (NET) [K] following Li & Chan (2006). NET represents the temperature of a standard environment that produces the same thermal sensation as the actual conditions at 1.2m wind height. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 298.15, 288.15]) # 30, 25, 15 °C va = np.array([1.0, 3.0, 6.0]) # 10m wind speed [m/s] rh = np.array([70.0, 50.0, 40.0]) # relative humidity [%] net_k = thermofeel.calculate_normal_effective_temperature(t2_k, va, rh) print(thermofeel.kelvin_to_celsius(net_k)) # [30.2... 22.8... 10.4...] °C ``` ``` -------------------------------- ### Calculate Humidex Source: https://github.com/ecmwf/thermofeel/blob/main/docs/source/guide/humidex.md Use this function to calculate the Humidex. It requires 2m air temperature and 2m dew point temperature, both in Kelvin. The output is the Humidex value, also in Kelvin. ```python calculate_humidex(2m_temperature, 2m_dew_point_temperature) ``` -------------------------------- ### Rename and Convert Variables to Datasets Source: https://github.com/ecmwf/thermofeel/blob/main/examples/thermofeeljupyterexamples.ipynb Renames selected xarray DataArrays to have appropriate short names and converts them back into xarray datasets. This is a preparatory step for plotting. ```python #This step makes sure that our variables have the right short names rhpn = rhpn.rename("r2") rhpnds = rhpn.to_dataset() aptmpn = aptmpn.rename("aptmp") aptmpnds = aptmpn.to_dataset() hdn = hdn.rename("heatx") hdnds = hdn.to_dataset() utcin = utcin.rename("utci") utcinds = utcin.to_dataset() ``` -------------------------------- ### approximate_dsrp Source: https://context7.com/ecmwf/thermofeel/llms.txt Approximates direct solar radiation at the surface (dsrp) from total sky direct solar radiation (fdir) and the cosine of the solar zenith angle. Use only when dsrp is not directly available in your dataset; introduces errors as cossza → 0. ```APIDOC ## approximate_dsrp Approximates direct solar radiation at the surface (dsrp) from total sky direct solar radiation (fdir) and the cosine of the solar zenith angle. Use only when dsrp is not directly available in your dataset; introduces errors as cossza → 0. ```python import thermofeel import numpy as np fdir = np.array([500.0, 300.0, 100.0]) # W m-2 cossza = np.array([0.8, 0.5, 0.15]) # cosine of solar zenith angle dsrp = thermofeel.approximate_dsrp(fdir, cossza, threshold=0.1) print(dsrp) # [625. 600. 666.67] W m-2 (last value uses fdir directly; cossza > threshold) ``` ``` -------------------------------- ### Calculate Full WBGT (Python) Source: https://context7.com/ecmwf/thermofeel/llms.txt Computes the full Wet Bulb Globe Temperature (WBGT) using the standard 0.7·Twb + 0.2·Tg + 0.1·T formula. This calculation requires air temperature, mean radiant temperature, wind speed, and dew point temperature. ```python import thermofeel import numpy as np t2_k = np.array([303.15, 308.15]) # 30, 35 °C mrt = np.array([315.0, 325.0]) # mean radiant temperature [K] va = np.array([1.0, 0.5]) # 10m wind speed [m/s] td_k = np.array([293.15, 298.15]) # dew point temperature [K] wbgt_k = thermofeel.calculate_wbgt(t2_k, mrt, va, td_k) print(thermofeel.kelvin_to_celsius(wbgt_k)) # [27.3... 33.8...] °C → moderate to high risk ```