pynibs.util package¶
Submodules¶
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 [3]) – Coordinates of the hotspot in the first c-map
t2 (np.ndarray of float [3]) – Coordinates of the hotspot in the second c-map
nodes (np.ndarray of float [n_nodes x 3]) – Node coordinates
tris (np.ndarray of float [n_tris x 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 onskin_cortex_distance
as a proxy for the (local) change of the stimulation.delta_pos
anddelta_rot
are expected to quantify motion w.r.t. the target coil position/roation, for example the absolute deltas to the first stimulation.Example
# get TriggerMarkers from a Localite session mats = pynibs.read_triggermarker_localite(tm_fn)[0] # calculate absolute and relative coil displacements delta_pos_abs, delta_rot_abs, delta_pos_rel, delta_rot_rel = pynibs.calc_tms_motion_params(mats) # Compute PCD pcd, delta_pos, delta_rot = pynibs.compute_pcd(delta_pos_abs, delta_rot_abs) # plot movement axes = pynibs.plot_tms_motion_parameter(pos_diff_rel, euler_rots_rel, pcd) matplotlib.pyplot.show()
- Parameters:
delta_pos (np.ndarray) – (3, n_pulses) Absolute position differences (R, A, S).
delta_rot (np.ndarray) – (3, n_pulses) Absolute rotation angles in euler angles (alpha, beta, gamma).
skin_cortex_distance (int, default: 20) – Cortical depth of target to adjust coil rotations for.
- Returns:
pcd (np.ndarray) – Pulsewise coil displacements.
delta_pos (np.ndarray) – (n_pulses, ) sum(abs(delta_pos)) per pulse.
delta_rot (np.ndarray) – (n_pulses, ) sum(abs(delta_rot projected by skin_cortex_distance)) per pulse.
- pynibs.util.quality_measures.euclidean_dist(nodes, tris, source, source_is_node=True)¶
Returns euclidean_dist distance of all nodes to source node (tria).
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)
- pynibs.util.quality_measures.geodesic_dist(nodes, tris, source, source_is_node=True)¶
Returns geodesic distance of all nodes to source node (or tri).
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:
- Returns:
nodes_dist (np.ndarray(n_nodes,))
tris_dist (np.ndarray(n_tris,))
- 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.
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.
- 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¶
- pynibs.util.rotations.bases2rotmat(v1, v2)¶
Computes roation 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 [3]) – Euler angles in rad
- Returns:
r – Rotation matrix (z, y’, x’’)
- Return type:
np.ndarray [3 x 3]
- 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 –
q2 –
- Returns:
- Return type:
- pynibs.util.rotations.quaternion_inverse(q)¶
https://stackoverflow.com/questions/15425313/inverse-quaternion
- Parameters:
q –
- Returns:
- Return type:
- pynibs.util.rotations.roatate_matsimnibs_euler(axis, angle, matsimnibs, metric='rad')¶
Rotates a matsimnibs matrix around
axis
byangle
- Parameters:
- Returns:
rotated_matsimnibs – (4, 4) Rotated system.
- Return type:
np.ndarray
- pynibs.util.rotations.rot_to_quat(rot)¶
Computes the quaternions from rotation matrix. (see e.g. http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/)
- 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.array [3 x 3]) – Rotation matrix (z, y’, x’’)
- Returns:
theta – Euler angles in rad
- Return type:
np.array [3]
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).
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]]) –
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
- 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.
- Parameters:
A (np.ndarray of float 2 x [N x 3]) –
B (np.ndarray of float 2 x [N x 3]) – Input vectors, the cross product is evaluated between
- Returns:
c – Cross product between vector pairs in a and b
- Return type:
np.ndarray of float [N x 3]
- 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.
- Parameters:
a (np.ndarray of float 2 x [N x 3]) –
b (np.ndarray of float 2 x [N x 3]) – Input vectors, the cross product is evaluated between
- Returns:
c – Cross product between vector pairs in a and b
- Return type:
np.ndarray of float [N x 3]
- 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) – Mutation factor
crossp (float) – Cross population factor
popsize (int) – Population size
its (int) – 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 – Array containing the cartesian products (all combinations of input vectors) (M, len(arrays))
- Return type:
ndarray of float
Examples
>>> import pygpc >>> out = pygpc.get_cartesian_product(([1, 2, 3], [4, 5], [6, 7])) >>> out
- 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, default: None) – 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 – Normalized dataset
- Return type:
np.ndarray [n_data, ]
- 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 – Relative difference between the columns of array and array_ref
- Return type:
ndarray of float [array.shape[1]]
- 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/