Skip to content

A Python wrapper for the CSI API (ETABS and SAP2000) that simplifies retrieving table results from structural analysis models.

Notifications You must be signed in to change notification settings

viktor-platform/etabs-sap-wrapper

Repository files navigation

ETABS/SAP2000 Wrapper

A Python wrapper for the CSI API (ETABS and SAP2000) that simplifies retrieving table results from structural analysis models.

Features

  • Dual Application Support: Works with both ETABS and SAP2000
  • Easy connection to running application instances
  • Simplified interface for retrieving analysis results as pandas DataFrames
  • Shared API: Same methods work for both applications (ETABS and SAP2000 use identical COM interfaces)
  • Type hints for better IDE support
  • Clean, modern Python API

Installation

From GitLab (recommended)

pip install git+https://github.com/viktor-platform/etabs-sap-wrapper

For development

git clone https://github.com/viktor-platform/etabs-sap-wrapper
cd etabs-wrapper
uv sync

Requirements

  • Python 3.10+
  • ETABS installed on Windows
  • comtypes, pandas, numpy

Quick Start

ETABS

from etabs_wrapper import ETABSClient

# Connect to a running ETABS instance
client = ETABSClient.from_running_instance()

# Get frame element forces
df = client.results.tables.element_forces_frames(
    load_cases=["DEAD", "LIVE"],
    load_combinations=["COMB1"],
    group_name="ALL"
)
print(df)

SAP2000

from etabs_wrapper import SAPClient

# Connect to a running SAP2000 instance
client = SAPClient.from_running_instance()

# Get frame element forces (same API as ETABS!)
df = client.results.tables.element_forces_frames(
    load_cases=["DEAD", "LIVE"],
    load_combinations=["COMB1"],
    group_name="ALL"
)
print(df)

Using Context Manager

from etabs_wrapper import ETABSClient

with ETABSClient.from_running_instance() as client:
    # Get joint displacements
    displacements = client.results.tables.joint_displacements(
        load_cases=["DEAD"],
        group_name="Floor1"
    )
    print(displacements)

Available Table Methods

The client.results.tables object provides the following methods:

get_table(table_key, group_name="")

Generic method to retrieve any ETABS table by name.

df = client.results.tables.get_table("Joint Displacements", group_name="Floor1")

element_forces_frames(load_cases=None, load_combinations=None, group_name="")

Retrieve frame element forces (axial, shear, moment).

df = client.results.tables.element_forces_frames(
    load_cases=["DEAD", "LIVE"],
    load_combinations=["COMB1", "COMB2"],
    group_name="Columns"
)
# Returns DataFrame with: Frame, OutputCase, P, V2, V3, T, M2, M3, ...

joint_displacements(load_cases=None, load_combinations=None, group_name="")

Retrieve joint displacements (translations and rotations).

df = client.results.tables.joint_displacements(
    load_cases=["DEAD"],
    load_combinations=["COMB1"]
)
# Returns DataFrame with: Joint, OutputCase, U1, U2, U3, R1, R2, R3

base_reactions(load_cases=None, load_combinations=None, group_name="")

Retrieve base reactions (forces and moments).

df = client.results.tables.base_reactions(load_combinations=["COMB1", "COMB2"])
# Returns DataFrame with: OutputCase, FX, FY, FZ, MX, MY, MZ

element_forces_beams(load_cases=None, load_combinations=None, group_name="")

Retrieve beam element forces.

df = client.results.tables.element_forces_beams(load_cases=["DEAD", "LIVE"])

Advanced Usage

Direct API Access

You can access the underlying ETABS COM object for methods not wrapped by this library:

client = ETABSClient.from_running_instance()

# Direct access to ETABS API
ret = client.model.Analyze.RunAnalysis()

# Access to any ETABS API method
file_path = client.model.GetModelFilename()
print(f"Current model: {file_path}")

Working with Results

All table methods return pandas DataFrames, so you can use standard pandas operations:

# Get frame forces
forces = client.results.tables.element_forces_frames(load_cases=["DEAD"])

# Filter and analyze
max_moment = forces["M3"].max()
critical_frames = forces[forces["M3"] > 1000]

# Export to CSV
forces.to_csv("frame_forces.csv", index=False)

# Export to Excel
forces.to_excel("frame_forces.xlsx", index=False)

Error Handling

from etabs_wrapper import ETABSClient
from etabs_wrapper import ETABSConnectionError

try:
    client = ETABSClient.from_running_instance()
except ETABSConnectionError as e:
    print(f"Failed to connect to ETABS: {e}")
    # Handle error - maybe start a new instance?

Development

Running Tests

pytest tests/

Linting and Formatting

ruff check src/
ruff format src/

Project Structure

etabs-wrapper/
├── src/
│   └── etabs_wrapper/
│       ├── __init__.py              # Main exports (ETABSClient, SAPClient)
│       ├── client.py                # ETABSClient and SAPClient classes
│       ├── core/                    # Core functionality
│       │   ├── __init__.py
│       │   ├── base_client.py       # Base class (shared code)
│       │   └── connection.py        # COM connection (ETABS & SAP2000)
│       ├── results/                 # Results retrieval
│       │   ├── __init__.py
│       │   └── tables.py            # Table results (works for both apps)
│       ├── analysis/                # Analysis operations (future)
│       │   └── __init__.py
│       └── model/                   # Model manipulation (future)
│           └── __init__.py
├── examples/                        # Usage examples
│   ├── basic_usage.py              # ETABS examples
│   └── sap2000_usage.py            # SAP2000 examples
├── tests/                           # Test files
├── pyproject.toml                  # Package configuration
└── README.md                       # This file

Application Support

Why Both ETABS and SAP2000?

ETABS and SAP2000 share the same COM API interface. This means:

  • All table names are identical
  • All method signatures are the same
  • Results have the same structure
  • Code written for one works for the other!

The only difference is the connection - once connected, everything else is identical.

Switching Between Applications

# Same code works for both!
def get_frame_forces(client):
    return client.results.tables.element_forces_frames(
        load_cases=["DEAD"]
    )

# Use with ETABS
etabs = ETABSClient.from_running_instance()
forces = get_frame_forces(etabs)

# Use with SAP2000
sap = SAPClient.from_running_instance()
forces = get_frame_forces(sap)

Future Enhancements

Future versions may include:

  • Model manipulation methods
  • Load case/combination management
  • Section property access
  • Material property access
  • Export/import functionality
  • Bridge design features (SAP2000-specific)

License

[Add your license here]

Contributing

Contributions welcome! Please open an issue or submit a merge request.

Support

For issues or questions:

Acknowledgments

Based on the CSI ETABS API and inspired by previous SAP2000/ETABS Python wrappers.

About

A Python wrapper for the CSI API (ETABS and SAP2000) that simplifies retrieving table results from structural analysis models.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages