2026-09-08 02:12:15 -04:00
|
|
|
|
<p align="center">
|
|
|
|
|
|
<img src="docs/logo.svg" alt="OTKO" width="640">
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p align="center">
|
2026-09-08 02:41:03 -04:00
|
|
|
|
A SAP2000-style desktop GUI for
|
|
|
|
|
|
<a href="https://openseespydoc.readthedocs.io/">OpenSeesPy</a>.
|
|
|
|
|
|
Draw the model, click run, look at the diagrams.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p align="center">
|
2026-09-08 02:41:03 -04:00
|
|
|
|
<em>Pre-alpha. Under active development. APIs and file formats will change.</em>
|
2026-09-08 02:12:15 -04:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
## Why
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
OpenSees does nonlinear FEM well. Its user interface is a script.
|
|
|
|
|
|
OTKO puts a visual front-end on it:
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
- Draw nodes, frames, supports, and loads on a snapped grid.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
- Assign materials, sections, and load patterns through dialogs.
|
|
|
|
|
|
- Run static, modal, pushover, and time-history analyses with progress
|
2026-09-08 02:41:03 -04:00
|
|
|
|
and cancel.
|
|
|
|
|
|
- Look at the results — deformed shape, mode shapes, force
|
2026-09-08 02:12:15 -04:00
|
|
|
|
diagrams, pushover curves, time-history plots, hysteresis loops.
|
2026-09-08 02:41:03 -04:00
|
|
|
|
- Save the model as one `.osmodel` JSON file. Diffs cleanly in Git,
|
|
|
|
|
|
builds cleanly from Python.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Underneath, the `core` Pydantic model works fine from a script or
|
|
|
|
|
|
notebook. The GUI is a front-end, not the whole product.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
## What works today
|
|
|
|
|
|
|
|
|
|
|
|
- **Modeling** — grids, nodes, frames (elastic + force-based), trusses,
|
|
|
|
|
|
quads, zero-length sections, restraints, equalDOF constraints,
|
|
|
|
|
|
distributed loads, ground motions (`PathTimeSeries` /
|
|
|
|
|
|
`UniformExcitation`).
|
|
|
|
|
|
- **Materials and sections** — `Steel01`, `Steel02`, `Concrete01`,
|
|
|
|
|
|
`Concrete02`, `ElasticPP`, `Hysteretic`, fiber sections (rectangular /
|
|
|
|
|
|
circular patches + rebar layers), `SectionAggregator`,
|
|
|
|
|
|
`BeamWithHinges`.
|
|
|
|
|
|
- **Analyses** — static (load- or displacement-controlled), modal,
|
|
|
|
|
|
displacement-controlled pushover, transient time-history with
|
|
|
|
|
|
mode-1 Rayleigh damping. Chained workflows: gravity preload →
|
|
|
|
|
|
`loadConst -time 0.0` → pushover or transient.
|
|
|
|
|
|
- **Post-processing** — deformed shape (with scale slider), animated
|
|
|
|
|
|
mode shapes, axial / shear / moment diagrams, pushover curves
|
|
|
|
|
|
(in display units), time-history plots, hysteresis loops,
|
|
|
|
|
|
response-spectrum SRSS / CQC, snapshot + video export.
|
2026-09-08 02:41:03 -04:00
|
|
|
|
- **Persistence** — one JSON `.osmodel` per project, Pydantic-validated,
|
|
|
|
|
|
round-trips clean.
|
|
|
|
|
|
- **Examples** — 20+ verified examples, including OpenSees
|
|
|
|
|
|
Wiki Examples 1–4 and a fiber-section RC frame pushover.
|
|
|
|
|
|
See [`examples/README.md`](examples/README.md).
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
## Tech stack
|
|
|
|
|
|
|
|
|
|
|
|
| Layer | Library |
|
|
|
|
|
|
| ------------ | ------------------------------------ |
|
|
|
|
|
|
| GUI | PySide6 (Qt 6) |
|
|
|
|
|
|
| 3D viewport | PyVista + pyvistaqt (VTK) |
|
|
|
|
|
|
| 2D plots | pyqtgraph |
|
|
|
|
|
|
| Solver | OpenSeesPy 3.8.0.0 |
|
|
|
|
|
|
| Numerics | NumPy |
|
|
|
|
|
|
| Storage | Pydantic v2 (model), h5py (results) |
|
|
|
|
|
|
| Tests | pytest, pytest-qt |
|
|
|
|
|
|
| Lint / type | ruff, mypy |
|
|
|
|
|
|
|
|
|
|
|
|
## Architecture
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Strict MVVM + service layer. `core` is pure Python — no Qt,
|
|
|
|
|
|
no OpenSeesPy imports — and unit-tests in isolation.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
views (Qt) → viewmodels → services (OpenSeesRunner, Persistence) → core (model)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Long version in [`docs/architecture.md`](docs/architecture.md),
|
|
|
|
|
|
including the OpenSeesPy command order the runner emits.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
## Install (development)
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
**Desktop GUI** (Qt, PyVista, pyqtgraph, imageio):
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-09-08 02:41:03 -04:00
|
|
|
|
git clone ssh://git@smill-home.ddns.net/smill/otko.git
|
2026-09-08 02:12:15 -04:00
|
|
|
|
cd otko
|
|
|
|
|
|
|
|
|
|
|
|
python -m venv .venv
|
|
|
|
|
|
.venv\Scripts\activate # Windows
|
|
|
|
|
|
source .venv/bin/activate # Linux / macOS
|
|
|
|
|
|
|
|
|
|
|
|
pip install -e ".[gui,dev]"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
**Headless** (core + services only, no Qt):
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
pip install -e .
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
That pulls pydantic, numpy, h5py, openseespy and nothing else.
|
|
|
|
|
|
Use it for scripts, notebooks, and web backends that reuse
|
|
|
|
|
|
`otko.core` or `otko.services` without the GUI.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Python 3.10+. On Windows use **3.12+** — `openseespywin==3.8.0.0`
|
|
|
|
|
|
has no 3.11 wheel (`Requires-Python >=3.12`). Both pins already
|
|
|
|
|
|
live in `pyproject.toml`.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
## Quick start
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python -m otko
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Then:
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
1. **File → Open** → `examples/cantilever.osmodel`.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
2. **Analyze → Cases** → run `Tip-Load`.
|
2026-09-08 02:41:03 -04:00
|
|
|
|
3. **Display → Show Force Diagram** → **M3**: linear moment,
|
|
|
|
|
|
50 kN·m at the fixed end. **V2**: constant -10 kN.
|
|
|
|
|
|
4. **Display → Show Deformed Shape** → cantilever curve, as advertised.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Nonlinear version: open `examples/portal_pushover.osmodel`,
|
|
|
|
|
|
run `Push-X`, **Display → Show Pushover Curve**. Elastic ramp,
|
|
|
|
|
|
then a yield plateau as the base hinges form.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
## Run the test suite
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-09-08 02:41:03 -04:00
|
|
|
|
pytest tests/unit # pure logic, milliseconds
|
2026-09-08 02:12:15 -04:00
|
|
|
|
pytest tests/gui # Qt event-loop tests (pytest-qt)
|
|
|
|
|
|
pytest tests/integration # real OpenSeesPy runs on bundled examples
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
CI runs lint + the non-`slow` subset on Linux / macOS / Windows
|
|
|
|
|
|
× Python 3.10 / 3.11 / 3.12.
|
|
|
|
|
|
|
|
|
|
|
|
## Roadmap
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
[`docs/roadmap.md`](docs/roadmap.md) has the phase-by-phase plan.
|
|
|
|
|
|
Phases 0–7 (modeling, analysis, post-processing) are mostly done.
|
|
|
|
|
|
Phase 8 (isolators, ground-motion library, IDA, fiber-section
|
|
|
|
|
|
editor polish) is where the open work is.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
## Collaborators wanted
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Most useful to people who already work with OpenSees and want a
|
|
|
|
|
|
shorter path from idea to model — and would rather build it together
|
|
|
|
|
|
than alone. Open an issue or say hi if you are:
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
- A **structural / earthquake engineer** who knows OpenSees Tcl
|
|
|
|
|
|
or OpenSeesPy and can tell us when a feature is almost right
|
|
|
|
|
|
but not quite.
|
|
|
|
|
|
- A **researcher** running pushover, IDA, or response-spectrum studies
|
|
|
|
|
|
who can check the GUI against hand-built scripts.
|
|
|
|
|
|
- A **Python / Qt developer** into scientific desktop apps,
|
|
|
|
|
|
VTK rendering, or Pydantic schema design.
|
|
|
|
|
|
- A **student** learning FEM and GUI architecture at the same time —
|
|
|
|
|
|
the examples and tests are meant to read as documentation.
|
|
|
|
|
|
- A **UX / icon designer** willing to argue about dialogs, toolbar
|
|
|
|
|
|
icons, and visual language.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Bug reports and reproducible test cases count as contributions.
|
|
|
|
|
|
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup and the rules
|
|
|
|
|
|
enforced in review.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
OTKO is **GNU Affero General Public License v3.0**
|
|
|
|
|
|
([`LICENSE`](LICENSE)). Read the license itself, not just this:
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
- Research, education, personal projects: fine, keep the copyright
|
|
|
|
|
|
notice.
|
|
|
|
|
|
- Fork and modify: fine.
|
|
|
|
|
|
- Distribute it (modified or not): release your full source under
|
2026-09-08 02:12:15 -04:00
|
|
|
|
AGPL-3.0.
|
2026-09-08 02:41:03 -04:00
|
|
|
|
- Run a modified version as a network service: release your
|
|
|
|
|
|
modifications under AGPL-3.0.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
2026-09-08 02:41:03 -04:00
|
|
|
|
Commercial forks stay open. If you need a different arrangement
|
|
|
|
|
|
(e.g. closed-source commercial license), open an issue.
|
2026-09-08 02:12:15 -04:00
|
|
|
|
|
|
|
|
|
|
Copyright © 2026 Ozan and contributors.
|