pynibs.util package¶
Submodules¶
pynibs.util.dosing module¶
pynibs.util.quality_measures module¶
- pynibs.util.quality_measures.c_map_comparison(c1, c2, t1, t2, nodes, tris)¶
Compares two c-maps in terms of NRMSD and calculates the geodesic distance between the hotspots.
- Parameters:
c1 (np.ndarray of float) – (n_ele) First c-map.
c2 (np.ndarray of float) – (n_ele) Second c-map (reference).
t1 (np.ndarray of float) –
Coordinates of the hotspot in the first c-map.
t2 (np.ndarray of float) – Coordinates of the hotspot in the second c-map.
nodes (np.ndarray of float) – (n_nodes, 3) Node coordinates
tris (np.ndarray of float) – (n_tris, 3) Connectivity of ROI elements
- Returns:
nrmsd (float) – Normalized root-mean-square deviation between the two c-maps in (%).
gdist (float) – Geodesic distance between the two hotspots in (mm).
- pynibs.util.quality_measures.calc_tms_motion_params(coil_positions, reference=None)¶
Computes motion parameters for a set of
coil_positions, i.e., coil shifts in [mm] in RAS coordinate system and rotations (pitch, roll, yaw) in [°]. Motion is computed w.r.t. the first (‘absolute’) and to the previous (‘relative’) stimulation.Position shifts are quantified with respect to the subject/nifti-specific RAS coordinate system. Rorational changes are quantified with respect to the coil axes as follows:
pitch: rotation around left/right axis of coil
roll: rotation around coil handle axis
yaw: rotation around axis from center of coil towards head
Motion parameters for first coil position are set to 0.
- Parameters:
- Returns:
pos_diff_abs (np.ndarray) – (3, n_pulses) Absolute position differences (R, A, S).
euler_rots_abs (np.ndarray) – (3, n_pulses) Absolute rotation angles in euler angles (alpha, beta, gamma).
pos_diff_rel (np.ndarray) – (3, n_pulses) Relative position differences (R, A, S).
euler_rots_rel (np.ndarray) – (3, n_pulses) Relative rotation angles in euler angles (alpha, beta, gamma).
- pynibs.util.quality_measures.compute_pcd(delta_pos, delta_rot, skin_cortex_distance=20)¶
Computes _P_ulsewise _C_oil _D_isplacements (PCD) based on 3 position parameters (
delta_pos) and 3 rotation parmeters (delta_rot).The coil rotations (in euler angles) are transformed into a positional change projected on the cortex based on
skin_cortex_distanceas a proxy for the (local) change of the stimulation.delta_posanddelta_rotare expected to quantify motion w.r.t. the target coil position/roation, for example the absolute deltas to the first stimulation.
- pynibs.util.quality_measures.euclidean_dist(nodes, tris, source, source_is_node=True)¶
Returns euclidean distance of all nodes to source node (triangle). This is just a wrapper for the gdist package.
Example
with h5py.File(fn,'r') as f: tris = f['/mesh/elm/triangle_number_list'][:] nodes = f['/mesh/nodes/node_coord'][:] nodes_dist_euc, tris_dist_euc = euclidean_dist(nodes, tris, 3017) pynibs.write_data_hdf5(data_fn, data=[tris_dist_euc, nodes_dist_euc], data_names=["tris_dist_euc", "nodes_dist_euc", "]) pynibs.write_xdmf(data_fn,hdf5_geo_fn=fn)
- Parameters:
nodes (np.ndarray) – (n_nodes,3) The nodes, determined by their x-y-z-coordinates.
tris (np.ndarray) – (n_tris,3) Every triangle, determined by the node indices (vertices) that form it.
source (np.ndarray(int) or int) – Euclidean distances of all nodes (or triangles) to this one will be computed.
source_is_node (bool) – Whether source is a node idx or a triangle idx.
- Returns:
nodes_dist (np.ndarray) – (n_nodes,) Geodesic distance between source and all nodes in mm.
tris_dist (np.ndarray) – (n_tris,) Geodesic distance between source and all triangles in mm.
- pynibs.util.quality_measures.geodesic_dist(nodes, tris, source, source_is_node=True)¶
Returns geodesic distance in mm from all nodes to source node (or triangle). This is just a wrapper for the gdist package.
Example
with h5py.File(fn,'r') as f: tris = f['/mesh/elm/triangle_number_list'][:] nodes = f['/mesh/nodes/node_coord'][:] nodes_dist_ged, tris_dist_ged = geodesic_dist(nodes, tris, 3017) pynibs.write_data_hdf5(data_fn, data=[tris_dist_ged, nodes_dist_ged], data_names=["tris_dist_ged", "nodes_dist_ged"]) pynibs.write_xdmf(data_fn,hdf5_geo_fn=fn)
- Parameters:
nodes (np.ndarray) – (n_nodes,3) The nodes, determined by their x-y-z-coordinates.
tris (np.ndarray) – (n_tris,3) Every triangle, determined by the node indices (vertices) that form it.
source (np.ndarray(int) or int) – Geodesic distances of all nodes (or triangles) to this one will be computed.
source_is_node (bool) – Whether source is a node idx or a triangle idx.
- Returns:
nodes_dist (np.ndarray) – (n_nodes,) Geodesic distance between source and all nodes in mm.
tris_dist (np.ndarray) – (n_tris,) Geodesic distance between source and all triangles in mm.
- pynibs.util.quality_measures.nrmsd(array, array_ref, error_norm='relative', x_axis=False)¶
Determine the normalized root-mean-square deviation between input data and reference data.
Notes
nrmsd = np.sqrt(1.0 / n_points * np.sum((data - data_ref) ** 2)) / (max(array_ref) - min(array_ref))
- Parameters:
array (np.ndarray) – input data [ (x), y0, y1, y2 … ].
array_ref (np.ndarray) – reference data [ (x_ref), y0_ref, y1_ref, y2_ref … ]. if array_ref is 1D, all sizes have to match.
error_norm (str, optional, default="relative") – Decide if error is determined “relative” or “absolute”.
x_axis (bool, default: False) – If True, the first column of array and array_ref is interpreted as the x-axis, where the data points are evaluated. If False, the data points are assumed to be at the same location.
- Returns:
normalized_rms – ([array.shape[1]]) Normalized root-mean-square deviation between the columns of array and array_ref.
- Return type:
np.ndarray of float
- pynibs.util.quality_measures.nrmse(array, array_ref, x_axis=False)¶
Determine the normalized root-mean-square deviation between input data and reference data.
nrmse = np.linalg.norm(array - array_ref) / np.linalg.norm(array_ref)
- Parameters:
array (np.ndarray) – input data [ (x), y0, y1, y2 … ].
array_ref (np.ndarray) – reference data [ (x_ref), y0_ref, y1_ref, y2_ref … ]. if array_ref is 1D, all sizes have to match.
error_norm (str, optional, default="relative") – Decide if error is determined “relative” or “absolute”.
x_axis (bool, default: False) – If True, the first column of array and array_ref is interpreted as the x-axis, where the data points are evaluated. If False, the data points are assumed to be at the same location.
- Returns:
nrmse – ([array.shape[1]]) Normalized root-mean-square deviation between the columns of array and array_ref.
- Return type:
np.ndarray of float
- pynibs.util.quality_measures.plot_tms_motion_parameter(pos_diff, euler_rots, pcd=None, fname=None)¶
Plots TMS coil motion parameters.
Pulsewise Coil Displacement (PCD) is a compound metric to quantify TMS coil movements. Data for a double (space) cTBS400 protocol is shown (with a break after 200 bursts).¶
- Parameters:
pos_diff (np.ndarray) – (3, n_pulses) Position differences (R, A, S).
euler_rots (np.ndarray) – (3, n_pulses) Rotation angles in euler angles (alpha, beta, gamma).
pcd (np.ndarray, optional) – (n_pulses,) pulsewise coil displacements.
fname (str, optional) – Filename to save plot.
- Returns:
axes – Figure axes.
- Return type:
matplotlib.pyplot.axes
pynibs.util.rotations module¶
Some helper functions to take care of geometric rotations
- pynibs.util.rotations.bases2rotmat(v1, v2)¶
Computes rotation matrix to rotate basis 1 (
v1) to another basis (v2).- Parameters:
v1 (np.ndarray) – (3, 3) original basis.
v2 (np.ndarray) – (3, 3) rotated basis.
- Returns:
rot_mat – (3, 3) rotation matrix to go from v1 to v2.
- Return type:
np.ndarray
- pynibs.util.rotations.euler_angles_to_rotation_matrix(theta)¶
Determines the rotation matrix from the three Euler angles theta = [Psi, Theta, Phi] (in rad), which rotate the coordinate system in the order z, y’, x’’.
- Parameters:
theta (np.ndarray) –
Euler angles in rad.
- Returns:
r –
Rotation matrix (z, y’, x’’).
- Return type:
np.ndarray
- pynibs.util.rotations.normalize_rot(rot)¶
Normalize rotation matrix.
- pynibs.util.rotations.quat_rotation_angle(q)¶
Computes the rotation angle from the quaternion in rad.
- pynibs.util.rotations.quat_to_rot(q)¶
Computes the rotation matrix from quaternions.
- pynibs.util.rotations.quaternion_conjugate(q)¶
https://stackoverflow.com/questions/15425313/inverse-quaternion
- Parameters:
q –
- Returns:
- Return type:
- pynibs.util.rotations.quaternion_diff(q1, q2)¶
https://math.stackexchange.com/questions/2581668/ error-measure-between-two-rotations-when-one-matrix-might-not-be-a-valid-rotatio
- Parameters:
q1 (np.ndarray) – Quaternion 1.
q2 (np.ndarray) – Quaternion 2.
- Returns:
Difference between the two quaternions.
- Return type:
- pynibs.util.rotations.quaternion_inverse(q)¶
Compute the inverse of a quaternion.
The inverse of a quaternion is computed by taking the conjugate of the quaternion and dividing it by the norm of the quaternion. https://stackoverflow.com/questions/15425313/inverse-quaternion
- Parameters:
q (np.ndarray) – Input quaternion.
- Returns:
Inverse of the input quaternion.
- Return type:
np.ndarray
- pynibs.util.rotations.rot_to_quat(rot)¶
Computes the quaternions from rotation matrix (see e.g. https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/).
- pynibs.util.rotations.rotate_matsimnibs_euler(axis, angle, matsimnibs, metric='rad')¶
Rotates a matsimnibs matrix around
axisbyangle.- Parameters:
- Returns:
rotated_matsimnibs – (4, 4) Rotated system.
- Return type:
np.ndarray
- pynibs.util.rotations.rotation_matrix_to_euler_angles(r)¶
Calculates the euler angles theta = [Psi, Theta, Phi] (in rad) from the rotation matrix R which, rotate the coordinate system in the order z, y’, x’’ (https://www.learnopencv.com/rotation-matrix-to-euler-angles/).
- Parameters:
r (np.ndarray) – (3, 3) Rotation matrix (z, y’, x’’).
- Returns:
theta –
Euler angles in rad.
- Return type:
np.ndarray
- pynibs.util.rotations.rotmat_from_vecs(vec1, vec2)¶
Find the rotation matrix that aligns vec1 to vec2
- Parameters:
1 (vec) – A 3D vector (‘source’).
2 (vec) – A 3D vector (‘destination’).
- Returns:
rot_mat (scipy.Rotation)
A transform matrix (3x3) which when applied to vec1, aligns it with vec2.
pynibs.util.simnibs module¶
- pynibs.util.simnibs.calc_e_in_midlayer_roi(e, roi, mesh=None, qoi=None, layer_gm_wm_info=None)¶
This is to be called by Simnibs as postprocessing function per FEM solve.
- Parameters:
e (np.ndarray or tuple) – E to interpolate. Used to be (v, dAdt).
roi (pynibs.roi.RegionOfInterestSurface) –
mesh (simnibs.msh.Mesh) –
qoi (list of str) – List of identifiers of the to-be calculated quantities of interest.
layer_gm_wm_info (dict[str, dict[str, np.ndarray]], optional) –
For each layer defined in the mesh (outer dict key: layer_id), provide pre-computed geometrical information as a dictionary (outer dict value):
key: gm_nodes, For each layer node, the corresponding point on the GM surface.
key: wm_nodes, For each layer node, the corresponding point on the WM surface.
key: gm_center_distance, The distance between the layer nodes and the corresponding points on the GM.
key: wm_center_distance, The distance between the layer nodes and the corresponding points on the WM.
- Returns:
(roi.n_tris, 4) – (len(roi.layers)x(roi.layers[idx].surface.n_tris,4)) : np.vstack((e_mag, e_norm, e_tan, e_angle)).transpose()
- Return type:
np.vstack((e_mag, e_norm, e_tan, e_angle)).transpose() for the midlayer
- pynibs.util.simnibs.check_mesh(mesh, verbose=False)¶
Check a simmibs.Mesh for degenerated elements:
zero surface triangles
zerso volume tetrahedra
negative volume tetrahedra
- Parameters:
mesh (str or simnibs.Mesh) –
verbose (book, default: False) – Print some verbosity messages.
- Returns:
zero_tris (np.ndarray) – Element indices for zero surface tris (0-indexed)
zero_tets (np.ndarray) – Element indices for zero volume tets (0-indexed)
neg_tets (np.ndarray) – Element indicies for negative volume tets (0-indexed)
- pynibs.util.simnibs.e_field_angle_theta(surface, mesh)¶
Compute angle between local the E-field vector and surface vector at the ROI nodes.
- Parameters:
surface (simnibs.Msh) – The surface object representing the ROI.
mesh (simnibs.Msh) – The (volumetric) head mesh.
- Returns:
theta – The angle between local the E-field vector and surface vector for each surface element of the ROI.
- Return type:
simnibs.mesh.mesh_io.ElementData
- pynibs.util.simnibs.e_field_gradient_between_wm_gm(roi_surf, mesh, gm_nodes, wm_nodes, gm_center_distance, wm_center_distance)¶
Compute local the E-field gradient at the ROI nodes between the gray and white matter boundary sufaces. Adapted from neuronibs/cortical_layer.py/add_e_field_gradient_between_wm_gm_field
- Parameters:
roi_surf (simnibs.Msh) – The surface object representing the ROI.
mesh (simnibs.Msh) – SimNIBS headmesh.
gm_nodes (np.ndarray, (3, len(roi_surf.nodes))) – For each node of ‘roi_surf’ (representing, e.g., a cortical layer) the corresponding point on the gray matter surface. -> as returned by ‘precompute_geo_info_for_layer_field_interpolation’
wm_nodes (np.ndarray, (3, len(roi_surf.nodes))) – For each node of ‘roi_surf’ (representing, e.g., a cortical layer) the corresponding point on the white matter surface. -> as returned by ‘precompute_geo_info_for_layer_field_interpolation’
gm_center_distance (np.ndarray, (3, len(roi_surf.nodes))) – The distance between the layer nodes and their corresponding point on the gray matter surface. -> as returned by ‘precompute_geo_info_for_layer_field_interpolation’
wm_center_distance (np.ndarray, (3, len(roi_surf.nodes))) – The distance between the layer nodes and their corresponding point on the white matter surface. -> as returned by ‘precompute_geo_info_for_layer_field_interpolation’
- Returns:
e_field_gradient_per_mm – The E-field gradient from the GM to the WM surface normalized to 1 mm with respect to the gray matter thickness. per ROI node
- Return type:
simnibs.mesh.mesh_io.ElementData
- pynibs.util.simnibs.fix_mesh(mesh, verbose=False)¶
Fixes simnibs.Mesh by removing any zero surface tris and zero volume tets and by fixing negative volume tets.
- pynibs.util.simnibs.get_opt_mat(folder, roi=0)¶
Load optimal coil position/orientation matsimnibs from SimNIBS online FEM.
- pynibs.util.simnibs.get_skin_cortex_distance(mesh, coords, radius=5)¶
Computes the skin-cortex distance (SCD).
- Parameters:
- Returns:
SCD (np.ndarray of float) – Skin-cortex distance.
elm_in_roi (np.ndarray of int) – Elelement numbers from mesh.elm.elm_number that where used to calculate PCD for.
- pynibs.util.simnibs.precompute_geo_info_for_layer_field_interpolation(simnibs_mesh, roi)¶
Precomputes geometric properties of the corresponding GM and WM nodes in the ‘simnibs_mesh’ of each node of each layer in
'roi'.The corresponding point on the GM and WM surface to each vertex of te ROI surface are determined (by raycasting and nearest neighbour search as fallback) (interpolation will take place between these nodes)
The nodes are moved inside the gray matter by 20 % of their total distance from the GM/WM boundary to the midlayer.
The distance of the relocated GM and WM nodes to the ROI nodes is determined (required to computed the gradient per mm).
- Parameters:
simnibs_mesh (simnibs.Msh) – The head model volume mesh.
roi (pynibs.roi.RegionOfInterestSurface) – The ROI object containing the layers.
- Returns:
layer_gm_wm_info – For each layer defined in the mesh (outer dict key: layer_id), provide pre-computed geometrical information as a dictionary (outer dict value):
key: gm_nodes For each layer node, the corresponding point on the GM surface.
key: wm_nodes For each layer node, the corresponding point on the WM surface.
key: gm_center_distance The distance between the layer nodes and the corresponding points on the GM.
key: wm_center_distance The distance between the layer nodes and the corresponding points on the WM.
- Return type:
- pynibs.util.simnibs.read_coil_geo(fn_coil_geo)¶
Reads a coil .geo file.
- Parameters:
fn_coil_geo (str) – Filename of .geo file created from SimNIBS containing the dipole information
this (This reads data from lines like) – SP(-5.906416407434245, -56.83325018618547, 104.15283927746198){0.0}; or VP(-70.46122751969759, -68.28080005454271, 29.538763084748382){-0.10087956492712635, 0.0, -0.9948986447775034};
- Returns:
dipole_pos (np.ndarray of float) – (n_dip, 3) Dipole positions
(x, y, z).dipole_mag (np.ndarray of float) – (n_dip, 1) Dipole magnitude.
- pynibs.util.simnibs.smooth_mesh(mesh, output_fn, smooth=0.8, approach='taubin', skin_only_output=False, smooth_tissue='skin')¶
Smoothes the skin compartment of a simnibs mesh. Uses one of three trimesh.smoothing approaches. Because tetrahedra and triangle share the same nodes, this also smoothes the volume domain.
- Parameters:
mesh (str or simnibs.Mesh) –
output_fn (str) –
smooth (float, default: 0.8) – Smoothing aggressiveness.
[0, ..., 1].approach (str, default: 'taubin') – Which smoothing approach to use. One of (
'taubin','laplacian','humphrey'.)smooth_tissue (str or list of int, default: 'skin') – Which tissue type to smooth. E.g.
'gm'or[2, 1002].skin_only_output (bool, default: True) – If true, a skin only mesh is written out instead of the full mesh.
- Returns:
<file> (The smoothed mesh.)
.. figure:: ../../doc/images/smooth_mesh.png – :scale: 50 % :alt: Original and smoothed surfaces and volumes.
Left: original, spiky mesh. Right: smoothed mesh.
pynibs.util.util module¶
- pynibs.util.util.add_center(var)¶
Adds center to argument list.
- pynibs.util.util.bash(command)¶
Executes bash command and returns output message in stdout (uses os.popen).
- Parameters:
command (str) – Bash command.
- Returns:
output (str) – Output from stdout.
error (str) – Error message from stdout.
- pynibs.util.util.bash_call(command)¶
Executes bash command and returns output message in stdout (uses subprocess.Popen).
- Parameters:
command (str) – bash command.
- pynibs.util.util.calc_n_network_combs(n_e, n_c, n_i)¶
Determine number of combinations if all conditions may be replaced between N_i elements (mixed interaction).
- pynibs.util.util.compute_chunks(seq, num)¶
Splits up a sequence _seq_ into _num_ chunks of similar size. If len(seq) < num, (num-len(seq)) empty chunks are returned so that len(out) == num.
- pynibs.util.util.cross_product(A, B)¶
Evaluates the cross product between the vector pairs in a and b using pure Python.
- pynibs.util.util.cross_product_einsum2(a, b)¶
Evaluates the cross product between the vector pairs in a and b using the double Einstein sum.
- pynibs.util.util.differential_evolution(fobj, bounds, mut=0.8, crossp=0.7, popsize=20, its=1000, **kwargs)¶
Differential evolution optimization algorithm
- Parameters:
fobj (function object) – Function to optimize.
bounds (dict) – Dictionary containing the bounds of the free variables to optimize.
mut (float, default: 0.8) – Mutation factor.
crossp (float, default: 0.7) – Cross population factor.
popsize (int, default: 20) – Population size.
its (int, default: 1000) – Number of iterations.
kwargs (dict) – Arguments passed to fobj (constants etc…).
- Returns:
best (dict) – Dictionary containing the best values.
fitness (float) – Fitness value of best solution.
- pynibs.util.util.generalized_extreme_value_distribution(x, mu, sigma, k)¶
Generalized extreme value distribution.
- pynibs.util.util.get_cartesian_product(array_list)¶
Generate a cartesian product of input arrays (all combinations).
cartesian_product = get_cartesian_product(array_list)
- Parameters:
array_list (list of 1D ndarray of float) – Arrays to compute the cartesian product with.
- Returns:
cartesian_product – (M, len(arrays)) Array containing the cartesian products (all combinations of input vectors).
- Return type:
ndarray of float
Examples
- pynibs.util.util.intersection_vec_plan(ray_dir, ray_origin, plane_n, plane_p, eps=1e-06)¶
Computes intersection between vector (‘ray’) and plane.
- Parameters:
ray_dir (np.ndarray) – (3,) (Rotated) vector direction.
ray_origin (np.ndarray) – (3,) Any point on the ray.
plane_n (np.ndarray) – (3,) Plane normal.
plane_p (np.ndarray) – (3,) Any point on the plane.
eps (float, default=1e-6) – Resolution.
- Returns:
inters – (3,) Intersection location. (np.inf, np.inf, np.inf) if no intersection.
- Return type:
np.ndarray
- pynibs.util.util.invert(trans)¶
Invert rotation matrix.
- pynibs.util.util.likelihood_posterior(x, y, fun, bounds=None, verbose=True, normalized_params=False, **params)¶
Determines the likelihood of the data following the function “fun” assuming a two variability source of the data pairs (x, y) using the posterior distribution.
- Parameters:
x (ndarray of float) – (n_points) x data.
y (ndarray of float) – (n_points) y data
fun (function) – Function to fit the data to (e.g. sigmoid).
bounds (dict, optional) – Dictionary containing the bounds of “sigma_x” and “sigma_y” and the free parameters of fun.
verbose (bool, default: True) – Print function output after every calculation.
normalized_params (bool, default: False) – Are the parameters passed in normalized space between [0, 1]? If so, bounds are used to denormalize them before calculation.
**params (dict) – Free parameters to optimize. Contains “sigma_x”, “sigma_y”, and the free parameters of fun.
- Returns:
l – Negative likelihood.
- Return type:
- pynibs.util.util.list2dict(l)¶
Transform list of dicts with same keys to dict of list
- pynibs.util.util.load_muaps(fn_muaps, fs=1000000.0, fs_downsample=100000.0)¶
- pynibs.util.util.mutual_coherence(array)¶
Calculate the mutual coherence of a matrix A. It can also be referred as the cosine of the smallest angle between two columns.
mutual_coherence = mutual_coherence(array)
- pynibs.util.util.norm_percentile(data, percentile)¶
Normalizes data to a given percentile.
- Parameters:
data (np.ndarray) – (n_data, ) Dataset to normalize.
percentile (float) – Percentile of normalization value [0 … 100].
- Returns:
data_norm – (n_data, ) Normalized dataset.
- Return type:
np.ndarray
- pynibs.util.util.rd(array, array_ref)¶
Determine the relative difference between input data and reference data.
- Parameters:
array (np.ndarray) – input data [ (x), y0, y1, y2 … ].
array_ref (np.ndarray) – reference data [ (x_ref), y0_ref, y1_ref, y2_ref … ] if array_ref is 1D, all sizes have to match.
- Returns:
rd – (array.shape[1]) Relative difference between the columns of array and array_ref.
- Return type:
ndarray of float
- pynibs.util.util.recursive_len(item)¶
Determine len of list of lists (recursively).
- pynibs.util.util.sigmoid_log_p(x, p)¶
- pynibs.util.util.tal2mni(coords, direction='tal2mni', style='nonlinear')¶
Transform Talairach coordinates into (SPM) MNI space and vice versa.
This is taken from https://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach and http://gibms.mc.ntu.edu.tw/bmlab/tools/data-analysis-codes/mni2tal-m/
