Getting Started with Layer 2 Forecasting

Get energy predictions running in just a few minutes with Qubit’s AI-powered forecasting models. This guide walks you through installation, setup, and generating your first forecasts.

Installation

1

Install the Package

pip install qubit-energy-forecasting

# Or with specific ML backends
pip install qubit-energy-forecasting[all]  # All models
pip install qubit-energy-forecasting[deep]  # TensorFlow/Keras
pip install qubit-energy-forecasting[prophet]  # Facebook Prophet
2

Verify Installation

import qubit.forecasting
print(f"Qubit Forecasting v{qubit.forecasting.__version__}")

# Check available models
from qubit.forecasting import SolarForecaster, DemandForecaster
print("✅ Installation successful!")

Quick Examples

Solar Generation Forecast

Generate a 24-hour solar generation forecast:
from qubit.forecasting import SolarForecaster
import pandas as pd
import numpy as np

# 1. Create sample historical data
dates = pd.date_range('2024-01-01', periods=720, freq='1H')
np.random.seed(42)

# Simulate solar generation pattern
hours = dates.hour
seasonal_factor = 0.8 + 0.4 * np.sin(2 * np.pi * dates.dayofyear / 365)
daily_pattern = np.where(
    (hours >= 6) & (hours <= 18),
    1000 * np.exp(-((hours - 12) ** 2) / 18),
    0
)

historical_data = pd.DataFrame({
    'irradiance': daily_pattern * seasonal_factor + np.random.normal(0, 50, len(dates)),
    'temperature': 25 + np.random.normal(0, 5, len(dates)),
    'cloud_cover': np.random.beta(2, 5, len(dates)),
    'generation': daily_pattern * seasonal_factor * 0.18 + np.random.normal(0, 10, len(dates))
}, index=dates)

historical_data = historical_data.clip(lower=0)

# 2. Initialize and train forecaster
forecaster = SolarForecaster(
    system_capacity_kw=1000,
    panel_type="polycrystalline",
    tilt_angle=35
)

# Prepare features and target
X = historical_data[['irradiance', 'temperature', 'cloud_cover']]
y = historical_data['generation']

# Train the model
forecaster.fit(X, y)
print("✅ Model trained successfully!")

# 3. Generate forecast
# Create future weather forecast (normally from weather API)
future_weather = pd.DataFrame({
    'irradiance': [800, 850, 900, 950, 1000, 950, 900, 800, 600, 300, 0, 0,
                   0, 0, 0, 0, 0, 0, 200, 600, 850, 950, 900, 800],
    'temperature': [20, 22, 25, 27, 30, 32, 30, 28, 25, 22, 18, 15,
                   12, 10, 10, 12, 15, 18, 20, 22, 25, 27, 25, 22],
    'cloud_cover': [0.2] * 24
}, index=pd.date_range(dates[-1] + pd.Timedelta(hours=1), periods=24, freq='1H'))

forecast = forecaster.predict(
    X.tail(24),  # Last 24 hours for context
    horizon="24h",
    weather_forecast=future_weather,
    confidence_levels=[0.80, 0.95],
    asset_id="solar_farm_001"
)

print(f"🌞 24-hour Solar Forecast Generated!")
print(f"Peak generation: {forecast.peak_value:.2f} kW at {forecast.peak_time.strftime('%H:%M')}")
print(f"Total energy: {forecast.total:.2f} kWh")
print(f"Confidence: 80% interval [{forecast.confidence_intervals[0.8][0].max():.0f}, {forecast.confidence_intervals[0.8][1].max():.0f}] kW")

Demand Forecast

Generate electricity demand predictions:
from qubit.forecasting import DemandForecaster
import pandas as pd
import numpy as np

# 1. Create sample load data
dates = pd.date_range('2024-01-01', periods=720, freq='1H')
np.random.seed(42)

# Simulate demand patterns
hours = dates.hour
weekday_pattern = 50 + 30 * (
    ((hours >= 7) & (hours <= 9)) |  # Morning peak
    ((hours >= 17) & (hours <= 21))  # Evening peak
).astype(int)

weekend_pattern = 40 + 10 * np.sin(2 * np.pi * hours / 24)
is_weekend = dates.dayofweek >= 5

base_load = np.where(is_weekend, weekend_pattern, weekday_pattern)
temperature_effect = 2 * (25 - np.abs(dates.hour - 12)) # Temperature effect

historical_load = pd.DataFrame({
    'temperature': 20 + 10 * np.sin(2 * np.pi * dates.dayofyear / 365) + np.random.normal(0, 2, len(dates)),
    'load': base_load + temperature_effect + np.random.normal(0, 5, len(dates))
}, index=dates)

historical_load['load'] = historical_load['load'].clip(lower=0)

# 2. Initialize and train demand forecaster
demand_forecaster = DemandForecaster(
    customer_type="mixed",
    include_weather=True,
    include_calendar=True
)

# Prepare data
X_demand = historical_load[['temperature']]
y_demand = historical_load['load']

