Metadata-Version: 2.4
Name: civix
Version: 0.13.2
Summary: Structural-engineering calculation library where Jupyter notebooks are the living, reviewable deliverable.
Author: mohamadalitellawi
Author-email: mohamadalitellawi <mohamadalitellawi@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: Programming Language :: Python :: 3
Requires-Dist: httpx>=0.28
Requires-Dist: loguru>=0.7.3
Requires-Dist: numpy>=2.0
Requires-Dist: openpyxl>=3.1.5
Requires-Dist: pandas>=2.2
Requires-Dist: plotly>=5.20
Requires-Dist: scipy>=1.13
Requires-Dist: civix[notebook,streamlit,host,ifc] ; extra == 'all'
Requires-Dist: pythonnet>=3.1.0 ; extra == 'host'
Requires-Dist: laspy[lazrs]>=2.5 ; extra == 'host'
Requires-Dist: pyclipper>=1.4 ; extra == 'host'
Requires-Dist: ifcopenshell>=0.8.5 ; extra == 'ifc'
Requires-Dist: trimesh>=4.12 ; extra == 'ifc'
Requires-Dist: manifold3d>=3.5 ; extra == 'ifc'
Requires-Dist: networkx>=3.2 ; extra == 'ifc'
Requires-Dist: handcalcs>=1.11.0 ; extra == 'notebook'
Requires-Dist: jupytext>=1.16 ; extra == 'notebook'
Requires-Dist: markdown>=3.10.2 ; extra == 'notebook'
Requires-Dist: matplotlib>=3.10.9 ; extra == 'notebook'
Requires-Dist: nbformat>=5.10.4 ; extra == 'notebook'
Requires-Dist: notebook>=7.5.6 ; extra == 'notebook'
Requires-Dist: streamlit>=1.58.0 ; extra == 'streamlit'
Requires-Dist: pydantic>=2.0 ; extra == 'streamlit'
Requires-Dist: streamlit-pydantic>=0.6.0 ; extra == 'streamlit'
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/mohamadalitellawi/civix
Project-URL: Repository, https://github.com/mohamadalitellawi/civix
Provides-Extra: all
Provides-Extra: host
Provides-Extra: ifc
Provides-Extra: notebook
Provides-Extra: streamlit
Description-Content-Type: text/markdown

# civix

A structural-engineering design library for Python where Jupyter notebooks are
the primary deliverable — living calculation documents suitable for review and
submission.

> Status: the **foundation cycle is complete**. The cross-cutting
> infrastructure (errors, logging, notebook display, the Quarto export pipeline,
> the console tools) is in place, and so are the vendor-tool subpackages:
> `civix.csilib`, the `etabs2safe` and `foundation_forces` workflows, and the
> `civix.site` Grasshopper engines. The structural-domain modules
> (`core` / `elements` / `codes` / `loads`) are still stubs and arrive in later
> cycles.

Civix has two rendering paths:

- **`civix.display`** — the *live* view inside a running notebook (self-rendering
  PASS/FAIL cards, headers, input tables).
- **`civix.report`** — the *printed* deliverable: scaffold a Quarto project and render
  a notebook to PDF/HTML/docx.

Plus domain tooling:

- **`civix.workflows.etabs2safe` + `hosts/etabs2safe/`** — ETABS → SAFE raft
  pipeline built on `civix.csilib`: read per-building live ETABS models — the
  attached one, or **N model files opened sequentially in one launched
  instance** (TOML project config with per-building shifts, solved from point
  pairs or given directly; opt-in analyse of result-less models) — place them
  into one SAFE frame with full 6-DOF reaction handling, emit a validated
  raft JSON + Plotly overlay, and build/run the SAFE mat model. See
  `docs/workflows/etabs2safe-guide.md`.
- **`civix.workflows.foundation_forces` + `hosts/foundation_forces/`** — the
  **read-only** companion to `etabs2safe`, for models where the foundation is
  built *inside* ETABS, so no joint reactions remain at the level of interest.
  Sums *element joint forces* over every object rising above a configured
  elevation — one row per joint per case — and returns pandas DataFrames, plus
  a closure residual that measures the force crossing an ETABS auto edge
  constraint and is reported, never corrected. See
  `docs/workflows/reference/etabs-element-joint-forces.md`.
