Metadata-Version: 2.4
Name: varunayan
Version: 0.3.0
Summary: Analysis-ready climate data downloader and processor for custom regions
Project-URL: Homepage, https://github.com/saketlab/varunayan
Project-URL: Documentation, https://saketlab.github.io/varunayan
Project-URL: Repository, https://github.com/saketlab/varunayan
Project-URL: Issues, https://github.com/saketlab/varunayan/issues
Author-email: Atharva Jagtap <atharvajagtap1108@gmail.com>, Saket Choudhary <saketc@iitb.ac.in>
Maintainer-email: Atharva Jagtap <atharvajagtap1108@gmail.com>, Saket Choudhary <saketc@iitb.ac.in>
License-Expression: MIT
License-File: LICENSE
Keywords: atmospheric-science,climate,era5,geospatial,netcdf,weather
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.10
Requires-Dist: cdsapi>=0.5.1
Requires-Dist: geopandas>=0.10.0
Requires-Dist: matplotlib>=3.3.0
Requires-Dist: netcdf4>=1.5.0
Requires-Dist: numpy>=1.20.0
Requires-Dist: pandas>=1.3.0
Requires-Dist: python-dateutil>=2.8.0
Requires-Dist: shapely>=1.8.0
Requires-Dist: tqdm>=4.60.0
Requires-Dist: xarray>=0.20.0
Provides-Extra: all
Requires-Dist: bandit>=1.7.0; extra == 'all'
Requires-Dist: black>=22.0; extra == 'all'
Requires-Dist: build>=0.7.0; extra == 'all'
Requires-Dist: check-manifest>=0.48; extra == 'all'
Requires-Dist: coverage[toml]>=6.0; extra == 'all'
Requires-Dist: docutils>=0.17; extra == 'all'
Requires-Dist: flake8>=4.0; extra == 'all'
Requires-Dist: furo>=2023.3.27; extra == 'all'
Requires-Dist: ipykernel>=6.0; extra == 'all'
Requires-Dist: ipython>=7.0; extra == 'all'
Requires-Dist: isort>=5.10; extra == 'all'
Requires-Dist: jupyter-client>=7.0; extra == 'all'
Requires-Dist: jupyter>=1.0; extra == 'all'
Requires-Dist: linkify-it-py>=2.0; extra == 'all'
Requires-Dist: livereload>=2.6.3; extra == 'all'
Requires-Dist: markdown-it-py>=2.0; extra == 'all'
Requires-Dist: mdit-py-plugins>=0.3.0; extra == 'all'
Requires-Dist: mypy>=0.910; extra == 'all'
Requires-Dist: myst-nb>=0.13.0; extra == 'all'
Requires-Dist: myst-parser>=0.15; extra == 'all'
Requires-Dist: nbclient>=0.8; extra == 'all'
Requires-Dist: nbconvert>=6.0; extra == 'all'
Requires-Dist: nbconvert>=7.0; extra == 'all'
Requires-Dist: pandas-stubs; extra == 'all'
Requires-Dist: pre-commit>=2.15; extra == 'all'
Requires-Dist: pylint>=2.12.0; extra == 'all'
Requires-Dist: pytest-cov>=2.10; extra == 'all'
Requires-Dist: pytest-mock>=3.6.1; extra == 'all'
Requires-Dist: pytest-timeout>=2.1.0; extra == 'all'
Requires-Dist: pytest-xdist>=2.5.0; extra == 'all'
Requires-Dist: pytest>=6.0; extra == 'all'
Requires-Dist: safety>=2.0.0; extra == 'all'
Requires-Dist: setuptools>=60.0.0; extra == 'all'
Requires-Dist: sphinx-autoapi>=2.0; extra == 'all'
Requires-Dist: sphinx-autobuild>=2021.3.14; extra == 'all'
Requires-Dist: sphinx-copybutton>=0.5.0; extra == 'all'
Requires-Dist: sphinx-design>=0.3.0; extra == 'all'
Requires-Dist: sphinx-multiversion>=0.2.4; extra == 'all'
Requires-Dist: sphinx-sitemap>=2.5.0; extra == 'all'
Requires-Dist: sphinx-tabs>=3.0.0; extra == 'all'
Requires-Dist: sphinx-togglebutton>=0.3.0; extra == 'all'
Requires-Dist: sphinx>=4.0; extra == 'all'
Requires-Dist: sphinxext-opengraph>=0.9.0; extra == 'all'
Requires-Dist: tox>=3.24.0; extra == 'all'
Requires-Dist: twine>=4.0.0; extra == 'all'
Requires-Dist: types-requests; extra == 'all'
Requires-Dist: watchdog>=2.1.0; extra == 'all'
Requires-Dist: wheel>=0.37.0; extra == 'all'
Provides-Extra: build
Requires-Dist: build>=0.7.0; extra == 'build'
Requires-Dist: check-manifest>=0.48; extra == 'build'
Requires-Dist: setuptools>=60.0.0; extra == 'build'
Requires-Dist: twine>=4.0.0; extra == 'build'
Requires-Dist: wheel>=0.37.0; extra == 'build'
Provides-Extra: dev
Requires-Dist: black>=22.0; extra == 'dev'
Requires-Dist: flake8>=4.0; extra == 'dev'
Requires-Dist: isort>=5.10; extra == 'dev'
Requires-Dist: mypy>=0.910; extra == 'dev'
Requires-Dist: pandas-stubs; extra == 'dev'
Requires-Dist: pre-commit>=2.15; extra == 'dev'
Requires-Dist: pytest-cov>=2.10; extra == 'dev'
Requires-Dist: pytest>=6.0; extra == 'dev'
Requires-Dist: types-requests; extra == 'dev'
Provides-Extra: docs
Requires-Dist: docutils>=0.17; extra == 'docs'
Requires-Dist: furo>=2023.3.27; extra == 'docs'
Requires-Dist: ipython>=7.0; extra == 'docs'
Requires-Dist: jupyter>=1.0; extra == 'docs'
Requires-Dist: linkify-it-py>=2.0; extra == 'docs'
Requires-Dist: markdown-it-py>=2.0; extra == 'docs'
Requires-Dist: mdit-py-plugins>=0.3.0; extra == 'docs'
Requires-Dist: myst-nb>=0.13.0; extra == 'docs'
Requires-Dist: myst-parser>=0.15; extra == 'docs'
Requires-Dist: nbconvert>=6.0; extra == 'docs'
Requires-Dist: sphinx-autoapi>=2.0; extra == 'docs'
Requires-Dist: sphinx-copybutton>=0.5.0; extra == 'docs'
Requires-Dist: sphinx-design>=0.3.0; extra == 'docs'
Requires-Dist: sphinx-multiversion>=0.2.4; extra == 'docs'
Requires-Dist: sphinx-sitemap>=2.5.0; extra == 'docs'
Requires-Dist: sphinx-tabs>=3.0.0; extra == 'docs'
Requires-Dist: sphinx-togglebutton>=0.3.0; extra == 'docs'
Requires-Dist: sphinx>=4.0; extra == 'docs'
Requires-Dist: sphinxext-opengraph>=0.9.0; extra == 'docs'
Provides-Extra: docs-build
Requires-Dist: docutils>=0.17; extra == 'docs-build'
Requires-Dist: furo>=2023.3.27; extra == 'docs-build'
Requires-Dist: jupyter>=1.0; extra == 'docs-build'
Requires-Dist: linkify-it-py>=2.0; extra == 'docs-build'
Requires-Dist: markdown-it-py>=2.0; extra == 'docs-build'
Requires-Dist: mdit-py-plugins>=0.3.0; extra == 'docs-build'
Requires-Dist: myst-nb>=0.13.0; extra == 'docs-build'
Requires-Dist: myst-parser>=0.15; extra == 'docs-build'
Requires-Dist: nbconvert>=6.0; extra == 'docs-build'
Requires-Dist: sphinx-autoapi>=2.0; extra == 'docs-build'
Requires-Dist: sphinx-book-theme>=1.0.0; extra == 'docs-build'
Requires-Dist: sphinx-copybutton>=0.5.0; extra == 'docs-build'
Requires-Dist: sphinx-design>=0.3.0; extra == 'docs-build'
Requires-Dist: sphinx-multiversion>=0.2.4; extra == 'docs-build'
Requires-Dist: sphinx-sitemap>=2.5.0; extra == 'docs-build'
Requires-Dist: sphinx-tabs>=3.0.0; extra == 'docs-build'
Requires-Dist: sphinx-togglebutton>=0.3.0; extra == 'docs-build'
Requires-Dist: sphinx>=4.0; extra == 'docs-build'
Requires-Dist: sphinxext-opengraph>=0.9.0; extra == 'docs-build'
Provides-Extra: docs-serve
Requires-Dist: livereload>=2.6.3; extra == 'docs-serve'
Requires-Dist: sphinx-autobuild>=2021.3.14; extra == 'docs-serve'
Requires-Dist: watchdog>=2.1.0; extra == 'docs-serve'
Provides-Extra: notebooks
Requires-Dist: ipykernel>=6.0; extra == 'notebooks'
Requires-Dist: jupyter-client>=7.0; extra == 'notebooks'
Requires-Dist: nbclient>=0.8; extra == 'notebooks'
Requires-Dist: nbconvert>=7.0; extra == 'notebooks'
Provides-Extra: quality
Requires-Dist: bandit>=1.7.0; extra == 'quality'
Requires-Dist: black>=22.0; extra == 'quality'
Requires-Dist: flake8>=4.0; extra == 'quality'
Requires-Dist: isort>=5.10; extra == 'quality'
Requires-Dist: mypy>=0.910; extra == 'quality'
Requires-Dist: pandas-stubs; extra == 'quality'
Requires-Dist: pre-commit>=2.15; extra == 'quality'
Requires-Dist: pylint>=2.12.0; extra == 'quality'
Requires-Dist: safety>=2.0.0; extra == 'quality'
Requires-Dist: types-requests; extra == 'quality'
Provides-Extra: test
Requires-Dist: coverage[toml]>=6.0; extra == 'test'
Requires-Dist: pytest-cov>=2.10; extra == 'test'
Requires-Dist: pytest-mock>=3.6.1; extra == 'test'
Requires-Dist: pytest-timeout>=2.1.0; extra == 'test'
Requires-Dist: pytest-xdist>=2.5.0; extra == 'test'
Requires-Dist: pytest>=6.0; extra == 'test'
Requires-Dist: tox>=3.24.0; extra == 'test'
Description-Content-Type: text/markdown

