5. Data and File Formats#

ANDES supports multiple file formats for loading power system data, including its native Excel format, PSS/E files, and MATPOWER cases. This tutorial covers loading data from different sources, inspecting and modifying parameters, and saving modified cases.

Understanding how to work with data is essential for practical power system studies, where you often need to adapt standard test cases to specific scenarios or import data from other simulation tools.

5.1. Setup#

%matplotlib inline

import andes
import pandas as pd

andes.config_logger(stream_level=20)

# Configure pandas to show all columns
pd.options.display.max_columns = 20

5.2. Loading ANDES Excel Files#

The native ANDES Excel format (.xlsx) is the best-supported format and is recommended for most use cases. Each sheet in the workbook corresponds to a model type (Bus, Line, GENROU, etc.), and each row represents a device instance.

Use andes.load() to create a System object from a case file. The andes.get_case() function returns the path to built-in test cases.

ss = andes.load(andes.get_case('kundur/kundur_full.xlsx'))
ss
Working directory: "/home/docs/checkouts/readthedocs.org/user_builds/andes/checkouts/stable/docs/source/tutorials"
> Loaded generated Python code in "/home/docs/.andes/pycode".
Parsing input file "/home/docs/checkouts/readthedocs.org/user_builds/andes/envs/stable/lib/python3.11/site-packages/andes/cases/kundur/kundur_full.xlsx"...
Input file parsed in 0.0313 seconds.
Connectivity check completed in 0.0001 seconds.
-> System connectivity check results:
  No islanded bus detected.
  System is interconnected.
  Each island has a slack bus correctly defined and enabled.
System internal structure set up in 0.0203 seconds.
<andes.system.facade.System at 0x73deecee8990>

The System object provides a summary of all loaded models. Each model can be accessed as an attribute of the system, for example ss.Bus, ss.Line, or ss.GENROU.

5.3. Loading PSS/E Files#

PSS/E is the industry-standard power system simulation software from Siemens. ANDES can import PSS/E data files directly, supporting RAW files for power flow data and DYR files for dynamic model parameters.

File Type

Extension

Contents

RAW

.raw

Power flow data (buses, generators, loads, branches)

DYR

.dyr

Dynamic model parameters (exciters, governors, stabilizers)

To load PSS/E files, pass the RAW file path to andes.load() and use the addfile argument for the DYR file. The addfile argument accepts a single file path or a list of paths.

raw_path = andes.get_case('kundur/kundur.raw')
dyr_path = andes.get_case('kundur/kundur_full.dyr')

ss_psse = andes.load(raw_path, addfile=dyr_path)
ss_psse.PFlow.run()
Working directory: "/home/docs/checkouts/readthedocs.org/user_builds/andes/checkouts/stable/docs/source/tutorials"
> Reloaded generated Python code of module "pycode".
Parsing input file "/home/docs/checkouts/readthedocs.org/user_builds/andes/envs/stable/lib/python3.11/site-packages/andes/cases/kundur/kundur.raw"...
  MODIFIED KUNDUR'S TWO-AREA TEST SYSTEM, DISTRIBUTED WITH ANDES
  SEE THE BOOK "POWER SYSTEM STABILITY AND CONTROL" FOR ORIGINAL DATA
Input file parsed in 0.0542 seconds.
Parsing additional file "/home/docs/checkouts/readthedocs.org/user_builds/andes/envs/stable/lib/python3.11/site-packages/andes/cases/kundur/kundur_full.dyr"...
Addfile parsed in 0.0720 seconds.
Connectivity check completed in 0.0001 seconds.
-> System connectivity check results:
  No islanded bus detected.
  System is interconnected.
  Each island has a slack bus correctly defined and enabled.
System internal structure set up in 0.0186 seconds.

-> Power flow calculation
           Numba: Off
   Sparse solver: KLU
 Solution method: NR method
Power flow initialized in 0.0036 seconds.
0: |F(x)| = 3.175850023
1: |F(x)| = 3.176155228e-08
Converged in 2 iterations in 0.0010 seconds.
Report saved to "kundur_out.txt" in 0.0006 seconds.
True

