A comprehensive Python client for the California Irrigation Management Information System (CIMIS) API
Project description
Python CIMIS Client
A comprehensive Python client library for the California Irrigation Management Information System (CIMIS) API. This library provides easy access to CIMIS weather station data, spatial data, and station information with built-in CSV export functionality.
๐ Documentation
๐ Complete Documentation - Detailed guides, API reference, and examples
๐ Table of Contents
- ๐ Quick Start
- โจ Features
- ๐ฆ Installation
- ๐ API Key Setup
- ๐ Usage Examples
- ๐ Available Data Items
- ๐ ๏ธ Advanced Usage
- ๐ง Configuration
- ๐ API Reference
- ๐ค Contributing
๐ Quick Start
from python_cimis import CimisClient
from datetime import date
# Initialize the client with your API key
client = CimisClient(app_key="your-api-key-here")
# Get daily weather data for specific stations
weather_data = client.get_daily_data(
targets=[2, 8, 127], # Station numbers
start_date="2023-01-01",
end_date="2023-01-05"
)
# Export to CSV with all available columns
client.export_to_csv(weather_data, "weather_data.csv")
# Or get data and export in one step
weather_data = client.get_data_and_export_csv(
targets=[2, 8, 127],
start_date=date(2023, 1, 1),
end_date=date(2023, 1, 5),
filename="comprehensive_weather_data.csv"
)
โจ Features
- ๐ Comprehensive API Coverage: Access all CIMIS API endpoints including weather data, station information, and zip code data
- ๐ก Multiple Data Sources: Support for both Weather Station Network (WSN) and Spatial CIMIS System (SCS) data
- ๐ฏ Flexible Data Retrieval: Get data by station numbers, zip codes, coordinates, or street addresses
- ๐ Built-in CSV Export: Export all data with comprehensive column coverage by default
- ๐ Easy to Use: Simple, Pythonic interface with sensible defaults
- โ ๏ธ Error Handling: Comprehensive exception handling with descriptive error messages
- ๐ Type Hints: Full type hint support for better IDE integration
- โก Performance: Efficient data processing and export functionality
๐ฆ Installation
From PyPI (Recommended)
pip install python-CIMIS
From Source
git clone https://github.com/python-cimis/python-cimis-client.git
cd python-cimis-client
pip install -e .
๐ API Key Setup
You need a CIMIS API key to use this library.
Get Your API Key
- Visit the CIMIS website
- Register for a free account
- Generate your API key from your account dashboard
Set Up Your API Key
# Option 1: Pass directly to client (not recommended for production)
client = CimisClient(app_key="your-api-key-here")
# Option 2: Use environment variable (recommended)
import os
os.environ['CIMIS_API_KEY'] = 'your-api-key-here'
client = CimisClient(app_key=os.getenv('CIMIS_API_KEY'))
# Option 3: Load from config file
import json
with open('config.json') as f:
config = json.load(f)
client = CimisClient(app_key=config['cimis_api_key'])
๐ Usage Examples
Daily Weather Data
๐ญ By Station Numbers
from python_cimis import CimisClient
from datetime import date, timedelta
client = CimisClient(app_key="your-api-key-here")
# Get data for specific weather stations
weather_data = client.get_daily_data(
targets=[2, 8, 127], # Station numbers: Davis, UC Davis, Five Points
start_date="2023-01-01",
end_date="2023-01-31"
# unit_of_measure defaults to "Metric"
)
print(f"Retrieved {len(weather_data.get_all_records())} records")
๐ฎ By Zip Codes
# Get data for specific zip codes
weather_data = client.get_daily_data(
targets=["95823", "94503", "93624"],
start_date="2023-01-01",
end_date="2023-01-31",
prioritize_scs=True # Prioritize Spatial CIMIS System data
)
# Export to CSV
client.export_to_csv(weather_data, "zip_code_weather.csv")
๐บ๏ธ By Coordinates
# Get data for specific coordinates (latitude, longitude)
weather_data = client.get_data(
targets=[
"lat=39.36,lng=-121.74", # Near Yuba City
"lat=38.22,lng=-122.82" # Near Santa Rosa
],
start_date="2023-01-01",
end_date="2023-01-31",
data_items=["day-asce-eto", "day-sol-rad-avg"] # Only ETo and solar radiation
)
๐ By Addresses
# Get data for specific addresses
weather_data = client.get_data(
targets=[
"addr-name=State Capitol,addr=1315 10th Street Sacramento, CA 95814",
"addr-name=SF City Hall,addr=1 Dr Carlton B Goodlett Pl, San Francisco, CA 94102"
],
start_date="2023-01-01",
end_date="2023-01-31",
data_items=["day-asce-eto", "day-sol-rad-avg"]
)
Hourly Weather Data
# Get hourly data (only available from WSN stations)
# Note: Hourly data requests should be for shorter periods due to data volume
from datetime import datetime, timedelta
yesterday = datetime.now() - timedelta(days=1)
start_date = yesterday.strftime('%Y-%m-%d')
end_date = start_date # Same day for hourly data
hourly_data = client.get_hourly_data(
targets=[2, 8, 127],
start_date=start_date,
end_date=end_date
)
# Export hourly data (automatically uses clean column names)
client.export_to_csv(hourly_data, "hourly_weather.csv")
Station Information
# Get all available stations
all_stations = client.get_stations()
print(f"Total stations: {len(all_stations)}")
# Get specific station information
station = client.get_stations(station_number="2")
print(f"Station: {station[0].name} in {station[0].city}")
# Export station information to CSV
client.export_stations_to_csv(all_stations, "all_stations.csv")
# Get zip code information
station_zips = client.get_station_zip_codes()
spatial_zips = client.get_spatial_zip_codes()
CSV Export
# Basic export with all columns (default)
client.export_to_csv(weather_data, "complete_data.csv")
# Export with automatic filename generation
filename = client.export_to_csv(weather_data)
print(f"Data exported to: {filename}")
# Export daily and hourly data separately (recommended)
mixed_data = client.get_data(
targets=[2, 8],
start_date="2023-01-01",
end_date="2023-01-02"
)
result = client.export_to_csv(mixed_data, "weather_data.csv")
# Creates: weather_data_daily.csv and weather_data_hourly.csv
# One-step data retrieval and export
client.get_data_and_export_csv(
targets=[2, 8, 127],
start_date="2023-01-01",
end_date="2023-01-05",
filename="january_weather.csv"
)
Error Handling
from python_cimis import (
CimisClient,
CimisAPIError,
CimisAuthenticationError,
CimisDataError,
CimisConnectionError
)
client = CimisClient("your-api-key")
try:
weather_data = client.get_daily_data(
targets=[999999], # Invalid station
start_date="2023-01-01",
end_date="2023-01-01"
)
except CimisAuthenticationError:
print("โ Invalid API key or authentication failed")
except CimisConnectionError:
print("โ Network connection error")
except CimisDataError as e:
print(f"โ Data error: {e}")
except CimisAPIError as e:
print(f"โ API Error: {e}")
except Exception as e:
print(f"โ Unexpected error: {e}")
Custom Data Items
# Specify custom data items for specific needs
temperature_only = [
"day-air-tmp-avg",
"day-air-tmp-max",
"day-air-tmp-min"
]
eto_and_weather = [
"day-asce-eto",
"day-precip",
"day-sol-rad-avg",
"day-wind-spd-avg",
"day-rel-hum-avg"
]
# Get only temperature data
temp_data = client.get_daily_data(
targets=[2, 8, 127],
start_date="2023-01-01",
end_date="2023-01-31",
data_items=temperature_only
)
# Get ETo calculation inputs
eto_data = client.get_daily_data(
targets=[2, 8, 127],
start_date="2023-01-01",
end_date="2023-01-31",
data_items=eto_and_weather
)
๐ Available Data Items
๐ Daily Data Items (WSN + SCS)
| Category | Data Items | Description |
|---|---|---|
| ๐ก๏ธ Temperature | day-air-tmp-avg, day-air-tmp-max, day-air-tmp-min |
Average, maximum, and minimum air temperature |
| ๐ง Humidity | day-rel-hum-avg, day-rel-hum-max, day-rel-hum-min |
Relative humidity measurements |
| ๐ฟ Evapotranspiration | day-eto, day-asce-eto, day-asce-etr |
Reference evapotranspiration calculations |
| โ๏ธ Solar Radiation | day-sol-rad-avg, day-sol-rad-net |
Solar radiation measurements |
| ๐จ Wind | day-wind-spd-avg, day-wind-run |
Wind speed and directional components |
| ๐ Soil | day-soil-tmp-avg, day-soil-tmp-max, day-soil-tmp-min |
Soil temperature at various depths |
| ๐ง๏ธ Other | day-precip, day-dew-pnt, day-vap-pres-avg |
Precipitation, dew point, vapor pressure |
โฐ Hourly Data Items (WSN only)
| Category | Data Items | Description |
|---|---|---|
| ๐ก๏ธ Temperature | hly-air-tmp, hly-soil-tmp |
Hourly air and soil temperature |
| ๐ง Humidity | hly-rel-hum |
Hourly relative humidity |
| ๐ฟ Evapotranspiration | hly-eto, hly-asce-eto, hly-asce-etr |
Hourly ET calculations |
| โ๏ธ Solar | hly-sol-rad, hly-net-rad |
Hourly solar radiation |
| ๐จ Wind | hly-wind-spd, hly-wind-dir, hly-res-wind |
Hourly wind measurements |
| ๐ง๏ธ Other | hly-precip, hly-dew-pnt, hly-vap-pres |
Hourly precipitation and atmospheric data |
๐ Note: When exporting hourly data to CSV, column names automatically have the "Hly" prefix removed for cleaner formatting (e.g.,
HlyAirTmpbecomesAirTmp_Value).
๐ ๏ธ Advanced Usage
Batch Processing Multiple Locations
from concurrent.futures import ThreadPoolExecutor
import pandas as pd
def get_station_data(station_id):
"""Get data for a single station"""
try:
data = client.get_daily_data(
targets=[station_id],
start_date="2023-01-01",
end_date="2023-01-31"
)
return station_id, data
except Exception as e:
print(f"Error for station {station_id}: {e}")
return station_id, None
# Process multiple stations in parallel
stations = [2, 8, 127, 54, 6]
results = {}
with ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(get_station_data, station) for station in stations]
for future in futures:
station_id, data = future.result()
if data:
results[station_id] = data
Data Analysis Integration
import pandas as pd
import matplotlib.pyplot as plt
# Get weather data
weather_data = client.get_daily_data(
targets=[2], # Davis station
start_date="2023-01-01",
end_date="2023-12-31",
data_items=["day-air-tmp-avg", "day-asce-eto", "day-precip"]
)
# Export to CSV
csv_file = client.export_to_csv(weather_data, "davis_2023.csv")
# Load into pandas for analysis
df = pd.read_csv(csv_file)
df['Date'] = pd.to_datetime(df['Date'])
# Basic analysis
print(f"Average temperature: {df['DayAirTmpAvg_Value'].mean():.1f}ยฐC")
print(f"Total precipitation: {df['DayPrecip_Value'].sum():.1f}mm")
print(f"Total ETo: {df['DayAsceEto_Value'].sum():.1f}mm")
# Simple visualization
plt.figure(figsize=(12, 6))
plt.plot(df['Date'], df['DayAirTmpAvg_Value'])
plt.title('Daily Average Temperature - Davis Station 2023')
plt.ylabel('Temperature (ยฐC)')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
Custom Data Validation
def validate_weather_data(weather_data):
"""Validate weather data quality"""
records = weather_data.get_all_records()
issues = []
for record in records:
# Check for missing critical data
if 'DayAsceEto' in record.data_values:
eto_value = record.data_values['DayAsceEto'].value
qc_flag = record.data_values['DayAsceEto'].qc
if not eto_value or eto_value == '':
issues.append(f"Missing ETo data for {record.date}")
elif qc_flag and qc_flag.strip() not in [' ', '']:
issues.append(f"Quality issue for ETo on {record.date}: {qc_flag}")
return issues
# Use validation
weather_data = client.get_daily_data(targets=[2], start_date="2023-01-01", end_date="2023-01-31")
issues = validate_weather_data(weather_data)
if issues:
print("Data quality issues found:")
for issue in issues[:5]: # Show first 5 issues
print(f" - {issue}")
๐ง Configuration
Environment Variables
# Set your API key as an environment variable (recommended)
export CIMIS_API_KEY="your-api-key-here"
# Optional: Set default timeout
export CIMIS_TIMEOUT="30"
Client Configuration
# Configure client with custom settings
client = CimisClient(
app_key="your-api-key",
timeout=60, # Custom timeout in seconds
base_url="https://et.water.ca.gov/api" # Custom base URL if needed
)
# Check client configuration
print(f"API Key configured: {'Yes' if client.app_key else 'No'}")
print(f"Timeout: {client.timeout} seconds")
๐ API Reference
CimisClient Class
from python_cimis import CimisClient
client = CimisClient(
app_key: str, # Your CIMIS API key (required)
timeout: int = 30, # Request timeout in seconds
base_url: str = None # Custom API base URL (optional)
)
Main Methods
| Method | Description | Returns |
|---|---|---|
get_daily_data() |
Get daily weather data | WeatherData object |
get_hourly_data() |
Get hourly weather data | WeatherData object |
get_data() |
Get weather data (flexible) | WeatherData object |
get_stations() |
Get station information | List[Station] |
get_station_zip_codes() |
Get WSN zip codes | List[ZipCode] |
get_spatial_zip_codes() |
Get SCS zip codes | List[SpatialZipCode] |
export_to_csv() |
Export data to CSV | str (filename) |
export_stations_to_csv() |
Export stations to CSV | str (filename) |
get_data_and_export_csv() |
Get data and export in one step | Tuple[WeatherData, str] |
Method Parameters
get_daily_data() / get_hourly_data()
client.get_daily_data(
targets: Union[str, List[str]], # Station numbers, zip codes, coordinates
start_date: Union[str, date, datetime], # Start date (YYYY-MM-DD)
end_date: Union[str, date, datetime], # End date (YYYY-MM-DD)
data_items: Optional[List[str]] = None, # Specific data items (optional)
unit_of_measure: str = 'Metric', # 'Metric' or 'English'
csv: bool = False, # Export to CSV immediately
filename: Optional[str] = None # CSV filename (if csv=True)
)
๐งฉ Data Models
WeatherData
Container for weather data responses with methods:
get_all_records(): Get all weather recordsget_daily_records(): Get only daily recordsget_hourly_records(): Get only hourly records
WeatherRecord
Individual weather data record with attributes:
date: Record date (YYYY-MM-DD)station: Station identifierdata_values: Dictionary of data measurementsscope: 'daily' or 'hourly'
Station
Weather station information with attributes:
station_nbr: Station numbername: Station namecity: City locationlatitude,longitude: Coordinateselevation: Station elevation
๐ก Best Practices
1. API Key Security
# โ
Good: Use environment variables
import os
client = CimisClient(app_key=os.getenv('CIMIS_API_KEY'))
# โ Avoid: Hardcoding API keys
client = CimisClient(app_key="your-key-here") # Don't do this!
2. Date Range Management
# โ
Good: Reasonable date ranges
from datetime import date, timedelta
# For daily data: up to 1 year
start_date = date.today() - timedelta(days=365)
end_date = date.today() - timedelta(days=1)
# For hourly data: keep it short (1-7 days)
start_date = date.today() - timedelta(days=1)
end_date = date.today() - timedelta(days=1)
3. Error Handling
# โ
Good: Comprehensive error handling
from python_cimis import CimisClient, CimisAPIError
try:
weather_data = client.get_daily_data(targets=[2], start_date="2023-01-01", end_date="2023-01-31")
except CimisAPIError as e:
print(f"API Error: {e}")
# Handle error appropriately
4. Performance Optimization
# โ
Good: Request specific data items when possible
data_items = ["day-asce-eto", "day-precip", "day-air-tmp-avg"]
weather_data = client.get_daily_data(
targets=[2, 8, 127],
start_date="2023-01-01",
end_date="2023-01-31",
data_items=data_items # Reduces response size
)
Requirements
- Python: 3.8+
- Dependencies:
- requests >= 2.25.0
๐ค Contributing
Contributions are welcome! Here's how you can help:
Development Setup
# Clone the repository
git clone https://github.com/python-cimis/python-cimis-client.git
cd python-cimis-client
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linting
black python_cimis/
flake8 python_cimis/
mypy python_cimis/
Contributing Guidelines
- ๐ด Fork the repository
- ๐ Create a feature branch (
git checkout -b feature/amazing-feature) - โจ Make your changes
- โ Add tests for new functionality
- ๐งช Run the test suite (
pytest) - ๐ Update documentation if needed
- ๐พ Commit your changes (
git commit -m 'Add amazing feature') - ๐ค Push to the branch (
git push origin feature/amazing-feature) - ๐ Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ฅ Contributors
Authors:
- Mahipal Reddy Ramireddy
- M. A. Andrade
Maintainer:
- Precision Irrigation Management Lab (PRIMA)
We welcome contributions from the community! See CONTRIBUTING.md for guidelines.
โ ๏ธ Disclaimer
This library is not affiliated with the California Department of Water Resources or the CIMIS program. It is an independent client library for accessing the public CIMIS API.
๐ Useful Links
- ๏ฟฝ Python CIMIS Documentation - Complete library documentation
- ๏ฟฝ๐ CIMIS Website - Official CIMIS portal
- ๐ CIMIS API Documentation - Official API docs
- ๐๏ธ California Department of Water Resources - DWR website
- ๐ Report Issues - Bug reports and feature requests
- ๐ฆ PyPI Package - Package on PyPI
Made with โค๏ธ for the California agricultural and research community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_cimis-1.3.5.tar.gz.
File metadata
- Download URL: python_cimis-1.3.5.tar.gz
- Upload date:
- Size: 55.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98801142a8ea2380e5b0b7789316cbfa379beb87ad543f5ece3fe7aecc768400
|
|
| MD5 |
df4cd1c051f275dff404f1ab492eb8ae
|
|
| BLAKE2b-256 |
7549da9aa0d1c60834c5c8ba4dc2d1f33cab7457f73576650fec2077b8c61845
|
File details
Details for the file python_cimis-1.3.5-py3-none-any.whl.
File metadata
- Download URL: python_cimis-1.3.5-py3-none-any.whl
- Upload date:
- Size: 27.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d814adbd8c74b2563fe35b90f2264db4b80cc178c623749a22aa6ccd58a74cf
|
|
| MD5 |
1429e6824b4333446aa8b3583f9871ff
|
|
| BLAKE2b-256 |
f85bbf02d9322724aefaddd6f90adc4a1b1d3aca01994a07cdbcd7dec933f071
|