Brain geometry

OSS-DBSv2 distinguishes between a brain-only geometry and the final simulation geometry. The brain geometry defines the simulation domain, while the full model geometry combines that domain with implanted electrodes, contact surfaces, and optional encapsulation layers.

Two geometry levels

  • BrainGeometry describes the outer brain domain used for meshing and field computation.

  • ModelGeometry combines the brain domain with one or more electrode models and assigns the contact and material regions needed for the FEM solve.

In practical terms, most users configure geometry indirectly through the input JSON. The code then constructs the necessary CAD objects automatically.

Brain geometry definition

The brain domain can be defined in two main ways:

  • as a simple analytic shape such as a sphere, ellipsoid, or box

  • from imaging-derived information, for example by using the MRI bounding box and affine transformation

This level is mainly responsible for setting the spatial extent of the simulation and naming the outer surface as BrainSurface.

Electrode integration

Electrodes are created separately and then inserted into the brain domain. When the final ModelGeometry is assembled, OSS-DBSv2:

  • places the electrode CAD models according to position, direction, and rotation

  • creates contact surfaces with stable names such as E1C1

  • adds encapsulation layers when requested

  • prepares surface and volume names used later for materials, boundary conditions, and mesh refinement

This step is central because it connects the anatomical model to the numerical problem that is solved by the volume conductor model.

Encapsulation layers

After electrode implantation, a thin tissue reaction layer (fibrous encapsulation) forms around the electrode shaft. This layer has different electrical properties from the surrounding brain tissue and can significantly affect current spread and impedance.

OSS-DBSv2 models encapsulation as an additional volume region between the electrode surface and the brain tissue. It is configured per electrode in the JSON input:

"EncapsulationLayer": {
  "Thickness[mm]": 0.2,
  "Material": "Gray matter",
  "DielectricModel": "ColeCole4",
  "MaxMeshSize": 0.1
}
  • Thickness[mm]: radial thickness of the layer around the electrode shaft. Set to 0.0 to disable encapsulation entirely.

  • Material: tissue class used for dielectric properties (e.g. Gray matter, Blood). This determines the baseline conductivity of the layer.

  • DielectricModel: dielectric model applied to the encapsulation material. Typically the same model as the surrounding tissue.

  • MaxMeshSize: maximum mesh element size inside the encapsulation volume. Because the layer is thin, a smaller value than the global mesh size is often needed to ensure adequate resolution.

During geometry construction, the encapsulation volume is created from the electrode shaft geometry, intersected with the brain domain, and glued into the model. The resulting regions are named EncapsulationLayer_N (volume) and EncapsulationLayerSurface_N (outer surface), where N is the electrode index.

Practical considerations

  • Choose a brain region that is large enough to avoid boundary effects but not so large that meshing becomes unnecessarily expensive.

  • Start with standard electrode models whenever possible before introducing custom geometries.

  • If geometry construction fails, reduce complexity first: smaller domain, simpler shape, or no encapsulation layer.

  • Use the example cases to understand how contact numbering maps to the final geometry.

API reference

Brain geometry

class ossdbs.model_geometry.brain_geometry.BrainGeometry(shape: str, bounding_box: BoundingBox | None = None, trafo_matrix: ndarray | None = None, translation: ndarray | None = None, rotate_initial_geo: bool = False)[source]

Bases: object

CAD model of the brain geometry.

Parameters:
  • shape (str) – Choose between “Sphere”, “Ellipsoid”, “Box”, and “Custom”

  • bounding_box (BoundingBox) – Bounding box of the geometry in voxel space, can be none for custom geometry

  • trafo_matrix (np.ndarray) – Matrix for affine transformation

  • rotate_initial_geo (bool) – for spheres and ellipsoids, the initial geometry might have an edge on the surface that causes problems when merging with the electrode

Notes

The geometry will be initialized once. A custom shape can be loaded from a STEP or BREP file using import_geometry.

The brain has a single surface named BrainSurface and a single volume named Brain. An exception can be made by adding the geometry via the set_geometry method.

Examples

>>> from ossdbs.model_geometry import BrainGeometry, BoundingBox
>>> bbox = BoundingBox((-20, -20, -20), (20, 20, 20))
>>> brain = BrainGeometry("Sphere", bounding_box=bbox)
property brain_region

Return box-shaped region covered by brain.

property geometry: netgen.occ.Solid

Return OCC shape of the brain geometry.

Return type:

netgen.occ.Solid

get_surface_areas() dict[source]

Get areas of surfaces in geometry.

get_surface_names() list[str][source]

Get names of surfaces in geometry.

import_geometry(path_to_geo_file: str)[source]

Import brain geometry from a CAD file (STEP, IGES, or STL).

The imported shape is assigned the boundary name BrainSurface and the material name Brain. The file is loaded via Netgen’s OCC interface.

set_geometry(geo: netgen.occ.Solid)[source]

Set brain geometry from externally prepared OCC solid.

Notes

This function is the only possibility to use custom-defined names for surface parts of the brain!

Model geometry

class ossdbs.model_geometry.model_geometry.ModelGeometry(brain: BrainGeometry, electrodes: list[ossdbs.electrodes.electrode_model_template.ElectrodeModel])[source]

Bases: object

The final model geometry.

bounding_boxBoundingBox

Localization in 3D space of the geometry

electrodesElectrodes

Collection of electrode models

TODO refactor

property brain_surface_names: list[str]