5.3.1. Command Line Usage#

PSS/E files can also be loaded from the command line. The -a flag can be repeated to load multiple additional files:

# Power flow only (RAW file)
andes run kundur.raw

# With dynamic models (RAW + DYR)
andes run kundur.raw --addfile kundur.dyr -r tds

5.3.2. Cross-Format Loading#

The addfile argument is not limited to PSS/E DYR files. Any supported format (xlsx, json, matpower) can be used as an additional file. For example, an ANDES Excel file containing only dynamic models can be loaded on top of a RAW power flow case:

ss = andes.load('case.raw', addfile='dynamics.xlsx')

5.3.3. Converting to ANDES Format#

PSS/E files can be converted to the native ANDES Excel format for easier editing:

andes run kundur.raw --addfile kundur.dyr --convert xlsx

5.4. Inspecting Parameters#

After loading a system, you can inspect model parameters in several ways. Each model provides an as_df() method that returns a pandas DataFrame containing all parameter values.

5.4.1. Viewing Model Parameters#

# View GENROU parameters as DataFrame
ss.GENROU.as_df()
idx u name bus gen coi coi2 Sn Vn fn ... gammaq xd xq xd2 xq1 xq2 Td10 Td20 Tq10 Tq20
uid
0 1 1.0 GENROU_1 1 1 None None 900.0 20.0 60.0 ... 1.0 0.2 0.188889 0.027778 0.061111 0.027778 8.0 0.03 0.4 0.05
1 2 1.0 GENROU_2 2 2 None None 900.0 20.0 60.0 ... 1.0 0.2 0.188889 0.027778 0.061111 0.027778 8.0 0.03 0.4 0.05
2 3 1.0 GENROU_3 3 3 None None 900.0 20.0 60.0 ... 1.0 0.2 0.188889 0.027778 0.061111 0.027778 8.0 0.03 0.4 0.05
3 4 1.0 GENROU_4 4 4 None None 900.0 20.0 60.0 ... 1.0 0.2 0.188889 0.027778 0.061111 0.027778 8.0 0.03 0.4 0.05

4 rows × 30 columns

The DataFrame shows all parameters for each device, with the unique device index (idx) in the first column. Parameters are shown after conversion to per-unit on the system base.

To see the original input values before per-unit conversion, use as_df(vin=True).

# Original input values
ss.GENROU.as_df(vin=True)[['idx', 'Sn', 'M', 'xd', 'xq']]
idx Sn M xd xq
uid
0 1 900.0 13.00 1.8 1.7
1 2 900.0 13.00 1.8 1.7
2 3 900.0 12.35 1.8 1.7
3 4 900.0 12.35 1.8 1.7

5.4.2. Getting Specific Parameters#

To retrieve a specific parameter value for a device, use the get() method. This is useful when you need to read a value for use in calculations or comparisons.

# Get the inertia constant M for generator 1
M_value = ss.GENROU.get('M', 1)
print(f"Inertia M for GENROU 1: {M_value} pu")
Inertia M for GENROU 1: 117.0 pu

5.4.3. Accessing Parameter Arrays#

Each parameter is stored as a NumParam object with a v attribute containing the numerical values as a NumPy array. This provides direct access for bulk operations.

# Get all M values as an array
print("All generator inertia constants:")
print(ss.GENROU.M.v)
All generator inertia constants:
[117.   117.   111.15 111.15]

5.5. Modifying Parameters#

Parameters can be modified using the set() method. By default, set() writes values in system base — the same base returned by get(). This means the read-modify-write cycle is straightforward:

h = ss.GENROU.get('M', 1)        # read system-base value
ss.GENROU.set('M', 1, h * 1.1)   # write back in system base

To provide values in device/input base (as they appear in the case file), use base='device'. This converts through pu_coeff and also updates the vin record so that dumped case files remain consistent.

5.5.1. Using set() with device base#

