Models#
This section of the documentation provides detailed documentation on the various thermal comfort models, heat and cold indexes implemented in the pythermalcomfort package. These models are used to assess and predict thermal comfort, heat stress, physiological variables and more as a function of both environmental and personal parameters. Each model is accompanied by detailed descriptions, usage examples, and references to relevant standards and research. This documentation aims to provide a comprehensive understanding of how to use these models to evaluate thermal comfort in various scenarios. Please note that models are shown in alphabetical order and are not sorted based on their accuracy.
Adaptive Model#
The adaptive thermal comfort model is a method that relates indoor design temperatures or acceptable temperature ranges to outdoor meteorological or climatological parameters. It’s specifically intended for occupant-controlled naturally conditioned spaces, where the thermal conditions are primarily regulated by occupants through the use of openings in the building envelope, such as windows. The adaptive model is based on the idea that people in naturally ventilated spaces adjust to their environment through a variety of behavioural and physiological adaptations.
Below are some key characteristics and criteria of the adaptive model, according to the ASHRAE 55-2023 standard [55ASHRAE2023]:
- Applicability: The adaptive model can only be applied in spaces that meet specific criteria:
There is no mechanical cooling or heating system in operation.
Occupants have metabolic rates ranging from 1.0 to 1.5 met.
Occupants are able to adjust their clothing to indoor or outdoor thermal conditions within a range of 0.5 to 1.0 clo.
The prevailing mean outdoor temperature is between 10°C (50°F) and 33.5°C (92.3°F).
The space has operable fenestration that can be readily opened and adjusted by the occupants.
- Methodology: The model uses the prevailing mean outdoor air temperature to determine acceptable indoor operative temperatures. The prevailing mean outdoor temperature is calculated as a running average of the mean daily outdoor temperatures over a period of days.
The calculation of the prevailing mean outdoor temperature gives more weight to recent days, since these have a greater influence on occupants’ comfort temperatures.
- Comfort Zone: The adaptive model defines comfort zones differently from the PMV model. Instead of using a heat balance approach to determine an ideal temperature, it relies on an empirical model that links satisfaction with the prevailing mean outdoor temperature.
The comfort zone is defined by the 80% or 90% acceptability limits.
The model does not require estimation of clothing values, since it accounts for clothing adaptation by relating the range of satisfactory indoor temperatures to the outdoor climate.
Air Speed: When using the adaptive model, no humidity or air speed limits are required. However, if elevated air movement is present, air movement extensions to the comfort zone’s lower and upper operative temperature limits can be used.
Underlying Basis: The adaptive model is derived from a global database of measurements taken primarily in office buildings. It is based on the observation that people adapt to their environment over time.
Purpose: The adaptive model is specifically intended for use in naturally conditioned spaces, where occupants have a degree of control over their environment. It is not appropriate for other types of spaces.
The adaptive model, in contrast to the PMV model, does not rely on a heat-balance approach. Instead, it uses an empirical model that relates satisfaction to the prevailing mean outdoor air temperature. The comfort zone is defined by the percentage of people who find the environment acceptable. The adaptive model is based on the idea that people adjust to their environment over time.
The use of the adaptive model requires documentation of the compliance time periods, the prevailing mean outdoor design temperature, and any increased air speed adjustments.
ASHRAE 55#
- pythermalcomfort.models.adaptive_ashrae.adaptive_ashrae(tdb, tr, t_running_mean, v, units='SI', limit_inputs=True, round_output=True)[source]#
Calculate the adaptive thermal comfort based on ASHRAE 55.
The adaptive model relates indoor design temperatures or acceptable temperature ranges to outdoor meteorological or climatological parameters. The adaptive model can only be used in occupant-controlled naturally conditioned spaces that meet all the following criteria:
There is no mechanical cooling or heating system in operation.
Occupants have a metabolic rate between 1.0 and 1.5 met.
Occupants are free to adapt their clothing within a range as wide as 0.5 and 1.0 clo.
The prevailing mean (running mean) outdoor temperature is between 10 and 33.5 °C.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, default in [°C] or [°F] if units = ‘IP’.
tr (float or list of floats) – Mean radiant temperature, default in [°C] or [°F] if units = ‘IP’.
t_running_mean (float or list of floats) – Running mean temperature, default in [°C] or [°F] if units = ‘IP’.
Note
The running mean temperature can be calculated using the function
pythermalcomfort.utilities.running_mean_outdoor_temperature().v (float or list of floats) – Air speed, default in [m/s] or [fps] if units = ‘IP’.
units (str, optional) – Units system, ‘SI’ or ‘IP’. Defaults to ‘SI’.
limit_inputs (bool, optional) – If True, returns nan for inputs outside standard limits. Defaults to True.
Note
ASHRAE 55 2020 limits: 10 < tdb [°C] < 40, 10 < tr [°C] < 40, 0 < vr [m/s] < 2, 10 < t_running_mean [°C] < 33.5.
round_output (bool, optional) – If True, rounds
t_cmfto one decimal place in SI before the comfort bounds are derived, sotmp_cmf_80_low,tmp_cmf_80_up,tmp_cmf_90_lowandtmp_cmf_90_upinherit that rounding. If False,t_cmfand the derived bounds are returned at full precision. Underunits='IP'the rounded SI value is then converted to °F, so IP outputs carry the extra decimals from the °C-to-°F conversion. Defaults to True.
- Returns:
AdaptiveASHRAE – A dataclass containing the results. See
AdaptiveASHRAEfor more details.
Examples
from pythermalcomfort.models import adaptive_ashrae results = adaptive_ashrae(tdb=25, tr=25, t_running_mean=20, v=0.1) print(results) # AdaptiveASHRAE(tmp_cmf=np.float64(24.0), tmp_cmf_80_low=np.float64(20.5), tmp_cmf_80_up=np.float64(27.5), tmp_cmf_90_low=np.float64(21.5), tmp_cmf_90_up=np.float64(26.5), acceptability_80=array(True), acceptability_90=array(True)) print(results.acceptability_80) # or use print(results["acceptability_80"]) # True # The conditions you entered are considered to be comfortable for 80% of the occupants. # You can also pass arrays as input to the function results = adaptive_ashrae(tdb=[25, 26], tr=25, t_running_mean=20, v=0.1) print(results) # AdaptiveASHRAE(tmp_cmf=array([24., 24.]), tmp_cmf_80_low=array([20.5, 20.5]), tmp_cmf_80_up=array([27.5, 27.5]), tmp_cmf_90_low=array([21.5, 21.5]), tmp_cmf_90_up=array([26.5, 26.5]), acceptability_80=array([ True, True]), acceptability_90=array([ True, True])) # For users who want to use the IP system results = adaptive_ashrae(tdb=77, tr=77, t_running_mean=68, v=0.3, units="IP") print(results) # AdaptiveASHRAE(tmp_cmf=np.float64(75.2), tmp_cmf_80_low=np.float64(68.9), tmp_cmf_80_up=np.float64(81.5), tmp_cmf_90_low=np.float64(70.7), tmp_cmf_90_up=np.float64(79.7), acceptability_80=array(True), acceptability_90=array(True)) adaptive_ashrae(tdb=25, tr=25, t_running_mean=9, v=0.1) # AdaptiveASHRAE(tmp_cmf=np.float64(nan), ... acceptability_90=array(False)) # The adaptive thermal comfort model can only be used if the running mean temperature is higher than 10°C.
- class pythermalcomfort.classes_return.AdaptiveASHRAE(tmp_cmf, tmp_cmf_80_low, tmp_cmf_80_up, tmp_cmf_90_low, tmp_cmf_90_up, acceptability_80, acceptability_90)[source]#
A dataclass to store the results of the adaptive thermal comfort model based on ASHRAE 55.
- Variables:
tmp_cmf (float or list of floats) – Comfort temperature at a specific running mean temperature, default in [°C] or [°F].
tmp_cmf_80_low (float or list of floats) – Lower acceptable comfort temperature for 80% occupants, default in [°C] or [°F].
tmp_cmf_80_up (float or list of floats) – Upper acceptable comfort temperature for 80% occupants, default in [°C] or [°F].
tmp_cmf_90_low (float or list of floats) – Lower acceptable comfort temperature for 90% occupants, default in [°C] or [°F].
tmp_cmf_90_up (float or list of floats) – Upper acceptable comfort temperature for 90% occupants, default in [°C] or [°F].
acceptability_80 (bool or list of bools) – Acceptability for 80% occupants.
acceptability_90 (bool or list of bools) – Acceptability for 90% occupants.
EN 16798-1 2019#
- pythermalcomfort.models.adaptive_en.adaptive_en(tdb, tr, t_running_mean, v, units='SI', limit_inputs=True, round_output=True)[source]#
Calculate the adaptive thermal comfort based on EN 16798-1 2019 [16798EN2019].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, default in [°C] or [°F] if units = ‘IP’.
tr (float or list of floats) – Mean radiant temperature, default in [°C] or [°F] if units = ‘IP’.
t_running_mean (float or list of floats) – Running mean temperature, default in [°C] or [°F] if units = ‘IP’.
Note
The running mean temperature can be calculated using the function
pythermalcomfort.utilities.running_mean_outdoor_temperature().v (float or list of floats) – Air speed, default in [m/s] or [fps] if units = ‘IP’.
Note
Indoor operative temperature correction is applicable for buildings equipped with fans or personal systems providing building occupants with personal control over air speed at occupant level. For operative temperatures above 25°C the comfort zone upper limit can be increased by 1.2 °C (0.6 < v < 0.9 m/s), 1.8 °C (0.9 < v < 1.2 m/s), 2.2 °C (v > 1.2 m/s).
units ({‘SI’, ‘IP’}) – Select the SI (International System of Units) or the IP (Imperial Units) system.
limit_inputs (bool, default True) – If True, returns NaN for inputs outside the standard applicability limits.
round_output (bool, default True) – If True, rounds the returned comfort temperature and category bounds to one decimal place in the output unit (rounding is applied after any IP unit conversion). If False, returns the unrounded values.
- Returns:
AdaptiveEN – A dataclass containing the results. See
AdaptiveENfor more details.
Examples
from pythermalcomfort.models import adaptive_en results = adaptive_en(tdb=25, tr=25, t_running_mean=20, v=0.1) print(results) # AdaptiveEN(tmp_cmf=np.float64(25.4), acceptability_cat_i=np.True_, acceptability_cat_ii=np.True_, ...) print(results.acceptability_cat_i) # or print(results["acceptability_cat_i"]) # True # The conditions you entered are considered to comply with Category I # For users who want to use the IP system, units="IP" or "ip" are both valid results = adaptive_en(tdb=77, tr=77, t_running_mean=68, v=0.3, units="IP") print(results) # AdaptiveEN(tmp_cmf=np.float64(77.7), acceptability_cat_i=np.True_, ...) results = adaptive_en(tdb=25, tr=25, t_running_mean=9, v=0.1) print(results) # AdaptiveEN(tmp_cmf=np.float64(nan), acceptability_cat_i=np.False_, ...) # The adaptive thermal comfort model can only be used # if the running mean temperature is between 10 °C and 30 °C.
- class pythermalcomfort.classes_return.AdaptiveEN(tmp_cmf, acceptability_cat_i, acceptability_cat_ii, acceptability_cat_iii, tmp_cmf_cat_i_up, tmp_cmf_cat_ii_up, tmp_cmf_cat_iii_up, tmp_cmf_cat_i_low, tmp_cmf_cat_ii_low, tmp_cmf_cat_iii_low)[source]#
Dataclass to store the results of the adaptive thermal comfort calculation based on EN 16798-1 2019.
- Variables:
tmp_cmf (float or list of floats) – Comfort temperature at that specific running mean temperature, default in [°C] or in [°F].
acceptability_cat_i (bool or list of bools) – If the indoor conditions comply with comfort category I.
acceptability_cat_ii (bool or list of bools) – If the indoor conditions comply with comfort category II.
acceptability_cat_iii (bool or list of bools) – If the indoor conditions comply with comfort category III.
tmp_cmf_cat_i_up (float or list of floats) – Upper acceptable comfort temperature for category I, default in [°C] or in [°F].
tmp_cmf_cat_ii_up (float or list of floats) – Upper acceptable comfort temperature for category II, default in [°C] or in [°F].
tmp_cmf_cat_iii_up (float or list of floats) – Upper acceptable comfort temperature for category III, default in [°C] or in [°F].
tmp_cmf_cat_i_low (float or list of floats) – Lower acceptable comfort temperature for category I, default in [°C] or in [°F].
tmp_cmf_cat_ii_low (float or list of floats) – Lower acceptable comfort temperature for category II, default in [°C] or in [°F].
tmp_cmf_cat_iii_low (float or list of floats) – Lower acceptable comfort temperature for category III, default in [°C] or in [°F].
Apparent Temperature (AT)#
- pythermalcomfort.models.at.at(tdb, rh, v, q=None, round_output=True)[source]#
Calculate the Apparent Temperature (AT). The AT is defined as the temperature at the reference humidity level producing the same amount of discomfort as that experienced under the current ambient temperature, humidity, and solar radiation [Steadman1984]. In other words, the AT is an adjustment to the dry bulb temperature based on the relative humidity value. Absolute humidity with a dew point of 14°C is chosen as a reference.
It includes the chilling effect of the wind at lower temperatures. [Blazejczyk2012]
Note
Two formulas for AT are in use by the Australian Bureau of Meteorology: one includes solar radiation and the other one does not (http://www.bom.gov.au/info/thermal_stress/ , 29 Sep 2021). Please specify q if you want to estimate AT with solar load.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C]
rh (float or list of floats) – Relative humidity, [%]
v (float or list of floats) – Wind speed 10m above ground level, [m/s]
q (float or list of floats, optional) – Net radiation absorbed per unit area of body surface [W/m2]
round_output (bool, default True) – If True, rounds the output value; if False, does not round it.
- Returns:
AT – Dataclass containing the apparent temperature, [°C]. See
ATfor more details.
Examples
from pythermalcomfort.models import at at(tdb=25, rh=30, v=0.1) # AT(at=24.1)
Ankle draft#
- pythermalcomfort.models.ankle_draft.ankle_draft(tdb, tr, vr, rh, met, clo, v_ankle, units='SI', limit_inputs=True)[source]#
Calculate the percentage of thermally dissatisfied people with the ankle draft (0.1 m) above floor level [Liu2017].
This equation is only applicable for vr < 0.2 m/s (40 fps).
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, default in [°C] or [°F] if units = ‘IP’.
Note
The air temperature is the average value over two heights: 0.6 m (24 in.) and 1.1 m (43 in.) for seated occupants, and 1.1 m (43 in.) and 1.7 m (67 in.) for standing occupants.
tr (float or list of floats) – Mean radiant temperature, default in [°C] or [°F] if units = ‘IP’.
vr (float or list of floats) – Relative air speed, default in [m/s] or [fps] if units = ‘IP’.
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
this is the basic insulation also known as the intrinsic clothing insulation value of the clothing ensemble (Icl,r), this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under actual environmental conditions. This value is not the total insulation (IT,r). The dynamic clothing insulation, clo, can be calculated using the function
pythermalcomfort.utilities.clo_dynamic_ashrae().v_ankle (float or list of floats) – Air speed at 0.1 m (4 in.) above the floor, default in [m/s] or [fps] if units = ‘IP’.
units ({‘SI’, ‘IP’}) – Select the SI (International System of Units) or the IP (Imperial Units) system.
limit_inputs (bool, optional) – By default, if the inputs are outside the standard applicability limits the function returns nan. If False, returns values even if input values are outside the applicability limits of the model. Defaults to True. The applicability limits are 10 < tdb [°C] < 40, 10 < tr [°C] < 40, 0 < vr [m/s] < 0.2, 1 < met [met] < 4, and 0 < clo [clo] < 1.5.
- Returns:
AnkleDraft – Dataclass containing the results of the ankle draft calculation. See
AnkleDraftfor more details.
Examples
from pythermalcomfort.models import ankle_draft results = ankle_draft(25, 25, 0.2, 50, 1.2, 0.5, 0.3, units="SI") print(results) # AnkleDraft(ppd_ad=18.5, acceptability=True)
- class pythermalcomfort.classes_return.AnkleDraft(ppd_ad, acceptability)[source]#
Dataclass to store the results of the ankle draft calculation.
- Variables:
ppd_ad (float or list of floats) – Predicted Percentage of Dissatisfied occupants with ankle draft, [%].
acceptability (bool or list of bools) – Indicates if the air speed at the ankle level is acceptable according to ASHRAE 55 2020 standard.
Clothing prediction#
- pythermalcomfort.models.clo_tout.clo_tout(tout, units='SI')[source]#
Calculate representative clothing insulation Icl based on outdoor air temperature at 06:00 a.m. [Schiavon2013].
- Parameters:
tout (float or list of floats) – Outdoor air temperature at 06:00 a.m., default in [°C] or [°F] if units = ‘IP’.
units (str, optional) – Select the SI (International System of Units) or the IP (Imperial Units) system. Supported values are ‘SI’ and ‘IP’. Defaults to ‘SI’.
- Returns:
CloTOut – A dataclass containing the representative clothing insulation Icl. See
CloTOutfor more details. To access the clo_tout value, use the clo_tout attribute of the returned CloTOut instance, e.g., result.clo_tout.- Raises:
TypeError – If tout is not a float, int, NumPy array, or a list of floats or integers.
ValueError – If an invalid unit is provided or non-numeric elements are found in tout.
Notes
Note
The ASHRAE 55 2020 states that it is acceptable to determine the clothing insulation Icl using this equation in mechanically conditioned buildings [55ASHRAE2023].
Note
Limitations: - This equation may not be accurate for extreme temperature ranges.
Examples
from pythermalcomfort.models import clo_tout result = clo_tout(tout=27) print(result.clo_tout) # 0.46 result = clo_tout(tout=[27, 25]) print(result.clo_tout) # array([0.46, 0.47])
Cooling Effect (CE)#
- pythermalcomfort.models.cooling_effect.cooling_effect(tdb, tr, vr, rh, met, clo, wme=0, units='SI')[source]#
Return the value of the Cooling Effect (CE) calculated in compliance with the ASHRAE 55 2020 Standard [55ASHRAE2023]. The CE of the elevated air speed is the value that, when subtracted equally from both the average air temperature and the mean radiant temperature, yields the same SET under still air as in the first SET calculation under elevated air speed. The cooling effect is calculated only for air speed higher than 0.1 m/s.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, default in [°C] or [°F] if units = ‘IP’.
tr (float or list of floats) – Mean radiant temperature, default in [°C] or [°F] if units = ‘IP’.
vr (float or list of floats) – Relative air speed, default in [m/s] or [fps] if units = ‘IP’.
Note
The cooling effect is calculated only for air speed higher than 0.1 m/s. If the air speed is lower than 0.1 m/s the function will return 0.
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Where Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
this is the basic insulation also known as the intrinsic clothing insulation value of the clothing ensemble (Icl,r), this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under actual environmental conditions. This value is not the total insulation (IT,r). The dynamic clothing insulation, clo, can be calculated using the function
pythermalcomfort.utilities.clo_dynamic_ashrae().wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
units ({‘SI’, ‘IP’}, optional) – Select the SI (International System of Units) or the IP (Imperial Units) system. Supported values are ‘SI’ and ‘IP’. Defaults to ‘SI’.
- Returns:
CE – A dataclass containing the Cooling Effect value. See
CoolingEffectfor more details. To access the ce value, use the ce attribute of the returned CoolingEffect instance, e.g., result.ce.
Notes
Note
Limitations: - This equation may not be accurate for extreme temperature ranges.
Examples
from pythermalcomfort.models import cooling_effect result = cooling_effect(tdb=25, tr=25, vr=0.3, rh=50, met=1.2, clo=0.5) print(result.ce) # 1.68 result = cooling_effect( tdb=[25, 77], tr=[25, 77], vr=[0.3, 1.64], rh=[50, 50], met=[1.2, 1], clo=[0.5, 0.6], units="IP", ) print(result.ce) # [0, 3.95]
Discomfort Index (DI)#
- pythermalcomfort.models.discomfort_index.discomfort_index(tdb, rh)[source]#
Calculate the Discomfort Index (DI).
The index is essentially an effective temperature based on air temperature and humidity. The discomfort index is usually divided into 6 discomfort categories and it only applies to warm environments: [Polydoros2015]
class 1 - DI < 21 °C - No discomfort
class 2 - 21 <= DI < 24 °C - Less than 50% feels discomfort
class 3 - 24 <= DI < 27 °C - More than 50% feels discomfort
class 4 - 27 <= DI < 29 °C - Most of the population feels discomfort
class 5 - 29 <= DI < 32 °C - Everyone feels severe stress
class 6 - DI >= 32 °C - State of medical emergency
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
- Returns:
DI – A dataclass containing the Discomfort Index and its classification. See
DIfor more details. To access the di and discomfort_condition values, use the respective attributes of the returned DI instance, e.g., result.di.
Examples
from pythermalcomfort.models import discomfort_index result = discomfort_index(tdb=25, rh=50) print(result.di) # 22.1 print(result.discomfort_condition) # Less than 50% feels discomfort result = discomfort_index(tdb=[25, 30], rh=[50, 60]) print(result.di) # [22.1, 27.3] print( result.discomfort_condition ) # ['Less than 50% feels discomfort', 'Most of the population feels discomfort']
- class pythermalcomfort.classes_return.DI(di, discomfort_condition)[source]#
Dataclass to represent the Discomfort Index (DI) and its classification.
- Variables:
di (float or list of floats) – Discomfort Index, [°C].
discomfort_condition (str or list of str) – Classification of the thermal comfort conditions according to the discomfort index.
Environmental Stress Index (ESI)#
- pythermalcomfort.models.esi.esi(tdb, rh, sol_radiation_global, round_output=True)[source]#
Calculate the Environmental Stress Index (ESI) [Moran2001].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
sol_radiation_global (float or list of floats) – Global solar radiation, [W/m2].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
ESI – A dataclass containing the Environmental Stress Index. See
ESIfor more details. To access the esi value, use the esi attribute of the returned ESI instance, e.g., result.esi.
Examples
from pythermalcomfort.models import esi result = esi(tdb=30.2, rh=42.2, sol_radiation_global=766) print(result.esi) # 26.2 result = esi(tdb=[30.2, 27.0], rh=[42.2, 68.8], sol_radiation_global=[766, 289]) print(result.esi) # [26.2, 25.6]
Gagge two-node model#
- pythermalcomfort.models.two_nodes_gagge.two_nodes_gagge(tdb, tr, v, rh, met, clo, wme=0, body_surface_area=1.8258, p_atm=101325, position='standing', max_skin_blood_flow=90, round_output=True, max_sweating=500, w_max=False, calculate_ce=False)[source]#
Gagge Two-node model of human temperature regulation Gagge et al (1986) [Gagge1986].
[Gagge1986] This model can be used to calculate a variety of indices, including:
Gagge’s version of Fanger’s Predicted Mean Vote (PMV). This function uses the Fanger’s PMV equations but it replaces the heat loss and gain terms with those calculated by the two-node model developed by Gagge et al. (1986) [Gagge1986].
PMV SET and the predicted thermal sensation based on SET [Gagge1986]. This function is similar in all aspects to the
pythermalcomfort.models.pmv_gagge()however, it uses thepythermalcomfort.models.set()equation to calculate the dry heat loss by convection.Thermal discomfort (DISC) as the relative thermoregulatory strain necessary to restore a state of comfort and thermal equilibrium by sweating [Gagge1986]. DISC is described numerically as: comfortable and pleasant (0), slightly uncomfortable but acceptable (1), uncomfortable and unpleasant (2), very uncomfortable (3), limited tolerance (4), and intolerable (5). The range of each category is ± 0.5 numerically. In the cold, the classical negative category descriptions used for Fanger’s PMV apply [Gagge1986].
Heat gains and losses via convection, radiation, and conduction.
The Standard Effective Temperature (SET).
The New Effective Temperature (ET).
The Predicted Thermal Sensation (TSENS).
The Predicted Percent Dissatisfied Due to Draft (PD).
Predicted Percent Satisfied With the Level of Air Movement (PS).
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Air speed, [m/s].
rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
body_surface_area (float or list of floats, optional) – Body surface area, default value 1.8258 [m2]. Defaults to 1.8258.
Note
The body surface area can be calculated using the function
pythermalcomfort.utilities.body_surface_area().p_atm (float or list of floats, optional) – Atmospheric pressure, default value 101325 [Pa]. Defaults to 101325.
position (str, optional) – Select either “sitting” or “standing”. Defaults to “standing”.
max_skin_blood_flow (float or list of floats, optional) – Maximum blood flow from the core to the skin, [kg/h/m2]. Defaults to 90.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
max_sweating (float or list of floats, optional) – Maximum rate at which regulatory sweat is generated, [kg/h/m2]. Defaults to 500.
w_max (float or list of floats, optional) – Maximum skin wettedness (w) adimensional. Ranges from 0 and 1. Defaults to False.
- Returns:
GaggeTwoNodes – A dataclass containing the results of the two-node model of human temperature regulation. See
GaggeTwoNodesfor more details. To access the results, use the corresponding attributes of the returned GaggeTwoNodes instance, e.g., result.e_skin.
Examples
from pythermalcomfort.models import two_nodes_gagge result = two_nodes_gagge(tdb=25, tr=25, v=0.1, rh=50, clo=0.5, met=1.2) print(result.w) # 100.0 result = two_nodes_gagge(tdb=[25, 25], tr=25, v=0.3, rh=50, met=1.2, clo=0.5) print(result.e_skin) # [100.0, 100.0]
- class pythermalcomfort.classes_return.GaggeTwoNodes(e_skin, e_rsw, e_max, q_sensible, q_skin, q_res, t_core, t_skin, m_bl, m_rsw, w, w_max, set, et, pmv_gagge, pmv_set, disc, t_sens)[source]#
Dataclass to represent the results of the two-node model of human temperature regulation.
- Variables:
e_skin (float or list of floats) – Total rate of evaporative heat loss from skin, [W/m2]. Equal to e_rsw + e_diff.
e_rsw (float or list of floats) – Rate of evaporative heat loss from sweat evaporation, [W/m2].
e_max (float or list of floats) – Maximum rate of evaporative heat loss from skin, [W/m2].
q_sensible (float or list of floats) – Sensible heat loss from skin, [W/m2].
q_skin (float or list of floats) – Total rate of heat loss from skin, [W/m2]. Equal to q_sensible + e_skin.
q_res (float or list of floats) – Total rate of heat loss through respiration, [W/m2].
t_core (float or list of floats) – Core temperature, [°C].
t_skin (float or list of floats) – Skin temperature, [°C].
m_bl (float or list of floats) – Skin blood flow, [kg/h/m2].
m_rsw (float or list of floats) – Rate at which regulatory sweat is generated, [mL/h/m2].
w (float or list of floats) – Skin wettedness, adimensional. Ranges from 0 to 1.
w_max (float or list of floats) – Skin wettedness (w) practical upper limit, adimensional. Ranges from 0 to 1.
set (float or list of floats) – Standard Effective Temperature (SET).
et (float or list of floats) – New Effective Temperature (ET).
pmv_gagge (float or list of floats) – PMV Gagge.
pmv_set (float or list of floats) – PMV SET.
disc (float or list of floats) – Thermal discomfort.
t_sens (float or list of floats) – Predicted Thermal Sensation.
Two-node model sleep#
- pythermalcomfort.models.two_nodes_gagge_sleep.two_nodes_gagge_sleep(tdb, tr, v, rh, clo, thickness_quilt, wme=0, p_atm=101325, **kwargs)[source]#
Adaption of the Gagge two-node model for sleep thermal environment, developed by Yan, S., Xiong, J., Kim, J. and de Dear, R. [Yan2022].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
Note
tdb, tr, v, rh, clo and thickness must have the same length. This length will be the duration of the simulation.
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Air speed, [m/s].
rh (float or list of floats) – Relative humidity, [%].
clo (float or list of floats) – Clothing insulation, [clo].
thickness_quilt (float or list of floats) – Thickness of the quilt. [cm].
wme (float, optional) – External work, [met]. Defaults to 0.
p_atm (float, optional) – Atmospheric pressure, default value 101325 [Pa]. Defaults to 101325.
**kwargs (dict) – Keyword arguments:
- ltimeint, optional
Number of time steps for each iteration. Defaults to 1.
- heightfloat, optional
Height of the person, [cm]. Defaults to 171.
- weightfloat, optional
Weight of the person, [kg]. Defaults to 70.
- c_swfloat, optional
Driving coefficient for regulatory sweating. Defaults to 170.
- c_dilfloat, optional
Driving coefficient for vasodilation. Defaults to 120.
- c_strfloat, optional
Driving coefficient for vasoconstriction. Defaults to 0.5.
- temp_skin_neutralfloat, optional
Skin temperature at neutral conditions, [°C]. Defaults to 33.7.
- temp_core_neutralfloat, optional
Core temperature at neutral conditions, [°C]. Defaults to 36.8.
- e_skinfloat, optional
Total evaporative heat loss, [W]. Defaults to 0.094.
- alfafloat, optional
Dynamic fraction of total body mass assigned to the skin node. Defaults to 0.1.
- skin_blood_flowfloat, optional
Skin-blood-flow rate per unit surface area, [kg/h/m2]. Defaults to 6.3.
- met_shiveringfloat, optional
Metabolic rate due to shivering, [met]. Defaults to 0.
- Returns:
GaggeTwoNodesSleep – A dataclass containing the results of the Gagge two-node model for sleep thermal environment. See
GaggeTwoNodesSleepfor more details. To access the results, use the corresponding attributes of the returned instance, e.g. result.e_skin.
- class pythermalcomfort.classes_return.GaggeTwoNodesSleep(set, t_core, t_skin, wet, t_sens, disc, e_skin, met_shivering, alfa, skin_blood_flow)[source]#
Dataclass to represent the results of the two-node sleep model.
- Variables:
set (float or list of floats) – Standard Effective Temperature (SET).
t_core (float or list of floats) – Core temperature, [°C].
t_skin (float or list of floats) – Skin temperature, [°C].
wet (float or list of floats) – Skin wettedness, adimensional. Ranges from 0 to 1.
t_sens (float or list of floats) – Predicted Thermal Sensation.
disc (float or list of floats) – Thermal discomfort.
e_skin (float or list of floats) – Total rate of evaporative heat loss from skin, [W/m2]. Equal to e_rsw + e_diff.
met_shivering (float or list of floats) – Metabolic rate due to shivering, [W/m2].
alfa (float or list of floats) – Dynamic fraction of total body mass assigned to the skin node (dimensionless).
skin_blood_flow (float or list of floats) – Skin-blood-flow rate per unit surface area, [kg/h/m2].
Gagge-Ji two-node model#
- pythermalcomfort.models.two_nodes_gagge_ji.two_nodes_gagge_ji(tdb, tr, v, met, clo, vapor_pressure, wme=0, body_surface_area=1.8258, p_atm=101325, position='sitting', **kwargs)[source]#
Two-node model for older people under hot and cold exposures proposed by Ji et al. [Ji2022].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Air speed, [m/s].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
vapor_pressure (float or list of floats) – Vapor pressure, [torr].
Note
Vapor pressure can be calculated using the relative humidity and the saturation vapor pressure, which can be computed using the function
pythermalcomfort.utilities.p_sat_torr().wme (float or list of floats) – External work, [met]. Defaults to 0.
body_surface_area (float or list of floats) – Body surface area, [m2]. Defaults to 1.8258.
Note
Body surface area can be calculated with weight and height using the function
pythermalcomfort.utilities.body_surface_area().p_atm (float or list of floats) – Atmospheric pressure, [Pa]. Defaults to 101325.
position (str, optional) – Select either “sitting” or “standing”. Defaults to “sitting”.
- Other Parameters:
body_weight (float, optional) – Body weight, [kg]. Defaults to 70 kg.
length_time_simulation (int, optional) – Length of the simulation, [minutes]. Defaults to 120 minutes.
initial_skin_temp (float, optional) – Initial skin temperature, [°C]. Defaults to 36.8 °C.
initial_core_temp (float, optional) – Initial core temperature, [°C]. Defaults to 36.49 °C.
acclimatized (bool, optional) – If True, the model assumes the person is acclimatized to heat. Defaults to True.
- Returns:
GaggeTwoNodesJi – A dataclass containing the simulated core and skin temperatures over time. See
GaggeTwoNodesJifor more details. To access the individual attributes, use the corresonding attrubute of the returned instance, e.g. result.t_core or result.t_skin.
Example
from pythermalcomfort.models import two_nodes_gagge_ji from pythermalcomfort.utilities import body_surface_area from pythermalcomfort.utilities import p_sat_torr rh = 20 vapor_pressure = rh * p_sat_torr(tdb=36.5) / 100 result = two_nodes_gagge_ji( tdb=36.5, tr=36.5, v=0.25, met=0.95, clo=0.1, vapor_pressure=vapor_pressure, wme=0, body_surface_area=body_surface_area(weight=80.1, height=1.8), p_atm=101325, position="sitting", acclimatized=True, body_weight=80.1, length_time_simulation=120, )
Heat Index (HI)#
The Heat Index (HI) is a commonly used metric to estimate apparent temperature (AT) incorporating the effects of humidity based on Steadman’s model [Steadman1979] of human thermoregulation.
Lu and Romps (2022) [lu] found that Steadman’s model produces unrealistic results under extreme conditions, such as excessively hot and humid or cold and dry environments, rendering the heat index undefined. For instance, at 80% relative humidity, the heat index is only valid within a temperature range of 288–304 K. To address this issue, Lu and Romps (2022) [lu] developed a new model that extends the range of validity of the heat index.
pythermalcomfort therefore includes two equations to calculate the Heat Index. One in accordance with the new Lu and Romps (2022) model which is an extension of the first version of Steadman’s (1979) apparent temperature heat_index_lu.
The other is developed by Rothfusz (1990) and it is a simplified model derived by multiple regression analysis in temperature and relative humidity from the first version of Steadman’s (1979) apparent temperature (AT) [Rothfusz1990] heat_index_rothfusz.
Heat Index (HI) Lu and Romps (2022)#
- pythermalcomfort.models.heat_index_lu.heat_index_lu(tdb, rh, round_output=True)[source]#
Calculate the Heat Index (HI) in accordance with the Lu and Romps (2022) model [lu].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
HI – A dataclass containing the Heat Index. See
HIfor more details. To access the hi value, use the hi attribute of the returned HI instance, e.g., result.hi.
Examples
from pythermalcomfort.models import heat_index_lu result = heat_index_lu(tdb=25, rh=50) print(result.hi) # 25.9
Heat Index (HI) Rothfusz (1990)#
- pythermalcomfort.models.heat_index_rothfusz.heat_index_rothfusz(tdb, rh, round_output=True, limit_inputs=True)[source]#
Calculate the Heat Index (HI) in accordance with the Rothfusz (1990) model [Rothfusz1990].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
limit_inputs (bool, optional) – If True, limits the inputs to the standard applicability limits. Defaults to True.
Note
By default, if the inputs are outside the standard applicability limits the function returns NaN. If False returns heat index values even if input values are outside the applicability limits of the model.
The applicability limit is tdb >= 27°C.
- Returns:
HI – A dataclass containing the Heat Index. See
HIfor more details. To access the hi value, use the hi attribute of the returned HI instance, e.g., result.hi.
Examples
from pythermalcomfort.models import heat_index_rothfusz result = heat_index_rothfusz(tdb=29, rh=50) print(result.hi) # 29.7 print(result.stress_category) # "caution"
- class pythermalcomfort.classes_return.HI(hi, stress_category=None)[source]
Dataclass to represent the Heat Index (HI).
- Variables:
hi (float or list of floats) – Heat Index, [°C] or [°F] depending on the units.
Humidex#
- pythermalcomfort.models.humidex.humidex(tdb, rh, model='rana', round_output=True)[source]#
Calculate the humidex (short for “humidity index”). It has been developed by the Canadian Meteorological service. It was introduced in 1965 and then it was revised by Masterson and Richardson (1979) [Masterson1979]. It aims to describe how hot, humid weather is felt by the average person. The Humidex differs from the heat index in being related to the dew point rather than relative humidity [Havenith2016].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
model (str, optional) – The model to be used for the calculation. Options are ‘rana’ and ‘masterson’. Defaults to ‘rana’.
Note
The ‘rana’ model is the Humidex model proposed by Rana et al. (2013). The ‘masterson’ model is the Humidex model proposed by Masterson and Richardson (1979) [Masterson1979].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
Humidex – A dataclass containing the Humidex value and its discomfort category. See
Humidexfor more details. To access the humidex and discomfort values, use the respective attributes of the returned Humidex instance, e.g., result.humidex.
Examples
from pythermalcomfort.models import humidex result = humidex(tdb=25, rh=50) print(result.humidex) # 28.2 print(result.discomfort) # Little or no discomfort result = humidex(tdb=[25, 30], rh=[50, 60], round_output=False) print(result.humidex) # [28.2, 39.1] print(result.discomfort) # ['Little or no discomfort', 'Evident discomfort']
- class pythermalcomfort.classes_return.Humidex(humidex, discomfort)[source]#
Dataclass to represent the Humidex and its discomfort category.
- Variables:
humidex (float or list of floats) – Humidex value, [°C].
discomfort (str or list of str) – Degree of comfort or discomfort as defined in Havenith and Fiala (2016).
Joint system thermoregulation model (JOS-3)#
- class pythermalcomfort.models.jos3.JOS3(height=1.72, weight=74.43, fat=15, age=20, sex='male', ci=2.59, bmr_equation='harris-benedict', bsa_equation='dubois')[source]#
JOS-3 model simulates human thermal physiology including skin temperature, core temperature, sweating rate, etc. for the whole body and 17 local body parts.
This model was developed at Shin-ichi Tanabe Laboratory, Waseda University and was derived from 65 Multi-Node model (https://doi.org/10.1016/S0378-7788(02)00014-2) and JOS-2 model (https://doi.org/10.1016/j.buildenv.2013.04.013).
To use this model, create an instance of the JOS3 class with optional body parameters such as body height, weight, age, sex, etc.
Environmental conditions such as air temperature, mean radiant temperature, air velocity, etc. can be set using the setter methods. (ex. X.tdb, X.tr, X.v) If you want to set the different conditions in each body part, set them as a 17 lengths of list, dictionary, or numpy array format.
List or numpy array format input must be 17 lengths and means the order of “head”, “neck”, “chest”, “back”, “pelvis”, “left_shoulder”, “left_arm”, “left_hand”, “right_shoulder”, “right_arm”, “right_hand”, “left_thigh”, “left_leg”, “left_foot”, “right_thigh”, “right_leg” and “right_foot”.
The model output includes local and mean skin temperature, local core temperature, local and mean skin wettedness, and heat loss from the skin etc. The model output can be accessed using the dict_results() method and be converted to a csv file using the to_csv method. Each output parameter also can be accessed using getter methods. (ex. X.t_skin, X.t_skin_mean, X.t_core)
If you use this package, please cite us as follows and mention the version of pythermalcomfort used: Y. Takahashi, A. Nomoto, S. Yoda, R. Hisayama, M. Ogata, Y. Ozeki, S. Tanabe, Thermoregulation Model JOS-3 with New Open Source Code, Energy & Buildings (2020), doi: https://doi.org/10.1016/j.enbuild.2020.110575
Note: To maintain consistency in variable names for pythermalcomfort, some variable names differ from those used in the original paper.
- Variables:
tdb (float or list of floats) – Dry bulb air temperature.
tr (float or list of floats) – Mean radiant temperature.
to (float or list of floats) – Operative temperature.
rh (float or list of floats) – Relative humidity.
v (float or list of floats) – Air velocity.
clo (float or list of floats) – Clothing insulation.
posture (str) – Posture of the subject.
par (float) – Physical activity ratio.
t_body (numpy.ndarray) – Body temperature.
bsa (numpy.ndarray) – Body surface area.
r_t (numpy.ndarray) – Radiative heat transfer coefficient.
r_et (numpy.ndarray) – Evaporative heat transfer coefficient.
w (numpy.ndarray) – Skin wettedness.
w_mean (float) – Mean skin wettedness.
t_skin_mean (float) – Mean skin temperature.
t_skin (numpy.ndarray) – Skin temperature.
t_core (numpy.ndarray) – Core temperature.
t_cb (numpy.ndarray) – Central blood temperature.
t_artery (numpy.ndarray) – Arterial blood temperature.
t_vein (numpy.ndarray) – Venous blood temperature.
t_superficial_vein (numpy.ndarray) – Superficial venous blood temperature.
t_muscle (numpy.ndarray) – Muscle temperature.
t_fat (numpy.ndarray) – Fat temperature.
body_names (list of str) – Names of the body parts.
results (dict) – Dictionary of the simulation results.
bmr (float) – Basal metabolic rate.
version (str) – Version of the JOS3 model.
- Returns:
cardiac_output – cardiac output (the sum of the whole blood flow) [L/h]
dt – time step [sec]
q_res – heat loss by respiration [W]
q_skin2env – total heat loss from the skin (each body part) [W]
q_thermogenesis_total – total thermogenesis of the whole body [W]
simulation_time – simulation times [sec]
t_core – core temperature (each body part) [°C]
t_skin – skin temperature (each body part) [°C]
t_skin_mean – mean skin temperature [°C]
w – skin wettedness (each body part) [-]
w_mean – mean skin wettedness [-]
weight_loss_by_evap_and_res – weight loss by the evaporation and respiration of the whole body [g/sec]
age – age [years]
bf_ava_foot – AVA blood flow rate of one foot [L/h]
bf_ava_hand – AVA blood flow rate of one hand [L/h]
bf_core – core blood flow rate (each body part) [L/h]
bf_fat – fat blood flow rate (each body part) [L/h]
bf_muscle – muscle blood flow rate (each body part) [L/h]
bf_skin – skin blood flow rate (each body part) [L/h]
bsa – body surface area (each body part) [m2]
clo – clothing insulation (each body part) [clo]
e_max – maximum evaporative heat loss from the skin (each body part) [W]
e_skin – evaporative heat loss from the skin (each body part) [W]
e_sweat – evaporative heat loss from the skin by only sweating (each body part) [W]
fat – body fat rate [%]
height – body height [m]
par – physical activity ratio [-]
q_bmr_core – core thermogenesis by basal metabolism (each body part) [W]
q_bmr_fat – fat thermogenesis by basal metabolism (each body part) [W]
q_bmr_muscle – muscle thermogenesis by basal metabolism (each body part) [W]
q_bmr_skin – skin thermogenesis by basal metabolism (each body part) [W]
q_nst – core thermogenesis by non-shivering (each body part) [W]
q_res_latent – latent heat loss by respiration (each body part) [W]
q_res_sensible – sensible heat loss by respiration (each body part) [W]
q_shiv – core or muscle thermogenesis by shivering (each body part) [W]
q_skin2env_latent – latent heat loss from the skin (each body part) [W]
q_skin2env_sensible – sensible heat loss from the skin (each body part) [W]
q_thermogenesis_core – core total thermogenesis (each body part) [W]
q_thermogenesis_fat – fat total thermogenesis (each body part) [W]
q_thermogenesis_muscle – muscle total thermogenesis (each body part) [W]
q_thermogenesis_skin – skin total thermogenesis (each body part) [W]
q_work – core or muscle thermogenesis by work (each body part) [W]
r_et – total clothing evaporative heat resistance (each body part) [(m2*kPa)/W]
r_t – total clothing heat resistance (each body part) [(m2*K)/W]
rh – relative humidity (each body part) [%]
sex (str) – sex
t_artery – arterial temperature (each body part) [°C]
t_cb – central blood temperature [°C]
t_core_set – core set point temperature (each body part) [°C]
t_fat – fat temperature (each body part) [°C]
t_muscle – muscle temperature (each body part) [°C]
t_skin_set – skin set point temperature (each body part) [°C]
t_superficial_vein – superficial vein temperature (each body part) [°C]
t_vein – vein temperature (each body part) [°C]
tdb – dry bulb air temperature (each body part) [°C]
to – operative temperature (each body part) [°C]
tr – mean radiant temperature (each body part) [°C]
v – air velocity (each body part) [m/s]
weight – body weight [kg]
Examples
Build a model and set a body built Create an instance of the JOS3 class with optional body parameters such as body height, weight, age, sex, etc.
from pythermalcomfort.classes_return import get_attribute_values import numpy as np import pandas as pd import matplotlib.pyplot as plt import os from pythermalcomfort.models import JOS3 from pythermalcomfort.jos3_functions.parameters import ( local_clo_typical_ensembles, ) model = JOS3( height=1.7, weight=60, fat=20, age=30, sex="male", bmr_equation="japanese", bsa_equation="fujimoto", ) # Set environmental conditions such as air temperature, mean radiant temperature using the setter methods. # Set the first condition # Environmental parameters can be input as int, float, list, dict, numpy array format. model.tdb = 28 # Air temperature [°C] model.tr = 30 # Mean radiant temperature [°C] model.rh = 40 # Relative humidity [%] model.v = np.asarray( # Air velocity [m/s] [ 0.2, # head 0.4, # neck 0.4, # chest 0.1, # back 0.1, # pelvis 0.4, # left shoulder 0.4, # left arm 0.4, # left hand 0.4, # right shoulder 0.4, # right arm 0.4, # right hand 0.1, # left thigh 0.1, # left leg 0.1, # left foot 0.1, # right thigh 0.1, # right leg 0.1, # right foot ] ) model.clo = get_attribute_values( local_clo_typical_ensembles[ "briefs, socks, undershirt, work jacket, work pants, safety shoes" ]["local_body_part"] ) # par should be input as int, float. model.par = 1.2 # Physical activity ratio [-], assuming a sitting position # posture should be input as int (0, 1, or 2) or str ("standing", "sitting" or "lying"). # (0="standing", 1="sitting" or 2="lying") model.posture = "sitting" # Posture [-], assuming a sitting position # Run JOS-3 model model.simulate( times=30, # Number of loops of a simulation dtime=60, # Time delta [sec]. The default is 60. ) # Exposure time = 30 [loops] * 60 [sec] = 30 [min] # Set the next condition (You only need to change the parameters that you want to change) model.to = 20 # Change operative temperature model.v = { # Air velocity [m/s], assuming to use a desk fan "head": 0.2, "neck": 0.4, "chest": 0.4, "back": 0.1, "pelvis": 0.1, "left_shoulder": 0.4, "left_arm": 0.4, "left_hand": 0.4, "right_shoulder": 0.4, "right_arm": 0.4, "right_hand": 0.4, "left_thigh": 0.1, "left_leg": 0.1, "left_foot": 0.1, "right_thigh": 0.1, "right_leg": 0.1, "right_foot": 0.1, } # Run JOS-3 model model.simulate( times=60, # Number of loops of a simulation dtime=60, # Time delta [sec]. The default is 60. ) # Additional exposure time = 60 [loops] * 60 [sec] = 60 [min] # Set the next condition (You only need to change the parameters that you want to change) model.tdb = 30 # Change air temperature [°C] model.tr = 35 # Change mean radiant temperature [°C] # Run JOS-3 model model.simulate( times=30, # Number of loops of a simulation dtime=60, # Time delta [sec]. The default is 60. ) # Additional exposure time = 30 [loops] * 60 [sec] = 30 [min] # The easiest way to access the results is to use the `results` method results = model.results() # you can then use dot notation to access the results print( results.t_skin_mean ) # Print the mean skin temperature or you can use print(results['t_skin_mean']) # some attributes have results for each body part, you can access them by using the body part name print(results.t_skin.head) # Print the skin temperature of the head # You can also save the results as a pandas dataframe and plot them df = pd.DataFrame( [results.t_skin.head, results.t_skin.pelvis] ).transpose() # Make pandas.DataFrame df.plot() # Plot time series of local skin temperature. plt.legend(["Head", "Pelvis"]) # Reset the legends plt.ylabel("Skin temperature [°C]") # Set y-label as 'Skin temperature [°C]' plt.xlabel("Time [min]") # Set x-label as 'Time [min]' plt.show() # Show the plot
- __init__(height=1.72, weight=74.43, fat=15, age=20, sex='male', ci=2.59, bmr_equation='harris-benedict', bsa_equation='dubois')[source]#
Initialize a new instance of the JOS3 class, which models and simulates various physiological parameters related to human thermoregulation.
This class uses mathematical models to calculate and predict body temperature, basal metabolic rate, body surface area, and other related parameters.
- Parameters:
height (float, optional) – Body height in meters.
weight (float, optional) – Body weight in kilograms.
fat (float, optional) – Fat percentage.
age (int, optional) – Age in years.
sex (str, optional) – Sex (“male” or “female”).
ci (float, optional) – Cardiac index in liters per minute per square meter.
bmr_equation (str, optional) – The equation used to calculate basal metabolic rate (BMR). Options are “harris-benedict” for Caucasian data (DOI: doi.org/10.1073/pnas.4.12.370) or “japanese” for Ganpule’s equation (DOI: doi.org/10.1038/sj.ejcn.1602645).
bsa_equation (str, optional) – The equation used to calculate body surface area (BSA). Choose one from pythermalcomfort.utilities.BodySurfaceAreaEquations.
- Returns:
None.
Examples
Create an instance of the JOS3 class with optional body parameters:
jos3_model = JOS3(height=1.75, weight=70, age=25, sex="female")
- dict_results()[source]#
Get simulation results as a dictionary.
This method returns the results of the JOS-3 model simulation as a dictionary, where each key corresponds to a specific parameter and the value is an array containing the time series data for that parameter.
- Returns:
dict – A dictionary of the simulation results. Keys are parameter names, and values are arrays containing the time series data for each parameter.
Examples
Access the results after running a simulation:
jos3_model = JOS3(height=1.75, weight=70, age=25, sex="female") jos3_model.simulate(times=30, dtime=60) results = jos3_model.dict_results() print( results["t_skin_mean"] ) # Access the mean skin temperature time series
- results()[source]#
Consolidate the results into a single JOS3Output instance. This makes it very easy to access the time series data for each parameter.
- Returns:
JOS3Output – A single JOS3Output instance where each attribute is an array of values representing the time series data for that attribute.
Examples
from pythermalcomfort.models import JOS3 model = JOS3(height=1.75, weight=70, age=25, sex="female") model.simulate(times=3, dtime=60) output = model.results() print(output.t_skin_mean) print(output.t_skin.head)
- simulate(times, dtime=60, output=True)[source]#
Run the JOS-3 model simulation.
This method executes the JOS-3 model for a specified number of loops, simulating human thermoregulation over time. The results of each simulation step can be recorded and accessed later.
- Parameters:
times (int) – Number of loops of the simulation.
dtime (int or float, optional) – Time delta in seconds for each simulation step. Default is 60.
output (bool, optional) – If True, records the parameters at each simulation step. Default is True.
- Returns:
None
Examples
Create an instance of the JOS3 class and run the simulation:
from pythermalcomfort.models import JOS3 # Create an instance of the JOS3 class jos3_model = JOS3(height=1.75, weight=70, age=25, sex="female") # Run the simulation for 30 loops with a time delta of 60 seconds jos3_model.simulate(times=30, dtime=60) # Access the results results = jos3_model.dict_results() print(results)
- to_csv(path=None, folder=None, unit=True, meaning=True)[source]#
Export results as csv format.
- Parameters:
path (str, optional) – Output path. If you don’t use the default file name, set a name. The default is None.
folder (str, optional) – Output folder. If you use the default file name with the current time, set a only folder path. The default is None.
unit (bool, optional) – Write units in csv file. The default is True.
meaning (bool, optional) – Write meanings of the parameters in csv file. The default is True.
- Returns:
None
Examples
from pythermalcomfort.models import JOS3 # Create an instance of the JOS3 model model = JOS3() # Simulate for 60 steps model.simulate(60) # Export results to a CSV file model.to_csv()
Normal Effective Temperature (NET)#
- pythermalcomfort.models.net.net(tdb, rh, v, round_output=True)[source]#
Calculate the Normal Effective Temperature (NET). Missenard (1933) devised a formula for calculating effective temperature. The index establishes a link between the same condition of the organism’s thermoregulatory capability (warm and cold perception) and the surrounding environment’s temperature and humidity. The index is calculated as a function of three meteorological factors: air temperature, relative humidity of air, and wind speed. This index allows to calculate the effective temperature felt by a person. Missenard original equation was then used to calculate the Normal Effective Temperature (NET), by considering normal atmospheric pressure and a normal human body temperature (37°C). The NET is still in use in Germany, where medical check-ups for subjects working in the heat are decided on by prevailing levels of ET, depending on metabolic rates. The NET is also constantly monitored by the Hong Kong Observatory [Blazejczyk2012]. In central Europe the following thresholds are in use: <1°C = very cold; 1-9 = cold; 9-17 = cool; 17-21 = fresh; 21-23 = comfortable; 23-27 = warm; >27°C = hot [Blazejczyk2012].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
v (float or list of floats) – Wind speed [m/s] at 1.2 m above the ground.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
NET – A dataclass containing the Normal Effective Temperature. See
Netfor more details. To access the net value, use the net attribute of the returned Net instance, e.g., result.net.
Examples
from pythermalcomfort.models import net result = net(tdb=37, rh=100, v=0.1) print(result.net) # 37.0 result = net(tdb=[37, 30], rh=[100, 60], v=[0.1, 0.5], round_output=False) print(result.net) # [37.0, 26.38977535]
Predicted Heat Strain (PHS) Index#
- pythermalcomfort.models.phs.phs(tdb, tr, v, rh, met, clo, posture, wme=0, round_output=True, model='7933-2023', **kwargs)[source]#
Calculate the Predicted Heat Strain (PHS).
The PHS is calculated in compliance with the ISO 7933:2004 [7933ISO2004] or 2023 Standard [7933ISO2023]. The ISO 7933 provides a method for the analytical evaluation and interpretation of the thermal stress experienced by a subject in a hot environment. It describes a method for predicting the sweat rate and the internal core temperature that the human body will develop in response to the working conditions.
The PHS model can be used to predict the: heat by respiratory convection, heat flow by respiratory evaporation, steady state mean skin temperature, instantaneous value of skin temperature, heat accumulation associated with the metabolic rate, maximum evaporative heat flow at the skin surface, predicted sweat rate, predicted evaporative heat flow, and rectal temperature.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Air speed, [m/s].
rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
posture (string or list of strings) – a string value presenting posture of person “sitting”, “standing”, or “crouching”
wme (float or list of floats) – external work, [met] default 0
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
model (str, optional) – Select the model you want to use to calculate the PHS. The default option is “7933-2023”, and the other option is “7933-2004”.
- Other Parameters:
limit_inputs (bool, optional) – If True, limits the input parameters to the standard’s applicability limits. Defaults to True.
Note
By default, if the inputs are outside the standard applicability limits the function returns nan. If False returns values even if input values are outside the applicability limits of the model.
The 7933 limits are 15 < tdb [°C] < 50, 0 < tr [°C] < 60, 0 < vr [m/s] < 3, 1.7 < met [met] < 7.5, and 0.1 < clo [clo] < 1.
i_mst (float, optional) – Static moisture permeability index, [dimensionless]. Defaults to 0.38.
a_p (float, optional) – Fraction of the body surface covered by the reflective clothing, [dimensionless]. Defaults to 0.54.
drink (int, optional) – 1 if workers can drink freely, 0 otherwise. Defaults to 1.
weight (float, optional) – Body weight, [kg]. Defaults to 75.
height (float, optional) – Height, [m]. Defaults to 1.8.
walk_sp (float, optional) – Walking speed, [m/s]. Defaults to 0.
theta (float, optional) – Angle between walking direction and wind direction, [degrees]. Defaults to 0.
acclimatized (int, optional) – 100 if acclimatized subject, 0 otherwise. Defaults to 100.
duration (int, optional) – Duration of the work sequence, [minutes]. Defaults to 480.
f_r (float, optional) – Emissivity of the reflective clothing, [dimensionless]. Defaults to 0.97 in the 2004 standard and 0.42 in the 2023 standard.
t_sk (float, optional) – Mean skin temperature when worker starts working, [°C]. Defaults to 34.1.
t_cr (float, optional) – Mean core temperature when worker starts working, [°C]. Defaults to 36.8.
t_re (float, optional) – Mean rectal temperature when worker starts working, [°C]. If False in the 2004 standard, then t_re = t_cr, whereas in the 2023 standard t_re = 36.8 °C
t_cr_eq (float, optional) – Mean core temperature as a function of met when worker starts working, [°C]. If False in the 2004 standard, then t_cr_eq = t_cr, whereas in the 2023 standard t_cr_eq = 36.8 °C.
t_sk_t_cr_wg (float, optional) – Initial weighting fraction for skin/core temperature coupling, dimensionless.
sweat_rate_watt (float, optional) – Initial instantaneous regulatory sweat (evaporative) rate at the skin, per unit area, [W·m⁻²]. This is an instantaneous rate (W/m²) used at each simulation time step.
evap_load_wm2_min (float, optional) – Initial accumulated evaporative load per unit area. Input value is expected as an instantaneous rate in [W·m⁻²]; during the simulation the value is updated by adding instantaneous rates each minute and therefore the accumulated quantity represents the sum over minutes (units W·min·m⁻²). It is intended for carry over between consecutive simulation segments.
- Returns:
PHS – A dataclass containing the Predicted Heat Strain. See
PHSfor more details. To access the individual attributes, use the corresponding attribute of the returned PHS instance, e.g., result.t_re.
Examples
from pythermalcomfort.models import phs result = phs( tdb=40, tr=40, rh=33.85, v=0.3, met=2.5, clo=0.5, posture="standing", wme=0, duration=480, ) print(result.t_re) # 37.5 result = phs( tdb=[40, 45], tr=[40, 45], v=[0.3, 0.4], rh=[33.85, 40], met=[2.5, 2.6], clo=[0.5, 0.6], posture=["standing", "standing"], wme=[0, 0], duration=480, ) print(result.t_re) # [37.5 42.5] # example: pass previous results as initial values to chain simulations from pythermalcomfort.models import phs # first simulation result = phs( tdb=40, tr=40, v=0.3, rh=50, met=2.5, clo=0.5, posture="standing", wme=0, round_output=False, duration=60, ) print(result.t_re) # 37.8 # second simulation - using previous results as initial values # NOTE: when chaining runs, prefer round_output=False to avoid rounding drift. result = phs( tdb=40, tr=40, v=0.3, rh=50, met=2.5, clo=0.5, posture="standing", wme=0, round_output=False, duration=60, t_sk=result.t_sk, t_cr=result.t_cr, t_re=result.t_re, t_cr_eq=result.t_cr_eq, t_sk_t_cr_wg=result.t_sk_t_cr_wg, sweat_rate_watt=result.sweat_rate_watt, evap_load_wm2_min=result.evap_load_wm2_min, ) print(result.t_re) # 38.5
- class pythermalcomfort.classes_return.PHS(t_re, t_sk, t_cr, t_cr_eq, t_sk_t_cr_wg, d_lim_loss_50, d_lim_loss_95, d_lim_t_re, sweat_loss_g, sweat_rate_watt, evap_load_wm2_min)[source]#
Dataclass to represent the Predicted Heat Strain (PHS).
- Variables:
t_re (float or list of floats) – Rectal temperature, [°C].
t_sk (float or list of floats) – Skin temperature, [°C].
t_cr (float or list of floats) – Core temperature, [°C].
t_cr_eq (float or list of floats) – Core temperature as a function of the metabolic rate, [°C].
t_sk_t_cr_wg (float or list of floats) – Fraction of the body mass at the skin temperature.
d_lim_loss_50 (float or list of floats) – Maximum allowable exposure time limited by cumulative sweat mass loss for a mean worker (dehydration constraint), [minutes].
d_lim_loss_95 (float or list of floats) – Maximum allowable exposure time limited by cumulative sweat mass loss for 95% of the working population (dehydration constraint), [minutes].
d_lim_t_re (float or list of floats) – Maximum allowable exposure time for heat storage, [minutes].
sweat_loss_g (float or list of floats) – Cumulative evaporated sweat mass for the whole person over the simulated duration, [grams (g)]. This is a total mass per person (not per unit area).
sweat_rate_watt (float or list of floats) – Instantaneous evaporative heat flux due to regulatory sweating at the skin, per unit area, [W·m⁻²]. Used at each simulation time step.
evap_load_wm2_min (float or list of floats) – Accumulated evaporative load per unit area over the simulated duration, [W·min·m⁻²]. Computed as the running sum of the instantaneous evaporative heat flux (W·m⁻²) at each 1 minute step. Intended for chaining simulation segments.
Physiological Equivalent Temperature (PET)#
- pythermalcomfort.models.pet_steady.pet_steady(tdb, tr, v, rh, met, clo, p_atm=1013.25, position='sitting', age=23, sex='male', weight=75, height=1.8, wme=0)[source]#
Calculate the steady physiological equivalent temperature (PET) using the Munich Energy-balance Model for Individuals (MEMI) to simulate the human body’s thermal state in a medically realistic manner.
PET is defined as the air temperature at which, in a typical indoor setting the heat budget of the human body is balanced with the same core and skin temperature as under the complex outdoor conditions to be assessed [Hoppe1999]. The following assumptions are made for the indoor reference climate: tdb = tr, v = 0.1 m/s, water vapour pressure = 12 hPa, clo = 0.9 clo, and met = 1.37 met + basic metabolism. PET allows a layperson to compare the total effects of complex thermal circumstances outside with his or her own personal experience indoors in this way. This function solves the heat balances without accounting for heat storage in the human body.
The PET was originally proposed by Hoppe [Hoppe1999]. In 2018, Walther and Goestchel [Walther2018] proposed a correction of the original model, purging the errors in the PET calculation routine, and implementing a state-of-the-art vapour diffusion model. Walther and Goestchel (2018) model is therefore used to calculate the PET.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Wind speed, [m/s].
rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
p_atm (float or list of floats, optional) – Atmospheric pressure, [hPa]. Defaults to 1013.25.
position (str or list of str, optional) – Position of the person “sitting”, “standing”, “standing, forced convection”. Defaults to “sitting”.
age (int or list of ints, optional) – Age of the person. Defaults to 23.
sex (str or list of str, optional) – Sex of the person “male” or “female”. Defaults to “male”
weight (float or list of floats, optional) – Weight of the person, [kg]. Defaults to 75.
height (float or list of floats, optional) – Height of the person, [m]. Defaults to 1.8.
wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
- Returns:
PETSteady – A dataclass containing the Physiological Equivalent Temperature. See
PETSteadyfor more details. To access the pet value, use the pet attribute of the returned PETSteady instance, e.g., result.pet.
Examples
from pythermalcomfort.models import pet_steady result = pet_steady(tdb=25, tr=25, v=0.1, rh=50, met=1.2, clo=0.5) print(result.pet) # 24.67 result = pet_steady( tdb=[25, 30], tr=[25, 30], v=[0.1, 0.2], rh=[50, 60], met=[1.2, 1.4], clo=[0.5, 0.6], ) print(result.pet) # [24.67 31.46]
Predicted Mean Vote (PMV) and Predicted Percentage of Dissatisfied (PPD)#
The Predicted Mean Vote (PMV) is an index that aims to predict the mean value of thermal sensation votes from a large group of people, based on a seven-point scale ranging from “cold” (-3) to “hot” (+3). It was developed by Fanger [Fanger1970].
The PMV is designed to predict the average thermal sensation of a large group of people exposed to the same environment [7730ISO2005]. It calculates the heat balance of a typical occupant and relates their thermal gains or losses to their predicted mean thermal sensation [55ASHRAE2023].
The PMV can be used to check if a thermal environment meets comfort criteria and to establish requirements for different levels of acceptability. The PMV model is applicable to healthy men and women exposed to indoor environments where thermal comfort is desirable, but moderate deviations from thermal comfort occur, in the design of new environments or the assessment of existing ones. The PMV is intended to be used for moderate thermal environments.
- The PMV calculation considers several factors:
Dry-bulb air temperature (T db).
Mean radiant temperature (T r).
Relative humidity (RH).
Relative air velocity (V r), the relative air speed caused by body movement and not the air speed measured by the air speed sensor
Metabolic rate (M), which is the rate of heat production in the body. Metabolic rate data is available in the ASHRAE Handbook—Fundamentals and users should use their judgement to match activities to comparable activities in the table.
Clothing insulation (I cl,r), dynamic intrinsic insulation, this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under the environmental conditions.
The PMV model is applicable when the six main parameters are within specific intervals. These values are specified by the ASHRAE 55 [55ASHRAE2023] and ISO 7730 standards [7730ISO2005]. The ISO also states that the PMV model is only applicable for PMV between -2 and +2 [7730ISO2005].
There are several formulations of the PMV model that have been developed over the years. The two most commonly used are the original PMV model [Fanger1970] and the ASHRAE 55 PMV model [55ASHRAE2023]. Tartarini and Schiavon (2025) [Tartarini2025PMV] compared the accuracy of the PMV models implemented in the ISO 7730:2005 and ASHRAE 55:2023 standards and found that the ISO 7730:2005 model has a higher accuracy than the ASHRAE 55:2023 model. However, it should be noted that both PMV models have low accuracy in predicting thermal sensation votes, especially outside thermal neutrality [Tartarini2025PMV]. For this reason, it is recommended that the use of the PMV be restricted to values between -0.5 and +0.5 [Tartarini2025PMV], where an environment may be deemed thermally neutral by a large group of occupants.
The Predicted Percentage Dissatisfied (PPD) is an index that provides a quantitative prediction of the percentage of people likely to feel too warm or too cool in a given environment. The PPD is derived from the PMV. Specifically, the PPD predicts the number of thermally dissatisfied persons among a large group of people, where thermally dissatisfied people are those who would vote hot, warm, cool, or cold on a seven-point thermal sensation scale.
PMV formulations#
After Fanger developed the original PMV model which it is still included in the ISO 7330 in its original form, several other PMV formulations have been proposed. These include but are not limited to:
the aPMV model [Yao2009]
pythermalcomfort.models.pmv_a.pmv_a(),the ASHRAE 55 PMV model [55ASHRAE2023]
pythermalcomfort.models.pmv_ppd_ashrae.pmv_ppd_ashrae(),the ATHB model [Schweiker2022]
pythermalcomfort.models.pmv_athb.pmv_athb(),the ePMV model [Fanger2002]
pythermalcomfort.models.pmv_e.pmv_e().
ISO 7730 - PMV and PPD#
- pythermalcomfort.models.pmv_ppd_iso.pmv_ppd_iso(tdb, tr, vr, rh, met, clo, wme=0, model='7730-2005', units='SI', limit_inputs=True, round_output=True)[source]#
Return Predicted Mean Vote (PMV) and Predicted Percentage of Dissatisfied (PPD) calculated in accordance with the ISO 7730.
The ISO uses the same formulation of the PMV as published by Fanger [Fanger1970].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C] in [°F] if units = ‘IP’
tr (float or list of floats) – Mean radiant temperature, [°C] in [°F] if units = ‘IP’
vr (float or list of floats) – Relative air speed, [m/s] in [fps] if units = ‘IP’
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Where Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
this is the basic insulation also known as the intrinsic clothing insulation value of the clothing ensemble (Icl,r), this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under actual environmental conditions. This value is not the total insulation (IT,r). The dynamic clothing insulation, clo, can be calculated using the function
pythermalcomfort.utilities.clo_dynamic_iso().wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
model (str, optional) – Select the model you want to use to calculate the PMV. Currently, the only option available is “7730-2005”.
units (str, optional) – Select the SI (International System of Units) or the IP (Imperial Units) system. Supported values are ‘SI’ and ‘IP’. Defaults to ‘SI’.
limit_inputs (bool, optional) – If True, limits the inputs to the standard applicability limits. Defaults to True.
Note
By default, if the inputs are outside the standard applicability limits the function returns nan. If False returns pmv and ppd values even if input values are outside the applicability limits of the model.
The ISO 7730 2005 limits are 10 < tdb [°C] < 30, 10 < tr [°C] < 40, 0 < vr [m/s] < 1, 0.8 < met [met] < 4, 0 < clo [clo] < 2, and -2 < PMV < 2.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
PMVPPD – A dataclass containing the Predicted Mean Vote and Predicted Percentage of Dissatisfied. See
PMVPPDfor more details. To access the pmv, ppd, tsv values, use the corresponding attributes of the returned PMVPPD instance, e.g., result.pmv.
Examples
from pythermalcomfort.models import pmv_ppd_iso from pythermalcomfort.utilities import v_relative tdb = 25 tr = 25 rh = 50 v = 0.1 met = 1.4 clo_dynamic = 0.5 # calculate relative air speed v_r = v_relative(v=v, met=met) results = pmv_ppd_iso( tdb=tdb, tr=tr, vr=v_r, rh=rh, met=met, clo=clo_dynamic, model="7730-2005", ) print(results.pmv) # 0.17 print(results.ppd) # 5.6 result = pmv_ppd_iso( tdb=[22, 25], tr=25, vr=0.1, rh=50, met=1.4, clo=0.5, model="7730-2005", ) print(result.pmv) # [-0. 0.41] print(result.ppd) # [5. 8.5]
- class pythermalcomfort.classes_return.PMVPPD(pmv, ppd, tsv)[source]#
Dataclass to represent the Predicted Mean Vote (PMV) and Predicted Percentage of Dissatisfied (PPD).
- Variables:
pmv (float or list of floats) – Predicted Mean Vote.
ppd (float or list of floats) – Predicted Percentage of Dissatisfied.
tsv (str or list of strings) – Predicted thermal sensation vote.
ASHRAE 55 - PMV and PPD#
- pythermalcomfort.models.pmv_ppd_ashrae.pmv_ppd_ashrae(tdb, tr, vr, rh, met, clo, wme=0, model='55-2023', units='SI', limit_inputs=True, airspeed_control=True, round_output=True)[source]#
Return Predicted Mean Vote (PMV) and Predicted Percentage of Dissatisfied (PPD) calculated in accordance with the ASHRAE 55 Standard.
While the PMV equation is the same for both the ISO and ASHRAE standards, in the ASHRAE 55 PMV equation, the SET is used to calculate the cooling effect first, this is then subtracted from both the air and mean radiant temperatures, and the differences are used as input to the PMV model, while the airspeed is set to 0.1m/s.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C] in [°F] if units = ‘IP’
tr (float or list of floats) – Mean radiant temperature, [°C] in [°F] if units = ‘IP’
vr (float or list of floats) – Relative air speed, [m/s] in [fps] if units = ‘IP’
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Where Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
this is the basic insulation also known as the intrinsic clothing insulation value of the clothing ensemble (Icl,r), this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under actual environmental conditions. This value is not the total insulation (IT,r). The dynamic clothing insulation, clo, can be calculated using the function
pythermalcomfort.utilities.clo_dynamic_ashrae().wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
model (str, optional) – Select the version of the ASHRAE 55 Standard to use. Currently, the only option available is “55-2023”.
units (str, optional) – Select the SI (International System of Units) or the IP (Imperial Units) system. Supported values are ‘SI’ and ‘IP’. Defaults to ‘SI’.
limit_inputs (bool, optional) – If True, limits the inputs to the standard applicability limits. Defaults to True.
Note
By default, if the inputs are outside the standard applicability limits, the function returns NaN. If False returns pmv and ppd values even if input values are outside the applicability limits of the model.
The ASHRAE 55 2020 limits are 10 < tdb [°C] < 40, 10 < tr [°C] < 40, 0 < vr [m/s] < 2, 1 < met [met] < 4, and 0 < clo [clo] < 1.5.
airspeed_control (bool, optional) – By default, this function assumes that the occupant has control over the airspeed. In this case, the ASHRAE 55 Standard does not impose any airspeed limits. On the other hand, if the occupant has no control over the airspeed, the ASHRAE 55 imposes an upper limit for v which varies as a function of the operative temperature, for more information please consult the Standard.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
PMVPPDAshrae – A dataclass containing the Predicted Mean Vote and Predicted Percentage of Dissatisfied. See
PMVPPDAshraefor more details. To access the pmv, ppd, tsv, and compliance values, use the corresponding attributes of the returned PMVPPDAshrae instance, e.g., result.pmv, result.compliance.
Examples
from pythermalcomfort.models import pmv_ppd_ashrae from pythermalcomfort.utilities import v_relative, clo_dynamic_ashrae tdb = 25 tr = 25 rh = 50 v = 0.1 met = 1.4 clo = 0.5 # calculate relative air speed v_r = v_relative(v=v, met=met) # calculate dynamic clothing clo_d = clo_dynamic_ashrae(clo=clo, met=met) results = pmv_ppd_ashrae( tdb=tdb, tr=tr, vr=v_r, rh=rh, met=met, clo=clo_d, model="55-2023" ) print(results.pmv) # 0.0 print(results.ppd) # 5.0 print(results.compliance) # True result = pmv_ppd_ashrae( tdb=[22, 25, 28], tr=25, vr=0.1, rh=50, met=1.4, clo=0.5, model="55-2023", ) print(result)
- class pythermalcomfort.classes_return.PMVPPDAshrae(pmv, ppd, tsv, compliance)[source]#
Dataclass to represent the Predicted Mean Vote (PMV) and Predicted Percentage of Dissatisfied (PPD) calculated in accordance with ASHRAE Standard 55.
- Variables:
pmv (float or list of floats) – Predicted Mean Vote.
ppd (float or list of floats) – Predicted Percentage of Dissatisfied.
tsv (str or list of strings) – Predicted thermal sensation vote.
compliance (bool or list of bools) – True if PMV is within the acceptable range (-0.5 < PMV < 0.5) according to ASHRAE Standard 55-2023. When
limit_inputs=Trueand any input is outside the standard applicability limits,compliancewill benan.
Adaptive Predicted Mean Vote (aPMV)#
- pythermalcomfort.models.pmv_a.pmv_a(tdb, tr, vr, rh, met, clo, a_coefficient, wme=0, units='SI', limit_inputs=True)[source]#
Return Adaptive Predicted Mean Vote (aPMV) [Yao2009]. This index was developed by Yao, R. et al. (2009). The model takes into account factors such as culture, climate, social, psychological, and behavioral adaptations, which have an impact on the senses used to detect thermal comfort. This model uses an adaptive coefficient (λ) representing the adaptive factors that affect the sense of thermal comfort.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, default in [°C] or [°F] if units = ‘IP’.
tr (float or list of floats) – Mean radiant temperature, default in [°C] or [°F] if units = ‘IP’.
vr (float or list of floats) – Relative air speed, default in [m/s] or [fps] if units = ‘IP’.
Note
vr is the sum of the average air speed measured by the sensor and the activity-generated air speed (Vag). Calculate vr using
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
Correct for body movement effects using
pythermalcomfort.utilities.clo_dynamic_iso().a_coefficient (float) – Adaptive coefficient.
wme (float or list of floats, optional) – External work, [met], default is 0.
units (str, optional) – Units system, ‘SI’ or ‘IP’. Defaults to ‘SI’.
limit_inputs (bool, optional) – If True, returns nan for inputs outside standard limits. Defaults to True.
Note
ISO 7730 2005 limits: 10 < tdb [°C] < 30, 10 < tr [°C] < 40, 0 < vr [m/s] < 1, 0.8 < met [met] < 4, 0 < clo [clo] < 2, -2 < PMV < 2.
- Returns:
APMV – A dataclass containing the Predicted Mean Vote (a_pmv). See
AdaptivePMVfor more details. To access the a_pmv value, use the a_pmv attribute of the returned AdaptivePMV instance, e.g., result.a_pmv.
Examples
from pythermalcomfort.models import pmv_a from pythermalcomfort.utilities import v_relative, clo_dynamic_iso v = 0.1 met = 1.4 clo = 0.5 # Calculate relative air speed v_r = v_relative(v=v, met=met) # Calculate dynamic clothing clo_d = clo_dynamic_iso(clo=clo, met=met, v=v) results = pmv_a( tdb=28, tr=28, vr=v_r, rh=50, met=met, clo=clo_d, a_coefficient=0.293, ) print(results) # AdaptivePMV(a_pmv=0.74) print(results.a_pmv) # 0.71
Adaptive Thermal Heat Balance (ATHB)#
- pythermalcomfort.models.pmv_athb.pmv_athb(tdb, tr, vr, rh, met, t_running_mean, clo=False)[source]#
Return the PMV value calculated with the Adaptive Thermal Heat Balance Framework [Schweiker2022]. The adaptive thermal heat balance (ATHB) framework introduced a method to account for the three adaptive principals, namely physiological, behavioral, and psychological adaptation, individually within existing heat balance models. The objective is a predictive model of thermal sensation applicable during the design stage or in international standards without knowing characteristics of future occupants.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, in [°C].
tr (float or list of floats) – Mean radiant temperature, in [°C].
vr (float or list of floats) – Relative air speed, in [m/s].
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Where Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (bool, float or list of floats, optional) – Clothing insulation, in [clo]. If clo is set to False, the clothing insulation value will be calculated using the equation provided in the paper. Defaults to False.
t_running_mean (float or list of floats) – Running mean temperature, in [°C].
Note
The running mean temperature can be calculated using the function
pythermalcomfort.utilities.running_mean_outdoor_temperature().
- Returns:
ATHB – Dataclass containing the results of the ATHB calculation. See
ATHBfor more details.
Examples
from pythermalcomfort.models import pmv_athb # calculate the predicted mean vote (PMV) using the Adaptive Thermal Heat Balance model results = pmv_athb(tdb=25, tr=25, vr=0.1, rh=50, met=1.2, t_running_mean=20) print(results.athb_pmv) # returns the PMV value # for multiple points results = pmv_athb( tdb=[25, 25, 25], tr=[25, 25, 25], vr=[0.1, 0.1, 0.1], rh=[50, 50, 50], met=[1.2, 1.2, 1.2], t_running_mean=[20, 20, 20], ) print(results.athb_pmv)
Adjusted Predicted Mean Votes with Expectancy Factor (ePMV)#
- pythermalcomfort.models.pmv_e.pmv_e(tdb, tr, vr, rh, met, clo, e_coefficient, wme=0, units='SI', limit_inputs=True)[source]#
Return Adjusted Predicted Mean Votes with Expectancy Factor (ePMV). This index was developed by Fanger, P. O. et al. (2002). In non-air- conditioned buildings in warm climates, occupants may sense the warmth as being less severe than the PMV predicts. The main reason is low expectations, but a metabolic rate that is estimated too high can also contribute to explaining the difference. An extension of the PMV model that includes an expectancy factor is introduced for use in non-air- conditioned buildings in warm climates [Fanger2002].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, default in [°C] in [°F] if units = ‘IP’.
tr (float or list of floats) – Mean radiant temperature, default in [°C] in [°F] if units = ‘IP’.
vr (float or list of floats) – Relative air speed, default in [m/s] in [fps] if units = ‘IP’.
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Where Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
this is the basic insulation also known as the intrinsic clothing insulation value of the clothing ensemble (Icl,r), this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under actual environmental conditions. This value is not the total insulation (IT,r). The dynamic clothing insulation, clo, can be calculated using the function
pythermalcomfort.utilities.clo_dynamic_iso().e_coefficient (float or list of floats) – Expectancy factor.
wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
units ({‘SI’, ‘IP’}, optional) – Select the SI (International System of Units) or the IP (Imperial Units) system. Supported values are ‘SI’ and ‘IP’. Defaults to ‘SI’.
limit_inputs (bool, optional) – By default, if the inputs are outside the standard applicability limits the function returns nan. If False, returns pmv and ppd values even if input values are outside the applicability limits of the model. Defaults to True.
Note
The ISO 7730 2005 limits are 10 < tdb [°C] < 30, 10 < tr [°C] < 40, 0 < vr [m/s] < 1, 0.8 < met [met] < 4, 0 < clo [clo] < 2, and -2 < PMV < 2.
- Returns:
EPMV – A dataclass containing the Adjusted Predicted Mean Votes with Expectancy Factor. See
EPMVfor more details. To access the e_pmv value, use the e_pmv attribute of the returned e_pmv instance, e.g., result.e_pmv.
Examples
from pythermalcomfort.models import pmv_e from pythermalcomfort.utilities import v_relative, clo_dynamic_iso tdb = 28 tr = 28 rh = 50 v = 0.1 met = 1.4 clo = 0.5 # calculate relative air speed v_r = v_relative(v=v, met=met) # Calculate dynamic clothing clo_d = clo_dynamic_iso(clo=clo, met=met, v=v) results = pmv_e(tdb, tr, v_r, rh, met, clo_d, e_coefficient=0.6) print(results.e_pmv) # 0.48
Ridge Regression to predict Rectal and Skin Temperatures#
- pythermalcomfort.models.ridge_regression_predict_t_re_t_sk.ridge_regression_predict_t_re_t_sk(sex, age, height, weight, tdb, rh, duration, t_re=None, t_sk=None, limit_inputs=True, round_output=True)[source]#
Predicts the full history of core and skin temperature changes based on a ridge regression model.
This model simulates the rectal (t_re) and mean skin (t_sk) temperatures by first establishing a baseline in a thermoneutral environment (23°C, 50% RH for 120 mins) and then simulating exposure to the specified environmental conditions for duration. If a t_re and t_sk are provided, then the initial 120 min simulation is skipped. Coefficients are taken from fold one from the study [Forbes2025] (https://doi.org/10.1016/j.jtherbio.2025.104078). See notes documentation for limitations with this model.
- Parameters:
sex (Sex or str or list of (Sex or str)) – Biological sex. Pass the enum instance (e.g., Sex.male), its string value (e.g., Sex.male.value or “male”), or a list of either for vectorized inputs.
age (float or list) – Age, in years.
height (float or list) – Body height in meters [m].
weight (float or list) – Body weight in kilograms [kg].
tdb (float or list) – Ambient (dry bulb) air temperature, in °C.
rh (float or list) – Relative humidity, in %.
duration (int) – Duration of the simulation in the specified environment, in minutes.
t_re (float or list, optional) – Initial rectal temperature (°C). If provided, the baseline simulation at 23°C, 50% RH for 120 minutes is skipped, and this value is used as the starting rectal temperature for the main simulation.
t_sk (float or list, optional) – Initial mean skin temperature (°C). If provided, the baseline simulation at 23°C, 50% RH for 120 minutes is skipped, and this value is used as the starting mean skin temperature for the main simulation.
limit_inputs (bool, optional) – If True, limits the inputs to the standard applicability limits. Defaults to True.
round_output (bool, optional) – If True, rounds outputs to 2 decimal places; otherwise leaves full precision. Defaults to True.
- Returns:
PredictedBodyTemperatures – A dataclass containing the predicted rectal (t_re) and skin (t_sk) temperature history in °C. See
PredictedBodyTemperaturesfor more details. The outputs are numpy arrays. For scalar inputs, the shape is (duration,). For vector inputs, the shape is (n_inputs, duration).- Raises:
ValueError – If input arrays have inconsistent shapes after broadcasting. If sex contains invalid values (must be “male”/”female” or Sex enum members). If only one of t_re or t_sk is provided. If t_re and t_sk are not broadcastable to the input shape.
Notes
The model is applicable for adults aged between 60 and 100 years. The ranges for the input parameters are:
Age: 60 to 100 years
Height: 1.30 to 2.30 m
Weight: 40 to 140 kg
Ambient Temperature: 0 to 60 °C
Relative Humidity: 0 to 100 %
If inputs fall outside applicability limits and limit_inputs=True, the corresponding output time series are filled with NaN for all time steps.
The model does not have inputs such as: air velocity, radiative heat transfer, clothing level and an individual’s activity level due to there being little variation in the dataset.
All individuals in the dataset were in minimal clothing while stationary in a heat chamber, therefore stationary individuals in minimal clothing are best represented by this model.
The function supports vectorized inputs for all parameters, allowing for batch predictions.
Examples
from pythermalcomfort.utilities import Sex from pythermalcomfort.models.ridge_regression_predict_t_re_t_sk import ( ridge_regression_predict_t_re_t_sk, ) # Scalar example for a single person results = ridge_regression_predict_t_re_t_sk( sex=Sex.male.value, age=60, height=1.8, weight=75, tdb=35, rh=60, duration=540, ) print(f"Final Rectal temp: {results.t_re[-1]:.2f}°C") print(f"Final Skin temp: {results.t_sk[-1]:.2f}°C") # Vectorized example for multiple scenarios results_vec = ridge_regression_predict_t_re_t_sk( sex=[Sex.male.value, Sex.female.value], age=[60, 65], height=[1.8, 1.65], weight=[75, 60], tdb=[35, 40], rh=[60, 50], duration=540, ) print(f"Final rectal temps: {results_vec.t_re[:, -1]}") print(f"Rectal temp history shape: {results_vec.t_re.shape}")
- class pythermalcomfort.classes_return.PredictedBodyTemperatures(t_re, t_sk)[source]#
Dataclass for returning predicted temperature history.
The duration mentioned in the shapes below is the duration parameter passed to the prediction function.
- Variables:
t_re (numpy.ndarray of float, in °C) – Predicted rectal temperature history. - If scalar inputs are provided, this is a 1D array of shape (duration,). - If vector inputs are provided, this is a 2D array of shape (n_inputs, duration).
t_sk (numpy.ndarray of float, in °C) – Predicted mean skin temperature history. - If scalar inputs are provided, this is a 1D array of shape (duration,). - If vector inputs are provided, this is a 2D array of shape (n_inputs, duration).
Solar gain on people#
- pythermalcomfort.models.solar_gain.solar_gain(sol_altitude, sharp, sol_radiation_dir, sol_transmittance, f_svv, f_bes, asw=0.7, posture='sitting', floor_reflectance=0.6, round_output=True)[source]#
Calculate the solar gain to the human body using the Effective Radiant Field (ERF) [55ASHRAE2023]. The ERF is a measure of the net energy flux to or from the human body. ERF is expressed in W over human body surface area [W/m2]. In addition, it calculates the delta mean radiant temperature. Which is the amount by which the mean radiant temperature of the space should be increased if no solar radiation is present.
- Parameters:
sol_altitude (float or list of floats) – Solar altitude, degrees from horizontal [deg]. Ranges between 0 and 90.
sharp (float or list of floats) – Solar horizontal angle relative to the front of the person (SHARP) [deg]. Ranges between 0 and 180 and is symmetrical on either side. Zero (0) degrees represents direct-beam radiation from the front, 90 degrees represents direct-beam radiation from the side, and 180 degrees represents direct-beam radiation from the back. SHARP is the angle between the sun and the person only. Orientation relative to compass or to room is not included in SHARP.
sol_radiation_dir (float or list of floats) – Direct-beam solar radiation, [W/m2]. Ranges between 200 and 1000. See Table C2-3 of ASHRAE 55 2020 [55ASHRAE2023].
sol_transmittance (float or list of floats) – Total solar transmittance, ranges from 0 to 1. The total solar transmittance of window systems, including glazing unit, blinds, and other façade treatments, shall be determined using one of the following methods: i) Provided by manufacturer or from the National Fenestration Rating Council approved Lawrence Berkeley National Lab International Glazing Database. ii) Glazing unit plus venetian blinds or other complex or unique shades shall be calculated using National Fenestration Rating Council approved software or Lawrence Berkeley National Lab Complex Glazing Database.
f_svv (float or list of floats) – Fraction of sky-vault view fraction exposed to body, ranges from 0 to 1. It can be calculated using the function
pythermalcomfort.utilities.f_svv().f_bes (float or list of floats) – Fraction of the possible body surface exposed to sun, ranges from 0 to 1. See Table C2-2 and equation C-7 ASHRAE 55 2020 [55ASHRAE2023].
asw (float or list of floats, optional) – The average short-wave absorptivity of the occupant. It will range widely, depending on the color of the skin of the occupant as well as the color and amount of clothing covering the body. Defaults to 0.7.
Note
Short-wave absorptivity typically ranges from 0.57 to 0.84, depending on skin and clothing color. More information is available in Blum (1945).
posture (str, optional) – Default ‘sitting’ list of available options ‘standing’, ‘supine’ or ‘sitting’.
floor_reflectance (float or list of floats, optional) – Floor reflectance. It is assumed to be constant and equal to 0.6. Defaults to 0.6.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
SolarGain – A dataclass containing the solar gain to the human body and delta mean radiant temperature. See
SolarGainfor more details. To access the erf and delta_mrt values, use the corresponding attributes of the returned SolarGain instance, e.g., result.erf.- Raises:
ValueError – If the posture is not one of ‘standing’, ‘supine’, or ‘sitting’.
Examples
from pythermalcomfort.models import solar_gain result = solar_gain( sol_altitude=0, sharp=120, sol_radiation_dir=800, sol_transmittance=0.5, f_svv=0.5, f_bes=0.5, asw=0.7, posture="sitting", ) print(result.erf) # 42.9 print(result.delta_mrt) # 10.3
Applicability#
This model is applicable under the following conditions:
Solar altitude (sol_altitude) must be between 0° and 90°.
Solar horizontal angle (sharp) must be between 0° and 180°.
Direct-beam solar radiation (sol_radiation_dir) should typically range from 200 to 1000 W/m², as per ASHRAE 55 Table C2-3.
Solar transmittance (sol_transmittance) must be between 0 and 1.
Sky-vault view fraction (f_svv) and body surface exposure fraction (f_bes) must be between 0 and 1.
Average short-wave absorptivity (asw) typically ranges from 0.57 to 0.84, depending on skin and clothing color.
Posture must be one of ‘standing’, ‘supine’, or ‘sitting’.
Floor reflectance (floor_reflectance) is assumed constant at 0.6, but can vary.
All inputs are in SI units (e.g., angles in degrees, radiation in W/m²).
- class pythermalcomfort.classes_return.SolarGain(erf, delta_mrt)[source]#
Dataclass to represent the solar gain to the human body.
- Variables:
erf (float or list of floats) – Solar gain to the human body using the Effective Radiant Field [W/m2].
delta_mrt (float or list of floats) – Delta mean radiant temperature. The amount by which the mean radiant temperature of the space should be increased if no solar radiation is present.
Sports Heat Stress Risk#
- pythermalcomfort.models.sports_heat_stress_risk.sports_heat_stress_risk(tdb, tr, rh, vr, sport)[source]#
Calculate sports heat stress risk levels based on environmental conditions and sport-specific parameters.
This function assesses heat stress risk for athletes during outdoor sports by combining environmental conditions with sport-specific metabolic rates and clothing insulation. It uses the Predicted Heat Strain (PHS) model to determine threshold temperatures for different risk categories (Low, Medium, High, Extreme). The method is based on the Sports Medicine Australia heat policy framework [SportsHeatStress2025], with detailed guidelines [SportsHeatPolicy2025] and an online implementation available at the Sports Heat Tool [SportsHeatTool].
- Parameters:
tdb (float or list of float) – Dry bulb air temperature [°C].
tr (float or list of float) – Mean radiant temperature [°C].
rh (float or list of float) – Relative humidity [%].
vr (float or list of float) – Relative air speed [m/s]. Relative air speed [m/s]. If the input
vris lower than the minimum relative air speed defined for the selected sport (sport.vr), thensport.vrwill be used for the calculation.sport (_SportsValues) – Sport-specific activity dataclass with fields
clo(clothing insulation),met(metabolic rate),vr(minimum relative air speed), andduration(activity duration). Use one of the predefined entries from theSportsclass, e.g.,Sports.RUNNING,Sports.SOCCER,Sports.TENNIS, etc.
- Returns:
SportsHeatStressRisk – A dataclass containing the heat stress risk assessment results. See
SportsHeatStressRiskfor more details. To access individual values, use the corresponding attributes of the returned instance, e.g.,result.risk_level_interpolated.- Raises:
ValueError – If the risk level could not be determined due to NaN thresholds or if the internal solver fails to produce thresholds that allow a risk determination.
TypeError – If sport is not a valid _SportsValues instance.
Examples
from pythermalcomfort.models.sports_heat_stress_risk import ( sports_heat_stress_risk, Sports, ) # Example 1: Single condition for running result = sports_heat_stress_risk( tdb=35, tr=35, rh=40, vr=2.0, sport=Sports.RUNNING ) print(result.risk_level_interpolated) # 2.1 (Medium risk) print(result.t_medium) # 34.5 (Temperature threshold for medium risk) print(result.t_high) # 39.0 (Temperature threshold for high risk) print(result.t_extreme) # 41.6 (Temperature threshold for extreme risk) print( result.recommendation ) # "Increase frequency and/or duration of rest breaks" # Example 2: Array inputs for multiple conditions result = sports_heat_stress_risk( tdb=[30, 35, 40], tr=[30, 35, 40], rh=[50, 50, 50], vr=[1.0, 1.0, 1.5], sport=Sports.SOCCER, ) print(result.risk_level_interpolated) # Array of risk levels # Example 3: vr clamping — input vr (0.5 m/s) is below Sports.RUNNING.vr # (2.0 m/s), so the calculation uses sport.vr=2.0 m/s as the effective wind speed. result_clamped = sports_heat_stress_risk( tdb=35, tr=35, rh=40, vr=0.5, sport=Sports.RUNNING ) # Because vr is clamped to 2.0 m/s (same as Example 1), the output matches: print(result_clamped.risk_level_interpolated) # same as Example 1 print(result_clamped.t_medium) # same as Example 1 # Example 4: Different sports result_tennis = sports_heat_stress_risk( tdb=33, tr=70, rh=60, vr=0.75, sport=Sports.TENNIS ) result_cycling = sports_heat_stress_risk( tdb=33, tr=70, rh=60, vr=3.0, sport=Sports.CYCLING )
- class pythermalcomfort.models.sports_heat_stress_risk.Sports[source]#
Namespace of predefined sport values.
Use attributes like Sports.RUNNING to obtain a _SportsValues instance. This class uses a frozen dataclass decorator to prevent modification of the namespace. Attributes are class-level constants, not instance fields.
- class pythermalcomfort.classes_return.SportsHeatStressRisk(risk_level_interpolated, t_medium, t_high, t_extreme, recommendation)[source]#
Dataclass to represent the Sports Heat Stress Risk calculation results.
- Variables:
risk_level_interpolated (float or list of floats) – Interpolated risk level (1.0-4.0), [dimensionless]. Risk levels: 1-<2 = low, 2-<3 = moderate, 3-<4 = high, 4 = extreme.
t_medium (float or list of floats) – Temperature threshold for medium risk level, [°C].
t_high (float or list of floats) – Temperature threshold for high risk level, [°C].
t_extreme (float or list of floats) – Temperature threshold for extreme risk level, [°C].
recommendation (str or list of str) – Heat stress management recommendations for the calculated risk level.
Standard Effective Temperature (SET)#
- pythermalcomfort.models.set_tmp.set_tmp(tdb, tr, v, rh, met, clo, wme=0.0, body_surface_area=1.8258, p_atm=101325, position='standing', limit_inputs=True, round_output=True, calculate_ce=False)[source]#
Calculate the Standard Effective Temperature (SET).
The SET is the temperature of a hypothetical isothermal environment at 50% (rh), <0.1 m/s (20 fpm) average air speed (v), and tr = tdb, in which the total heat loss from the skin of an imaginary occupant wearing clothing, standardized for the activity concerned is the same as that from a person in the actual environment with actual clothing and activity level. [Gagge1986]
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Air speed, [m/s].
rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
body_surface_area (float or list of floats, optional) – Body surface area, default value 1.8258 [m2]
Note
The body surface area can be calculated using the function
pythermalcomfort.utilities.body_surface_area().p_atm (float or list of floats, optional) – Atmospheric pressure, default value 101325 [Pa]
position (str, optional) – Select either “sitting” or “standing”. Defaults to “standing”.
limit_inputs (bool, optional) – If True, limits the inputs to the standard applicability limits. Defaults to True.
Note
By default, if the inputs are outside the standard applicability limits the function returns nan. If False returns values regardless of the input values. The limits are 10 < tdb [°C] < 40, 10 < tr [°C] < 40, 0 < v [m/s] < 2, 1 < met [met] < 4, and 0 < clo [clo] < 1.5.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
SET – A dataclass containing the Standard Effective Temperature. See
SetTmpfor more details. To access the set value, use the corresponding attribute of the returned SetTmp instance, e.g., result.set.
Examples
from pythermalcomfort.models import set_tmp result = set_tmp(tdb=25, tr=25, v=0.1, rh=50, met=1.2, clo=0.5) print(result.set) # 24.3 result = set_tmp(tdb=[25, 25], tr=25, v=0.1, rh=50, met=1.2, clo=0.5) print(result.set) # [24.3, 24.3]
Universal Thermal Climate Index (UTCI)#
- pythermalcomfort.models.utci.utci(tdb, tr, v, rh, units='SI', limit_inputs=True, round_output=True)[source]#
Calculate the Universal Thermal Climate Index (UTCI).
The UTCI is the equivalent temperature for the environment derived from a reference environment. It is defined as the air temperature of the reference environment which produces the same strain index value in comparison with the reference individual’s response to the real environment. It is regarded as one of the most comprehensive indices for calculating heat stress in outdoor spaces. The parameters that are taken into account for calculating UTCI involve dry bulb temperature, mean radiation temperature, the pressure of water vapor or relative humidity, and wind speed (at the elevation of 10 m above the ground). [Zare2018]
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature. Default in [°C] in [°F] if units = ‘IP’.
tr (float or list of floats) – Mean radiant temperature. Default in [°C] in [°F] if units = ‘IP’.
v (float or list of floats) – Wind speed 10m above ground level. Default in [m/s] in [fps] if units = ‘IP’.
rh (float or list of floats) – Relative humidity, [%].
units (str, optional) – Select the SI (International System of Units) or the IP (Imperial Units) system. Defaults to ‘SI’.
limit_inputs (bool, optional) – By default, if the inputs are outside the standard applicability limits the function returns nan. If False, returns UTCI values even if input values are outside the applicability limits of the model. The valid input ranges are -50 < tdb [°C] < 50, tdb - 30 < tr [°C] < tdb + 70, and for 0.5 < v [m/s] < 17.0. Defaults to True.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
UTCI – A dataclass containing the Universal Thermal Climate Index and stress category. See
UTCIfor more details. To access the utci and stress_category values, use the corresponding attributes of the returned Utci instance, e.g., result.utci.
Examples
from pythermalcomfort.models import utci result = utci(tdb=25, tr=25, v=1.0, rh=50) print(result.utci) # 24.6 print(result.stress_category) # "no thermal stress" result = utci(tdb=[25, 40], tr=25, v=1.0, rh=50) print(result.utci) # [24.6, 40.6]
- class pythermalcomfort.classes_return.UTCI(utci, stress_category)[source]#
Dataclass to represent the Universal Thermal Climate Index (UTCI).
- Variables:
utci (float or list of floats) – Universal Thermal Climate Index, [°C] or in [°F].
stress_category (str or list of strs) – UTCI categorized in terms of thermal stress [Blazejczyk2013].
Use Fans During Heatwaves#
- pythermalcomfort.models.use_fans_heatwaves.use_fans_heatwaves(tdb, tr, v, rh, met, clo, wme=0, body_surface_area=1.8258, p_atm=101325, position='standing', max_skin_blood_flow=80, max_sweating=500, limit_inputs=True, round_output=True)[source]#
Estimate if the conditions you have selected would cause heat strain.
This occurs when either the following variables reaches its maximum value:
m_rsw Rate at which regulatory sweat is generated, [mL/h/m2]
w : Skin wettedness, adimensional. Ranges from 0 and 1.
m_bl : Skin blood flow [kg/h/m2]
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
tr (float or list of floats) – Mean radiant temperature, [°C].
v (float or list of floats) – Air speed, [m/s].
rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
wme (float or list of floats, optional) – External work, [met]. Defaults to 0.
body_surface_area (float or list of floats, optional) – Body surface area, default value 1.8258 [m2]. Defaults to 1.8258.
Note
The body surface area can be calculated using the function
pythermalcomfort.utilities.body_surface_area().p_atm (float or list of floats, optional) – Atmospheric pressure, default value 101325 [Pa]. Defaults to 101325.
position (str, optional) – Select either “sitting” or “standing”. Defaults to “standing”.
max_skin_blood_flow (float) – Maximum blood flow from the core to the skin. Defaults to 80.
limit_inputs (bool, optional) – By default, if the inputs are outside the standard applicability limits the function returns nan. If False, returns values even if input values are outside the applicability limits of the model. Defaults to True. The applicability limits are 20 < tdb [°C] < 50, 20 < tr [°C] < 50, 0.1 < v [m/s] < 4.5, 0.7 < met [met] < 2, and 0 < clo [clo] < 1.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
max_sweating (float or list of floats, optional) – Maximum rate at which regulatory sweat is generated, [kg/h/m2]. Defaults to 500.
- Returns:
UseFansHeatwaves – A dataclass containing the results of using fans during heatwaves. See
UseFansHeatwavesfor more details. To access the results, use the corresponding attributes of the returned UseFansHeatwaves instance, e.g., result.e_skin.
Examples
from pythermalcomfort.models import use_fans_heatwaves result = use_fans_heatwaves(tdb=35, tr=35, v=1.0, rh=50, met=1.2, clo=0.5) print(result.e_skin) # 63.0
- class pythermalcomfort.classes_return.UseFansHeatwaves(e_skin, e_rsw, e_max, q_sensible, q_skin, q_res, t_core, t_skin, m_bl, m_rsw, w, w_max, heat_strain, heat_strain_blood_flow, heat_strain_w, heat_strain_sweating)[source]#
Dataclass to represent the results of using fans during heatwaves.
- Variables:
e_skin (float or list of floats) – Total rate of evaporative heat loss from skin, [W/m2]. Equal to e_rsw + e_diff.
e_rsw (float or list of floats) – Rate of evaporative heat loss from sweat evaporation, [W/m2].
e_max (float or list of floats) – Maximum rate of evaporative heat loss from skin, [W/m2].
q_sensible (float or list of floats) – Sensible heat loss from skin, [W/m2].
q_skin (float or list of floats) – Total rate of heat loss from skin, [W/m2]. Equal to q_sensible + e_skin.
q_res (float or list of floats) – Total rate of heat loss through respiration, [W/m2].
t_core (float or list of floats) – Core temperature, [°C].
t_skin (float or list of floats) – Skin temperature, [°C].
m_bl (float or list of floats) – Skin blood flow, [kg/h/m2].
m_rsw (float or list of floats) – Rate at which regulatory sweat is generated, [mL/h/m2].
w (float or list of floats) – Skin wettedness, adimensional. Ranges from 0 to 1.
w_max (float or list of floats) – Skin wettedness (w) practical upper limit, adimensional. Ranges from 0 to 1.
heat_strain (bool or list of bools) – True if the model predicts that the person may be experiencing heat strain.
heat_strain_blood_flow (bool or list of bools) – True if heat strain is caused by skin blood flow (m_bl) reaching its maximum value.
heat_strain_w (bool or list of bools) – True if heat strain is caused by skin wettedness (w) reaching its maximum value.
heat_strain_sweating (bool or list of bools) – True if heat strain is caused by regulatory sweating (m_rsw) reaching its maximum value.
Vertical air temperature gradient#
- pythermalcomfort.models.vertical_tmp_grad_ppd.vertical_tmp_grad_ppd(tdb, tr, vr, rh, met, clo, vertical_tmp_grad, round_output=True, limit_inputs=True)[source]#
Calculate the percentage of thermally dissatisfied people with a vertical temperature gradient between feet and head [55ASHRAE2023]. This equation is only applicable for vr < 0.2 m/s (40 fps).
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
Note
The air temperature is the average value over two heights: 0.6 m (24 in.) and 1.1 m (43 in.) for seated occupants and 1.1 m (43 in.) and 1.7 m (67 in.) for standing occupants.
tr (float or list of floats) – Mean radiant temperature, [°C].
vr (float or list of floats) – Relative air speed, [m/s].
Note
vr is the relative air speed caused by body movement and not the air speed measured by the air speed sensor. The relative air speed is the sum of the average air speed measured by the sensor plus the activity-generated air speed (Vag). Where Vag is the activity-generated air speed caused by motion of individual body parts. vr can be calculated using the function
pythermalcomfort.utilities.v_relative().rh (float or list of floats) – Relative humidity, [%].
met (float or list of floats) – Metabolic rate, [met].
clo (float or list of floats) – Clothing insulation, [clo].
Note
this is the basic insulation also known as the intrinsic clothing insulation value of the clothing ensemble (Icl,r), this is the thermal insulation from the skin surface to the outer clothing surface, including enclosed air layers, under actual environmental conditions. This value is not the total insulation (IT,r). The dynamic clothing insulation, clo, can be calculated using the function
pythermalcomfort.utilities.clo_dynamic_ashrae().vertical_tmp_grad (float or list of floats) – Vertical temperature gradient between the feet and the head, [°C/m].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
limit_inputs (bool, optional) – By default, if the inputs are outside the standard applicability limits the function returns nan. If False, returns values even if input values are outside the applicability limits of the model. Defaults to True. The applicability limits are 10 < tdb [°C] < 40, 10 < tr [°C] < 40, 0 < vr [m/s] < 0.2, 1 < met [met] < 4, and 0 < clo [clo] < 1.5.
- Returns:
VerticalTGradPPD – A dataclass containing the Predicted Percentage of Dissatisfied occupants with vertical temperature gradient and acceptability. See
VerticalTmpGradPPDfor more details. To access the ppd_vg and acceptability values, use the corresponding attributes of the returned VerticalTmpGradPPD instance, e.g., result.ppd_vg.
Examples
from pythermalcomfort.models import vertical_tmp_grad_ppd result = vertical_tmp_grad_ppd( tdb=25, tr=25, vr=0.1, rh=50, met=1.2, clo=0.5, vertical_tmp_grad=7 ) print(result.ppd_vg) # 12.6 print(result.acceptability) # False
- class pythermalcomfort.classes_return.VerticalTGradPPD(ppd_vg, acceptability)[source]#
Dataclass to represent the Predicted Percentage of Dissatisfied (PPD) with vertical temperature gradient.
- Variables:
ppd_vg (float or list of floats) – Predicted Percentage of Dissatisfied occupants with vertical temperature gradient.
acceptability (bool or list of bools) – True if the value of air speed at the ankle level is acceptable (PPD_vg <= 5%).
Wet Bulb Globe Temperature Index (WBGT)#
- pythermalcomfort.models.wbgt.wbgt(twb, tg, tdb=None, with_solar_load=False, round_output=True)[source]#
Calculate the Wet Bulb Globe Temperature (WBGT) index in compliance with the ISO 7243 Standard [7243ISO2017].
The WBGT is a heat stress index that measures the thermal environment to which a person is exposed. In most situations, this index is simple to calculate. It should be used as a screening tool to determine whether heat stress is present. The PHS model allows a more accurate estimation of stress. PHS can be calculated using the function
pythermalcomfort.models.phs().The WBGT determines the impact of heat on a person throughout the course of a working day (up to 8 hours). It does not apply to very brief heat exposures. It pertains to the evaluation of male and female people who are fit for work in both indoor and outdoor occupational environments, as well as other sorts of surroundings [7243ISO2017].
The WBGT is defined as a function of only twb and tg if the person is not exposed to direct radiant heat from the sun. When a person is exposed to direct radiant heat, tdb must also be specified.
- Parameters:
twb (float or list of floats) – Natural (no forced air flow) wet bulb temperature, [°C].
tg (float or list of floats) – Globe temperature, [°C].
tdb (float or list of floats, optional) – Dry bulb air temperature, [°C]. This value is needed as input if the person is exposed to direct solar radiation.
with_solar_load (bool, optional) – True if the globe sensor is exposed to direct solar radiation. Defaults to False.
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
WBGT – A dataclass containing the Wet Bulb Globe Temperature Index. See
WBGTfor more details. To access the wbgt value, use the wbgt attribute of the returned wbgt instance, e.g., result.wbgt.
Examples
from pythermalcomfort.models import wbgt result = wbgt(twb=25, tg=32) print(result.wbgt) # 27.1 result = wbgt(twb=25, tg=32, tdb=20, with_solar_load=True) print(result.wbgt) # 25.9
Wind chill index#
- pythermalcomfort.models.wci.wci(tdb, v, round_output=True)[source]#
Calculate the Wind Chill Index (WCI) in accordance with the ASHRAE 2017 Handbook Fundamentals - Chapter 9 [ashrae2017].
The wind chill index (WCI) is an empirical index based on cooling measurements taken on a cylindrical flask partially filled with water in Antarctica (Siple and Passel 1945). For a surface temperature of 33°C, the index describes the rate of heat loss from the cylinder via radiation and convection as a function of ambient temperature and wind velocity.
This formulation has been met with some valid criticism. WCI is unlikely to be an accurate measure of heat loss from exposed flesh, which differs from plastic in terms of curvature, roughness, and radiation exchange qualities, and is always below 33°C in a cold environment. Furthermore, the equation’s values peak at 90 km/h and then decline as velocity increases. Nonetheless, this score reliably represents the combined effects of temperature and wind on subjective discomfort for velocities below 80 km/h [ashrae2017].
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
v (float or list of floats) – Wind speed 10m above ground level, [m/s].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
WCI – A dataclass containing the Wind Chill Index. See
WCIfor more details. To access the wci value, use the wci attribute of the returned WCI instance, e.g., result.wci.
Examples
from pythermalcomfort.models import wci result = wci(tdb=-5, v=5.5) print(result.wci) # 1255.2 result = wci(tdb=[-5, -10], v=[5.5, 10], round_output=True) print(result.wci) # [1255.2 1603.9]
Wind chill temperature#
- pythermalcomfort.models.wind_chill_temperature.wind_chill_temperature(tdb, v, round_output=True)[source]#
Calculate the Wind Chill Temperature (WCT).
We validated the implementation of this model by comparing the results with the Wind Chill Temperature Calculator on Calculator.net
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
v (float or list of floats) – Wind speed 10m above ground level, [km/h].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
WCT – A dataclass containing the Wind Chill Temperature. See
WCTfor more details. To access the wct value, use the wct attribute of the returned WCT instance, e.g., result.wct.
Examples
from pythermalcomfort.models import wind_chill_temperature result = wind_chill_temperature(tdb=-5, v=5.5) print(result.wct) # -7.5 result = wind_chill_temperature(tdb=[-5, -10], v=[5.5, 10], round_output=True) print(result.wct) # [-7.5, -15.3]
Work capacity (Dunne et al.)#
- pythermalcomfort.models.work_capacity_dunne.work_capacity_dunne(wbgt, work_intensity='heavy')[source]#
Estimate work capacity due to heat based on Dunne et al [Dunne2013].
Estimates the amount of work that will be done at a given WBGT and intensity of work as a percent. 100% means work is unaffected by heat. 0% means no work is done.
This is based upon NIOSH safety standards. See: Dunne JP, Stouffer RJ, John JG. Reductions in labour capacity from heat stress under climate warming. Nature Climate Change. 2013 Jun;3(6):563 6.
Heavy intensity work is sometimes labelled as 400 W, but this is only nominal. Moderate work is assumed to be half as much as heavy intensity, and light half as much as moderate.
- Parameters:
wbgt (float or list of floats) – Wet bulb globe temperature, [°C].
work_intensity (str) – Which work intensity to use for the calculation, choice of “heavy”, “moderate” or “light”. Default is “heavy”.
Note
Dunne et al [Dunne2013] suggests that heavy intensity work is 350-500 kcal/h, moderate is 200-350 kcal/h, and light is less than 100-200 kcal/h.
- Returns:
WorkCapacity – A dataclass containing the work capacity. See
WorkCapacityfor more details. To access the capacity value, use the capacity attribute of the returned WorkCapacity instance, e.g., result.capacity.
Work capacity (Hothaps)#
- pythermalcomfort.models.work_capacity_hothaps.work_capacity_hothaps(wbgt, work_intensity='heavy')[source]#
Estimate work capacity due to heat based on Kjellstrom et al. [Kjellstrom2018].
Estimates the amount of work that will be done at a given WBGT and intensity of work as a percent. 100% means work is unaffected by heat. 0% means no work is done. Note that in this version the functions do not reach 0% as it is assumed that it is always possible to work in short bursts for 10% of the time.
Note that for this function “the empirical evidence is from studies in heavyly distinct locations, including a gold mine (Wyndham, 1969), 124 rice harvesters in West Bengal in India (Sahu et al., 2013), and six women observed in a climatic chamber (Nag and Nag, 1992).” (https://adaptecca.es/sites/default/files/documentos/2018_jrc_pesetaiii_impact_labour_productivity.pdf). The shape of the function is just an assumption, and the fit of the sigmoid to the data it is analysing is not especially good.
Heavy intensity work is sometimes labelled as 400 W, moderate 300 W, light 200 W, but this is only nominal.
The correction citation is: Bröde P, Fiala D, Lemke B, Kjellstrom T. Estimated work ability in warm outdoor environments depends on the chosen heat stress assessment metric. International Journal of Biometeorology. 2018 Mar;62(3):331 45.
The relevant definitions of the functions can be found most clearly in: Orlov A, Sillmann J, Aunan K, Kjellstrom T, Aaheim A. Economic costs of heat-induced reductions in worker productivity due to global warming. Global Environmental Change [Internet]. 2020 Jul;63. Available from: https://doi.org/10.1016/j.gloenvcha.2020.102087
For a comparison of different functions see Fig 1 of Day E, Fankhauser S, Kingsmill N, Costa H, Mavrogianni A. Upholding labour productivity under climate change: an assessment of adaptation options. Climate Policy. 2019 Mar;19(3):367 85.
- Parameters:
wbgt (float or list of floats) – Wet bulb globe temperature, [°C].
work_intensity (str) – Which work intensity to use for the calculation, choice of “heavy”, “moderate” or “light”.
- Returns:
WorkCapacity – A dataclass containing the work capacity. See
WorkCapacityfor more details. To access the capacity value, use the capacity attribute of the returned WorkCapacity instance, e.g., result.capacity.
- class pythermalcomfort.classes_return.WorkCapacity(capacity)[source]
Dataclass to represent work loss.
- Variables:
capacity (float or list of floats) – Work capacity affected by heat.
Work capacity (ISO)#
- pythermalcomfort.models.work_capacity_iso.work_capacity_iso(wbgt, met)[source]#
Estimate work capacity due to heat based on ISO standards as described by Brode et al.
Estimates the amount of work that will be done at a given WBGT and intensity of work as a percent. 100% means work is unaffected by heat. 0% means no work is done.
The function definitions / parameters can be found in: 1. Bröde P, Fiala D, Lemke B, Kjellstrom T. Estimated work ability in warm outdoor environments depends on the chosen heat stress assessment metric. International Journal of Biometeorology. 2018 Mar;62(3):331 45.
For a comparison of different functions see Fig 1 of Day E, Fankhauser S, Kingsmill N, Costa H, Mavrogianni A. Upholding labour productivity under climate change: an assessment of adaptation options. Climate Policy. 2019 Mar;19(3):367 85.
- Parameters:
wbgt (float or list of floats) – Wet bulb globe temperature, [°C].
met (float or list of floats) – Metabolic heat production in Watts
- Returns:
WorkCapacity – A dataclass containing the work capacity. See
WorkCapacityfor more details. To access the capacity value, use the capacity attribute of the returned WorkCapacity instance, e.g., result.capacity.
- class pythermalcomfort.classes_return.WorkCapacity(capacity)[source]
Dataclass to represent work loss.
- Variables:
capacity (float or list of floats) – Work capacity affected by heat.
Work capacity (NIOSH)#
- pythermalcomfort.models.work_capacity_niosh.work_capacity_niosh(wbgt, met)[source]#
Estimate work capacity due to heat based on NIOSH standards as described by Brode et al.
Estimates the amount of work that will be done at a given WBGT and intensity of work as a percent. 100% means work is unaffected by heat. 0% means no work is done.
The function definitions / parameters can be found in: 1. Bröde P, Fiala D, Lemke B, Kjellstrom T. Estimated work ability in warm outdoor environments depends on the chosen heat stress assessment metric. International Journal of Biometeorology. 2018 Mar;62(3):331 45.
For a comparison of different functions see Fig 1 of Day E, Fankhauser S, Kingsmill N, Costa H, Mavrogianni A. Upholding labour productivity under climate change: an assessment of adaptation options. Climate Policy. 2019 Mar;19(3):367 85.
- Parameters:
wbgt (float or list of floats) – Wet bulb globe temperature, [°C].
met (float or list of floats) – Metabolic heat production in Watts
- Returns:
WorkCapacity – A dataclass containing the work capacity. See
WorkCapacityfor more details. To access the capacity value, use the capacity attribute of the returned WorkCapacity instance, e.g., result.capacity.
- class pythermalcomfort.classes_return.WorkCapacity(capacity)[source]
Dataclass to represent work loss.
- Variables:
capacity (float or list of floats) – Work capacity affected by heat.
Temperature Humidity Index (THI)#
- pythermalcomfort.models.thi.thi(tdb, rh, round_output=True)[source]#
Calculate the Temperature-Humidity Index (THI) defined in [Yan2025], equivalent to the definition in [Schlatter1987], but uses Celsius instead of Fahrenheit.
- Parameters:
tdb (float or list of floats) – Dry bulb air temperature, [°C].
rh (float or list of floats) – Relative humidity, [%].
round_output (bool, optional) – If True, rounds output value. If False, it does not round it. Defaults to True.
- Returns:
THI – A dataclass containing the Temperature-Humidity Index. See
THIfor more details. To access the thi value, use the thi attribute of the returned THI instance, e.g., result.thi.