Return the boundary names of the outer brain surface.

check_brain_geo(brain_geo: netgen.occ.Solid, electrode: ElectrodeModel) bool[source]

Check if brain geo has all contacts.

property contacts: list[ossdbs.model_geometry.contacts.Contact]

Return collection of contacts.

Return type:

list[Contact]

property electrodes: list[ossdbs.electrodes.electrode_model_template.ElectrodeModel]

Return collection of electrodes.

Return type:

list[ElectrodeModel]

property encapsulation_layers: list

Return collection of active contacts and contacts of property floating.

property geometry: netgen.occ.OCCGeometry

Return netgen geometry of the model.

The OCCGeometry is built lazily so that mesh size properties (maxh on faces/edges) are captured by the constructor.

Return type:

netgen.occ.OCCGeometry

get_contact_index(contact_name: str) int[source]

Get index of contact by name.

get_contact_name(electrode_index: int, contact_index: int) str[source]

Return contact name.

get_encapsulation_layer_index(encapsulation_layer_name: str) int[source]

Get index of encapsulation layer by name.

get_floating_mode()[source]

Check if floating and if yes, which mode.

Returns:

"FloatingImpedance" if any floating contact carries a surface impedance model, "Floating" if there are floating contacts but none has an impedance model, or None if no contacts are floating.

Return type:

str or None

set_edge_mesh_sizes(mesh_sizes: dict) None[source]

Set mesh sizes on edges.

set_face_mesh_sizes(mesh_sizes) None[source]

Set mesh sizes on faces.

set_mesh_sizes(mesh_sizes: dict) None[source]

Set mesh sizes on edges, faces, and volumes.

set_volume_mesh_sizes(mesh_sizes: dict) None[source]

Set mesh sizes on volumes.

update_contact(idx: int, settings: dict) None[source]

Overwrite contact properties.

update_contact_areas() None[source]

Update contact areas.

update_encapsulation_layer(idx: int, settings: dict) None[source]

Overwrite encapsulation layer properties.

Helper classes

class ossdbs.model_geometry.bounding_box.BoundingBox(start: tuple = (0, 0, 0), end: tuple = (0, 0, 0))[source]

Bases: object

Represents a cuboid aligned with the cartesian axis.

start

Start point (x, y, z) of bounding box.

Type:

tuple

end

End point (x, y, z) of bounding box.

Type:

tuple

intersection(other: BoundingBox) BoundingBox[source]

Returns the overlapping volume of this and another bounding boxes.

Parameters:

other (BoundingBox) – Second bounding box

Return type:

BoundingBox

points(offset: tuple, voxel_size: tuple) list[tuple][source]

Generate point coordinates matrix.

Parameters:
  • offset (tuple) – Shift of the point matrix along the cartesian coordinates (x, y, z).

  • voxel_size (tuple) – Distances (x, y, z) between adjacent points along the cartesian coordinates.

property shape: tuple[int]

Return the integer distances between start and end point of bounding box.

Return type:

tuple of int

class ossdbs.model_geometry.contacts.Contact(name: str, area: float | None = None, max_h: float = 10000000000.0, edge_max_h: float = 10000000000.0, active: bool = False, floating: bool = False, current: float = 0.0, voltage: float = 0.0, surface_impedance_model: str | None = None, surface_impedance_parameters: dict | None = None)[source]

Bases: object

Electrode contact settings.

Notes

This class stores the main parameters of the electrode contacts.

General property:

  • name: Will be set during the geometry creation process.

  • area: Will be set during the geometry creation process.

Mesh related properties:

  • max_h: Maximum element size on surface

  • edge_max_h: Maximum element size on contact edges

Volume conductor model related properties:

  • active: Whether it needs a Dirichlet BC.

  • floating: Whether the voltage shall be fixed but unknown.

  • current: Assigned or computed current value.

  • voltage: Assigned or computed voltage value.

  • surface_impedance_model: Assigned surface impedance model.

  • surface_impedance_parameters: Parameters for surface impedance model.

active: bool = False
area: float | None = None
current: float = 0.0
edge_max_h: float = 10000000000.0
floating: bool = False
get_surface_impedance(frequency: float, is_complex: bool) float | complex[source]

Return surface impedance at fixed frequency.

max_h: float = 10000000000.0
name: str
surface_impedance_model: str | None = None
surface_impedance_parameters: dict | None = None
voltage: float = 0.0
class ossdbs.model_geometry.contacts.Contacts(contacts: list[ossdbs.model_geometry.contacts.Contact])[source]

Bases: object

Wrapper class to classify contacts.

Notes

This class is intended to take the list of contacts of the model geometry and detect active, floating and unused contacts.

property active: list[ossdbs.model_geometry.contacts.Contact]

List of all active contacts.

Return type:

list of Contacts

append(contact: Contact) None[source]

Add another contact.

property currents: dict

Returns the current values of each contact.

Return type:

dict

property floating: list[ossdbs.model_geometry.contacts.Contact]

List of all floating contacts.

Return type:

list of Contacts

get_surface_impedances(frequency: float, is_complex: bool) dict[source]

Returns the floating impedance values of each contact at a fixed frequency.

Return type:

dict

update_contact(name, floating=None, active=None)[source]

Change type of contact.

property voltages: dict

Returns the voltage values of each contact.

Return type:

dict

ossdbs.model_geometry.contacts.check_contact(contact: Contact)[source]

Check if contact has a clear role.