Open Data Schema for Energy

OpenOA Integration

Bridge ODS-E normalized telemetry directly into NREL’s OpenOA (Open Operational Assessment) scientific framework for wind plant operational analysis, annual energy production (AEP) estimation, wake loss analysis, and electrical loss calculations.

The odse.adapters.openoa module provides a zero-drift, bidirectional adapter aligned with OpenOA conventions:


Installation

Install ODS-E with the optional openoa extra:

pip install "odse[openoa]"

This installs openoa>=2.0.0 and pandas>=1.5.0. The core odse package remains lightweight and importable without scientific dependencies.


Python API Walkthrough

1. Ingest ODS-E Telemetry to OpenOA DataFrames

odse_to_openoa() accepts a file path (str or Path), a raw JSON/JSONL string, or an in-memory dictionary/list:

from odse.adapters.openoa import odse_to_openoa

# Ingest SCADA telemetry from file
result = odse_to_openoa("wind_telemetry.json", table_type="scada", return_plantdata=False)

df_scada = result["scada"]
metadata = result["metadata"]

print(metadata)
# {'site_id': 'windfarm-alpha', 'turbines': 12}

print(df_scada.head())

The resulting DataFrame is indexed with a chronologically sorted UTC DatetimeIndex and standardized column names (WMET_HorWdSpd, pitch_angle, rotor_rpm, generator_rpm, etc.).

2. Multi-Table Assembly

When assembling an entire wind plant dataset across SCADA, met tower, and revenue meter:

from odse.adapters.openoa import odse_to_openoa

# Ingest multi-table dictionary payload
plant_tables = odse_to_openoa({
    "scada": scada_payload,
    "tower": met_mast_payload,
    "meter": grid_meter_payload,
}, return_plantdata=False)

df_scada = plant_tables["scada"]
df_tower = plant_tables["tower"]
df_meter = plant_tables["meter"]

3. Export Back to Canonical ODS-E

Export simulated or filtered DataFrames back to standard ODS-E JSON dictionary payloads:

from odse.adapters.openoa import openoa_to_odse
import json

# Export DataFrame to ODS-E payload
odse_payload = openoa_to_odse(df_scada, asset_id="WTG01", metadata={"plant": "windfarm-alpha"})

# Save to disk
with open("export_openoa_odse.json", "w") as f:
    json.dump(odse_payload, f, indent=2)

CLI Usage

ODS-E provides first-class CLI commands for operational workflows:

# Convert ODS-E telemetry to OpenOA table format
odse to-openoa wind_scada.json --table scada --output openoa_scada.json

# Using alias
odse openoa wind_scada.json --table scada --output openoa_scada.json

Canonical Field Mapping

SCADA Table Mapping

ODS-E Canonical Key OpenOA SCADA Column Name Unit / Type Description
timestamp time / DatetimeIndex UTC datetime Telemetry timestamp (UTC)
asset_id asset_id string Turbine identifier (e.g. WTG01)
active_power_kW WMET_HorWdSpd / wtg_power kW (float) Turbine Active Power
wind_speed_ms WMET_HorWdSpd / wtg_windspeed m/s (float) Nacelle Wind Speed
wind_direction_deg WMET_HorWdDir / wtg_winddirection degrees (float) Wind Direction
pitch_angle_deg pitch_angle degrees (float) Blade Pitch Angle
generator_rpm generator_rpm RPM (float) Generator Rotational Speed
rotor_rpm rotor_rpm RPM (float) Rotor Rotational Speed
ambient_temperature_c temp_air °C (float) Ambient Temperature
nacelle_position_deg nacelle_position degrees (float) Nacelle Yaw Orientation

Met Tower Table Mapping

ODS-E Canonical Key OpenOA Tower Column Name Unit / Type Description
timestamp time / DatetimeIndex UTC datetime Measurement timestamp (UTC)
wind_speed_ms WMET_HorWdSpd m/s (float) Met Mast Wind Speed
wind_direction_deg WMET_HorWdDir degrees (float) Met Mast Wind Direction
ambient_temperature_c temp_air °C (float) Air Temperature
surface_pressure_pa pressure Pa (float) Atmospheric Pressure

Revenue Meter Table Mapping

ODS-E Canonical Key OpenOA Meter Column Name Unit / Type Description
timestamp time / DatetimeIndex UTC datetime Timestamp (UTC)
active_power_kW net_power kW (float) Net Grid Active Power
kWh ac_energy kWh (float) Cumulative Meter Energy

Edge Cases & Troubleshooting Guide

Edge Case 1: Inverter / Turbine OEM Power Casing & Custom Naming

Edge Case 2: Multi-Turbine asset_id Partitioning

Edge Case 3: Negative Power vs. Curtailment

Edge Case 4: Anemometer Yaw Offset and Wind Direction Wrapping

Edge Case 5: Timezone Normalization and Offsets

Edge Case 6: Missing Mandatory timestamp

Edge Case 7: Non-Standard NaN Values in JSON Output