def isneginf(x, y=None): """Return a boolean array y with y[i] True for x[i] = -Inf. If y is an array, the result replaces the contents of y. """ if y is None: x = asarray(x) y = empty(x.shape, dtype=nx.bool_) umath.logical_and(isinf(x), signbit(x), y) return y
def label_region(self, regionMask, regionIndex, imageData, k, queryMaskDict=None, spatialInfo=None, dtLabels=None, preEdtErosion=0, useQueryMaskOnAtlases=False, dtSeeds=None, overallMask=None, spatialRegionLabels=None, numProcessors=8): if queryMaskDict is not None: newQueryDict = dict((label, logical_and(queryMaskDict[label], regionMask)) for label in queryMaskDict) else: newQueryDict = {1: regionMask} return self.saps.label_image(imageData, k, self.regionalAtlasDict[regionIndex], queryMaskDict=newQueryDict, spatialInfo=spatialInfo, dtLabels=dtLabels, preDtErosion=preEdtErosion, spatialRegionIndex=regionIndex, useQueryMaskOnAtlases=useQueryMaskOnAtlases, dtSeeds=dtSeeds, overallMask=overallMask, spatialRegionLabels=spatialRegionLabels, numProcessors=numProcessors)
def make_random_split(self, source_value, target_value, absolute_per_class=1, relative_per_class=0): # if num_test is None and num_train is None and percentage_train is None: # logging.error("Your need to provide at lease on of the parameters num_train, num_test or percentage_train!") # raise Exception # if num_train is not None and num_test is not None: # logging.error("You can only specify either num_train or num_test!") # raise Exception if source_value not in self.split_assignments: logging.warning( "No element with value 'source_value' in self.split_assignments!" ) if absolute_per_class < 1: logging.error("Invalid value for parameter absolute_per_class.") raise Exception if relative_per_class > 1 or relative_per_class < 0: logging.error("Invalid value for parameter relative_per_class.") raise Exception self.split_assignments = array(self.split_assignments) # for all classes classes = unique(self.labels) for c in classes: class_elements = where( logical_and( transpose(array(self.labels)[newaxis]) == c, transpose(array( self.split_assignments)[newaxis]) == source_value))[0] if len(class_elements) <= absolute_per_class: self.split_assignments[class_elements] = target_value else: how_many = max(absolute_per_class, int(relative_per_class * len(class_elements))) self.split_assignments[permutation(class_elements) [:how_many]] = target_value
def get_patch_dict(self, patchSize, spatialWeight=0, boundaryDilation=None, spatialRegionLabels=None, spatialRegionIndex=None, spatialLabels=None, dtSeeds=None, labelErosion=0, boundaryClipSize=0, spatialInfoType=EDT, roiMask=None, separateSpatial=False, includePatchSizeKey=False): """ @param patchSize: int or tuple to determine size of patch. if int, assume isotropic @param spatialWeight: spatial weighting to apply if using spatial info @param boundaryDilation: boundary around labels (if getting boundary refinement patches) @param spatialRegionIndex: (index of region -> indexed by edt labels) or counts from 0 if spatial labels not provided @param spatialLabels: labels to use to get edt/gdt based spatial info, if none @param labelErosion: @param boundaryClipSize: @param roiMask: @return: a dictionary of {label: patches} """ imageData = self._get_image_data() labelsData = open_image(self.labelsPath) # put check in that transformed atlas actually overlaps if labelsData.max() == 0: return None elif spatialLabels is not None: uniqueLabels = numpy.unique(labelsData) if set(uniqueLabels).intersection(set(spatialLabels)) == set(): return None voxelSize = self._get_dt_voxel_size() getBoundaryPatches = roiMask is None if self.imageExpand: try: boundaryClipSize -= 1 except TypeError: boundaryClipSize = numpy.asarray(boundaryClipSize) - 1 spatialLabelDict = None spatialData = None # get spatial information if spatialWeight > 0 and spatialInfoType is not None: if spatialInfoType in GENERIC_SPATIAL_INFO_TYPES: spatialData = get_generic_spatial_info(imageData, spatialInfoType) else: if dtSeeds is not None: dtLabelsData = dtSeeds else: dtLabelsData = labelsData if self.dtLabelsPath is not None: dtLabelsData = open_image(self.dtLabelsPath) if dtLabelsData.shape != labelsData.shape: dtLabelsData = interpolate_to_shape( dtLabelsData, labelsData.shape) dtImage = self._get_dt_image_data(spatialInfoType, imageData) spatialLabelDict = get_dt_spatial_context_dict( dtLabelsData, spatialInfoType, spatialLabels=spatialLabels, voxelSize=voxelSize, labelErosion=labelErosion, boundaryClipSize=boundaryClipSize, imageData=dtImage, is2D=self.is2D, imageExpand=self.imageExpand) spatialData = spatialLabelDict.values() spatialData = numpy.asarray(spatialData) * spatialWeight # get regional mask if roiMask is not None: roiMask = interpolate_to_shape(roiMask, imageData.shape) if spatialRegionIndex is not None: if spatialRegionLabels is None: spatialRegionLabels = spatialLabels if spatialLabelDict is None: dtImage = self._get_dt_image_data(spatialInfoType, imageData) dtLabelsData = labelsData if self.dtLabelsPath is not None: dtLabelsData = open_image(self.dtLabelsPath) spatialLabelDict = get_dt_spatial_context_dict( dtLabelsData, spatialInfoType, spatialLabels=spatialLabels, voxelSize=voxelSize, labelErosion=labelErosion, boundaryClipSize=boundaryClipSize, imageData=dtImage, is2D=self.is2D, imageExpand=self.imageExpand) regionMask = region_dict_from_dt_dict( dict((l, spatialLabelDict[l]) for l in spatialRegionLabels), regionalOverlap=boundaryDilation, specificRegionIndex=spatialRegionIndex, is2D=self.is2D) if roiMask is None: roiMask = regionMask else: roiMask = logical_and(roiMask, regionMask) # get overall label and data masks if self.specificLabels is None: self.specificLabels = numpy.unique(labelsData) if self.boundaryLabels is None: self.boundaryLabels = auto_non_background_labels(labelsData) if self.imageExpand: labelsData = image_boundary_expand(labelsData, useGradient=False, is2D=self.is2D) labelMasks = mask.get_label_masks(labelsData, self.specificLabels) boundarySize = boundaryDilation if not getBoundaryPatches: boundarySize = None maskData = mask.get_data_mask(imageData, labelsData, boundarySize=boundarySize, specificLabels=self.boundaryLabels, roiMask=roiMask, minValue=self.minValue, maxValue=self.maxValue) if maskData is not None: labelMasks = [logical_and(m, maskData) for m in labelMasks] if self.rescaleIntensities: imageData = rescale_data(imageData, maskData=maskData) patchDict = dict((self.specificLabels[i], get_patches(imageData, patchSize, labelMasks[i], spatialData=spatialData, separateSpatial=separateSpatial)) for i in xrange(len(labelMasks))) if includePatchSizeKey: patchDict["patchSize"] = patchSize return patchDict
def label_image(self, imageData, k, atlases, queryMaskDict=None, spatialInfo=None, dtLabels=None, preDtErosion=0, spatialRegionIndex=None, useQueryMaskOnAtlases=False, dtSeeds=None, overallMask=None, spatialRegionLabels=None, numProcessors=8): """ @return results: labels of same shape/size as imageData: note if imageExpand, will need to modify @param imageData: image data to query @param k: number of nearest neighbours to search from atlases @param atlases: atlases (file names) to use for labelling @param queryMaskDict: dictionary of (label, mask) indicating which labels can be queried for at each location including background label. The union of masks defines total query mask - if None is given, all labels will be searched for at all locations - if a dictionary with a single (label, mask) is given, all labels will be search for within the mask - assume masks are same shape as image Data @param spatialInfo: list or array of 3D spatial info (assume it is unweighted) @param dtLabels: labels to get DT-spatial info for in atlases @param preDtErosion: specify any erosion of labels before atlases @param spatialRegionIndex: index (dt label) when using dts to define region (valid if not useQueryMaskOnAtlases) @param useQueryMaskOnAtlases: apply the queryMask to atlases as well as target image (regions no longer defined by edtRegionIndex) - requires image registration @param numProcessors: number of processors to use """ print "[INFO]--->Number of atlases to use:", len(atlases) print "[INFO]--->SpatialWeight:", self.spatialWeight locationModifier = numpy.int16(numpy.asarray(self.patchSize) / 2) print "[INFO]--->TargetImage Shape:", imageData.shape # setup spatial info if self.spatialInfoType is None or self.spatialWeight is None or self.spatialWeight == 0: spatialInfo = None else: if spatialInfo is None: if self.spatialInfoType in patchmaker.GENERIC_SPATIAL_INFO_TYPES: print "Getting initial spatial information..." spatialInfo = spatialcontext.get_generic_spatial_info(imageData, self.spatialInfoType) elif self.spatialInfoType in spatialcontext.SPATIAL_INFO_TYPES: raise Exception("No spatial info provided") spatialInfo = numpy.asarray(spatialInfo, numpy.float) * self.spatialWeight # initialise masks, indices queryMask = None patchesMask = get_min_max_mask(imageData, minValue=self.minValue, maxValue=self.maxValue) labelsIndices = None if queryMaskDict is not None: if not isinstance(queryMaskDict, dict): # bit hacky - make into a dictionary queryMaskDict = {1: queryMaskDict} if patchesMask is not None: patchesMask = logical_and(union_masks(queryMaskDict.values()), patchesMask) else: patchesMask = union_masks(queryMaskDict.values()) # cannot query boundary of image if not big enough for a patch patchesMask = zero_out_boundary(patchesMask, locationModifier) locationList = numpy.atleast_2d(numpy.squeeze(numpy.transpose(numpy.nonzero(patchesMask)))) locationList = list(locationList) if useQueryMaskOnAtlases: queryMask = patchesMask spatialRegionIndex = None if overallMask is not None and self.boundaryDilation > 0: queryMask = dilate_mask(queryMask, self.boundaryDilation) queryMask = logical_and(overallMask, queryMask) # get labelIndices if len(queryMaskDict.keys()) > 1: labelsIndices = dict() for i in xrange(len(locationList)): for label in queryMaskDict: if queryMaskDict[label][tuple(locationList[i])]: try: labelsIndices[label].append(i) except KeyError: labelsIndices[label] = deque([i]) for label in labelsIndices: labelsIndices[label] = numpy.asarray(labelsIndices[label]) else: if patchesMask is not None: patchesMask = zero_out_boundary(patchesMask, locationModifier) else: patchesMask = zero_out_boundary(numpy.ones(imageData.shape, numpy.bool), locationModifier) locationList = numpy.atleast_2d(numpy.squeeze(numpy.transpose(numpy.nonzero(patchesMask)))) locationList = list(locationList) numQueryLocations = len(locationList) print "Num Query Locations:", numQueryLocations # create patches print "Creating patches..." patches = patchmaker.get_patches(imageData, self.patchSize, maskData=patchesMask, spatialData=spatialInfo) consumerObj = DictResultsSorter(k, non_local_means_presq, labelsIndices, numQueryLocations) print "Searching..." results = multi_process_list_with_consumer(atlases, self.query_worker, consumerObj, min(MAX_JOBS, numProcessors), patches, labelsIndices, k, queryMask, self.boundaryDilation, spatialRegionIndex, spatialRegionLabels, dtLabels, preDtErosion, dtSeeds) print "Processing distances..." # results = consumerObj.results() results = arrange_results_by_location(results, locationList, imageData.shape) # Remove and clear loaded trees to clear memory return results