# Load a fresh system
ss_mod = andes.load(andes.get_case('kundur/kundur_full.xlsx'))

# Check original value
print(f"Original M: {ss_mod.GENROU.get('M', 1, attr='vin')}")

# Modify the inertia constant (value is in device/input base, like the case file)
ss_mod.GENROU.set('M', 1, 10.0, base='device')

# Verify the change
print(f"Modified M: {ss_mod.GENROU.get('M', 1, attr='vin')}")
Original M: 13.0
Modified M: 10.0
Working directory: "/home/docs/checkouts/readthedocs.org/user_builds/andes/checkouts/stable/docs/source/tutorials"
> Reloaded generated Python code of module "pycode".
Parsing input file "/home/docs/checkouts/readthedocs.org/user_builds/andes/envs/stable/lib/python3.11/site-packages/andes/cases/kundur/kundur_full.xlsx"...
Input file parsed in 0.0307 seconds.
Connectivity check completed in 0.0001 seconds.
-> System connectivity check results:
  No islanded bus detected.
  System is interconnected.
  Each island has a slack bus correctly defined and enabled.
System internal structure set up in 0.0195 seconds.

When base='device' is used, the value should be in the same units as the input file (before per-unit conversion). ANDES will automatically convert it to the appropriate system base and update the stored input value (vin).

When base is omitted (the default), the value is written directly in system base — matching what get() returns.

5.5.2. Direct Array Modification#

For bulk modifications or performance-critical operations, you can directly modify the parameter arrays. When doing so, always use in-place assignment with slicing to avoid memory issues.

# Scale all PQ loads by 10%
ss_mod.PQ.Ppf.v[:] *= 1.1
ss_mod.PQ.Qpf.v[:] *= 1.1

print("Scaled PQ loads:")
print(ss_mod.PQ.Ppf.v)
Scaled PQ loads:
[0. 0.]

5.5.3. Verifying Modified Parameters#

After modifying parameters, call as_df(vin=True) to inspect the updated input values.

ss_mod.GENROU.as_df(vin=True)[['idx', 'M']]
idx M
uid
0 1 10.00
1 2 13.00
2 3 12.35
3 4 12.35

5.6. Modifying Device Status#

Each device has a connectivity status parameter u that can be set to 0 (disabled) or 1 (enabled). This is useful for studying contingencies without removing devices from the data file.

To disable a device before running simulation, load with setup=False, modify the status, then call setup().

ss_cont = andes.load(andes.get_case('kundur/kundur_full.xlsx'), setup=False)

# Disable a transmission line
ss_cont.Line.set('u', 'Line_3', 0)

# Complete system setup and run power flow
ss_cont.setup()
ss_cont.PFlow.run()
Working directory: "/home/docs/checkouts/readthedocs.org/user_builds/andes/checkouts/stable/docs/source/tutorials"
> Reloaded generated Python code of module "pycode".
Parsing input file "/home/docs/checkouts/readthedocs.org/user_builds/andes/envs/stable/lib/python3.11/site-packages/andes/cases/kundur/kundur_full.xlsx"...
Input file parsed in 0.0308 seconds.
Connectivity check completed in 0.0002 seconds.
-> System connectivity check results:
  No islanded bus detected.
  System is interconnected.
  Each island has a slack bus correctly defined and enabled.
System internal structure set up in 0.0194 seconds.

-> Power flow calculation
           Numba: Off
   Sparse solver: KLU
 Solution method: NR method
Power flow initialized in 0.0031 seconds.
0: |F(x)| = 14.9282832
1: |F(x)| = 3.579044433
2: |F(x)| = 0.119268955
3: |F(x)| = 0.03278820195
4: |F(x)| = 2.880943096e-05
5: |F(x)| = 3.93747257e-11
Converged in 6 iterations in 0.0029 seconds.
Report saved to "kundur_full_out.txt" in 0.0005 seconds.
True

5.7. Saving Modified Cases#

After modifying parameters, you can save the system to a new file. This is useful for creating variations of a base case for parameter studies.

