@@ -33,7 +33,9 @@ def get_maximas(data, sphere, b_matrix, threshold, absolute_threshold,
3333 spherical_func = np .dot (data , b_matrix .T )
3434 spherical_func [np .nonzero (spherical_func < absolute_threshold )] = 0.
3535 return peak_directions (
36- spherical_func , sphere , threshold , min_separation_angle )
36+ spherical_func , sphere ,
37+ relative_peak_threshold = threshold ,
38+ min_separation_angle = min_separation_angle )
3739
3840
3941def get_sphere_neighbours (sphere , max_angle ):
@@ -57,3 +59,68 @@ def get_sphere_neighbours(sphere, max_angle):
5759 np .outer (zs , zs ))
5860 neighbours = scalar_prods >= np .cos (max_angle )
5961 return neighbours
62+
63+
64+ def is_data_peaks (img_data ):
65+ """
66+ Heuristic to find out if the input are peaks or fodf.
67+ fodf are always around 0.15 and peaks around 0.75.
68+ Peaks have more zero values than fodf. The first value of fodf is
69+ usually the highest.
70+
71+ Parameters
72+ ----------
73+ img_data : np.ndarray
74+ 4D image data where the last dimension contains directional info.
75+
76+ Returns
77+ -------
78+ is_peaks : bool
79+ True if data is likely peaks, False if likely fODF (SH).
80+ """
81+ last_dim = img_data .shape [- 1 ]
82+ if last_dim == 3 :
83+ return True
84+
85+ # Sum of absolute values to detect non-zero voxels correctly
86+ non_zeros_mask = np .any (np .abs (img_data ) > 0 , axis = - 1 )
87+ if not np .count_nonzero (non_zeros_mask ):
88+ return False
89+
90+ try :
91+ order , full = get_sh_order_and_fullness (last_dim )
92+ # Symmetric SH must be even order
93+ if not full and order % 2 != 0 :
94+ return False
95+ except ValueError :
96+ # If not a valid SH number of coefficients, and not 3,
97+ # it might be something else, but if it's a multiple of 3
98+ # it's likely Peaks.
99+ if last_dim % 3 == 0 :
100+ return True
101+ return False
102+
103+ data_nz = img_data [non_zeros_mask ]
104+
105+ # If all triplets have the same norm, it is likely peaks, otherwise SH.
106+ if last_dim % 3 == 0 :
107+ norm = np .linalg .norm (data_nz .reshape (- 1 , 3 ), axis = - 1 )
108+ if np .all (np .isclose (norm , norm [0 ])):
109+ return True
110+
111+ # If the max is in the first triplet but not at index 0, it's likely Peaks.
112+ # Smoothed SH almost always has max at index 0
113+ argmax_indices = np .argmax (np .abs (data_nz ), axis = - 1 )
114+ if last_dim % 3 == 0 and \
115+ np .mean (np .logical_or (argmax_indices == 1 ,
116+ argmax_indices == 2 )) > 0.1 :
117+ return True
118+
119+ # Exact zeros. SH almost never has exact zeros in real data.
120+ # Peaks often have exact zeros for unused lobes
121+ zero_ratio = np .mean (data_nz == 0 )
122+ if zero_ratio > 0.05 :
123+ return True
124+
125+ # Default to SH
126+ return False
0 commit comments