Coverage for nilearn/plotting/matrix/_utils.py: 0%
56 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-20 10:58 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-20 10:58 +0200
1from warnings import warn
3import numpy as np
4from scipy.cluster.hierarchy import leaves_list, linkage, optimal_leaf_ordering
6from nilearn._utils.logger import find_stack_level
7from nilearn.glm.contrasts import expression_to_contrast_vector
9VALID_REORDER_VALUES = (True, False, "single", "complete", "average")
10VALID_TRI_VALUES = ("full", "lower", "diag")
13def mask_matrix(mat, tri):
14 """Help for plot_matrix.
16 This function masks the matrix depending on the provided
17 value of ``tri``.
18 """
19 if tri == "lower":
20 mask = np.tri(mat.shape[0], k=-1, dtype=bool) ^ True
21 else:
22 mask = np.tri(mat.shape[0], dtype=bool) ^ True
23 return np.ma.masked_array(mat, mask)
26def pad_contrast_matrix(contrast_def, design_matrix):
27 """Pad contrasts with zeros.
29 Parameters
30 ----------
31 contrast_def : :class:`numpy.ndarray`
32 Contrast to be padded
34 design_matrix : :class:`pandas.DataFrame`
35 Design matrix to use.
37 Returns
38 -------
39 axes : :class:`numpy.ndarray`
40 Padded contrast
42 """
43 design_column_names = design_matrix.columns.tolist()
44 if isinstance(contrast_def, str):
45 contrast_def = expression_to_contrast_vector(
46 contrast_def, design_column_names
47 )
48 n_columns_design_matrix = len(design_column_names)
49 n_columns_contrast_def = (
50 contrast_def.shape[0]
51 if contrast_def.ndim == 1
52 else contrast_def.shape[1]
53 )
54 horizontal_padding = n_columns_design_matrix - n_columns_contrast_def
55 if horizontal_padding == 0:
56 return contrast_def
57 warn(
58 (
59 f"Contrasts will be padded with {horizontal_padding} "
60 "column(s) of zeros."
61 ),
62 category=UserWarning,
63 stacklevel=find_stack_level(),
64 )
65 contrast_def = np.pad(
66 contrast_def,
67 ((0, 0), (0, horizontal_padding)),
68 "constant",
69 constant_values=(0, 0),
70 )
71 return contrast_def
74def sanitize_labels(mat_shape, labels):
75 """Help for plot_matrix."""
76 # we need a list so an empty one will be cast to False
77 if isinstance(labels, np.ndarray):
78 labels = labels.tolist()
79 if labels and len(labels) != mat_shape[0]:
80 raise ValueError(
81 f"Length of labels ({len(labels)}) "
82 f"unequal to length of matrix ({mat_shape[0]})."
83 )
84 return labels
87def sanitize_reorder(reorder):
88 """Help for plot_matrix."""
89 if reorder not in VALID_REORDER_VALUES:
90 param_to_print = []
91 for item in VALID_REORDER_VALUES:
92 if isinstance(item, str):
93 param_to_print.append(f'"{item}"')
94 else:
95 param_to_print.append(str(item))
96 raise ValueError(
97 "Parameter reorder needs to be one of:"
98 f"\n{', '.join(param_to_print)}."
99 )
100 reorder = "average" if reorder is True else reorder
101 return reorder
104def sanitize_tri(tri, allowed_values=None):
105 """Help for plot_matrix."""
106 if allowed_values is None:
107 allowed_values = VALID_TRI_VALUES
108 if tri not in allowed_values:
109 raise ValueError(
110 f"Parameter tri needs to be one of: {', '.join(allowed_values)}."
111 )
114def reorder_matrix(mat, labels, reorder):
115 """Help for plot_matrix.
117 This function reorders the provided matrix.
118 """
119 if not labels:
120 raise ValueError("Labels are needed to show the reordering.")
122 linkage_matrix = linkage(mat, method=reorder)
123 ordered_linkage = optimal_leaf_ordering(linkage_matrix, mat)
124 index = leaves_list(ordered_linkage)
125 # make sure labels is an ndarray and copy it
126 labels = np.array(labels).copy()
127 mat = mat.copy()
128 # and reorder labels and matrix
129 labels = labels[index].tolist()
130 mat = mat[index, :][:, index]
131 return mat, labels