- **`civix.workflows.etabs_revit_beams`** — beam-detailing QC across two
  *exports* rather than two live APIs: an ETABS design-table workbook and a
  Revit parameter CSV. Reads each design table **with its units row** and takes
  the scale factor from it (rather than from a comment), resolves beam marks
  used twice into *collapsed* and *withheld-and-reported*, maps the Revit bar
  callouts onto ETABS's three design locations via `civix.rebar`, and gates the
  section size before comparing any steel. Reports every beam a person has to
  look at with the governing location, **face**, demand, capacity and DCR
  attached, and exports the whole comparison as the **two-sheet Excel schedule**
  a design report carries — passed beams and beams needing attention, the same
  columns on each, the Revit callout shown station-correct beside the area it
  produced. Torsion is **flagged, not checked** in this version: a beam carrying
  it is never silently passed, but neither is it failed — ETABS reports
  redistributable compatibility torsion as readily as equilibrium torsion, so
  such a beam passes on `Av`/`As` and carries a hand-check note. Driver
  notebook:
  [`notebooks/etabs/beams/etabs_revit_compare.ipynb`](notebooks/etabs/beams/etabs_revit_compare.ipynb).
- **`civix.workflows.ifcdiff`** — what changed between two IFC exports of the same
  building, as **solid volume**: added (green), removed (orange), unchanged (gray),
  per matched element, via exact manifold booleans. Outputs an Excel change report
  whose totals are live formulas over the rows, a `changes.ifc` overlay with a fresh
  GlobalId per change solid, and a Plotly 3D view; optional N-point alignment of B
  onto A and coordinate normalisation for georeferenced exports. Needs the `ifc`
  extra, no vendor product. Driver notebook:
  [`notebooks/ifc/ifcdiff_run.ipynb`](notebooks/ifc/ifcdiff_run.ipynb); see
  `docs/workflows/ifcdiff-guide.md`.
- **`civix.csilib` + `hosts/csilib/`** — object-level CSI OAPI wrapper for
  ETABS, SAP2000 and SAFE: typed enums, frozen dataclasses, pandas DataFrames,
  context-managed launch/attach with a hardened connection recipe, and SAFE's
  database-table layer as DataFrame in/out. Configured by the repo-root
  `csilib.toml`. See [`src/civix/csilib/README.md`](src/civix/csilib/README.md)
  and `docs/csilib/csilib-guide.md`.
- **`civix.site` + `hosts/grasshopper/`** — Rhino/Grasshopper site tools:
  point-cloud ground-Z extraction (LAS/LAZ), point-cloud reduction (TIN
  thinning under a vertical error budget, or grid decimation that keeps
  original survey points and reports what the reduction cost), Revit toposolid
  break-line creasing, 2D ring offsetting, and contour-fragment joining plus
  nested-curve filtering by level. Pure engines are unit-tested here; thin GH
  components run on the host. See `docs/gh-tools-cookbook.md`.
- **`app/csi_safe_builder/`** — a Streamlit control panel over the
  `civix.workflows.etabs2safe` pipeline (read the attached ETABS model, or
  multiple model files with per-building shifts → assemble the raft → build
  the SAFE `.fdb`), run on the Windows/SAFE host. Not shipped in the wheel.
  See [`app/csi_safe_builder/README.md`](app/csi_safe_builder/README.md).

## Documentation

**[`docs/README.md`](docs/README.md) is the index** — every document in the repository,
grouped by what it promises, with an "I want to…" table at the top. The four you will
reach for most:

| | |
|---|---|
| [`docs/guides/getting-started.md`](docs/guides/getting-started.md) | install, run the demo, make a first PDF |
| [`docs/calc-note-style-guide.md`](docs/calc-note-style-guide.md) | how a calculation note must be written |
| [`docs/backlog.md`](docs/backlog.md) | what is still open |
| [`docs/STATUS.md`](docs/STATUS.md) | what was built, when it was verified live, and why |

## Engineering use

civix is a tool for qualified engineers. Its results do not replace engineering
judgement or an independent check. You are responsible for every value you use, for
confirming each code clause against the published standard, and for the final design.
Clauses in the example notes are marked pending checker verification for this reason.
The software is provided "as is", without warranty — see [`LICENSE`](LICENSE).

## Quickstart

