Using Python to Automate Power System Data Analysis
One of the most time-consuming parts of power system consulting is turning raw simulation outputs into coherent, presentable analysis. Load flow results, fault level data, harmonic studies — all of it lands in formats that require hours of manual processing before it can be shared with a client.
Python changed that for me.
The Problem with Manual Data Processing
Before I started using Python systematically, a typical deliverable might involve exporting hundreds of rows of load flow results from DIgSILENT PowerFactory, copying them into Excel, writing pivot tables, formatting charts, and then repeating the process whenever the model was updated.
This wasn't just tedious — it was error-prone. A single copy-paste mistake could invalidate hours of work.
Building a Basic Analysis Pipeline
The core of my workflow is a Python script that reads the raw output files, processes them into a structured format, and generates charts and summary tables automatically.
Reading the Data
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
# Load raw load flow results
df = pd.read_csv('loadflow_results.csv', skiprows=2)
# Clean column names
df.columns = df.columns.str.strip().str.lower().str.replace(' ', '_')
# Filter for relevant voltage levels
hv_buses = df[df['nominal_voltage_kv'] >= 33].copy()
Voltage Profile Analysis
One of the most common deliverables is a voltage profile plot showing how bus voltages vary across the network. With matplotlib, this can be generated in seconds:
fig, ax = plt.subplots(figsize=(12, 5))
ax.bar(hv_buses['bus_name'], hv_buses['voltage_pu'],
color=['#E5513A' if v < 0.95 or v > 1.05 else '#0A7B5C'
for v in hv_buses['voltage_pu']])
ax.axhline(y=0.95, color='red', linestyle='--', alpha=0.7, label='Lower limit (0.95 pu)')
ax.axhline(y=1.05, color='red', linestyle='--', alpha=0.7, label='Upper limit (1.05 pu)')
ax.set_xlabel('Bus Name')
ax.set_ylabel('Voltage (pu)')
ax.set_title('Voltage Profile — HV Network')
ax.legend()
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig('voltage_profile.png', dpi=150, bbox_inches='tight')
The colour-coding immediately highlights any buses outside statutory limits — something that would take minutes to identify manually.
Integrating with PowerFactory via the Python API
DIgSILENT PowerFactory has a Python API that allows you to run scripts directly within the software. This means you can automate the entire workflow — run the load flow, extract the results, and generate the output files — from a single script.
import powerfactory as pf
app = pf.GetApplication()
project = app.GetActiveProject()
# Get all busbars in the network
busbars = app.GetCalcRelevantObjects('*.ElmTerm')
results = []
for bus in busbars:
results.append({
'name': bus.loc_name,
'voltage_pu': bus.GetAttribute('m:u'),
'voltage_kv': bus.GetAttribute('m:U'),
'nominal_kv': bus.uknom
})
df = pd.DataFrame(results)
The Bigger Picture
The shift to Python-based workflows isn't just about efficiency. It's about building muscle around data — understanding your results more deeply because you're engaging with them programmatically rather than just reading numbers off a spreadsheet.
For engineers entering the profession now, computational skills are becoming as important as traditional circuit theory. The tools are becoming more powerful and more accessible. The question is whether we use them.
I'm planning a follow-up post on using machine learning to identify patterns in historical fault data. Sign up to the newsletter to be notified.
Get my writing in your inbox
No spam. Just thoughtful perspectives on energy, AI, and startups — when I have something worth saying.