def make_forest(self): """Output an nipy forest structure to represent the ROI hierarchy. """ if self.k == 0: return None G = Forest(self.k, self.parents) return G
def reduce_to_leaves(self, rid=''): """create a new set of rois which are only the leaves of self """ isleaf = Forest(self.k, self.parents).isleaf() label = self.label.copy() label[isleaf[self.label] == 0] = -1 k = np.sum(isleaf.astype(np.int)) if self.k == 0: return HierarchicalROI(self.domain, label, np.array([]), rid) parents = np.arange(k) nroi = HierarchicalROI(self.domain, label, parents, rid) # now copy the features fids = self.features.keys() for fid in fids: df = [self.features[fid][k] for k in range(self.k) if isleaf[k]] nroi.set_feature(fid, df) return nroi
def select(self, valid, rid='', no_empty_label=True): """ Remove the rois for which valid==0 and update the hierarchy accordingly Note that auto=True automatically """ SubDomains.select(self, valid, rid, True, no_empty_label) if np.sum(valid) == 0: self.parents = np.array([]) else: self.parents = Forest(len(self.parents), self.parents).subforest( valid.astype(np.bool)).parents.astype(np.int)
def select(self, valid, rid='', no_empty_label=True): """Remove rois for which valid == 0 and update the hierarchy accordingly. Parameters ---------- valid: boolean array of shape(self.k) Array defining which regions must be merged. If valid[i] == False, the i_th region is discarded. (fixme: what does this refers to?) Note that auto=True automatically """ SubDomains.select(self, valid, rid, True, no_empty_label) if np.sum(valid) == 0: self.parents = np.array([]) else: self.parents = Forest(len(self.parents), self.parents).subforest( valid.astype(np.bool)).parents.astype(np.int)
def select_roi(self, id_list): """Returns an instance of HROI with only the subset of chosen ROIs. The hierarchy is set accordingly. Parameters ---------- id_list: list of id (any hashable type) The id of the ROI to be kept in the structure. """ valid = np.asarray([int(i in id_list) for i in self.get_id()]) if np.size(id_list) == 0: # handle the case of an empty selection new_parents = np.array([]) self = HierarchicalROI(self.domain, -np.ones(self.label.size), np.array([])) else: # get new parents new_parents = Forest(self.k, self.parents).subforest( valid.astype(np.bool)).parents.astype(np.int) SubDomains.select_roi(self, id_list) self.parents = new_parents self.recompute_labels()
class HierarchicalROI(SubDomains): """Class that handles hierarchical ROIs """ def __init__(self, domain, label, parents, rid=''): """Building the HierarchicalROI """ self.parents = np.ravel(parents).astype(np.int) SubDomains.__init__(self, domain, label, rid) def select(self, valid, rid='', no_empty_label=True): """Remove rois for which valid == 0 and update the hierarchy accordingly. Parameters ---------- valid: boolean array of shape(self.k) Array defining which regions must be merged. If valid[i] == False, the i_th region is discarded. (fixme: what does this refers to?) Note that auto=True automatically """ SubDomains.select(self, valid, rid, True, no_empty_label) if np.sum(valid) == 0: self.parents = np.array([]) else: self.parents = Forest(len(self.parents), self.parents).subforest( valid.astype(np.bool)).parents.astype(np.int) def make_graph(self): """Output an fff.graph structure to represent the ROI hierarchy """ if self.k == 0: return None weights = np.ones(self.k) edges = (np.vstack((np.arange(self.k), self.parents))).T return WeightedGraph(self.k, edges, weights) def make_forest(self): """Output an fff.forest structure to represent the ROI hierarchy """ if self.k == 0: return None G = Forest(self.k, self.parents) return G def merge_ascending(self, valid): """Remove the non-valid ROIs by including them in their parents when it exists. Parameters ---------- valid: boolean array of shape(self.k) Array defining which regions must be merged. If valid[i] == False, the i_th region is merged in its parent. Note ---- If valid[k]==0 and self.parents[k]==k, k is not removed """ if np.size(valid) != self.k: raise ValueError("not the correct dimension for valid") if self.k == 0: return order = self.make_forest().reorder_from_leaves_to_roots() for j in order: if valid[j] == 0: fj = self.parents[j] if fj != j: self.parents[self.parents == j] = fj self.label[self.label == j] = fj fids = self.features.keys() for fid in fids: dfj = self.features[fid][fj] dj = self.features[fid][j] if len(dfj.shape) == 1: dfj = dfj.reshape((-1, 1)) if len(dj.shape) == 1: dj = dj.reshape((-1, 1)) self.features[fid][fj] = np.concatenate( (np.ravel(dfj), np.ravel(dj))) else: valid[j] = 1 self.select(valid) def merge_descending(self, methods=None): """ Remove the items with only one son by including them in their son Parameters ---------- methods indicates the way possible features are dealt with (not implemented yet) Caveat ------ if roi_features have been defined, they will be removed """ if self.k == 0: return valid = np.ones(self.k).astype('bool') order = self.make_forest().reorder_from_leaves_to_roots()[:: - 1] for j in order: i = np.nonzero(self.parents == j) i = i[0] if np.sum(i != j) == 1: i = int(i[i != j]) self.parents[i] = self.parents[j] self.label[self.label == j] = i valid[j] = 0 fids = self.features.keys() for fid in fids: di = self.features[fid][i] dj = self.features[fid][j] self.features[fid][i] = np.concatenate( (np.ravel(di), np.ravel(dj))) # finally remove the non-valid items self.select(valid) def get_parents(self): return self.parents def get_k(self): return self.k def isleaf(self): """ """ if self.k == 0: return np.array([]) return Forest(self.k, self.parents).isleaf() def reduce_to_leaves(self, rid=''): """Create a new set of rois which are only the leaves of self """ if self.k == 0: return HierarchicalROI( self.domain, -np.ones(self.domain.size), np.array([]), rid) isleaf = Forest(self.k, self.parents).isleaf() label = self.label.copy() label[isleaf[self.label] == 0] = -1 k = np.sum(isleaf.astype(np.int)) parents = np.arange(k) nroi = HierarchicalROI(self.domain, label, parents, rid) # now copy the features fids = self.features.keys() for fid in fids: df = [self.features[fid][k] for k in range(self.k) if isleaf[k]] nroi.set_feature(fid, df) return nroi def copy(self, rid=''): """ Returns a copy of self. self.domain is not copied. """ cp = make_hroi_from_subdomain(SubDomains.copy(self, rid), self.parents.copy()) return cp def representative_feature(self, fid, method='mean'): """Compute an ROI-level feature given the discrete features Parameters ---------- fid: str, The discrete feature under consideration. method: str, The assessment method. Values can be: - 'mean' (default) - 'min' - 'max' - 'cumulated mean' - 'median' - 'weighted mean' Returns ------- The computed roi-feature is returned """ if method not in['min', 'max', 'mean', 'cumulated mean', 'median', 'weighted mean']: raise ValueError('unknown method') if method == 'cumulated mean': data = self.features[fid] d0 = data[0] if np.size(d0) == np.shape(d0)[0]: np.reshape(d0, (np.size(d0), 1)) fdim = d0.shape[1] ldata = np.zeros((self.k, fdim)) for k in range(self.k): dk = self.make_forest().get_descendents(k) card = np.sum(self.get_size()[dk]) for ch in dk: ldata[k] += np.sum(data[ch], 0) ldata[k] /= card self.set_roi_feature(fid, ldata) else: ldata = SubDomains.representative_feature(self, fid, method) return ldata