Python Examples¶
Complete Python integration examples for the Tessellate Renewables API.
Installation¶
For async operations:
Basic Client Class¶
"""
Tessellate Renewables API Client
"""
import requests
from typing import Optional, Dict, Any, List
import time
class TessellateClient:
"""Client for the Tessellate Renewables API."""
def __init__(self, api_key: Optional[str] = None):
self.base_url = "https://api.tessellaterenewables.com"
self.session = requests.Session()
if api_key:
self.session.headers["X-API-Key"] = api_key
self.session.headers["Content-Type"] = "application/json"
def get_solar_resource(self, latitude: float, longitude: float) -> Dict[str, Any]:
"""Get solar irradiance data for a location."""
response = self.session.post(
f"{self.base_url}/solar/resource",
json={"latitude": latitude, "longitude": longitude}
)
response.raise_for_status()
return response.json()
def quick_optimize(
self,
latitude: float,
longitude: float,
capacity_kw: float,
objective: str = "energy"
) -> Dict[str, Any]:
"""Run quick optimization."""
response = self.session.post(
f"{self.base_url}/solar/optimization/quick",
json={
"site": {
"latitude": latitude,
"longitude": longitude,
"capacity_kw": capacity_kw
},
"objective": objective
}
)
response.raise_for_status()
return response.json()
def full_optimize(
self,
latitude: float,
longitude: float,
capacity_kw: float,
objective: str = "energy",
max_iterations: int = 50,
bounds: Optional[Dict] = None,
poll_interval: float = 2.0
) -> Dict[str, Any]:
"""Run full optimization and wait for results."""
payload = {
"site": {
"latitude": latitude,
"longitude": longitude,
"capacity_kw": capacity_kw
},
"objective": objective,
"max_iterations": max_iterations
}
if bounds:
payload["bounds"] = bounds
# Submit job
response = self.session.post(
f"{self.base_url}/solar/optimization/run",
json=payload
)
response.raise_for_status()
job_id = response.json()["job_id"]
# Poll for results
while True:
result = self.session.get(
f"{self.base_url}/solar/optimization/{job_id}"
).json()
if result["status"] == "completed":
return result
elif result["status"] == "failed":
raise Exception(f"Optimization failed: {result.get('error_message')}")
time.sleep(poll_interval)
def multi_objective(
self,
latitude: float,
longitude: float,
capacity_kw: float,
objectives: List[str],
generations: int = 100,
poll_interval: float = 2.0
) -> Dict[str, Any]:
"""Run multi-objective optimization."""
response = self.session.post(
f"{self.base_url}/solar/optimization/multi",
json={
"site": {
"latitude": latitude,
"longitude": longitude,
"capacity_kw": capacity_kw
},
"objectives": objectives,
"generations": generations
}
)
response.raise_for_status()
job_id = response.json()["job_id"]
while True:
result = self.session.get(
f"{self.base_url}/solar/optimization/{job_id}"
).json()
if result["status"] == "completed":
return result
elif result["status"] == "failed":
raise Exception(f"Optimization failed: {result.get('error_message')}")
time.sleep(poll_interval)
def predict(
self,
latitude: float,
longitude: float,
capacity_kw: float,
tilt: float = 30.0,
azimuth: float = 180.0,
dc_ac_ratio: float = 1.2,
gcr: float = 0.4
) -> Dict[str, Any]:
"""Predict solar power output."""
response = self.session.post(
f"{self.base_url}/solar/predict",
json={
"latitude": latitude,
"longitude": longitude,
"capacity_kw": capacity_kw,
"tilt": tilt,
"azimuth": azimuth,
"dc_ac_ratio": dc_ac_ratio,
"gcr": gcr
}
)
response.raise_for_status()
return response.json()
# Usage
if __name__ == "__main__":
client = TessellateClient()
# Quick optimization
result = client.quick_optimize(
latitude=35.0,
longitude=-110.0,
capacity_kw=1000,
objective="energy"
)
print(f"Optimal tilt: {result['optimal_parameters']['tilt']}°")
print(f"Annual energy: {result['energy_metrics']['annual_energy_mwh']:,.0f} MWh")
Site Comparison Tool¶
"""Compare multiple sites for solar development."""
from dataclasses import dataclass
from typing import List
import pandas as pd
@dataclass
class SiteResult:
name: str
latitude: float
longitude: float
annual_energy_mwh: float
capacity_factor: float
lcoe: float
npv: float
irr: float
def compare_sites(client: TessellateClient, sites: List[dict], capacity_kw: float) -> pd.DataFrame:
"""Compare multiple sites and return a DataFrame."""
results = []
for site in sites:
result = client.quick_optimize(
latitude=site["latitude"],
longitude=site["longitude"],
capacity_kw=capacity_kw,
objective="npv"
)
results.append(SiteResult(
name=site["name"],
latitude=site["latitude"],
longitude=site["longitude"],
annual_energy_mwh=result["energy_metrics"]["annual_energy_mwh"],
capacity_factor=result["energy_metrics"]["capacity_factor"],
lcoe=result["financial_metrics"]["lcoe_cents_per_kwh"],
npv=result["financial_metrics"]["npv_dollars"],
irr=result["financial_metrics"]["irr_percent"]
))
df = pd.DataFrame([vars(r) for r in results])
df = df.sort_values("npv", ascending=False)
return df
# Usage
sites = [
{"name": "Phoenix, AZ", "latitude": 33.45, "longitude": -112.07},
{"name": "Denver, CO", "latitude": 39.74, "longitude": -104.99},
{"name": "Austin, TX", "latitude": 30.27, "longitude": -97.74},
{"name": "Miami, FL", "latitude": 25.76, "longitude": -80.19},
]
client = TessellateClient()
comparison = compare_sites(client, sites, capacity_kw=1000)
print(comparison.to_string(index=False))
Async Client for High Volume¶
"""Async client for parallel requests."""
import asyncio
import aiohttp
from typing import List, Dict, Any
class AsyncTessellateClient:
def __init__(self, api_key: str = None):
self.base_url = "https://api.tessellaterenewables.com"
self.headers = {"Content-Type": "application/json"}
if api_key:
self.headers["X-API-Key"] = api_key
async def quick_optimize(
self,
session: aiohttp.ClientSession,
latitude: float,
longitude: float,
capacity_kw: float,
objective: str = "energy"
) -> Dict[str, Any]:
async with session.post(
f"{self.base_url}/solar/optimization/quick",
json={
"site": {
"latitude": latitude,
"longitude": longitude,
"capacity_kw": capacity_kw
},
"objective": objective
},
headers=self.headers
) as response:
return await response.json()
async def batch_optimize(
self,
sites: List[Dict],
capacity_kw: float,
objective: str = "energy"
) -> List[Dict[str, Any]]:
async with aiohttp.ClientSession() as session:
tasks = [
self.quick_optimize(
session,
site["latitude"],
site["longitude"],
capacity_kw,
objective
)
for site in sites
]
return await asyncio.gather(*tasks)
# Usage
async def main():
client = AsyncTessellateClient()
sites = [
{"latitude": 33.45, "longitude": -112.07},
{"latitude": 39.74, "longitude": -104.99},
{"latitude": 30.27, "longitude": -97.74},
]
results = await client.batch_optimize(sites, capacity_kw=1000)
for site, result in zip(sites, results):
print(f"Lat {site['latitude']}: {result['energy_metrics']['annual_energy_mwh']:.0f} MWh")
asyncio.run(main())
Integration with Pandas¶
"""Export results to various formats."""
import pandas as pd
def optimization_to_dataframe(result: dict) -> pd.DataFrame:
"""Convert optimization result to DataFrame."""
data = {
"Parameter": ["Tilt", "Azimuth", "DC/AC Ratio", "GCR"],
"Value": [
f"{result['optimal_parameters']['tilt']:.1f}°",
f"{result['optimal_parameters']['azimuth']:.1f}°",
f"{result['optimal_parameters']['dc_ac_ratio']:.2f}",
f"{result['optimal_parameters']['gcr']:.2f}"
]
}
return pd.DataFrame(data)
def pareto_to_dataframe(pareto_front: list) -> pd.DataFrame:
"""Convert Pareto front to DataFrame."""
rows = []
for sol in pareto_front:
row = {
"tilt": sol["tilt"],
"azimuth": sol["azimuth"],
"dc_ac_ratio": sol["dc_ac_ratio"],
"gcr": sol["gcr"],
**sol["objectives"]
}
rows.append(row)
return pd.DataFrame(rows)
# Export to Excel
# pareto_df.to_excel("pareto_results.xlsx", index=False)
# Export to CSV
# pareto_df.to_csv("pareto_results.csv", index=False)