Skip to content

Getting started

Installation

git clone https://github.com/rwydaegh/aegis.git
cd aegis
git lfs install
git lfs pull
pip install -e ".[dev]"

If you plan to run the viewer, slow tests, or Docker builds, keep the data/ directory complete locally. CI deploys already check out with lfs: true, and the backend Docker image copies data/ into the image.

Optional dependency groups

pip install -e ".[viz]"   # matplotlib, pyvista, trame (visualization)
pip install -e ".[gpu]"   # JAX with CUDA (GPU acceleration)
pip install -e ".[rt]"    # DiffeRT (ray tracing integration)
pip install -e ".[docs]"  # mkdocs (documentation site)
pip install -e ".[all]"   # everything

Your first computation

The simplest AEGIS workflow: one plane wave hitting a single triangle.

import numpy as np
import aegis

# Skin tissue at 28 GHz
skin = aegis.TissueModel.from_params("Skin", 17.0, 25.0, 28e9)

# A single triangle facing upward
vertices = np.array([[[0, 0, 0], [1, 0, 0], [0, 1, 0]]], dtype=float)
normals = np.array([[0, 0, 1.0]])
centroids = np.array([[1/3, 1/3, 0.0]])
areas = np.array([0.5])
body = aegis.BodyMesh(
    vertices=vertices, normals=normals,
    centroids=centroids, areas=areas, name="triangle",
)

# One plane wave from directly above (1 W/m²)
paths = aegis.PropagationPaths.from_powers(
    k_hat=np.array([[0, 0, -1.0]]),
    power=np.array([1.0]),
)

# Compute at Level 2 (default)
engine = aegis.DosimetryEngine(skin)
result = engine.compute(body, paths, level=2)

print(f"S_ab: {result.sab[0]:.3f} W/m²")   # 0.539 (= T_0)
print(f"P_abs: {result.p_abs:.4f} W")

The absorbed power density equals \(T_0 = 0.539\) because the wave arrives at normal incidence. The ReLU factor \([\hat{n} \cdot (-\hat{k})]_+ = 1\) and the normal-incidence Fresnel transmission \(T_0 = 0.539\) for skin at 28 GHz.

Loading real meshes

For real dosimetry, load a human body mesh from an STL file:

body = aegis.BodyMesh.load("thelonious.stl")
print(f"{body.n_triangles} triangles, area = {body.total_area:.4f} m²")

Phantom meshes live in data/ inside the repo (thelonious, duke, eartha, ella). Animated viewer phantoms live in data/phantoms/ as GLB files. Override with AEGIS_DATA_DIR if needed.

Tissue model

Three ways to create tissue properties:

from aegis.tissue import TissueModel, SKIN_28GHZ

# 1. Predefined constants
print(SKIN_28GHZ.T0)         # 0.539
print(SKIN_28GHZ.n_complex)  # complex refractive index

# 2. From explicit parameters (eps_r, sigma, freq)
skin = TissueModel.from_params("Skin 60 GHz", eps_r=7.9, sigma=36.4, freq_hz=60e9)

# 3. From IT'IS v5.0 database (needs itis_v5.db)
skin_db = TissueModel.from_database("Skin", 28e9)

Coherent MIMO dosimetry

Levels 7 and 8 handle coherent multi-antenna systems with complex field amplitudes and precoding. See Coherent MIMO for the full API and examples.

Comparing fidelity levels

sweep_levels() runs all feasible incoherent levels in one call:

results = engine.sweep_levels(body, paths)
for level, r in results.items():
    print(f"Level {level}: P_abs = {r.p_abs:.4f} W, peak = {r.peak_sab:.2f} W/m²")

Higher levels add physical corrections (Fresnel, polarisation, curvature, diffraction) that typically change total power by less than 5%. Use DosimetryResult.compare() to quantify convergence across levels. See fidelity levels for when each correction matters.

Running tests

python -m pytest tests/ -m "not slow" -x   # fast tests (~8s)
python -m pytest tests/                     # all tests (~30s)
python -m ruff check src/ tests/            # lint

Interactive 3D viewer

python -m pip install -e ".[rt]"   # optional: ray tracing in the UI
python -m aegis.viewer --config configs/outdoor_urban.json

See Interactive viewer for scenarios, ports, and API overview.

Where to go next

WAVES Ghent University imec