Skip to main content

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.

PyPI version Python versions License: MIT

๐Ÿ“‹ Table of Contents

๐Ÿš€ 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

  1. Visit the CIMIS website
  2. Register for a free account
  3. 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., HlyAirTmp becomes AirTmp_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 records
  • get_daily_records(): Get only daily records
  • get_hourly_records(): Get only hourly records

WeatherRecord

Individual weather data record with attributes:

  • date: Record date (YYYY-MM-DD)
  • station: Station identifier
  • data_values: Dictionary of data measurements
  • scope: 'daily' or 'hourly'

Station

Weather station information with attributes:

  • station_nbr: Station number
  • name: Station name
  • city: City location
  • latitude, longitude: Coordinates
  • elevation: 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

  1. ๐Ÿด Fork the repository
  2. ๐ŸŒŸ Create a feature branch (git checkout -b feature/amazing-feature)
  3. โœจ Make your changes
  4. โœ… Add tests for new functionality
  5. ๐Ÿงช Run the test suite (pytest)
  6. ๐Ÿ“ Update documentation if needed
  7. ๐Ÿ’พ Commit your changes (git commit -m 'Add amazing feature')
  8. ๐Ÿ“ค Push to the branch (git push origin feature/amazing-feature)
  9. ๐Ÿ”„ Open a Pull Request

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

โš ๏ธ 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


Made with โค๏ธ for the California agricultural and research community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_cimis-1.3.1.tar.gz (53.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_cimis-1.3.1-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

Details for the file python_cimis-1.3.1.tar.gz.

File metadata

  • Download URL: python_cimis-1.3.1.tar.gz
  • Upload date:
  • Size: 53.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for python_cimis-1.3.1.tar.gz
Algorithm Hash digest
SHA256 9d50bbdf28b46a995f0667e3fb1ed73e68885951f83a39f742e5ee9f2747ee89
MD5 c64a8d455ee53e6aa713229ca6e6d08e
BLAKE2b-256 2f21c332d40e5b450830e438f931419434416d616555e3d96bc9ef3e93f156d8

See more details on using hashes here.

File details

Details for the file python_cimis-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: python_cimis-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 27.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for python_cimis-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5bf81fa524362ce402046bce9a9edb21de24d5f1d9a751dec19d9f3427e47743
MD5 e2b2455817d2c609da827bc01ec991c6
BLAKE2b-256 7e7dc71ba9e0c9128acf61c4b54195caff8f855b41c6d7de4d84df73b50c7ce0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page