# Train model
demand_forecaster.fit(X_demand, y_demand)
print("✅ Demand model trained successfully!")

# 3. Generate demand forecast
future_temp = pd.DataFrame({
    'temperature': 22 + 3 * np.sin(2 * np.pi * np.arange(24) / 24) + np.random.normal(0, 1, 24)
}, index=pd.date_range(dates[-1] + pd.Timedelta(hours=1), periods=24, freq='1H'))

demand_forecast = demand_forecaster.predict(
    X_demand.tail(24),
    horizon="24h",
    temperature_forecast=future_temp,
    asset_id="load_mixed_001"
)

print(f"⚡ 24-hour Demand Forecast Generated!")
print(f"Peak demand: {demand_forecast.peak_value:.2f} kW at {demand_forecast.peak_time.strftime('%H:%M')}")
print(f"Average demand: {demand_forecast.point_forecast.mean():.2f} kW")

# Peak metrics
peak_metrics = demand_forecaster.calculate_peak_metrics(demand_forecast)
print(f"Load factor: {peak_metrics['load_factor']:.2%}")

Integration with Layer 1

Layer 2 is designed to work seamlessly with Layer 1 data:
from qubit.connectors.mqtt import MQTTConnector
from qubit.forecasting import SolarForecaster
from qubit.adapters import AdapterPipeline

# 1. Set up Layer 1 data pipeline
connector = MQTTConnector({
    "broker": "mqtt://your-broker.com:1883",
    "topics": ["solar/+/telemetry"]
})

adapter_pipeline = AdapterPipeline([
    ("units", UnitConverter()),
    ("timezone", TimezoneAdapter()),
    ("validation", SchemaValidator("timeseries"))
])

# 2. Initialize forecaster
forecaster = SolarForecaster(system_capacity_kw=1000)

# 3. Process real-time data and forecast
@connector.on_message
async def process_and_forecast(mqtt_message):
    # Layer 1: Normalize data
    timeseries = adapter_pipeline.process(mqtt_message)
    
    # Layer 2: Generate forecast when enough data
    if len(historical_buffer) > 168:  # 1 week of data
        forecast = forecaster.predict(
            historical_buffer.tail(24),
            horizon="24h"
        )
        
        # Send forecast to Layer 3 or storage
        await send_to_layer3(forecast.to_timeseries())

await connector.start()

Configuration

Environment Variables

# Optional configuration
export QUBIT_FORECASTING_CACHE_DIR="/tmp/qubit_models"
export QUBIT_FORECASTING_LOG_LEVEL="INFO"
export QUBIT_FORECASTING_PARALLEL_JOBS="4"

Configuration File

forecasting:
  default_horizon: "24h"
  default_resolution: "1h"
  cache_models: true
  
models:
  solar:
    default_capacity: 1000  # kW
    include_weather: true
    confidence_levels: [0.8, 0.95]
    
  demand:
    customer_segments: ["residential", "commercial", "industrial"]
    include_calendar: true
    
performance:
  batch_size: 32
  n_jobs: -1
  memory_limit: "4GB"

Docker Deployment

Run forecasting models in containers:
FROM python:3.9-slim

# Install forecasting package
RUN pip install qubit-energy-forecasting[all]

# Copy your forecasting script
COPY forecast_app.py /app/
WORKDIR /app

# Run the forecasting service
CMD ["python", "forecast_app.py"]

API Server

Deploy forecasting as a REST API:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from qubit.forecasting import SolarForecaster, DemandForecaster
import pandas as pd

app = FastAPI(title="Qubit Energy Forecasting API")

# Initialize models
solar_forecaster = SolarForecaster(system_capacity_kw=1000)
demand_forecaster = DemandForecaster(customer_type="mixed")

class ForecastRequest(BaseModel):
    asset_id: str
    model_type: str  # "solar" or "demand"
    horizon: str = "24h"
    historical_data: dict
    weather_data: dict = None

@app.post("/forecast")
async def generate_forecast(request: ForecastRequest):
    try:
        if request.model_type == "solar":
            forecaster = solar_forecaster
        elif request.model_type == "demand":
            forecaster = demand_forecaster
        else:
            raise HTTPException(400, "Invalid model_type")
        
        # Convert data to DataFrame
        X = pd.DataFrame(request.historical_data)
        
        # Generate forecast
        forecast = forecaster.predict(
            X,
            horizon=request.horizon,
            asset_id=request.asset_id
        )
        
        return {
            "asset_id": forecast.asset_id,
            "forecast": forecast.point_forecast.tolist(),
            "timestamps": forecast.timestamps.isoformat().tolist(),
            "peak_value": forecast.peak_value,
            "total": forecast.total
        }
    
    except Exception as e:
        raise HTTPException(500, str(e))

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080)

Troubleshooting

Next Steps


You’re now ready to generate production-quality energy forecasts! Layer 2 provides the predictions that power intelligent energy optimization in Layer 3.