heatstress 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- heatstress-0.1.0/CHANGELOG.md +42 -0
- heatstress-0.1.0/CITATION.cff +20 -0
- heatstress-0.1.0/LICENSE +21 -0
- heatstress-0.1.0/MANIFEST.in +9 -0
- heatstress-0.1.0/PKG-INFO +213 -0
- heatstress-0.1.0/README.md +169 -0
- heatstress-0.1.0/pyproject.toml +135 -0
- heatstress-0.1.0/setup.cfg +4 -0
- heatstress-0.1.0/src/heatstress/__init__.py +120 -0
- heatstress-0.1.0/src/heatstress/__main__.py +5 -0
- heatstress-0.1.0/src/heatstress/_utils.py +164 -0
- heatstress-0.1.0/src/heatstress/apparent.py +61 -0
- heatstress-0.1.0/src/heatstress/cli.py +297 -0
- heatstress-0.1.0/src/heatstress/heat_index.py +111 -0
- heatstress-0.1.0/src/heatstress/heatwave.py +297 -0
- heatstress-0.1.0/src/heatstress/humidex.py +78 -0
- heatstress-0.1.0/src/heatstress/humidity.py +145 -0
- heatstress-0.1.0/src/heatstress/mrt.py +75 -0
- heatstress-0.1.0/src/heatstress/py.typed +0 -0
- heatstress-0.1.0/src/heatstress/risk.py +235 -0
- heatstress-0.1.0/src/heatstress/series.py +199 -0
- heatstress-0.1.0/src/heatstress/solar.py +164 -0
- heatstress-0.1.0/src/heatstress/units.py +142 -0
- heatstress-0.1.0/src/heatstress/utci.py +336 -0
- heatstress-0.1.0/src/heatstress/wbgt.py +589 -0
- heatstress-0.1.0/src/heatstress/wetbulb.py +114 -0
- heatstress-0.1.0/src/heatstress/windchill.py +94 -0
- heatstress-0.1.0/src/heatstress.egg-info/PKG-INFO +213 -0
- heatstress-0.1.0/src/heatstress.egg-info/SOURCES.txt +37 -0
- heatstress-0.1.0/src/heatstress.egg-info/dependency_links.txt +1 -0
- heatstress-0.1.0/src/heatstress.egg-info/entry_points.txt +2 -0
- heatstress-0.1.0/src/heatstress.egg-info/requires.txt +18 -0
- heatstress-0.1.0/src/heatstress.egg-info/top_level.txt +1 -0
- heatstress-0.1.0/tests/data/utci_test_data.tsv +1006 -0
- heatstress-0.1.0/tests/test_cli_series.py +219 -0
- heatstress-0.1.0/tests/test_heatwave_solar.py +136 -0
- heatstress-0.1.0/tests/test_indices.py +308 -0
- heatstress-0.1.0/tests/test_reference_values.py +246 -0
- heatstress-0.1.0/tests/test_vectorisation.py +139 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-11-09
|
|
8
|
+
### Added
|
|
9
|
+
- NWS Heat Index (`heat_index`) following the WPC algorithm: Steadman low-range
|
|
10
|
+
formula, Rothfusz regression and both NWS adjustments; `rothfusz_regression` for
|
|
11
|
+
comparison.
|
|
12
|
+
- Humidex (`humidex`, from RH or dew point) and Apparent Temperature
|
|
13
|
+
(`apparent_temperature`, Steadman/BoM with optional radiation term).
|
|
14
|
+
- Wet-bulb temperature: Stull (2011) formula and a WMO psychrometric Newton solver
|
|
15
|
+
with pressure dependence.
|
|
16
|
+
- WBGT: full Liljegren et al. (2008) outdoor model with globe, natural wet-bulb and
|
|
17
|
+
psychrometric wet-bulb components, direct-beam fraction estimate and wind-height
|
|
18
|
+
scaling; shade/indoor estimate; ISO 7243 formulas for measured values; the
|
|
19
|
+
Australian BoM approximation (labelled as such).
|
|
20
|
+
- UTCI operational polynomial (Broede et al. 2012) with the 210 coefficients of the
|
|
21
|
+
reference program, validity masking and stress categories.
|
|
22
|
+
- Wind Chill (NWS/MSC 2001) with the MSC light-wind formula, and an NWS-style
|
|
23
|
+
`feels_like`.
|
|
24
|
+
- Mean radiant temperature from globe temperature (ISO 7726, forced/natural
|
|
25
|
+
convection).
|
|
26
|
+
- NOAA solar position (zenith, elevation, azimuth, declination, equation of time,
|
|
27
|
+
Earth-Sun distance) with time-zone-aware input handling.
|
|
28
|
+
- Humidity helpers: saturation vapour pressure (Magnus, WMO, Buck, BoM, Hardy
|
|
29
|
+
ITS-90), vapour pressure, dew point and relative humidity conversions.
|
|
30
|
+
- Risk categories: NWS heat index bands, Humidex bands, UTCI stress classes, ACGIH
|
|
31
|
+
TLV / Action Limit WBGT work-rest allocation (OSHA Technical Manual), ISO 7243:2017
|
|
32
|
+
reference WBGT.
|
|
33
|
+
- Heatwave detection: fixed and calendar-day percentile thresholds, spells of
|
|
34
|
+
consecutive exceedance days with event statistics, Excess Heat Factor (Nairn &
|
|
35
|
+
Fawcett 2015) with severity classes.
|
|
36
|
+
- `compute_indices` for dicts and pandas DataFrames, and the `heatstress` CLI
|
|
37
|
+
(`hi`, `humidex`, `at`, `wetbulb`, `wbgt`, `utci`, `windchill`, `series`).
|
|
38
|
+
- Scalars, numpy arrays, pandas Series and xarray DataArrays are accepted and
|
|
39
|
+
returned in kind; `ValidityRangeWarning` for out-of-range inputs.
|
|
40
|
+
- Validation tests against the official UTCI test data set, the NWS heat index and
|
|
41
|
+
wind chill charts, published worked examples, an independent Liljegren
|
|
42
|
+
implementation and the NREL SPA solar position algorithm.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
authors:
|
|
4
|
+
- family-names: "Eminoğlu"
|
|
5
|
+
given-names: "Yusuf"
|
|
6
|
+
email: "yusufeminoglu@gmail.com"
|
|
7
|
+
orcid: "https://orcid.org/0009-0005-6000-2934"
|
|
8
|
+
title: "heatstress"
|
|
9
|
+
version: "0.1.0"
|
|
10
|
+
date-released: "2026-11-09"
|
|
11
|
+
license: "MIT"
|
|
12
|
+
repository-code: "https://github.com/YusufEminoglu/heatstress_sdk"
|
|
13
|
+
url: "https://pypi.org/project/heatstress/"
|
|
14
|
+
abstract: "Vectorised heat-stress indices for public-health, climate-adaptation and occupational-safety analysis: NWS Heat Index, Humidex, Apparent Temperature, wet-bulb temperature, WBGT (Liljegren et al. 2008), UTCI, wind chill, risk categories and heatwave detection including the Excess Heat Factor."
|
|
15
|
+
keywords:
|
|
16
|
+
- heat stress
|
|
17
|
+
- WBGT
|
|
18
|
+
- UTCI
|
|
19
|
+
- heat index
|
|
20
|
+
- heatwave
|
heatstress-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yusuf Eminoğlu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: heatstress
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Vectorised heat-stress indices: NWS Heat Index, Humidex, Apparent Temperature, wet bulb, WBGT (Liljegren), UTCI, wind chill, risk categories and heatwave detection.
|
|
5
|
+
Author-email: Yusuf Eminoğlu <yusufeminoglu@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/YusufEminoglu/heatstress_sdk
|
|
8
|
+
Project-URL: Repository, https://github.com/YusufEminoglu/heatstress_sdk
|
|
9
|
+
Project-URL: Issues, https://github.com/YusufEminoglu/heatstress_sdk/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/YusufEminoglu/heatstress_sdk/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: heat-stress,heat-index,wbgt,utci,humidex,apparent-temperature,wet-bulb,wind-chill,heatwave,excess-heat-factor,thermal-comfort,biometeorology,occupational-safety,public-health,climate-adaptation
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
22
|
+
Classifier: Intended Audience :: Science/Research
|
|
23
|
+
Classifier: Intended Audience :: Developers
|
|
24
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: numpy>=1.20.0
|
|
30
|
+
Provides-Extra: pandas
|
|
31
|
+
Requires-Dist: pandas>=1.3.0; extra == "pandas"
|
|
32
|
+
Provides-Extra: xarray
|
|
33
|
+
Requires-Dist: xarray>=0.19.0; extra == "xarray"
|
|
34
|
+
Requires-Dist: pandas>=1.3.0; extra == "xarray"
|
|
35
|
+
Provides-Extra: all
|
|
36
|
+
Requires-Dist: pandas>=1.3.0; extra == "all"
|
|
37
|
+
Requires-Dist: xarray>=0.19.0; extra == "all"
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
42
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# heatstress
|
|
46
|
+
|
|
47
|
+
Vectorised heat-stress indices for public-health, climate-adaptation and
|
|
48
|
+
occupational-safety analysis: NWS Heat Index, Humidex, Apparent Temperature,
|
|
49
|
+
wet-bulb temperature, WBGT (full Liljegren et al. 2008 model, shade/indoor, ISO 7243,
|
|
50
|
+
BoM approximation), UTCI, Wind Chill, mean radiant temperature, solar position,
|
|
51
|
+
risk categories and heatwave detection, including the Excess Heat Factor.
|
|
52
|
+
|
|
53
|
+
* Pure numpy core; every function takes scalars, numpy arrays, pandas Series or
|
|
54
|
+
xarray DataArrays and returns the same kind of object.
|
|
55
|
+
* Units are explicit: degC by default with a `units="C" | "F" | "K"` switch on
|
|
56
|
+
temperature functions, wind in m/s, pressure in hPa, radiation in W/m2, humidity in %.
|
|
57
|
+
Converters are in `heatstress.units`.
|
|
58
|
+
* Inputs outside a formula's validity range raise a `ValidityRangeWarning`; NaN propagates.
|
|
59
|
+
* Validated against published reference values and independent implementations
|
|
60
|
+
(see [Validation](#validation)).
|
|
61
|
+
* A command-line tool for single values and CSV time series.
|
|
62
|
+
|
|
63
|
+
> **Disclaimer.** heatstress computes screening indices from weather data. It is
|
|
64
|
+
> not medical advice and is not a substitute for on-site measurement, an
|
|
65
|
+
> occupational health programme, clinical judgement or the official warnings of
|
|
66
|
+
> your national meteorological or public-health service.
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install heatstress # numpy only
|
|
72
|
+
pip install "heatstress[pandas]" # + pandas helpers (DataFrames, events_to_frame)
|
|
73
|
+
pip install "heatstress[xarray]" # + xarray/pandas
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Python 3.9 or newer.
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import heatstress as hs
|
|
82
|
+
|
|
83
|
+
hs.heat_index(35, 60) # 45.1 degC (NWS algorithm)
|
|
84
|
+
hs.heat_index(95, 50, units="F") # 105.2 degF
|
|
85
|
+
hs.heat_index_category(45.1) # 'danger'
|
|
86
|
+
|
|
87
|
+
hs.humidex(30, dew_point=15) # 34.0
|
|
88
|
+
hs.apparent_temperature(30, 50, wind=2) # 31.6 degC
|
|
89
|
+
hs.wet_bulb_psychrometric(25, 50) # 17.9 degC
|
|
90
|
+
hs.utci(30, tmrt=50, wind=2, rh=50) # 34.6 degC
|
|
91
|
+
hs.utci_category(34.6) # 'strong heat stress'
|
|
92
|
+
|
|
93
|
+
# Outdoor WBGT from standard weather data (Liljegren et al. 2008)
|
|
94
|
+
z = hs.solar_zenith("2026-07-15T10:00Z", lat=38.42, lon=27.14)
|
|
95
|
+
w = hs.wbgt_liljegren_components(t=33, rh=55, wind=1.5, solar=850, zenith=z, pressure=1008)
|
|
96
|
+
w.wbgt, w.globe_temperature, w.natural_wet_bulb # 32.7, 49.7, 27.7 degC
|
|
97
|
+
hs.work_rest_allocation(w.wbgt, "moderate") # ACGIH TLV work-rest guidance
|
|
98
|
+
|
|
99
|
+
# Heatwaves on a daily series
|
|
100
|
+
import pandas as pd
|
|
101
|
+
tmax = pd.Series(..., index=pd.date_range("1991-01-01", periods=..., freq="D"))
|
|
102
|
+
thr = hs.calendar_day_percentile(tmax, tmax.index, q=90, window=15, baseline=(1991, 2020))
|
|
103
|
+
events = hs.heatwave_events(tmax, thr, min_duration=3)
|
|
104
|
+
hs.events_to_frame(events)
|
|
105
|
+
|
|
106
|
+
ehf = hs.excess_heat_factor(tmean_daily) # Nairn & Fawcett (2015)
|
|
107
|
+
hs.ehf_severity(ehf) # none / low-intensity / severe / extreme
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Indices
|
|
111
|
+
|
|
112
|
+
| Index | Function | Inputs | Source | Validity / notes |
|
|
113
|
+
|---|---|---|---|---|
|
|
114
|
+
| Heat Index | `heat_index` | T, RH | NWS/WPC algorithm: Steadman (1979) simple formula, Rothfusz (1990) regression and the two NWS adjustments | Regression error +/-1.3 degF; warning above 120 degF air temperature or 150 degF HI |
|
|
115
|
+
| Rothfusz regression only | `rothfusz_regression` | T, RH | Rothfusz (1990) NWS SR 90-23 | For comparison only |
|
|
116
|
+
| Humidex | `humidex` | T, RH or dew point | Masterton & Richardson (1979), Environment Canada | MSC vapour-pressure form |
|
|
117
|
+
| Apparent Temperature | `apparent_temperature` | T, RH, wind (10 m), optional net radiation | Steadman (1994), Australian Bureau of Meteorology | Shade and radiation forms |
|
|
118
|
+
| Wet bulb (Stull) | `wet_bulb_stull` | T, RH | Stull (2011) J. Appl. Meteor. Climatol. 50:2267 | RH 5-99 %, T -20 to 50 degC, 1013 hPa; error -1 to +0.65 K (larger in cold, dry air) |
|
|
119
|
+
| Wet bulb (psychrometric) | `wet_bulb_psychrometric` | T, RH, pressure | WMO No. 8 (2018) Annex 4.B psychrometer equation, Newton solver | Ventilated wet bulb, wick over water |
|
|
120
|
+
| WBGT outdoor | `wbgt_liljegren`, `wbgt_liljegren_components`, `globe_temperature_liljegren`, `natural_wet_bulb_liljegren` | T, RH, wind, global solar, zenith, pressure, optional direct fraction | Liljegren et al. (2008) J. Occup. Environ. Hyg. 5:645 | 50.8 mm globe; 2 m wind (other heights scaled with a power law); solar capped at 0.85 x top of atmosphere as in the reference code |
|
|
121
|
+
| WBGT shade / indoor | `wbgt_shade` | T, RH, pressure (wind for `method="liljegren"`) | Simplified `0.7 Tw + 0.3 Ta`, or Liljegren with no sun and `0.7 Tnwb + 0.3 Tg` | No solar load |
|
|
122
|
+
| WBGT from measurements | `wbgt_from_measurements` | Tnwb, Tg, (Ta) | ISO 7243:2017 | Indoor and outdoor formulas |
|
|
123
|
+
| WBGT approximation | `wbgt_bom` | T, RH | Australian Bureau of Meteorology | **Approximation**: assumes moderately high radiation and light wind; can be off by several degrees |
|
|
124
|
+
| UTCI | `utci` | T, Tmrt, wind (10 m), RH | Broede et al. (2012) Int. J. Biometeorol. 56:481, 6th-order polynomial, 210 coefficients from the reference program `UTCI_a002.f90` | Ta -50 to 50 degC, Tmrt-Ta -30 to 70 K, wind 0.5-17 m/s, vapour pressure <= 5 kPa; out-of-range values NaN by default; wind below 0.5 m/s raised to 0.5 |
|
|
125
|
+
| Wind Chill | `wind_chill` | T, wind (10 m) | NWS/MSC (2001), Osczevski & Bluestein (2005) | T <= 10 degC; MSC light-wind formula below 4.8 km/h |
|
|
126
|
+
| Feels like | `feels_like` | T, RH, wind | NWS convention | Wind chill / heat index / air temperature |
|
|
127
|
+
| Mean radiant temperature | `mean_radiant_temperature` | Tg, T, air speed | ISO 7726:1998 Annex B | Forced or natural convection; 150 mm globe, emissivity 0.95 by default |
|
|
128
|
+
| Solar position | `solar_position`, `solar_zenith` | time, lat, lon | NOAA solar calculator (Meeus 1991) | Geometric zenith, no refraction |
|
|
129
|
+
| Humidity helpers | `saturation_vapour_pressure`, `vapour_pressure`, `dew_point`, `relative_humidity_from_dew_point`, `relative_humidity_from_vapour_pressure` | T, RH / Td / e | Magnus (Alduchov & Eskridge 1996), WMO, Buck (1981), BoM, Hardy (1998) ITS-90 | Over liquid water |
|
|
130
|
+
|
|
131
|
+
### Risk categories
|
|
132
|
+
|
|
133
|
+
| Function | Scale |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `heat_index_category` | NWS: caution 80-89 degF, extreme caution 90-102, danger 103-124, extreme danger >= 125 |
|
|
136
|
+
| `humidex_category` | Environment Canada: < 30, 30-39, 40-45, >= 46 |
|
|
137
|
+
| `utci_category` | 10 UTCI stress classes from extreme cold (< -40) to extreme heat stress (> 46) |
|
|
138
|
+
| `work_rest_allocation` | ACGIH TLV (acclimatized) / Action Limit (unacclimatized) WBGT work-rest table as printed in the OSHA Technical Manual Sec. III Ch. 4, for light / moderate / heavy / very heavy work, with a clothing adjustment value |
|
|
139
|
+
| `iso7243_reference_wbgt`, `iso7243_assessment` | ISO 7243:2017 Annex A reference WBGT `56.7 - 11.5 log10(M)` (acclimatized) and `59.9 - 14.1 log10(M)` (unacclimatized) |
|
|
140
|
+
| `ehf_severity` | Nairn & Fawcett (2015): low-intensity, severe (EHF >= EHF85), extreme (EHF >= 3 EHF85) |
|
|
141
|
+
|
|
142
|
+
### Heatwave detection
|
|
143
|
+
|
|
144
|
+
* `percentile_threshold` and `calendar_day_percentile` (centred moving window of
|
|
145
|
+
calendar days, optional baseline years, 29 February merged with 28 February).
|
|
146
|
+
* `heatwave_mask`, `consecutive_runs` and `heatwave_events` find spells of at
|
|
147
|
+
least `min_duration` consecutive days above a scalar or day-varying threshold and
|
|
148
|
+
report start, end, duration, peak and exceedance statistics;
|
|
149
|
+
`events_to_frame` converts them to a DataFrame.
|
|
150
|
+
* `excess_heat_factor`: `EHI_sig = T3 - T95`, `EHI_accl = T3 - T30prev`,
|
|
151
|
+
`EHF = EHI_sig x max(1, EHI_accl)`, attributed to the first day of the three-day
|
|
152
|
+
window; `T95` from a reference period (`t95=` or `reference=`).
|
|
153
|
+
|
|
154
|
+
## Command line
|
|
155
|
+
|
|
156
|
+
```console
|
|
157
|
+
$ heatstress hi 35 --rh 60
|
|
158
|
+
heat_index: 45.1 degC
|
|
159
|
+
category: danger
|
|
160
|
+
|
|
161
|
+
$ heatstress wbgt 33 --rh 55 --wind 1.5 --solar 850 --time 2026-07-15T10:00Z --lat 38.42 --lon 27.14
|
|
162
|
+
$ heatstress utci 30 --tmrt 55 --wind 2 --rh 50
|
|
163
|
+
$ heatstress windchill 0 --wind 15 --wind-units mph --units F
|
|
164
|
+
$ heatstress series weather.csv -o indices.csv --lat 38.42 --lon 27.14
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Every value command accepts `--units C|F|K` and `--json`; wind accepts
|
|
168
|
+
`--wind-units ms|kmh|mph|kn`. `heatstress series` reads a CSV, recognises common
|
|
169
|
+
column names (`time`, `t`/`temperature`, `rh`, `td`, `wind`, `solar`/`ghi`,
|
|
170
|
+
`pressure`, `tmrt`, `tg`, `zenith`, `lat`, `lon`), and appends every index that
|
|
171
|
+
the columns allow (UTCI needs `tmrt` or a globe temperature; the Liljegren WBGT
|
|
172
|
+
needs wind, solar and either a zenith column or time plus coordinates). The same
|
|
173
|
+
logic is available in Python as `hs.compute_indices(df)`.
|
|
174
|
+
|
|
175
|
+
## Validation
|
|
176
|
+
|
|
177
|
+
All comparisons are in the test suite (`tests/test_reference_values.py`) unless noted.
|
|
178
|
+
|
|
179
|
+
| Check | Reference | Result |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| UTCI polynomial | 1000 official test conditions, Broede et al. UTCI-Test-Data (doi:10.5281/zenodo.5503968, CC BY 4.0), column `UTCI_polynomial` | max deviation 0.050 degC (= rounding of the published values) |
|
|
182
|
+
| UTCI vs UTCI-Fiala model | same data set, 921 cases with wind <= 17 m/s | RMS 1.17 K (Broede et al. report about 1.1 K) |
|
|
183
|
+
| UTCI vs independent code | thermofeel 2.3.0 `calculate_utci_polynomial` | max 1e-12 degC (scratch cross-check) |
|
|
184
|
+
| Heat index vs NWS chart | 135 cells of the NWS heat index chart | bare Rothfusz regression within 0.92 degF; full NWS algorithm within 0.92 degF where no adjustment applies and within 2.29 degF in the high-humidity cells where NWS adds its adjustment |
|
|
185
|
+
| Heat index vs independent code | thermofeel `calculate_heat_index_adjusted`, 5000 random cases T <= 43 degC | max 0.08 degC (scratch cross-check) |
|
|
186
|
+
| Liljegren WBGT, globe, natural wet bulb | thermofeel 2.3.0 `thermofeel.liljegren` (KNMI port of the reference C code), 3000 random cases | max 4e-13 degC; 8 frozen vectors in the tests |
|
|
187
|
+
| Wet bulb | Stull (2011) worked example 20 degC / 50 % -> 13.7 degC; psychrometric table 25 degC / 50 % -> 17.9 degC | exact to the published precision; Stull vs psychrometric within +/-1 K for 0-45 degC, RH 20-95 % |
|
|
188
|
+
| Wind chill | NWS wind chill chart (6 cells); thermofeel | within 0.6 degF; identical to thermofeel |
|
|
189
|
+
| Humidex | Environment Canada example 30 degC / Td 15 degC -> 34 | exact; thermofeel max 0.04 |
|
|
190
|
+
| Apparent temperature | thermofeel `calculate_apparent_temperature` | identical (scratch cross-check) |
|
|
191
|
+
| Mean radiant temperature | ISO 7726 formula; thermofeel | max 0.06 degC (thermofeel uses 273.15 K in place of ISO's 273) |
|
|
192
|
+
| Solar position | pvlib 0.16.1 NREL SPA, 4000 random times 1990-2060 and latitudes +/-80 deg | zenith max 0.017 deg, Earth-Sun distance max 7e-5 AU; 6 frozen cases in the tests |
|
|
193
|
+
| Excess Heat Factor | thermofeel `thermofeel.excess_heat` with pandas rolling windows | max 4e-11 |
|
|
194
|
+
|
|
195
|
+
## Units and conventions
|
|
196
|
+
|
|
197
|
+
* Temperatures: degC unless `units="F"` or `"K"` (applies to all temperature
|
|
198
|
+
inputs and outputs of that call).
|
|
199
|
+
* Relative humidity in %, wind speed in m/s (10 m for Apparent Temperature,
|
|
200
|
+
Wind Chill and UTCI; 2 m for Liljegren unless `wind_height` is given), pressure
|
|
201
|
+
in hPa (station pressure), solar radiation in W/m2 (global horizontal).
|
|
202
|
+
* Results come back as Python floats for scalar input, numpy arrays for array
|
|
203
|
+
input, and pandas Series / xarray DataArrays (same index or coordinates) when
|
|
204
|
+
the first array argument is one.
|
|
205
|
+
|
|
206
|
+
## Citation
|
|
207
|
+
|
|
208
|
+
See `CITATION.cff`. Please also cite the original authors of each index you use.
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT (c) 2026 Yusuf Eminoğlu. The UTCI test data shipped in `tests/data` are by
|
|
213
|
+
Broede et al., CC BY 4.0.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# heatstress
|
|
2
|
+
|
|
3
|
+
Vectorised heat-stress indices for public-health, climate-adaptation and
|
|
4
|
+
occupational-safety analysis: NWS Heat Index, Humidex, Apparent Temperature,
|
|
5
|
+
wet-bulb temperature, WBGT (full Liljegren et al. 2008 model, shade/indoor, ISO 7243,
|
|
6
|
+
BoM approximation), UTCI, Wind Chill, mean radiant temperature, solar position,
|
|
7
|
+
risk categories and heatwave detection, including the Excess Heat Factor.
|
|
8
|
+
|
|
9
|
+
* Pure numpy core; every function takes scalars, numpy arrays, pandas Series or
|
|
10
|
+
xarray DataArrays and returns the same kind of object.
|
|
11
|
+
* Units are explicit: degC by default with a `units="C" | "F" | "K"` switch on
|
|
12
|
+
temperature functions, wind in m/s, pressure in hPa, radiation in W/m2, humidity in %.
|
|
13
|
+
Converters are in `heatstress.units`.
|
|
14
|
+
* Inputs outside a formula's validity range raise a `ValidityRangeWarning`; NaN propagates.
|
|
15
|
+
* Validated against published reference values and independent implementations
|
|
16
|
+
(see [Validation](#validation)).
|
|
17
|
+
* A command-line tool for single values and CSV time series.
|
|
18
|
+
|
|
19
|
+
> **Disclaimer.** heatstress computes screening indices from weather data. It is
|
|
20
|
+
> not medical advice and is not a substitute for on-site measurement, an
|
|
21
|
+
> occupational health programme, clinical judgement or the official warnings of
|
|
22
|
+
> your national meteorological or public-health service.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install heatstress # numpy only
|
|
28
|
+
pip install "heatstress[pandas]" # + pandas helpers (DataFrames, events_to_frame)
|
|
29
|
+
pip install "heatstress[xarray]" # + xarray/pandas
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Python 3.9 or newer.
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import heatstress as hs
|
|
38
|
+
|
|
39
|
+
hs.heat_index(35, 60) # 45.1 degC (NWS algorithm)
|
|
40
|
+
hs.heat_index(95, 50, units="F") # 105.2 degF
|
|
41
|
+
hs.heat_index_category(45.1) # 'danger'
|
|
42
|
+
|
|
43
|
+
hs.humidex(30, dew_point=15) # 34.0
|
|
44
|
+
hs.apparent_temperature(30, 50, wind=2) # 31.6 degC
|
|
45
|
+
hs.wet_bulb_psychrometric(25, 50) # 17.9 degC
|
|
46
|
+
hs.utci(30, tmrt=50, wind=2, rh=50) # 34.6 degC
|
|
47
|
+
hs.utci_category(34.6) # 'strong heat stress'
|
|
48
|
+
|
|
49
|
+
# Outdoor WBGT from standard weather data (Liljegren et al. 2008)
|
|
50
|
+
z = hs.solar_zenith("2026-07-15T10:00Z", lat=38.42, lon=27.14)
|
|
51
|
+
w = hs.wbgt_liljegren_components(t=33, rh=55, wind=1.5, solar=850, zenith=z, pressure=1008)
|
|
52
|
+
w.wbgt, w.globe_temperature, w.natural_wet_bulb # 32.7, 49.7, 27.7 degC
|
|
53
|
+
hs.work_rest_allocation(w.wbgt, "moderate") # ACGIH TLV work-rest guidance
|
|
54
|
+
|
|
55
|
+
# Heatwaves on a daily series
|
|
56
|
+
import pandas as pd
|
|
57
|
+
tmax = pd.Series(..., index=pd.date_range("1991-01-01", periods=..., freq="D"))
|
|
58
|
+
thr = hs.calendar_day_percentile(tmax, tmax.index, q=90, window=15, baseline=(1991, 2020))
|
|
59
|
+
events = hs.heatwave_events(tmax, thr, min_duration=3)
|
|
60
|
+
hs.events_to_frame(events)
|
|
61
|
+
|
|
62
|
+
ehf = hs.excess_heat_factor(tmean_daily) # Nairn & Fawcett (2015)
|
|
63
|
+
hs.ehf_severity(ehf) # none / low-intensity / severe / extreme
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Indices
|
|
67
|
+
|
|
68
|
+
| Index | Function | Inputs | Source | Validity / notes |
|
|
69
|
+
|---|---|---|---|---|
|
|
70
|
+
| Heat Index | `heat_index` | T, RH | NWS/WPC algorithm: Steadman (1979) simple formula, Rothfusz (1990) regression and the two NWS adjustments | Regression error +/-1.3 degF; warning above 120 degF air temperature or 150 degF HI |
|
|
71
|
+
| Rothfusz regression only | `rothfusz_regression` | T, RH | Rothfusz (1990) NWS SR 90-23 | For comparison only |
|
|
72
|
+
| Humidex | `humidex` | T, RH or dew point | Masterton & Richardson (1979), Environment Canada | MSC vapour-pressure form |
|
|
73
|
+
| Apparent Temperature | `apparent_temperature` | T, RH, wind (10 m), optional net radiation | Steadman (1994), Australian Bureau of Meteorology | Shade and radiation forms |
|
|
74
|
+
| Wet bulb (Stull) | `wet_bulb_stull` | T, RH | Stull (2011) J. Appl. Meteor. Climatol. 50:2267 | RH 5-99 %, T -20 to 50 degC, 1013 hPa; error -1 to +0.65 K (larger in cold, dry air) |
|
|
75
|
+
| Wet bulb (psychrometric) | `wet_bulb_psychrometric` | T, RH, pressure | WMO No. 8 (2018) Annex 4.B psychrometer equation, Newton solver | Ventilated wet bulb, wick over water |
|
|
76
|
+
| WBGT outdoor | `wbgt_liljegren`, `wbgt_liljegren_components`, `globe_temperature_liljegren`, `natural_wet_bulb_liljegren` | T, RH, wind, global solar, zenith, pressure, optional direct fraction | Liljegren et al. (2008) J. Occup. Environ. Hyg. 5:645 | 50.8 mm globe; 2 m wind (other heights scaled with a power law); solar capped at 0.85 x top of atmosphere as in the reference code |
|
|
77
|
+
| WBGT shade / indoor | `wbgt_shade` | T, RH, pressure (wind for `method="liljegren"`) | Simplified `0.7 Tw + 0.3 Ta`, or Liljegren with no sun and `0.7 Tnwb + 0.3 Tg` | No solar load |
|
|
78
|
+
| WBGT from measurements | `wbgt_from_measurements` | Tnwb, Tg, (Ta) | ISO 7243:2017 | Indoor and outdoor formulas |
|
|
79
|
+
| WBGT approximation | `wbgt_bom` | T, RH | Australian Bureau of Meteorology | **Approximation**: assumes moderately high radiation and light wind; can be off by several degrees |
|
|
80
|
+
| UTCI | `utci` | T, Tmrt, wind (10 m), RH | Broede et al. (2012) Int. J. Biometeorol. 56:481, 6th-order polynomial, 210 coefficients from the reference program `UTCI_a002.f90` | Ta -50 to 50 degC, Tmrt-Ta -30 to 70 K, wind 0.5-17 m/s, vapour pressure <= 5 kPa; out-of-range values NaN by default; wind below 0.5 m/s raised to 0.5 |
|
|
81
|
+
| Wind Chill | `wind_chill` | T, wind (10 m) | NWS/MSC (2001), Osczevski & Bluestein (2005) | T <= 10 degC; MSC light-wind formula below 4.8 km/h |
|
|
82
|
+
| Feels like | `feels_like` | T, RH, wind | NWS convention | Wind chill / heat index / air temperature |
|
|
83
|
+
| Mean radiant temperature | `mean_radiant_temperature` | Tg, T, air speed | ISO 7726:1998 Annex B | Forced or natural convection; 150 mm globe, emissivity 0.95 by default |
|
|
84
|
+
| Solar position | `solar_position`, `solar_zenith` | time, lat, lon | NOAA solar calculator (Meeus 1991) | Geometric zenith, no refraction |
|
|
85
|
+
| Humidity helpers | `saturation_vapour_pressure`, `vapour_pressure`, `dew_point`, `relative_humidity_from_dew_point`, `relative_humidity_from_vapour_pressure` | T, RH / Td / e | Magnus (Alduchov & Eskridge 1996), WMO, Buck (1981), BoM, Hardy (1998) ITS-90 | Over liquid water |
|
|
86
|
+
|
|
87
|
+
### Risk categories
|
|
88
|
+
|
|
89
|
+
| Function | Scale |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `heat_index_category` | NWS: caution 80-89 degF, extreme caution 90-102, danger 103-124, extreme danger >= 125 |
|
|
92
|
+
| `humidex_category` | Environment Canada: < 30, 30-39, 40-45, >= 46 |
|
|
93
|
+
| `utci_category` | 10 UTCI stress classes from extreme cold (< -40) to extreme heat stress (> 46) |
|
|
94
|
+
| `work_rest_allocation` | ACGIH TLV (acclimatized) / Action Limit (unacclimatized) WBGT work-rest table as printed in the OSHA Technical Manual Sec. III Ch. 4, for light / moderate / heavy / very heavy work, with a clothing adjustment value |
|
|
95
|
+
| `iso7243_reference_wbgt`, `iso7243_assessment` | ISO 7243:2017 Annex A reference WBGT `56.7 - 11.5 log10(M)` (acclimatized) and `59.9 - 14.1 log10(M)` (unacclimatized) |
|
|
96
|
+
| `ehf_severity` | Nairn & Fawcett (2015): low-intensity, severe (EHF >= EHF85), extreme (EHF >= 3 EHF85) |
|
|
97
|
+
|
|
98
|
+
### Heatwave detection
|
|
99
|
+
|
|
100
|
+
* `percentile_threshold` and `calendar_day_percentile` (centred moving window of
|
|
101
|
+
calendar days, optional baseline years, 29 February merged with 28 February).
|
|
102
|
+
* `heatwave_mask`, `consecutive_runs` and `heatwave_events` find spells of at
|
|
103
|
+
least `min_duration` consecutive days above a scalar or day-varying threshold and
|
|
104
|
+
report start, end, duration, peak and exceedance statistics;
|
|
105
|
+
`events_to_frame` converts them to a DataFrame.
|
|
106
|
+
* `excess_heat_factor`: `EHI_sig = T3 - T95`, `EHI_accl = T3 - T30prev`,
|
|
107
|
+
`EHF = EHI_sig x max(1, EHI_accl)`, attributed to the first day of the three-day
|
|
108
|
+
window; `T95` from a reference period (`t95=` or `reference=`).
|
|
109
|
+
|
|
110
|
+
## Command line
|
|
111
|
+
|
|
112
|
+
```console
|
|
113
|
+
$ heatstress hi 35 --rh 60
|
|
114
|
+
heat_index: 45.1 degC
|
|
115
|
+
category: danger
|
|
116
|
+
|
|
117
|
+
$ heatstress wbgt 33 --rh 55 --wind 1.5 --solar 850 --time 2026-07-15T10:00Z --lat 38.42 --lon 27.14
|
|
118
|
+
$ heatstress utci 30 --tmrt 55 --wind 2 --rh 50
|
|
119
|
+
$ heatstress windchill 0 --wind 15 --wind-units mph --units F
|
|
120
|
+
$ heatstress series weather.csv -o indices.csv --lat 38.42 --lon 27.14
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Every value command accepts `--units C|F|K` and `--json`; wind accepts
|
|
124
|
+
`--wind-units ms|kmh|mph|kn`. `heatstress series` reads a CSV, recognises common
|
|
125
|
+
column names (`time`, `t`/`temperature`, `rh`, `td`, `wind`, `solar`/`ghi`,
|
|
126
|
+
`pressure`, `tmrt`, `tg`, `zenith`, `lat`, `lon`), and appends every index that
|
|
127
|
+
the columns allow (UTCI needs `tmrt` or a globe temperature; the Liljegren WBGT
|
|
128
|
+
needs wind, solar and either a zenith column or time plus coordinates). The same
|
|
129
|
+
logic is available in Python as `hs.compute_indices(df)`.
|
|
130
|
+
|
|
131
|
+
## Validation
|
|
132
|
+
|
|
133
|
+
All comparisons are in the test suite (`tests/test_reference_values.py`) unless noted.
|
|
134
|
+
|
|
135
|
+
| Check | Reference | Result |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| UTCI polynomial | 1000 official test conditions, Broede et al. UTCI-Test-Data (doi:10.5281/zenodo.5503968, CC BY 4.0), column `UTCI_polynomial` | max deviation 0.050 degC (= rounding of the published values) |
|
|
138
|
+
| UTCI vs UTCI-Fiala model | same data set, 921 cases with wind <= 17 m/s | RMS 1.17 K (Broede et al. report about 1.1 K) |
|
|
139
|
+
| UTCI vs independent code | thermofeel 2.3.0 `calculate_utci_polynomial` | max 1e-12 degC (scratch cross-check) |
|
|
140
|
+
| Heat index vs NWS chart | 135 cells of the NWS heat index chart | bare Rothfusz regression within 0.92 degF; full NWS algorithm within 0.92 degF where no adjustment applies and within 2.29 degF in the high-humidity cells where NWS adds its adjustment |
|
|
141
|
+
| Heat index vs independent code | thermofeel `calculate_heat_index_adjusted`, 5000 random cases T <= 43 degC | max 0.08 degC (scratch cross-check) |
|
|
142
|
+
| Liljegren WBGT, globe, natural wet bulb | thermofeel 2.3.0 `thermofeel.liljegren` (KNMI port of the reference C code), 3000 random cases | max 4e-13 degC; 8 frozen vectors in the tests |
|
|
143
|
+
| Wet bulb | Stull (2011) worked example 20 degC / 50 % -> 13.7 degC; psychrometric table 25 degC / 50 % -> 17.9 degC | exact to the published precision; Stull vs psychrometric within +/-1 K for 0-45 degC, RH 20-95 % |
|
|
144
|
+
| Wind chill | NWS wind chill chart (6 cells); thermofeel | within 0.6 degF; identical to thermofeel |
|
|
145
|
+
| Humidex | Environment Canada example 30 degC / Td 15 degC -> 34 | exact; thermofeel max 0.04 |
|
|
146
|
+
| Apparent temperature | thermofeel `calculate_apparent_temperature` | identical (scratch cross-check) |
|
|
147
|
+
| Mean radiant temperature | ISO 7726 formula; thermofeel | max 0.06 degC (thermofeel uses 273.15 K in place of ISO's 273) |
|
|
148
|
+
| Solar position | pvlib 0.16.1 NREL SPA, 4000 random times 1990-2060 and latitudes +/-80 deg | zenith max 0.017 deg, Earth-Sun distance max 7e-5 AU; 6 frozen cases in the tests |
|
|
149
|
+
| Excess Heat Factor | thermofeel `thermofeel.excess_heat` with pandas rolling windows | max 4e-11 |
|
|
150
|
+
|
|
151
|
+
## Units and conventions
|
|
152
|
+
|
|
153
|
+
* Temperatures: degC unless `units="F"` or `"K"` (applies to all temperature
|
|
154
|
+
inputs and outputs of that call).
|
|
155
|
+
* Relative humidity in %, wind speed in m/s (10 m for Apparent Temperature,
|
|
156
|
+
Wind Chill and UTCI; 2 m for Liljegren unless `wind_height` is given), pressure
|
|
157
|
+
in hPa (station pressure), solar radiation in W/m2 (global horizontal).
|
|
158
|
+
* Results come back as Python floats for scalar input, numpy arrays for array
|
|
159
|
+
input, and pandas Series / xarray DataArrays (same index or coordinates) when
|
|
160
|
+
the first array argument is one.
|
|
161
|
+
|
|
162
|
+
## Citation
|
|
163
|
+
|
|
164
|
+
See `CITATION.cff`. Please also cite the original authors of each index you use.
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT (c) 2026 Yusuf Eminoğlu. The UTCI test data shipped in `tests/data` are by
|
|
169
|
+
Broede et al., CC BY 4.0.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "heatstress"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Yusuf Eminoğlu", email = "yusufeminoglu@gmail.com" }
|
|
10
|
+
]
|
|
11
|
+
description = "Vectorised heat-stress indices: NWS Heat Index, Humidex, Apparent Temperature, wet bulb, WBGT (Liljegren), UTCI, wind chill, risk categories and heatwave detection."
|
|
12
|
+
keywords = [
|
|
13
|
+
"heat-stress",
|
|
14
|
+
"heat-index",
|
|
15
|
+
"wbgt",
|
|
16
|
+
"utci",
|
|
17
|
+
"humidex",
|
|
18
|
+
"apparent-temperature",
|
|
19
|
+
"wet-bulb",
|
|
20
|
+
"wind-chill",
|
|
21
|
+
"heatwave",
|
|
22
|
+
"excess-heat-factor",
|
|
23
|
+
"thermal-comfort",
|
|
24
|
+
"biometeorology",
|
|
25
|
+
"occupational-safety",
|
|
26
|
+
"public-health",
|
|
27
|
+
"climate-adaptation",
|
|
28
|
+
]
|
|
29
|
+
readme = "README.md"
|
|
30
|
+
license = "MIT"
|
|
31
|
+
license-files = ["LICENSE"]
|
|
32
|
+
requires-python = ">=3.9"
|
|
33
|
+
classifiers = [
|
|
34
|
+
"Development Status :: 4 - Beta",
|
|
35
|
+
"Programming Language :: Python :: 3",
|
|
36
|
+
"Programming Language :: Python :: 3.9",
|
|
37
|
+
"Programming Language :: Python :: 3.10",
|
|
38
|
+
"Programming Language :: Python :: 3.11",
|
|
39
|
+
"Programming Language :: Python :: 3.12",
|
|
40
|
+
"Programming Language :: Python :: 3.13",
|
|
41
|
+
"Operating System :: OS Independent",
|
|
42
|
+
"Topic :: Scientific/Engineering :: Atmospheric Science",
|
|
43
|
+
"Topic :: Scientific/Engineering :: Medical Science Apps.",
|
|
44
|
+
"Intended Audience :: Science/Research",
|
|
45
|
+
"Intended Audience :: Developers",
|
|
46
|
+
"Intended Audience :: Healthcare Industry",
|
|
47
|
+
"Typing :: Typed",
|
|
48
|
+
]
|
|
49
|
+
dependencies = [
|
|
50
|
+
"numpy>=1.20.0",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[project.optional-dependencies]
|
|
54
|
+
pandas = [
|
|
55
|
+
"pandas>=1.3.0",
|
|
56
|
+
]
|
|
57
|
+
xarray = [
|
|
58
|
+
"xarray>=0.19.0",
|
|
59
|
+
"pandas>=1.3.0",
|
|
60
|
+
]
|
|
61
|
+
all = [
|
|
62
|
+
"pandas>=1.3.0",
|
|
63
|
+
"xarray>=0.19.0",
|
|
64
|
+
]
|
|
65
|
+
dev = [
|
|
66
|
+
"pytest>=7.0.0",
|
|
67
|
+
"pytest-cov>=4.0.0",
|
|
68
|
+
"ruff>=0.1.0",
|
|
69
|
+
"mypy>=1.0.0",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[project.scripts]
|
|
73
|
+
heatstress = "heatstress.cli:main"
|
|
74
|
+
|
|
75
|
+
[project.urls]
|
|
76
|
+
Homepage = "https://github.com/YusufEminoglu/heatstress_sdk"
|
|
77
|
+
Repository = "https://github.com/YusufEminoglu/heatstress_sdk"
|
|
78
|
+
Issues = "https://github.com/YusufEminoglu/heatstress_sdk/issues"
|
|
79
|
+
Changelog = "https://github.com/YusufEminoglu/heatstress_sdk/blob/main/CHANGELOG.md"
|
|
80
|
+
|
|
81
|
+
[tool.setuptools]
|
|
82
|
+
package-dir = {"" = "src"}
|
|
83
|
+
|
|
84
|
+
[tool.setuptools.packages.find]
|
|
85
|
+
where = ["src"]
|
|
86
|
+
|
|
87
|
+
[tool.setuptools.package-data]
|
|
88
|
+
heatstress = ["py.typed"]
|
|
89
|
+
|
|
90
|
+
[tool.ruff]
|
|
91
|
+
line-length = 100
|
|
92
|
+
target-version = "py39"
|
|
93
|
+
exclude = [
|
|
94
|
+
"scratch",
|
|
95
|
+
".venv",
|
|
96
|
+
"build",
|
|
97
|
+
"dist",
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[tool.ruff.lint]
|
|
101
|
+
select = ["E", "F", "W", "I", "B", "C4"]
|
|
102
|
+
ignore = ["E501"]
|
|
103
|
+
|
|
104
|
+
[tool.mypy]
|
|
105
|
+
files = ["src"]
|
|
106
|
+
warn_unused_ignores = true
|
|
107
|
+
|
|
108
|
+
[[tool.mypy.overrides]]
|
|
109
|
+
module = [
|
|
110
|
+
"pandas.*",
|
|
111
|
+
"xarray.*",
|
|
112
|
+
]
|
|
113
|
+
ignore_missing_imports = true
|
|
114
|
+
|
|
115
|
+
[tool.pytest.ini_options]
|
|
116
|
+
testpaths = ["tests"]
|
|
117
|
+
# Lets `pytest` run straight from a clone, without an editable install first.
|
|
118
|
+
pythonpath = ["src"]
|
|
119
|
+
filterwarnings = [
|
|
120
|
+
"ignore::DeprecationWarning",
|
|
121
|
+
"ignore::PendingDeprecationWarning",
|
|
122
|
+
"ignore::FutureWarning",
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[tool.coverage.run]
|
|
126
|
+
source = ["heatstress"]
|
|
127
|
+
branch = true
|
|
128
|
+
|
|
129
|
+
[tool.coverage.report]
|
|
130
|
+
show_missing = true
|
|
131
|
+
fail_under = 85
|
|
132
|
+
exclude_lines = [
|
|
133
|
+
"pragma: no cover",
|
|
134
|
+
"if __name__ == .__main__.:",
|
|
135
|
+
]
|