Point analysis
Point analysis evaluates the FEM solution at selected locations after the volume conductor problem has been solved. This is the bridge between the raw field solution and downstream analyses such as VTA-like thresholding or pathway-based activation studies.
Available point models
OSS-DBSv2 includes multiple ways to sample the field:
Latticefor regular point grids around the electrodeVoxelLatticefor image-like outputs aligned with voxel spacePathwayfor points that lie on fiber trajectories or axon pathways
These models are especially important when the primary output is not just the potential field itself, but a derived spatial analysis.
Typical use cases
estimate VTA-like regions from electric field thresholds
export pointwise potentials or field magnitudes for post-processing
evaluate pathway trajectories for later axon activation modeling
Practical guidance
Disable point models during the very first setup run if you want to validate the core FEM workflow first.
Enable lattices when exploring field spread around the electrode.
Enable pathway models when tract data and axon activation workflows are part of the study design.
API reference
- class ossdbs.point_analysis.point_model.PointModel[source]
Bases:
ABCClass to support evaluation of VCM at points.
- property axon_index: ndarray
Mapping between axons and points.
- close_output_file()[source]
Close out-of-core file.
- property collapse_VTA: bool
Remove electrode from VTA.
- compute_solutions_in_time_domain(signal_length: int, convert_field: bool = False) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray][source]
Compute time-domain solution for all properties.
- Parameters:
signal_length (int) – Number of frequencies of input time vector. This value must be set correctly, otherwise the inverse FFT does not contain correct information.
convert_field (bool) – Whether to FFT-transform also the electric field.
- property coordinates: ndarray
Point coordinates.
- copy_frequency_domain_solution_from_vcm(freq_idx: int, potentials: ndarray, fields: ndarray | None = None) None[source]
Copy potentials and fields from volume conductor model.
- create_time_result(timesteps: ndarray, potential_in_time: ndarray, Ex_in_time: ndarray | None = None, Ey_in_time: ndarray | None = None, Ez_in_time: ndarray | None = None, truncation_index: int | None = None) TimeResult[source]
Prepare time result and save it to file.
- Parameters:
timesteps (np.ndarray) – Array with timesteps related to solution
potential_in_time (np.ndarray) – Solution array with electric potential
Ex_in_time (np.ndarray) – Solution array with x-component of field
Ey_in_time (np.ndarray) – Solution array with y-component of field
Ez_in_time (np.ndarray) – Solution array with z-component of field
truncation_index (int) – Index to truncate solution
- property export_field: str
Export electric field in time domain.
- export_field_at_frequency(frequency: float, frequency_index: int, electrode=None, activation_threshold: float | None = None)[source]
Write field values to CSV and Nifti (if defined).
- Parameters:
frequency (float) – Frequency of exported solution
frequency_index (int) – Index at which frequency is stored
activation_threshold (float) – Threshold to define VTA
electrode – Electrode object with geometry details
- export_point_model_information(filename: str) None[source]
Export all relevant information about the model to JSON.
- export_potential_at_frequency(frequency: float, frequency_index: float) None[source]
Export potential at frequency to CSV.
- Parameters:
frequency (float) – Frequency of exported solution
frequency_index (int) – Index at which frequency is stored
- filter_csf_encap(inside_csf: ndarray, inside_encap: ndarray)[source]
Remove points in CSF or encapsulation layer.
- Parameters:
inside_csf (np.ndarray) – list of points in csf
inside_encap (np.ndarray) – list of points in encapsulation layer
- filter_for_geometry(grid_pts: MaskedArray) ndarray[source]
Return a lattice that NGSolve can process.
Notes
The masked array is expected to be constructed by
points_in_mesh()
- get_points_in_csf(mesh: Mesh, conductivity_cf) ndarray[source]
Return mask for points in CSF.
- Parameters:
mesh (Mesh) – Mesh object on which VCM is defined
conductivity_cf (ConductivityCF) – Conductivity function that hold material info
Notes
TODO Type hint
- get_points_in_encapsulation_layer(mesh: Mesh) ndarray[source]
Return mask for points in encapsulation layer.
- Parameters:
mesh (Mesh) – Mesh object on which VCM is defined
- property inside_csf
Points inside csf.
- property inside_encap
Points inside encapsulation layer.
- property lattice
Lattice of points inside geometry.
- property lattice_mask
Mask of points inside geometry.
- property name: str
Name to distinguish model type.
- property output_path
Path where to save results.
- prepare_VCM_specific_evaluation(mesh: Mesh, conductivity_cf)[source]
Prepare data structure according to mesh.
- Parameters:
mesh (Mesh) – Mesh object on which VCM is defined
conductivity_cf (ConductivityCF) – Conductivity function that hold material info
Notes
Mask all points outside domain, filter CSF and encapsulation layer etc.
Prepares data storage for all frequencies at all points. TODO type hints
- prepare_frequency_domain_data_structure(signal_length: int, out_of_core: bool = False) None[source]
Allocate arrays that hold frequency domain data.
- Parameters:
signal_length (int) – Number of frequencies of FFT / input time vector
out_of_core (bool) – If arrays should be stored on the hard drive
- save(data: TimeResult, file_name: str) None[source]
Save time-domain result to HDF5 file.
- abstract save_as_nifti(scalar_field: ndarray, filename: str, binarize: bool = False, activation_threshold: float | None = None)[source]
Save scalar field in abstract orthogonal space in nifti format.
- Parameters:
scalar_field (numpy.ndarray) – Nx1 array of scalar values on the lattice
filename (str) – Name for the nifti file that should contain full path
binarize (bool) – Choose to threshold the scalar field and save the binarized result
activation_threshold (float) – Activation threshold for VTA estimate
- property time_domain_conversion: bool
If time-domain signal shall be computed.
- write_netgen_meshsize_file(meshsize: float, filename: str) None[source]
Write a Netgen mesh-size file from the point model coordinates.
This generates a file that can be passed to Netgen via the
MeshSizeFilenameparameter inMeshingHypothesisto refine the mesh around pathway or lattice points. This is particularly useful in convergence studies where the mesh needs to be fine near neuron trajectories.- Parameters:
meshsize (float) – Target element size (in mm) at each point. A common choice is the minimum MRI voxel size.
filename (str) – Output file path (e.g.
"meshsizes.txt").
Notes
The file follows the Netgen mesh-size format:
nr_points x1 y1 z1 meshsize x2 y2 z2 meshsize ... 0
The trailing
0indicates that no edge-based size constraints are written.
- class ossdbs.point_analysis.lattice.Lattice(shape: tuple, center: tuple, distance: float, direction: tuple, collapse_vta: bool = False, export_field: bool = True)[source]
Bases:
PointModelMatrix of point coordinates.
- shape
Number of points in each direction (x, y, z).
- Type:
tuple
- center
Center position of cuboid matrix.
- Type:
tuple
- distance
Distance between adjacent points.
- Type:
float
- direction
Orientation of cuboid in 3d space.
- Type:
tuple
- property VTA_volume: float | None
Return VTA volume in mm^3.
- export_point_model_information(filename: str) None[source]
Export all relevant information about the model to JSON.
- save_as_nifti(scalar_field: ndarray, filename: str, binarize: bool = False, activation_threshold: float | None = None)[source]
Save scalar field in abstract orthogonal space in nifti format.
- Parameters:
scalar_field (numpy.ndarray) – Nx1 array of scalar values on the lattice
filename (str) – Name for the nifti file that should contain full path
binarize (bool) – Choose to threshold the scalar field and save the binarized result
activation_threshold (float) – Activation threshold for VTA estimate
- class ossdbs.point_analysis.pathway.Pathway(input_path: str, export_field: bool = False)[source]
Bases:
PointModelPathways comprise populations of axons.
- class Axon(name: str, points: ndarray, status: int, orig_inx: int)[source]
Bases:
object- name
Naming of axons needs to be axon0, axon1, axon2, … to be processed in the correct order.
- Type:
str
- points
Contains 3D coordinates of each point within one axon.
- Type:
np.ndarray
- name: str
- orig_inx: int
- points: ndarray
- status: int
- class Population(name: str, axons: list['Pathway.Axon'])[source]
Bases:
object- name
Name of neuronal population, e.g. a pathway.
- Type:
str
- axons
List that contains all axons within one population.
- Type:
list[“Pathway.Axon”]
- axons: list['Pathway.Axon']
- name: str
- create_index(lattice: ndarray) ndarray[source]
Create index for each point to the matching axon.
- Returns:
index
- Return type:
np.ndarray.
- export_field_at_frequency(frequency: float, frequency_index: int, electrode=None, activation_threshold: float | None = None)[source]
Write field values to CSV.
- Parameters:
frequency (float) – Frequency of exported solution
frequency_index (int) – Index at which frequency is stored
activation_threshold (float) – Threshold to define VTA
electrode (ElectrodeModel) – electrode model that holds geometry information
Notes
No Nifti file is exported for a Pathway model.
- filter_csf_encap(inside_csf: ndarray, inside_encap: ndarray) None[source]
Change axon status if a single point of the axon is within the CSF or encapsulation layer.
- Parameters:
inside_csf (np.ndarray) – The array contains 1 if the corresponding point is inside the CSF, 0 otherwise.
inside_encap (np.ndarray) – The array contains 1 if the corresponding point is inside the encapsulation layer, 0 otherwise.
- filter_for_geometry(grid_pts: MaskedArray) ndarray[source]
Check if any point of an axon is outside the geometry. If this is the case, the entire axon will be marked, and its points will be removed from further processing.
- Parameters:
grid_pts (np.ma.MaskedArray) – Array containing points inside the mesh.
- Returns:
filtered_points – Returns filtered_points after removing axons that are (partially) outside the geometry.
- Return type:
np.ndarray
- get_axon_length() int[source]
- Returns:
axon_length – Number of points per axon
- Return type:
int
Notes
Assume the same length for all axons.
- get_axon_names() list[source]
- Returns:
axon_names – Names of axons in each population
- Return type:
list[list,list,…]
- get_axon_numbers() list[source]
Get list of number of axons per population.
- Returns:
axon_number – Number of axons per population
- Return type:
list[int]
- get_population_names() list[source]
- Returns:
population_names – Names of all populations defined
- Return type:
list[str]
- prepare_VCM_specific_evaluation(mesh: Mesh, conductivity_cf)[source]
Prepare data structure according to mesh.
- Parameters:
mesh (Mesh) – Mesh object on which VCM is defined
conductivity_cf (ConductivityCF) – Conductivity function that holds material info
Notes
Mask all points outside domain, filter CSF and encapsulation layer etc.
Prepares data storage for all frequencies at all points.
- save_as_nifti(scalar_field, filename, binarize=False, activation_threshold=None)[source]
Save scalar field in abstract orthogonal space in nifti format.
- Parameters:
scalar_field (numpy.ndarray) – Nx1 array of scalar values on the lattice
filename (str) – Name for the nifti file that should contain full path
binarize (bool) – Choose to threshold the scalar field and save the binarized result
activation_threshold (float) – Activation threshold for VTA estimate
- class ossdbs.point_analysis.voxel_lattice.VoxelLattice(imp_coord: ndarray, affine: ndarray, shape: ndarray, header: nibabel.Nifti1Header, export_field: bool = True)[source]
Bases:
PointModelMatrix of grid points in the centers of MRI voxels.
- imp_coord
Implantation coordinates in mm space, this will be the center of the grid
- Type:
np.ndarray
- affine
Affine transformation of the MRI image.
- Type:
np.ndarray
- shape
Number of points in each direction (x, y, z).
- Type:
np.ndarray
Notes
Each dimension of shape must be odd to ensure the grid is centered.
- property affine
Affine transformation.
- property imp_coord
Implantation coordinates.
- save_as_nifti(scalar_field: ndarray, filename: str, binarize: bool = False, activation_threshold: float | None = None)[source]
Save scalar field in abstract orthogonal space in nifti format.
- Parameters:
scalar_field (numpy.ndarray) – Nx1 array of scalar values on the lattice
filename (str) – Name for the nifti file that should contain full path
binarize (bool) – Choose to threshold the scalar field and save the binarized result
activation_threshold (float) – Activation threshold for VTA estimate
Notes
TODO add support for upsampled lattice
- property shape
Shape of MRI data.
- class ossdbs.point_analysis.time_results.TimeResult(time_steps: ndarray, points: ndarray, inside_csf: ndarray, inside_encap: ndarray, potential: ndarray, electric_field_magnitude: ndarray | None = None, electric_field_vector_x: ndarray | None = None, electric_field_vector_y: ndarray | None = None, electric_field_vector_z: ndarray | None = None)[source]
Compile time-domain solution.
Notes
The electric field is not always required and is not added by default.
- electric_field_magnitude: ndarray = None
- electric_field_vector_x: ndarray = None
- electric_field_vector_y: ndarray = None
- electric_field_vector_z: ndarray = None
- inside_csf: ndarray
- inside_encap: ndarray
- points: ndarray
- potential: ndarray
- time_steps: ndarray