def test_mass(self): # The mass calculated from the processed image should be independent # of added noise. Its absolute value is untested. # The mass calculated from the raw image should equal # noiseless mass + noise_size/2 * Npx_in_mask. self.check_skip() ndim = 2 radius = 6 N = 20 shape = (128, 127) # Calculate the expected mass from a single spot using the set masksize center = (radius * 2, ) * ndim spot = draw_spots((radius * 4, ) * ndim, [center], radius * 3, bitdepth=12) rect = [slice(c - radius, c + radius + 1) for c in center] mask = tp.masks.binary_mask(radius, 2) Npx = mask.sum() EXPECTED_MASS = (spot[rect] * mask).sum() # Generate feature locations and make the image expected = gen_nonoverlapping_locations(shape, N, radius * 3, radius + 2) expected = expected + np.random.random(expected.shape) N = expected.shape[0] image = draw_spots(shape, expected, radius * 3, bitdepth=12) # analyze the image without noise f = tp.locate(image, radius * 2 + 1, engine=self.engine, topn=N) PROCESSED_MASS = f['mass'].mean() assert_allclose(f['raw_mass'].mean(), EXPECTED_MASS, rtol=0.01) for n, noise in enumerate(np.arange(0.05, 0.8, 0.05)): noise_level = int((2**12 - 1) * noise) image_noisy = image + np.array(np.random.randint( 0, noise_level, image.shape), dtype=image.dtype) f = tp.locate(image_noisy, radius * 2 + 1, engine=self.engine, topn=N) assert_allclose(f['mass'].mean(), PROCESSED_MASS, rtol=0.1) assert_allclose(f['raw_mass'].mean(), EXPECTED_MASS + Npx * noise_level / 2, rtol=0.1)
def test_oldmass_16bit(self): old_minmass = 2800000 im = draw_spots(self.shape, self.pos, self.size, bitdepth=16, noise_level=10000) new_minmass = self.minmass_v02_to_v04(im, old_minmass) f = tp.locate(im, self.tp_diameter, minmass=new_minmass) assert len(f) == self.N
def test_nocharacterize_a(self): pos = gen_nonoverlapping_locations((200, 300), 9, 5) image = draw_spots((200, 300), pos, (0.5, 1)) f_c = tp.locate(image, (3, 5), engine=self.engine, characterize=True) f_nc = tp.locate(image, (3, 5), engine=self.engine, characterize=False) assert len(f_nc.columns) == 3 assert_allclose(f_c.values[:, :3], f_nc.values)
def test_nocharacterize(self): pos = gen_nonoverlapping_locations((200, 300), 9, 5) image = draw_spots((200, 300), pos, 5) f_c = tp.locate(image, 5, engine=self.engine, characterize=True) f_nc = tp.locate(image, 5, engine=self.engine, characterize=False) assert len(f_nc.columns) == 3 assert_allclose(f_c.values[:, :3], f_nc.values)
def test_oldmass_float(self): old_minmass = 5500 im = draw_spots(self.shape, self.pos, self.size, bitdepth=8, noise_level=50) im = (im / im.max()).astype(np.float) new_minmass = self.minmass_v02_to_v04(im, old_minmass) f = tp.locate(im, self.tp_diameter, minmass=new_minmass) assert len(f) == self.N
def test_oldmass_16bit(self): old_minmass = 2800000 im = draw_spots(self.shape, self.pos, self.draw_diameter, bitdepth=16, noise_level=10000) new_minmass = tp.minmass_version_change(im, old_minmass, smoothing_size=self.tp_diameter) f = tp.locate(im, self.tp_diameter, minmass=new_minmass) assert len(f) == self.N
def test_oldmass_float(self): old_minmass = 5500 im = draw_spots(self.shape, self.pos, self.draw_diameter, bitdepth=8, noise_level=50) im = (im / im.max()).astype(np.float) new_minmass = tp.minmass_version_change(im, old_minmass, smoothing_size=self.tp_diameter) f = tp.locate(im, self.tp_diameter, minmass=new_minmass) assert len(f) == self.N
def test_oldmass_invert(self): old_minmass = 2800000 im = draw_spots(self.shape, self.pos, self.draw_diameter, bitdepth=12, noise_level=500) im = (im.max() - im + 10000) new_minmass = tp.minmass_version_change(im, old_minmass, invert=True, smoothing_size=self.tp_diameter) f = tp.locate(im, self.tp_diameter, minmass=new_minmass, invert=True) assert len(f) == self.N
def test_oldmass_invert(self): old_minmass = 2800000 im = draw_spots(self.shape, self.pos, self.size, bitdepth=12, noise_level=500) im = (im.max() - im + 10000) new_minmass = self.minmass_v02_to_v04(im, old_minmass, invert=True) f = tp.locate(invert_image(im), self.tp_diameter, minmass=new_minmass) assert len(f) == self.N
def test_mass(self): # The mass calculated from the processed image should be independent # of added noise. Its absolute value is untested. # The mass calculated from the raw image should equal # noiseless mass + noise_size/2 * Npx_in_mask. self.check_skip() ndim = 2 size = 3 # for drawing radius = 6 # for locate diameter = radius * 2 + 1 N = 20 shape = (128, 127) # Calculate the expected mass from a single spot using the set masksize center = (diameter,) * ndim spot = draw_spots((diameter*2,) * ndim, [center], size, bitdepth=12) rect = [slice(c - radius, c + radius + 1) for c in center] mask = tp.masks.binary_mask(radius, 2) Npx = mask.sum() EXPECTED_MASS = (spot[rect] * mask).sum() # Generate feature locations and make the image expected = gen_nonoverlapping_locations(shape, N, diameter, diameter) expected = expected + np.random.random(expected.shape) N = expected.shape[0] image = draw_spots(shape, expected, size, bitdepth=12) # analyze the image without noise f = tp.locate(image, diameter, engine=self.engine, topn=N) PROCESSED_MASS = f['mass'].mean() assert_allclose(f['raw_mass'].mean(), EXPECTED_MASS, rtol=0.01) for n, noise in enumerate(np.arange(0.05, 0.8, 0.05)): noise_level = int((2**12 - 1) * noise) image_noisy = image + np.array(np.random.randint(0, noise_level, image.shape), dtype=image.dtype) f = tp.locate(image_noisy, radius*2+1, engine=self.engine, topn=N) assert_allclose(f['mass'].mean(), PROCESSED_MASS, rtol=0.1) assert_allclose(f['raw_mass'].mean(), EXPECTED_MASS + Npx*noise_level/2, rtol=0.1)
def test_oldmass_float(self): old_minmass = 5500 im = draw_spots(self.shape, self.pos, self.size, bitdepth=8, noise_level=50) im = (im / im.max()).astype(float) new_minmass = self.minmass_v02_to_v04(im, old_minmass) f = tp.locate(im, self.tp_diameter, minmass=new_minmass) assert len(f) == self.N
def compare(shape, count, radius, noise_level, engine): radius = tp.utils.validate_tuple(radius, len(shape)) # tp.locate ignores a margin of size radius, take 1 px more to be safe margin = tuple([r + 1 for r in radius]) diameter = tuple([(r * 2) + 1 for r in radius]) draw_range = tuple([d * 3 for d in diameter]) cols = ['x', 'y', 'z'][:len(shape)][::-1] pos = gen_nonoverlapping_locations(shape, count, draw_range, margin) image = draw_spots(shape, pos, draw_range, noise_level) f = tp.locate(image, diameter, engine=engine) actual = f[cols].sort(cols) expected = DataFrame(pos, columns=cols).sort(cols) return actual, expected
def test_ep(self): # Test whether the estimated static error equals the rms deviation from # the expected values. Next to the feature mass, the static error is # calculated from the estimated image background level and variance. # This estimate is also tested here. # A threshold is necessary to identify the background array so that # background average and standard deviation can be estimated within 1% # accuracy. # The (absolute) tolerance for ep in this test is 0.05 pixels. # Parameters are tweaked so that there is no deviation due to a too # small mask size. Signal/noise ratios up to 50% are tested. self.check_skip() draw_diameter = 21 locate_diameter = 15 N = 200 shape = (512, 513) noise_expectation = np.array([1 / 2., np.sqrt(1 / 12.)]) # average, stdev # Generate feature locations and make the image expected = gen_nonoverlapping_locations(shape, N, draw_diameter, locate_diameter) expected = expected + np.random.random(expected.shape) N = expected.shape[0] image = draw_spots(shape, expected, draw_diameter, bitdepth=12) for n, noise in enumerate([0.01, 0.02, 0.05, 0.1, 0.2, 0.3, 0.5]): noise_level = int((2**12 - 1) * noise) image_noisy = image + np.array(np.random.randint( 0, noise_level, image.shape), dtype=image.dtype) f = tp.locate(image_noisy, locate_diameter, engine=self.engine, topn=N, threshold=noise_level / 4) _, actual = sort_positions(f[['y', 'x']].values, expected) rms_dev = np.sqrt(np.mean(np.sum((actual - expected)**2, 1))) assert_allclose(rms_dev, f['ep'].mean(), atol=0.05) # Additionally test the measured noise actual_noise = tp.uncertainty.measure_noise( image, image_noisy, locate_diameter // 2) assert_allclose(actual_noise, noise_expectation * noise_level, rtol=0.01, atol=1)
def compare(shape, count, radius, noise_level, **kwargs): radius = tp.utils.validate_tuple(radius, len(shape)) # tp.locate ignores a margin of size radius, take 1 px more to be safe margin = tuple([r + 1 for r in radius]) diameter = tuple([(r * 2) + 1 for r in radius]) size = [d / 2 for d in diameter] separation = tuple([d * 3 for d in diameter]) cols = ['x', 'y', 'z'][:len(shape)][::-1] pos = gen_nonoverlapping_locations(shape, count, separation, margin) image = draw_spots(shape, pos, size, noise_level) f = tp.locate(image, diameter, **kwargs) actual = pandas_sort(f[cols], cols) expected = pandas_sort(DataFrame(pos, columns=cols), cols) return actual, expected
def test_ep(self): # Test wether the estimated static error equals the rms deviation from # the expected values. Next to the feature mass, the static error is # calculated from the estimated image background level and variance. # This estimate is also tested here. # A threshold is necessary to identify the background array so that # background average and standard deviation can be estimated within 1% # accuracy. # The (absolute) tolerance for ep in this test is 0.05 pixels. # Parameters are tweaked so that there is no deviation due to a too # small mask size. Signal/noise ratios upto 50% are tested. self.check_skip() draw_diameter = 21 locate_diameter = 15 N = 200 shape = (512, 513) noise_expectation = np.array([1/2., np.sqrt(1/12.)]) # average, stdev # Generate feature locations and make the image expected = gen_nonoverlapping_locations(shape, N, draw_diameter, locate_diameter) expected = expected + np.random.random(expected.shape) N = expected.shape[0] image = draw_spots(shape, expected, draw_diameter, bitdepth=12) for n, noise in enumerate([0.01, 0.02, 0.05, 0.1, 0.2, 0.3, 0.5]): noise_level = int((2**12 - 1) * noise) image_noisy = image + np.array(np.random.randint(0, noise_level, image.shape), dtype=image.dtype) f = tp.locate(image_noisy, locate_diameter, engine=self.engine, topn=N, threshold=noise_level/4) _, actual = sort_positions(f[['y', 'x']].values, expected) rms_dev = np.sqrt(np.mean(np.sum((actual-expected)**2, 1))) assert_allclose(rms_dev, f['ep'].mean(), atol=0.05) # Additionally test the measured noise actual_noise = tp.uncertainty.measure_noise(image_noisy, locate_diameter, noise_level/4) assert_allclose(actual_noise, noise_expectation * noise_level, rtol=0.01, atol=1)
def setUp(self): pos = gen_nonoverlapping_locations((512, 512), 200, 20) self.frame = draw_spots((512, 512), pos, 20, noise_level=100) self.margin = 11 self.bp_scipy = bandpass(self.frame, 2, 11)[self.margin:-self.margin, self.margin:-self.margin]
from __future__ import division import nose from numpy.testing.utils import assert_allclose from trackpy.preprocessing import (bandpass, legacy_bandpass, legacy_bandpass_fftw) from trackpy.artificial import gen_nonoverlapping_locations, draw_spots from trackpy.tests.common import StrictTestCase pos = gen_nonoverlapping_locations((512, 512), 200, 20) frame = draw_spots((512, 512), pos, 20, noise_level=100) margin = 11 bp_scipy = bandpass(frame, 3, 11)[margin:-margin, margin:-margin] def test_legacy_bandpass(): lbp_numpy = legacy_bandpass(frame, 3, 11)[margin:-margin, margin:-margin] assert_allclose(lbp_numpy, bp_scipy, atol=1.1) def test_legacy_bandpass_fftw(): try: import pyfftw except ImportError: raise nose.SkipTest("pyfftw not installed. Skipping.") lbp_fftw = legacy_bandpass_fftw(frame, 3, 11)[margin:-margin, margin:-margin] assert_allclose(lbp_fftw, bp_scipy, atol=1.1) if __name__ == '__main__': import nose nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
from __future__ import division import nose from numpy.testing.utils import assert_allclose from trackpy.preprocessing import * from trackpy.artificial import gen_nonoverlapping_locations, draw_spots pos = gen_nonoverlapping_locations((512, 512), 200, 20) frame = draw_spots((512, 512), pos, 20, noise_level=100) margin = 11 bp_scipy = bandpass(frame, 3, 11)[margin:-margin, margin:-margin] def test_legacy_bandpass(): lbp_numpy = legacy_bandpass(frame, 3, 11)[margin:-margin, margin:-margin] assert_allclose(lbp_numpy, bp_scipy, atol=1.1) def test_legacy_bandpass_fftw(): try: import pyfftw except ImportError: raise nose.SkipTest("pyfftw not installed. Skipping.") lbp_fftw = legacy_bandpass_fftw(frame, 3, 11)[margin:-margin, margin:-margin] assert_allclose(lbp_fftw, bp_scipy, atol=1.1) if __name__ == '__main__': import nose nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], exit=False)