def parcellation_dist(p1, p2, mask=None): """ Compute the distance between the two parcellation p1 and p2 as the minimum number of positions to remove in order to obtain equal partitions. "mask" may be a binary mask to limit the distance computation to some specific positions. Important convention: parcel label 0 is treated as background and corresponding positions are discarded if no mask is provided. Return: (distance value, parcellation overlap) """ assert np.issubdtype(p1.dtype, np.int) assert np.issubdtype(p2.dtype, np.int) assert p1.shape == p2.shape from munkres import Munkres if mask is None: mask = (p1 != 0) m = np.where(mask) pyhrf.verbose(6,'Nb pos inside mask: %d' %len(m[0])) fp1 = p1[m].astype(np.int32) fp2 = p2[m].astype(np.int32) # allocate cost matrix, assume that region labels are contiguous # ie all labels in [1, label_max] are represented cost_matrix = np.zeros((fp1.max()+1, fp2.max()+1), dtype=np.int32) pyhrf.verbose(6,'Cost matrix : %s' %str(cost_matrix.shape)) compute_intersection_matrix(fp1, fp2, cost_matrix) # discard 0-labelled parcels (background) cost_matrix = cost_matrix[1:,1:] # solve the assignement problem: indexes = np.array(Munkres().compute((cost_matrix*-1).tolist())) if 0: print 'assignement indexes:' print indexes print '->' print (indexes[:,0], indexes[:,1]) print cost_matrix[(indexes[:,0], indexes[:,1])] assignement = cost_matrix[(indexes[:,0], indexes[:,1])].sum() to_keep = np.zeros_like(fp1) for s1, s2 in indexes: to_keep += np.bitwise_and(fp1==(s1+1), fp2==(s2+1)) return fp1.size - assignement, expand_array_in_mask(to_keep, mask)
def parcellation_dist(p1, p2, mask=None): """ Compute the distance between the two parcellation p1 and p2 as the minimum number of positions to remove in order to obtain equal partitions. "mask" may be a binary mask to limit the distance computation to some specific positions. Important convention: parcel label 0 is treated as background and corresponding positions are discarded if no mask is provided. Return: (distance value, parcellation overlap) """ assert np.issubdtype(p1.dtype, np.int) assert np.issubdtype(p2.dtype, np.int) assert p1.shape == p2.shape from munkres import Munkres if mask is None: mask = (p1 != 0) m = np.where(mask) logger.debug('Nb pos inside mask: %d', len(m[0])) fp1 = p1[m].astype(np.int32) fp2 = p2[m].astype(np.int32) # allocate cost matrix, assume that region labels are contiguous # ie all labels in [1, label_max] are represented cost_matrix = np.zeros((fp1.max() + 1, fp2.max() + 1), dtype=np.int32) logger.debug('Cost matrix : %s', str(cost_matrix.shape)) compute_intersection_matrix(fp1, fp2, cost_matrix) # discard 0-labelled parcels (background) cost_matrix = cost_matrix[1:, 1:] # solve the assignement problem: indexes = np.array(Munkres().compute((cost_matrix * -1).tolist())) if 0: print 'assignement indexes:' print indexes print '->' print(indexes[:, 0], indexes[:, 1]) print cost_matrix[(indexes[:, 0], indexes[:, 1])] assignement = cost_matrix[(indexes[:, 0], indexes[:, 1])].sum() to_keep = np.zeros_like(fp1) for s1, s2 in indexes: to_keep += np.bitwise_and(fp1 == (s1 + 1), fp2 == (s2 + 1)) return fp1.size - assignement, expand_array_in_mask(to_keep, mask)
def test_intersection_matrix(self): from pyhrf.cparcellation import compute_intersection_matrix im = np.zeros((self.fp1.max() + 1, self.fp2.max() + 1), dtype=np.int32) compute_intersection_matrix(self.fp1, self.fp2, im) assert_array_equal(im, np.array([[0, 0, 0, 0], [0, 2, 1, 2], [0, 0, 5, 1], [0, 0, 0, 3]], dtype=np.int32), "Intersection graph not OK", 1)