```bash
uv sync                  # core library (numpy/scipy/pandas/plotly included)
uv sync --extra notebook # add Jupyter + handcalcs (optional, needed to run notebooks)
uv run poe demo          # executes the foundation reporting demo notebook
```

In a notebook:

```python
from civix.display import setup_notebook, CheckResult, CalculationReport

setup_notebook(project_name="Office Building A", engineer="J. Doe")

report = CalculationReport(title="Beam B-101")
report.add(
    CheckResult(
        "Bending",
        unity_ratio=0.73,
        demand=180.0,
        capacity=245.6,
        demand_unit="kNm",
        capacity_unit="kNm",
    )
)
report  # renders a styled PASS/FAIL report
```

## Exporting a PDF

Scaffold a Quarto project, then render a notebook. Export needs the external
[Quarto](https://quarto.org) CLI plus a LaTeX engine (e.g. TinyTeX).

```python
from civix.report import init_calc_project, render_report

init_calc_project("calcs", include_sample=True)  # writes Quarto templates
render_report("calcs/sample-calcsheet.ipynb")  # -> calcs/sample-calcsheet.pdf
```

The scaffold also has a CLI:

```bash
uv run python -m civix.report calcs --sample
```

## Command-line tools

Installing civix also installs three console commands:

```bash
civix-health              # read-only doctor: version, optional extras, Quarto CLI,
                          # csilib.toml discovery (never launches ETABS/SAP2000/SAFE)
civix-init-config [DIR]   # scaffold a starter csilib.toml (commented defaults) into DIR
civix-init-calc DIR       # scaffold the Quarto calc templates (same as python -m civix.report)
```

All three work on a bare `pip install civix` — optional extras are only detected,
never imported.

For a complete worked example — an ACI 318M-25 (SI) flexure calc note that pairs
[`handcalcs`](https://github.com/connorferster/handcalcs) equation rendering with
civix `CheckResult`/`CalculationReport` cards — see
[`notebooks/examples/sample-calcsheet.ipynb`](notebooks/examples/sample-calcsheet.ipynb)
and render it with `uv run --extra notebook quarto render
notebooks/examples/sample-calcsheet.ipynb --to pdf`.

## Conventions

Notebooks are submission-grade calculation documents. Units are **never encoded
in identifier names** — use clean engineering symbols (`A_s`, `M_u`, `f_c`) and
annotate the unit on the value (a `handcalcs` trailing comment, the value string
in `calc_input_table`, `demand_unit`/`capacity_unit` on `CheckResult`, or a
library docstring). The default system is metric: N/mm/MPa for section and
material values, kN/m/kPa/kN·m for loads and spans. Convert at boundaries; never
mix unit systems silently. Full discipline lives in
[`docs/calc-note-style-guide.md`](docs/calc-note-style-guide.md) and `CLAUDE.md`.

## Development

Dev tasks run through [Poe the Poet](https://poethepoet.natn.io) (`[tool.poe.tasks]`
in `pyproject.toml`) so they work identically on Windows, macOS and Linux:

```bash
uv sync --extra all    # dev setup: core + every extra (the dev group holds tools/stubs only)
uv run poe check       # format, lint, type-check, test (1731 tests; 73 skip unless --run-* flags are passed)
uv run poe gh39-check  # syntax-guard the civix.site engines + GH host scripts on CPython 3.9
```

Run the live-vendor integration suites (on the Windows/CSI host):

```bash
uv run pytest tests/integration/csilib tests/integration/workflows --run-etabs --run-sap2000 --run-safe
```

These flags turn pytest's `faulthandler` off. When a test closes a CSI app, csilib
releases the app's COM objects after the process has exited; Windows raises and handles
a `0x800706BA` for each one, and `faulthandler` would print it as "Windows fatal
exception" although nothing crashed. The trade-off: a real hard crash in a live run
prints no Python traceback. Details: `docs/csilib/csilib-guide.md`.

Run the ifcdiff sample-model regression (needs the two model pairs in `data/ifc/`, see
[`data/ifc/README.md`](data/ifc/README.md)):

```bash
uv run pytest tests/integration/ifcdiff/test_sample_models.py --run-ifc-samples
```

Run the Streamlit app (on the Windows/SAFE host):

```bash
uv run --extra host --extra streamlit streamlit run app/csi_safe_builder/main.py
```

## Repository layout

```text
src/civix/                 # the installable package (ships in the wheel)
├─ exceptions.py           #   CivixError hierarchy
├─ log_config.py           #   loguru setup
├─ cli.py                  #   civix-health / civix-init-config / civix-init-calc
├─ display/                #   live in-notebook PASS/FAIL rendering
├─ report/                 #   Quarto PDF/HTML/docx export (+ templates/ package data)
├─ utils/                  #   formatting + validation helpers
├─ rebar.py                #   detailing notation (4T20, 4L-T10@200) -> steel areas;
│                          #   a partly readable callout is nan, never a smaller area
├─ csilib/                 #   CSI OAPI wrapper — ETABS/SAP2000/SAFE (pythonnet via the optional `host` extra)
├─ workflows/              #   cross-tool pipelines (on csilib, or across tool exports)
│  ├─ etabs2safe/          #     ETABS → SAFE raft pipeline (optional `host` extra)
│  ├─ foundation_forces/   #     read-only element-joint-force extraction at a given elevation
│  ├─ etabs_revit_beams/   #     beam-detailing QC: ETABS design tables vs Revit parameter export
│  └─ ifcdiff/             #     IFC volume diff between two exports (optional `ifc` extra)
├─ site/                   #   Grasshopper engines (laspy/pyclipper via the optional `host` extra)
│  ├─ pointcloud/          #     LAS/LAZ ground-Z KD-tree engine + origin-shift + TIN thinning
│  │                       #     + grid decimation + point-file textio
│  ├─ topo/                #     Revit toposolid break-line helpers
│  ├─ curves/              #     2D ring prep + pyclipper offsetting (mm)
│  └─ contours/            #     contour-fragment joining + nested-curve filtering by level
└─ core/ elements/ codes/ loads/   # structural-domain stubs (later cycles)

hosts/                     # host-only adapter scripts — NOT in the wheel, ruff/ty-excluded
├─ etabs2safe/             #   raft-pipeline entry scripts + AutoCAD outline LISP helpers
├─ foundation_forces/      #   element-joint-force CLI (probe|read) + project TOML + guide
├─ csilib/                 #   csilib diagnostics, vendor gates, notebook generators, API index
├─ grasshopper/            #   Rhino/Revit GH components (load engines by file path); one
│                          #   folder per tool — topo_breaklines, curves_offset,
│                          #   join_contour_lines, filter_nested_curves,
│                          #   reading_writing_points, reduce_points_count,
│                          #   assign_point_level_from_pointcloud
└─ civil3d/                #   AutoLISP tools for AutoCAD / Civil 3D — BH_Plot draws a
                           #   borehole schedule from a CSV

app/                       # host-level Streamlit UIs — NOT in the wheel, ty-excluded
└─ csi_safe_builder/       #   settings.py / actions.py / main.py over the etabs2safe workflow

tests/
├─ unit/                   # mirrors library modules (test_workflows/, test_site/, …)
├─ integration/            # external toolchains — Quarto, plus workflows/ + csilib/ + ifcdiff/
└─ notebooks/              # deliverable calc-note benchmark suites

docs/
├─ README.md               # THE INDEX — every document in the repo, start here
├─ backlog.md              # the open work, one row per item
├─ STATUS.md               # what was built, when it was verified live, and why
├─ workflows/              # etabs2safe + ifcdiff guides, OAPI/element-joint-force references
├─ csilib/                 # civix.csilib binding domain reference (csilib-guide.md)
├─ guides/                 # git & release workflow, getting started, notebook tooling
├─ standards/              # binding engineering / API / debugging protocols
├─ calc-note-*.md          # how to write a calculation note (style guide + cookbook)
├─ gh-tools-cookbook.md    # the two-layer Grasshopper tool pattern
└─ history/                # FROZEN work records — design specs, plans, build logs
```

Three deliberately separate layers: **engines** (`src/civix/…`, pure, tested, in
the wheel), **hosts** (`hosts/…`, thin vendor-API adapters that run only inside
ETABS/SAFE or Rhino/Revit), and **apps** (`app/…`, host-level Streamlit UIs over
the engines). Only `src/civix/…` ships in the wheel; hosts and apps live outside
it and — like the host scripts — call the engines rather than reimplement them.
