def compute_centroids(patient): """Function for computing per-class centroid of a patient. This function takes a Patient object as an argument and, using its corresponding labelmap(s) [TODO: support multiple labelmaps], extracts centroid information for each class. This centroid information comes in three flavors, each an element of the corresponding label's dict: * 'voxel': centroid given as index of voxel * 'real': centroid given as real position in mm * 'relative': voxel centroid normalized in the volume Attributes ---------- patient : :obj:`Patient` Patient object to extract centroid from. Returns ------- centroids : `dict` dict of centroid information, keyed by label """ # Acquiring the first labelmap of the patient (TODO: multiple labelmap support) labelmap = next(iter(patient.labelmaps.values())) #patient.labelmaps['t2'] volume = next(iter(patient.volumes.values())) #patient.volumes['t2'] # get sorted labels and center-of-mass for each label labels = np.unique(labelmap.data) centers_of_mass = measure_center_of_mass(np.ones_like(labelmap.data), labels=labelmap.data, index=labels) # building centroid attribute list centroids = {} for label, centroid in zip(labels, centers_of_mass): centroids[label] = { "voxel": list(centroid), "real": [(centroid[i] * volume.header["spacings"][i]) + volume.header["initial_position"][i] for i in range(len(centroid))], "relative": [centroid[i] / volume.data.shape[i] for i in range(len(centroid))] } # normalize to mean 0, stddev 1 for flavor in ["voxel", "real", "relative"]: for index in range(3): mean, stddev = np.mean([ element[flavor][index] for element in centroids.values() ]), np.std( [element[flavor][index] for element in centroids.values()]) for element in centroids.values(): element[flavor][index] = (element[flavor][index] - mean) / stddev return centroids
def compute_centroids(volume, labelmap, specific_label=None): """Computes centroids for each label in a volume. Returns ------- centroids : `2darray` Array with `num_labels` lines and 3 columns. Each line contains the normalized, real x, y, and z of each label. """ # get sorted labels and center-of-mass for each label if specific_label is None: labels = np.unique(labelmap.data) centroids = measure_center_of_mass(np.ones_like(labelmap.data), labels=labelmap.data, index=labels) else: # specific label only centroids = measure_center_of_mass(labelmap.data == specific_label) centroids = np.array(centroids) # multiply voxel value by voxel size to get real centroid centroids *= volume.header["spacings"] return centroids
def compute_attributes(volume, labelmap, attribute): """Computes an specific attribute for an entire volume""" if attribute == "centroid": labels = np.unique(labelmap) centroids = measure_center_of_mass(np.ones_like(labelmap), labels=labelmap, index=labels) centroids = np.array(centroids) return centroids elif attribute == "intensity": labels, indexes = np.unique(labelmap, return_inverse=True) intensities = np.empty(len(labels)) for i, label in enumerate(labels): intensities[i] = np.mean(volume.flatten()[indexes==i]) return intensities elif attribute == "size": labels,voxel_count_per_labels = np.unique(labelmap, return_counts=True) sizes = voxel_count_per_labels return sizes else: raise Exception("{} is not a supported attribute".format(attribute))