def test_distance_source(self): """ (SourceComparison) distance to source """ s1 = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) s2 = Source([[20, 20], [20, 30]], values=[1.0, 2.0]) assert (s1.distance(s2) == sqrt(200))
def test_distance_array(self): """ (SourceComparison) distance to array """ s1 = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert(s1.distance([20, 25]) == sqrt(200)) assert(s1.distance(array([20, 25])) == sqrt(200))
def test_distance_array(self): """ (SourceComparison) distance to array """ s1 = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (s1.distance([20, 25]) == sqrt(200)) assert (s1.distance(array([20, 25])) == sqrt(200))
def test_distance_source(self): """ (SourceComparison) distance to source """ s1 = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) s2 = Source([[20, 20], [20, 30]], values=[1.0, 2.0]) assert(s1.distance(s2) == sqrt(200))
def test_to_array(self): """ (SourceConversion) to array """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (isinstance(s.toarray().center, ndarray)) assert (isinstance(s.tolist().toarray().center, ndarray)) assert (isinstance(s.tolist().toarray().bbox, ndarray))
def test_to_array(self): """ (SourceConversion) to array """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert(isinstance(s.toarray().center, ndarray)) assert(isinstance(s.tolist().toarray().center, ndarray)) assert(isinstance(s.tolist().toarray().bbox, ndarray))
def test_to_list(self): """ (SourceConversion) to list """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) getattr(s, "center") assert (isinstance(s.tolist().center, list)) getattr(s, "bbox") assert (isinstance(s.tolist().bbox, list))
def test_to_list(self): """ (SourceConversion) to list """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) getattr(s, "center") assert(isinstance(s.tolist().center, list)) getattr(s, "bbox") assert(isinstance(s.tolist().bbox, list))
def test_min(self): """ (BasicCleaner) min area """ list1 = [Source(random.randn(20, 2)) for _ in range(10)] list2 = [Source(random.randn(5, 2)) for _ in range(20)] sources = list1 + list2 model = SourceModel(sources) c = BasicCleaner(minArea=10) newmodel = model.clean(c) assert (len(newmodel.sources) == 10)
def test_min_max(self): """ (BasicCleaner) min and max area """ list1 = [Source(random.randn(20, 2)) for _ in range(10)] list2 = [Source(random.randn(10, 2)) for _ in range(20)] list3 = [Source(random.randn(15, 2)) for _ in range(5)] sources = list1 + list2 + list3 model = SourceModel(sources) c = BasicCleaner(minArea=11, maxArea=19) newmodel = model.clean(c) assert (len(newmodel.sources) == 5)
def test_merge(self): """ (SourceMethods) merge """ s1 = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) s2 = Source([[10, 30], [10, 40]], values=[4.0, 5.0]) s1.merge(s2) assert(array_equal(s1.coordinates, [[10, 10], [10, 20], [10, 30], [10, 40]])) assert(array_equal(s1.values, [1.0, 2.0, 4.0, 5.0])) s1 = Source([[10, 10], [10, 20]]) s2 = Source([[10, 30], [10, 40]]) s1.merge(s2) assert(array_equal(s1.coordinates, [[10, 10], [10, 20], [10, 30], [10, 40]]))
def test_match_sources(self): """ (SourceModelComparison) matching sources """ s1 = Source([[10, 10], [10, 20]]) s2 = Source([[20, 20], [20, 30]]) s3 = Source([[20, 20], [20, 30]]) s4 = Source([[10, 10], [10, 20]]) s5 = Source([[15, 15], [15, 20]]) sm1 = SourceModel([s1, s2]) sm2 = SourceModel([s3, s4, s5]) assert (sm1.match(sm2) == [1, 0]) assert (sm2.match(sm1) == [1, 0, 0])
def test_restore(self): """ (SourceProperties) remove lazy attributes """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert(array_equal(s.center, [10, 15])) assert("center" in s.__dict__.keys()) s.restore() assert("center" not in s.__dict__.keys()) assert(array_equal(s.center, [10, 15])) assert("center" in s.__dict__.keys()) s.restore(skip="center") assert("center" in s.__dict__.keys())
def extract(self, im): from numpy import ones, concatenate from skimage.feature import peak_local_max from skimage.draw import circle # extract local peaks if im.ndim == 2: peaks = peak_local_max(im, min_distance=self.minDistance, num_peaks=self.maxSources).tolist() else: peaks = [] for i in range(0, im.shape[2]): tmp = peak_local_max(im[:, :, i], min_distance=self.minDistance, num_peaks=self.maxSources) peaks = peaks.append( concatenate((tmp, ones((len(tmp), 1)) * i), axis=1)) # construct circular regions from peak points def pointToCircle(center, radius): rr, cc = circle(center[0], center[1], radius) return array(zip(rr, cc)) # return circles as sources circles = [pointToCircle(p, self.radius) for p in peaks] return SourceModel([Source(c) for c in circles])
def test_source_fromCoordinates(self): """ (SourceConstruction) from coordinates """ s = Source.fromCoordinates([[10, 10], [10, 20]]) assert(isinstance(s.coordinates, ndarray)) assert(array_equal(s.coordinates, array([[10, 10], [10, 20]])))
def extract(self, block): import sima # reshape the block to (t, z, y, x, c) dims = block.shape if len(dims) == 3: # (t, x, y) reshapedBlock = block.reshape(dims[0], 1, dims[2], dims[1], 1) else: # (t, x, y, z) reshapedBlock = block.reshape(dims[0], dims[3], dims[2], dims[1], 1) # create SIMA dataset from block dataset = sima.ImagingDataset( [sima.Sequence.create('ndarray', reshapedBlock)], None) # apply the sima strategy to the dataset rois = self.strategy.segment(dataset) # convert the coordinates between the SIMA and thunder conventions coords = [asarray(where(array(roi))).T for roi in rois] if len(dims) == 3: coords = [c[:, 1:] for c in coords] coords = [c[:, ::-1] for c in coords] # format the sources sources = [Source(c) for c in coords] return sources
def test_source_with_values(self): """ (SourceConstruction) create with values """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (array_equal(s.coordinates, array([[10, 10], [10, 20]]))) assert (array_equal(s.values, array([1.0, 2.0])))
def test_source(self): """ (SourceConstruction) create """ s = Source([[10, 10], [10, 20]]) assert (isinstance(s.coordinates, ndarray)) assert (array_equal(s.coordinates, array([[10, 10], [10, 20]])))
def test_polygon(self): """ (SourceProperties) polygon """ x, y = meshgrid(range(0, 10), range(0, 10)) coords = zip(x.flatten(), y.flatten()) s = Source(coords) assert (array_equal(s.polygon, [[0, 0], [9, 0], [9, 9], [0, 9]]))
def test_dilate(self): """ (SourceMethods) dilate """ # make base source m = zeros((10, 10)) m[5, 5] = 1 m[5, 6] = 1 m[6, 5] = 1 m[4, 5] = 1 m[5, 4] = 1 coords = asarray(where(m)).T s = Source(coords) # dilating by 0 doesn't change anything assert(array_equal(s.dilate(0).coordinates, s.coordinates)) assert(array_equal(s.dilate(0).bbox, [4, 4, 6, 6])) # dilating by 1 expands region but doesn't affect center assert(array_equal(s.dilate(1).center, s.center)) assert(array_equal(s.dilate(1).area, 21)) assert(array_equal(s.dilate(1).bbox, [3, 3, 7, 7])) assert(array_equal(s.dilate(1).mask().shape, [5, 5])) # manually construct expected shape of dilated source mask truth = ones((5, 5)) truth[0, 0] = 0 truth[4, 4] = 0 truth[0, 4] = 0 truth[4, 0] = 0 assert(array_equal(s.dilate(1).mask(), truth))
def test_crop(self): """ (SourceMethods) crop """ # without values s = Source([[10, 10], [10, 20]]) assert(array_equal(s.crop([0, 0], [21, 21]).coordinates, s.coordinates)) assert(array_equal(s.crop([0, 0], [11, 11]).coordinates, [[10, 10]])) assert(array_equal(s.crop([0, 0], [5, 5]).coordinates, [])) # with values (two dimensional) s = Source([[10, 10], [10, 20]]) assert(array_equal(s.crop([0, 0], [21, 21]).coordinates, s.coordinates)) assert(array_equal(s.crop([0, 0], [11, 11]).coordinates, [[10, 10]])) assert(array_equal(s.crop([0, 0], [5, 5]).coordinates, []))
def test_inbounds(self): """ (SourceMethods) in bounds """ # two dimensional s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert(s.inbounds([0, 0], [20, 20]) == 1) assert(s.inbounds([0, 0], [10, 10]) == 0.5) assert(s.inbounds([15, 15], [20, 20]) == 0) # three dimensional s = Source([[10, 10, 10], [10, 20, 20]], values=[1.0, 2.0]) assert(s.inbounds([0, 0, 0], [20, 20, 20]) == 1) assert(s.inbounds([0, 0, 0], [10, 10, 20]) == 0.5) assert(s.inbounds([15, 15, 15], [20, 20, 20]) == 0)
def test_source_fromMask_binary(self): """ (SourceConstruction) from mask """ mask = zeros((10, 10)) mask[5, 5] = 1 mask[5, 6] = 1 mask[5, 7] = 1 s = Source.fromMask(mask) assert(isinstance(s, Source)) assert(isinstance(s.coordinates, ndarray)) assert(array_equal(s.coordinates, array([[5, 5], [5, 6], [5, 7]]))) assert(array_equal(s.mask((10, 10), binary=True), mask)) assert(array_equal(s.mask((10, 10), binary=False), mask))
def test_overlap(self): """ (SourceMethods) overlap """ s1 = Source([[0, 0], [0, 1], [0, 2]], values=[0, 1, 2]) s2 = Source([[0, 1], [0, 2], [0, 3]], values=[1, 2, 3]) assert(s1.overlap(s2, 'fraction') == 0.5) assert(allclose(s1.overlap(s2, 'rates'), [2.0/3.0, 2.0/3.0])) assert(s1.overlap(s2, 'correlation') == 1.0)
def test_source_fromMask_values(self): """ (SourceConstruction) from mask with values """ mask = zeros((10, 10)) mask[5, 5] = 0.5 mask[5, 6] = 0.6 mask[5, 7] = 0.7 s = Source.fromMask(mask) assert(isinstance(s, Source)) assert(isinstance(s.coordinates, ndarray)) assert(isinstance(s.values, ndarray)) assert(array_equal(s.coordinates, array([[5, 5], [5, 6], [5, 7]]))) assert(array_equal(s.values, array([0.5, 0.6, 0.7]))) assert(array_equal(s.mask((10, 10), binary=False), mask))
def generateSources(self, padding, center=(15, 15), radius=6): """ Generate a set of sources and block keys by constructing a circular mask region, generating blocks (with or without padding), and returning the sources defined by the mask in each block, and the block keys """ from skimage.draw import circle mask = zeros((30, 30)) rr, cc = circle(center[0], center[1], radius) mask[rr, cc] = 1 img = ImagesLoader(self.sc).fromArrays([mask]) blks = img.toBlocks(size=(10, 10), padding=padding).collect() keys, vals = zip(*blks) sources = [[Source(asarray(where(squeeze(v))).T)] if sum(v) > 0 else [] for v in vals] return sources, keys, mask
def test_outline(self): """ (SourceMethods) outline """ # make base source m = zeros((10, 10)) m[5, 5] = 1 m[5, 6] = 1 m[6, 5] = 1 m[4, 5] = 1 m[5, 4] = 1 coords = asarray(where(m)).T s = Source(coords) # compare outlines to manual results o1 = s.outline(0, 1).mask((10, 10)) o2 = s.dilate(1).mask((10, 10)) - s.mask((10, 10)) assert(array_equal(o1, o2)) o1 = s.outline(1, 2).mask((10, 10)) o2 = s.dilate(2).mask((10, 10)) - s.dilate(1).mask((10, 10)) assert(array_equal(o1, o2))
def test_restore(self): """ (SourceProperties) remove lazy attributes """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (array_equal(s.center, [10, 15])) assert ("center" in s.__dict__.keys()) s.restore() assert ("center" not in s.__dict__.keys()) assert (array_equal(s.center, [10, 15])) assert ("center" in s.__dict__.keys()) s.restore(skip="center") assert ("center" in s.__dict__.keys())
def extract(self, block): from numpy import clip, inf, percentile, asarray, where, size, prod from sklearn.decomposition import NMF from skimage.measure import label from skimage.morphology import remove_small_objects # get dimensions n = self.componentsPerBlock dims = block.shape[1:] # handle maximum size if self.maxArea == "block": maxArea = prod(dims) / 2 else: maxArea = self.maxArea # reshape to be t x all spatial dimensions data = block.reshape(block.shape[0], -1) # build and apply NMF model to block model = NMF(n, max_iter=self.maxIter) model.fit(clip(data, 0, inf)) # reconstruct sources as spatial objects in one array comps = model.components_.reshape((n, ) + dims) # convert from basis functions into shape # by finding connected components and removing small objects combined = [] for c in comps: tmp = c > percentile(c, self.percentile) shape = remove_small_objects(label(tmp), min_size=self.minArea) coords = asarray(where(shape)).T if (size(coords) > 0) and (size(coords) < maxArea): combined.append(Source(coords)) return combined
def test_exclude(self): """ (SourceMethods) exclude """ # without values s = Source([[10, 10], [10, 20]]) o = Source([[10, 20]]) assert(array_equal(s.exclude(o).coordinates, [[10, 10]])) # with values (two dimensional) s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) o = Source([[10, 20]]) assert(array_equal(s.exclude(o).coordinates, [[10, 10]])) assert(array_equal(s.exclude(o).values, [1])) # with values (three dimensional) s = Source([[10, 10, 10], [10, 20, 20]], values=[1.0, 2.0]) o = Source([[10, 20, 20]]) assert(array_equal(s.exclude(o).coordinates, [[10, 10, 10]])) assert(array_equal(s.exclude(o).values, [1.0]))
def test_center(self): """ (SourceProperties) center """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (array_equal(s.center, [10, 15]))
def test_bbox(self): """ (SourceProperties) bounding box """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (array_equal(s.bbox, [10, 10, 10, 20]))
def test_area(self): """ (SourceProperties) area """ s = Source([[10, 10], [10, 20]], values=[1.0, 2.0]) assert (s.area == 2.0)
def extract(self, block): from numpy import clip, inf, percentile, asarray, where, size, prod, unique from scipy.ndimage import median_filter from sklearn.decomposition import NMF from skimage.measure import label from skimage.morphology import remove_small_objects # get dimensions n = self.componentsPerBlock dims = block.shape[1:] # handle maximum size if self.maxArea == "block": maxArea = prod(dims) / 2 else: maxArea = self.maxArea # reshape to be t x all spatial dimensions data = block.reshape(block.shape[0], -1) # build and apply NMF model to block model = NMF(n, max_iter=self.maxIter) model.fit(clip(data, 0, inf)) # reconstruct sources as spatial objects in one array comps = model.components_.reshape((n, ) + dims) # convert from basis functions into shape # by median filtering (optional), applying a threshold, # finding connected components and removing small objects combined = [] for c in comps: tmp = c > percentile(c, self.percentile) regions = remove_small_objects(label(tmp), min_size=self.minArea) ids = unique(regions) ids = ids[ids > 0] for ii in ids: r = regions == ii if self.medFilter is not None: r = median_filter(r, self.medFilter) coords = asarray(where(r)).T if (size(coords) > 0) and (size(coords) < maxArea): combined.append(Source(coords)) # merge overlapping sources if self.overlap is not None: # iterate over source pairs and find a pair to merge def merge(sources): for i1, s1 in enumerate(sources): for i2, s2 in enumerate(sources[i1 + 1:]): if s1.overlap(s2) > self.overlap: return i1, i1 + 1 + i2 return None # merge pairs until none left to merge pair = merge(combined) testing = True while testing: if pair is None: testing = False else: combined[pair[0]].merge(combined[pair[1]]) del combined[pair[1]] pair = merge(combined) return combined