# Save to new Excel file
andes.io.xlsx.write(ss_mod, 'modified_case.xlsx', overwrite=True)
xlsx file written to "modified_case.xlsx"
True

5.8. Accessing Variables After Simulation#

After running power flow or time-domain simulation, solved variable values can be accessed through the model objects. Each variable has a v attribute containing its current value.

5.8.1. Power Flow Results#

ss.PFlow.run()

# Bus voltage magnitudes
print("Bus voltages (pu):")
print(ss.Bus.v.v)
Bus voltages (pu):
[1.         1.         1.         1.         0.98337472 0.96908586
 0.95621812 0.95400019 0.96856366 0.98377143]
-> Power flow calculation
           Numba: Off
   Sparse solver: KLU
 Solution method: NR method
Power flow initialized in 0.0036 seconds.
0: |F(x)| = 14.9282832
1: |F(x)| = 3.608627841
2: |F(x)| = 0.1701107882
3: |F(x)| = 0.002038626956
4: |F(x)| = 3.745103977e-07
Converged in 5 iterations in 0.0024 seconds.
Report saved to "kundur_full_out.txt" in 0.0005 seconds.

5.8.2. Variable Types#

Variables are classified as either state (differential) or algebraic:

  • State variables (stored in ss.dae.x): Generator angles, speeds, flux linkages

  • Algebraic variables (stored in ss.dae.y): Bus voltages, angles, power injections

Each variable object has an a attribute containing its address(es) in the system arrays.

# Generator speed is a state variable
print(f"GENROU.omega type: {type(ss.GENROU.omega).__name__}")
print(f"GENROU.omega addresses: {ss.GENROU.omega.a}")

# Bus voltage is an algebraic variable
print(f"\nBus.v type: {type(ss.Bus.v).__name__}")
print(f"Bus.v addresses: {ss.Bus.v.a}")
GENROU.omega type: State
GENROU.omega addresses: []

Bus.v type: Algeb
Bus.v addresses: [10 11 12 13 14 15 16 17 18 19]

5.9. Working with Device Indices#

Each device is identified by a unique index (idx). The index can be any hashable type (string, integer, etc.) and is used consistently across ANDES for referencing devices.

5.9.1. Listing Device Indices#

# Get all Line indices
print("Line indices:")
print(ss.Line.idx.v)
Line indices:
['Line_0', 'Line_1', 'Line_2', 'Line_3', 'Line_4', 'Line_5', 'Line_6', 'Line_7', 'Line_8', 'Line_9', 'Line_10', 'Line_11', 'Line_12', 'Line_13', 'Line_14']
# Get all GENROU indices
print("GENROU indices:")
print(ss.GENROU.idx.v)
GENROU indices:
[1, 2, 3, 4]

5.9.2. Converting Index to Internal UID#

Internally, ANDES uses zero-based integer UIDs for array indexing. The idx2uid() method converts an external index to its internal UID.

# Convert idx to uid
uid = ss.GENROU.idx2uid(1)
print(f"GENROU idx=1 has uid={uid}")

# Access parameter by uid
print(f"M value at uid {uid}: {ss.GENROU.M.v[uid]}")
GENROU idx=1 has uid=0
M value at uid 0: 117.0

5.10. Parameter Units#

Parameters are typically specified in per-unit on the device or system base. Common conventions are:

Parameter Type

Typical Unit

Power (p0, q0)

pu on system MVA base

Voltage (v0)

pu on bus nominal voltage

Impedance (R, X)

pu on system base

Inertia (H, M)

seconds (M = 2H)

Time constants

seconds

Consult the model documentation for specific parameter definitions and units.

5.11. Cleanup#

!andes misc -C
!rm -f modified_case.xlsx
"/home/docs/checkouts/readthedocs.org/user_builds/andes/checkouts/stable/docs/source/tutorials/kundur_full_out.txt" removed.
"/home/docs/checkouts/readthedocs.org/user_builds/andes/checkouts/stable/docs/source/tutorials/kundur_out.txt" removed.

5.12. Next Steps#