circuitRF Reference Guide

Voxel and mesh import

Your own anatomy in a 3D view — a segmented label map (NIfTI, raw or a DiscMaterial file) or one closed surface per tissue (STL, OBJ, PLY) — each tissue given a material, and solved on openEMS.

circuitRF ships no anatomical model; it reads the one you have. Two forms come in:

Both land in a 3D view as ordinary objects, take a material per tissue from the technology, and run on openEMS with SAR and B1. Neither is meshed by Palace or the thermal solver.

Research and engineering use

circuitRF's SAR is for research and engineering. It is not a compliance tool. A model you import is yours: circuitRF copies it into your workspace and sends it nowhere, and whatever its licence allows is up to you.

Importing a label map

File ▸ Import ▸ Voxel Model… on the active 3D view. Pick the file; the dialog shows the import's report and a label table, one row per label the file holds:

Column
Label the integer in the file
Voxels how many voxels carry it
Tissue the name the tissue takes, <body>/<tissue> in the solve
Material a technology material, or Air

Every label the voxels carry must be mapped, to a material or to Air: one left unmapped would be solved as air, and the SAR in its neighbours would be wrong with nothing said, so the import refuses it, naming each label and its voxel count. Label 0 is air unless a row maps it. Names come from a label list you give, then the file's own names, then label k; a material is filled in only where a technology material has exactly the tissue's name.

File Read as
.nii, .nii.gz NIfTI-1 or NIfTI-2, either byte order, 3D integer data (or a float volume of whole numbers); the orientation from the file's sform, else its qform, else its voxel sizes; millimetres unless the file says otherwise
raw you state the dimensions, the type (uint8 … int32), the voxel size, the byte order and any header to skip; x varies fastest. The file's length must match exactly, which catches a wrong dimension or type
.h5 an openEMS DiscMaterial file; its own εr, σ and density tables are not used — the label table's materials are, and the import says so
label list .csv label,name[,material], a header row allowed, # comments, air as a material

Refused rather than guessed: an orientation turned off the axes (the angle is named: resampling a label map onto a turned grid is a decision about the anatomy that belongs to whoever segmented it — a flip or an axis permutation is fine); a NIfTI pair (.hdr/.img); a 4D series; a scaled volume; more than 255 tissues in one body (openEMS addresses its voxel materials with one byte — map labels that share a material to one row).

The body in the 3D view is one object, drawn as tissue-coloured surfaces at a reduced resolution; picking a tissue selects it. Properties shows its file, the air labels, the crop, its voxel extent, the grid step and one material per tissue; the tree lists its tissues under it.

Size, before the run. The report gives the voxel count, the dimensions and voxel size, what the crop keeps, the label histogram with each row's material, and the FDTD cells inside the body with openEMS's memory for them. Past 50 M cells it is a warning, not a refusal — a whole body at 1 mm is a legitimate run, only a slow one — naming a crop or a coarser grid step as the remedy.

Importing surfaces

File ▸ Import ▸ Surface Meshes…, with one file per tissue (STL ASCII or binary, OBJ, PLY ASCII or binary). A mesh file states no unit, so you give one. Each file is checked, and nothing is imported if one fails:

The surfaces are nested by containment, outermost first, so an inner tissue wins the volume it shares with an outer one, as a phantom's layers do; two surfaces that cross rather than nest are named. A material is matched to each by file name, and is set in Properties per mesh. A tetrahedral mesh (.node/.ele) is voxelized at a size you choose, each voxel the region of the tetrahedron holding its centre, and kept as a .nii.gz beside the 3D view: from then on it is a voxel body.

From the command line

$ circuitrf import voxels head.nii.gz --into model/3d/model.c3d --labels head.csv --report
$ circuitrf import voxels head.raw --into model/3d/model.c3d --dims 256,256,180 --type uint8 --voxel 1mm --material 0=air
$ circuitrf import surfaces tissues/ --into model/3d/model.c3d --unit mm --material "skull=Bone (cortical)"

A length always carries its unit (2.5mm); a bare number is refused. --crop, --grid-step and --name set what the dialog sets; --report prints the report without importing. The .c3d is created when it is absent. MCP's import tool takes what=voxels or what=surfaces with the same choices.