# Varunayan

<p align="center">
  <img src="https://raw.githubusercontent.com/saketlab/varunayan/main/docs/_static/varunayan_logo.png" alt="Varunayan Logo" width="200"/>
</p>

Python package for downloading and processing climate data from ERA5, IMD, HadEX3, and CRU TS. Includes heat stress index calculations (UTCI, WBGT, Heat Index, Humidex) and country-level temperature aggregation.

Also available in R: [varunayanR](https://github.com/saketlab/varunayanR)

## Data sources

| Source | Variables | Resolution | Coverage |
|--------|-----------|------------|----------|
| [ERA5](https://cds.climate.copernicus.eu/) | 100+ (temperature, precipitation, wind, radiation, etc.) | 0.25 deg, hourly to monthly | 1940-present, global |
| [IMD](https://www.imdpune.gov.in/) | Rainfall, Tmax, Tmin | 0.25/1.0 deg, daily | 1901-present, India |
| [HadEX3](https://www.metoffice.gov.uk/hadobs/hadex3/) | 29 ETCCDI climate extremes | 1.25x1.875 deg, annual/monthly | 1901-2018, global |
| [CRU TS v4.07](https://crudata.uea.ac.uk/cru/data/hrg/) | tmp, tmx, tmn, pre, vap, cld, wet, frs, dtr, pet | 0.5 deg, monthly | 1901-2022, land |

## Installation

```bash
pip install varunayan
```

For development:

```bash
pip install -e .
```

## Quick start

### ERA5 (requires CDS account)

```python
import varunayan

# Bounding box query
df = varunayan.era5ify_bbox(
    request_id="mumbai",
    variables=["2m_temperature", "total_precipitation"],
    start_date="2024-01-01", end_date="2024-01-31",
    north=19.2, south=18.9, east=72.9, west=72.8,
    frequency="daily"
)

# Single point
df = varunayan.era5ify_point(
    "shimla", ["2t"], "2024-01-01", "2024-01-07",
    latitude=31.1, longitude=77.2
)
```

### IMD gridded data (no credentials needed)

```python
# Rainfall for a bounding box
rain = varunayan.imd_rainfall_bbox(
    "maharashtra", start_year=2020, end_year=2023,
    north=22, south=16, east=80, west=73,
    resolution=0.25, frequency="monthly"
)

# Temperature with GeoJSON filter
tmax = varunayan.imd_temperature_geojson(
    "karnataka", start_year=2022, end_year=2023,
    geojson_file="karnataka.geojson", var_type="tmax"
)

# IMD station lookup
stations = varunayan.get_imd_stations()
```

### HadEX3 climate extremes

```python
# Hottest-day trend over India
txx = varunayan.hadex3_bbox(
    "TXx", start_year=1951, end_year=2018,
    north=38, south=6, east=98, west=68
)

# All 29 ETCCDI indices
varunayan.list_hadex3_indices()
```

### CRU TS monthly climate grids

```python
# Mean temperature for a bounding box
tmp = varunayan.cru_ts_bbox(
    "tmp", start_year=2000, end_year=2020,
    north=38, south=6, east=98, west=68
)

# All 10 variables with ERA5/HadEX3 equivalents
varunayan.list_cru_ts_variables()
```

### Country-level temperature

```python
# Cosine-latitude weighted national average
df = varunayan.get_era5_country_temperature(
    "India", "2000-01-01", "2023-12-31",
    variables=["mean", "max", "min"]
)
```

### Heat stress indices

```python
# Individual indices
utci = varunayan.utci(temp_c=35, rh=60, wind_ms=2, mrt_c=50)
hi = varunayan.heat_index(temp_c=35, rh=60)
wbgt = varunayan.wbgt_simple(temp_c=35, dewpoint_c=25)

# All indices at once
indices = varunayan.calc_heat_indices(temp_c=35, dewpoint_c=25, wind_ms=2)

# UTCI sparse Legendre polynomial (Roman et al. 2025, wider wind range)
utci_s = varunayan.utci_sparse(temp_c=35, tmrt=50, wind_speed=2, rh=60)

# Risk categories
varunayan.heat_index_risk_category(hi)
varunayan.utci_category(utci)
```

## CLI

```bash
varunayan bbox --request-id "test" --variables "temperature,relative_humidity" \
  --start "2024-01-01" --end "2024-01-15" \
  --north 30 --south 20 --east 80 --west 70 \
  --dataset-type pressure --pressure-levels "1000,900" \
  --freq daily --res 0.25
```

Also supports `varunayan geojson` and `varunayan point` subcommands.

## Documentation

[varunayan.saketlab.org](https://varunayan.saketlab.org)

## Contributing

Contributions welcome via pull request.

## License

MIT License. See [LICENSE](LICENSE).
