Beispiel #1
0
    def test_custom_dist_func(self):
        # Several 2D random walkers
        N = 5
        length = 5
        step_size = 2
        search_range = 3

        steps = (np.random.random((2, length, N)) - 0.5) * step_size
        x, y = np.cumsum(steps, axis=2)
        f = DataFrame(dict(x=x.ravel(), y=y.ravel(),
                           frame=np.repeat(np.arange(length), N)))

        # link in normal (2D Euclidean) coordinates
        expected = self.link(f, search_range)

        # compute radial coordinates
        f_radial = f.copy()
        f_radial['angle'] = np.arctan2(f_radial['y'], f_radial['x'])
        f_radial['r'] = np.sqrt(f_radial['y']**2 + f_radial['x']**2)
        # leave x, y for the comparison at the end

        def dist_func(a, b):
            x1 = a[0] * np.cos(a[1])
            y1 = a[0] * np.sin(a[1])
            x2 = b[0] * np.cos(b[1])
            y2 = b[0] * np.sin(b[1])

            return np.sqrt((x1 - x2)**2 + (y1 - y2)**2)

        # link using a custom distance function
        actual = self.link(f_radial, search_range, pos_columns=['r', 'angle'],
                           dist_func=dist_func)
        assert_traj_equal(actual, expected)
Beispiel #2
0
    def test_isolated_continuous_random_walks(self):
        # Two 2D random walks
        np.random.seed(0)
        N = 30
        Y = 250
        M = 20 # margin, because negative values raise OutOfHash
        a = DataFrame({'x': M + random_walk(N), 'y': M + random_walk(N), 'frame': np.arange(N)})
        b = DataFrame({'x': M + random_walk(N - 1), 'y': M + Y + random_walk(N - 1), 'frame': np.arange(1, N)})
        f = pd.concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.zeros(N), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)

        # Many 2D random walks
        np.random.seed(0)
        initial_positions = [(100, 100), (200, 100), (100, 200), (200, 200)]
        import itertools
        c = itertools.count()
        def walk(x, y): 
            i = next(c)
            return DataFrame({'x': x + random_walk(N - i), 
                              'y': y + random_walk(N - i),
                             'frame': np.arange(i, N)})
        f = pd.concat([walk(*pos) for pos in initial_positions])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([i*np.ones(N - i) for i in range(len(initial_positions))])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
Beispiel #3
0
 def test_two_isolated(self):
     shape = (32, 32)
     expected = DataFrame({'x': [8, 16, 24, 16], 'y': [8, 8, 24, 24],
                              'frame': [0, 1, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
Beispiel #4
0
    def test_quadrature_distances(self):
        """A simple test to check whether the subnet linker adds
        orthogonal coordinates in quadrature (as in Pythagoras).

        We have two possible linking results:

        1. A->C and B->D, cost (linear) = 16, cost (quadrature) = 200
        2. A->D and B->C, cost (linear) = 28, cost (quadrature) = 200
        """
        def subnet_test(epsilon):
            """Returns 2 features in 2 frames, which represent a special
            case when the subnet linker adds distances in quadrature. With
            epsilon=0, subnet linking is degenerate. Therefore
            linking should differ for positive and negative epsilon."""
            return pd.DataFrame([(0, 6, 0),             #A
                                 (0, 14 + epsilon, 8),  #B
                                 (1, 8, 0),             #C
                                 (1, 0, 8)],            #D
                                columns=['frame', 'x', 'y'])

        trpos = self.link(subnet_test(1), 20)
        expected = subnet_test(1)
        expected['particle'] = np.array([0, 1, 1, 0])
        assert_traj_equal(trpos, expected)

        trneg = self.link(subnet_test(-1), 20)
        expected = subnet_test(-1)
        expected['particle'] = np.array([0, 1, 0, 1])
        assert_traj_equal(trneg, expected)
Beispiel #5
0
    def test_custom_to_eucl(self):
        # Several 2D random walkers
        N = 5
        length = 5
        step_size = 2
        search_range = 3

        steps = (np.random.random((2, length, N)) - 0.5) * step_size
        x, y = np.cumsum(steps, axis=2)
        f = DataFrame(dict(x=x.ravel(), y=y.ravel(),
                           frame=np.repeat(np.arange(length), N)))

        # link in normal (2D Euclidean) coordinates
        expected = self.link(f, search_range)

        # compute radial coordinates
        f_radial = f.copy()
        f_radial['angle'] = np.arctan2(f_radial['y'], f_radial['x'])
        f_radial['r'] = np.sqrt(f_radial['y'] ** 2 + f_radial['x'] ** 2)
        # leave x, y for the comparison at the end

        def to_eucl(arr):
            r, angle = arr.T
            x = r * np.cos(angle)
            y = r * np.sin(angle)
            return np.array([x, y]).T

        # link using a custom distance function
        actual = self.link(f_radial, search_range, pos_columns=['r', 'angle'],
                           to_eucl=to_eucl)
        assert_traj_equal(actual, expected)
Beispiel #6
0
    def test_one(self):
        expected = DataFrame({'x': [8, 16], 'y': [16, 16],
                              'frame': [0, 1], 'particle': [0, 0]})

        actual = self.link(expected, shape=(24, 24), remove=[0])
        assert_traj_equal(actual, expected)
        actual = self.link(expected, shape=(24, 24), search_range=7, remove=[0])
        assert_equal(len(actual), 1)
Beispiel #7
0
    def test_link_memory(self):
        expected = pd.DataFrame(self.coords_link,
                                columns=self.pos_columns + ['frame'])
        expected['frame'] = expected['frame'].astype(np.int)
        actual = tp.link(expected, memory=self.memory, **self.link_params)
        expected['particle'] = self.expected_link_memory

        assert_traj_equal(actual, expected)
Beispiel #8
0
 def test_one_trivial_stepper(self):
     # One 1D stepper
     N = 5
     f = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
     expected = f.copy()
     expected['particle'] = np.zeros(N)
     actual = self.link_df(f, 5)
     assert_traj_equal(actual, expected)
Beispiel #9
0
 def test_blank_frame_no_memory(self):
     # One 1D stepper
     N = 5
     f = DataFrame({'x': np.arange(N), 'y': np.ones(N),
                   'frame': [0, 1, 2, 4, 5],
                   'particle': [0, 0, 0, 1, 1]})
     expected = f.copy()
     actual = self.link_df(f, 5)
     assert_traj_equal(actual, expected)
Beispiel #10
0
 def test_two_full_overlap(self):
     shape = (24, 24)
     # a --> b
     # c --> d    # a-c, b-c, b-d, a-d overlap
     expected = DataFrame({'x': [8, 15, 8, 15], 'y': [8, 8, 16, 16],
                           'frame': [0, 1, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
Beispiel #11
0
 def test_start_at_frame_other_than_zero(self):
     # One 1D stepper
     N = 5
     FIRST_FRAME = 3
     f = DataFrame({'x': np.arange(N), 'y': np.ones(N), 
                   'frame': FIRST_FRAME + np.arange(N)})
     expected = f.copy()
     expected['particle'] = np.zeros(N)
     actual = self.link_df(f, 5)
     assert_traj_equal(actual, expected)
Beispiel #12
0
    def test_splitting_subnets(self):
        shape = (24, 48)
        expected = pd.DataFrame({'x': [8, 12, 16, 20, 32, 28, 40, 36],
                                 'y': [8, 16, 8, 16, 8, 16, 8, 16],
                                 'frame': [1, 0, 1, 0, 1, 0, 1, 0],
                                 'particle': [0, 0, 1, 1, 2, 2, 3, 3]})

        for n in range(5):
            for remove in itertools.combinations(range(4), n):
                actual = self.link(expected, shape=shape, remove=remove)
                assert_traj_equal(actual, expected)
Beispiel #13
0
    def test_args_dtype(self):
        """Check whether find_link accepts float typed arguments"""
        # One 1D stepper
        N = 5
        f = DataFrame(
            {'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        expected = f.copy()
        expected['particle'] = np.zeros(N)

        # Should not raise
        actual = self.link_df(f, 5.2, separation=9.5, diameter=15.2)
        assert_traj_equal(actual, expected)
Beispiel #14
0
    def test_copy(self):
        """Check inplace/copy behavior of link_df """
        # One 1D stepper
        N = 5
        f = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        expected = f.copy()
        expected['particle'] = np.zeros(N)

        # Should copy
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        assert 'particle' not in f.columns
Beispiel #15
0
    def test_shifting_string(self):
        shape = (24, 48)
        shift = 5
        expected = pd.DataFrame({'x': [8, 8+shift, 16, 16+shift,
                                       24, 24+shift, 32, 32+shift],
                                 'y': [8, 16, 8, 16, 8, 16, 8, 16],
                                 'frame': [0, 1, 0, 1, 0, 1, 0, 1],
                                 'particle': [0, 0, 1, 1, 2, 2, 3, 3]})

        for n in range(5):
            for remove in itertools.combinations(range(4), n):
                actual = self.link(expected, shape=shape, remove=remove)
                assert_traj_equal(actual, expected)
    def test_copy(self):
        """Check inplace/copy behavior of link_df, link_df_iter"""
        # One 1D stepper
        N = 5
        f = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        f_inplace = f.copy()
        expected = f.copy()
        expected['particle'] = np.zeros(N)

        # Should add particle column in-place
        # UNLESS diagnostics are enabled (or input dataframe is not writeable)
        actual = self.link_df(f_inplace, 5)
        assert_traj_equal(actual, expected)
        if self.do_diagnostics:
            assert 'particle' not in f_inplace.columns
        else:
            assert_traj_equal(actual, f_inplace)

        # Should copy
        actual = self.link_df(f, 5, copy_features=True)
        assert_traj_equal(actual, expected)
        assert 'particle' not in f.columns

        # Should copy
        actual_iter = self.link_df_iter(f, 5, hash_size=(10, 2))
        assert_traj_equal(actual_iter, expected)
        assert 'particle' not in f.columns
Beispiel #17
0
 def test_multiple_lost_simple(self):
     shape = (32, 32)
     #   b      a, b, c, d in frame 0
     # a e c    e in frame 1, disappears, should be linked to correct one
     #   d
     # left
     expected = pd.DataFrame({'x': [8, 16, 24, 16, 15],
                              'y': [16, 8, 16, 24, 16],
                              'frame': [0, 0, 0, 0, 1],
                              'particle': [0, 1, 2, 3, 0]})
     actual = self.link(expected, shape=shape, remove=[0])
     assert_traj_equal(actual, expected)
     # top
     expected = pd.DataFrame({'x': [8, 16, 24, 16, 16],
                              'y': [16, 8, 16, 24, 15],
                              'frame': [0, 0, 0, 0, 1],
                              'particle': [0, 1, 2, 3, 1]})
     actual = self.link(expected, shape=shape, remove=[0])
     assert_traj_equal(actual, expected)
     # right
     expected = pd.DataFrame({'x': [8, 16, 24, 16, 17],
                              'y': [16, 8, 16, 24, 16],
                              'frame': [0, 0, 0, 0, 1],
                              'particle': [0, 1, 2, 3, 2]})
     actual = self.link(expected, shape=shape, remove=[0])
     assert_traj_equal(actual, expected)
     # bottom
     expected = pd.DataFrame({'x': [8, 16, 24, 16, 16],
                              'y': [16, 8, 16, 24, 17],
                              'frame': [0, 0, 0, 0, 1],
                              'particle': [0, 1, 2, 3, 3]})
     actual = self.link(expected, shape=shape, remove=[0])
     assert_traj_equal(actual, expected)
Beispiel #18
0
 def test_two_double_overlap(self):
     shape = (24, 32)
     # (a b) c --> d    # a-c and b-c overlap
     expected = DataFrame({'x': [8, 8, 16, 24], 'y': [8, 16, 12, 12],
                           'frame': [0, 1, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
     # (a b) d <-- c    # a-d and b-d overlap
     expected = DataFrame({'x': [8, 8, 16, 24], 'y': [8, 16, 12, 12],
                           'frame': [0, 1, 1, 0], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
    def test_blank_frame_no_memory(self):
        N = 5
        f = DataFrame({'x': np.arange(N), 'y': np.ones(N),
                      'frame': [0, 1, 2, 4, 5]})
        expected = f.copy()

        # Using link_df, the particle will be given a new ID after the gap.
        expected['particle'] = np.array([0, 0, 0, 1, 1], dtype=np.float64)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)

        # link_df_iter will (in this test suite) iterate over only the frames
        # present in the dataframe, so the gap will be ignored.
        expected['particle'] = 0.0
        actual = self.link_df_iter(f, 5, hash_size=(10, 10))
        assert_traj_equal(actual, expected)
 def test_one_trivial_stepper(self):
     # One 1D stepper
     N = 5
     f = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
     expected = f.copy()
     expected['particle'] = np.zeros(N)
     actual = self.link_df(f, 5)
     assert_traj_equal(actual, expected)
     actual_iter = self.link_df_iter(f, 5, hash_size=(10, 2))
     assert_traj_equal(actual_iter, expected)
     if self.do_diagnostics:
         assert 'diag_search_range' in self.diag.columns
         # Except for first frame, all particles should have been labeled
         # with a search_range
         assert not any(self.diag['diag_search_range'][
                            actual_iter.frame > 0].isnull())
 def test_drop_link(self):
     # One 1D stepper. A new particle appears in frame 2.
     # The resulting subnet causes the trajectory to be broken
     # when link_strategy is 'drop' and search_range is large enough.
     N = 2
     f_1particle = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
     f = f_1particle.append(DataFrame(
         {'x': [3], 'y': [1], 'frame': [1]}), ignore_index=True)
     f_expected_without_subnet = f.copy()
     f_expected_without_subnet['particle'] = [0, 0, 1]
     # The linker assigns new particle IDs in arbitrary order. So
     # comparing with expected values is tricky.
     # We just check for the creation of 2 new trajectories.
     without_subnet = self.link_df(f, 1.5, retain_index=True)
     assert_traj_equal(without_subnet, f_expected_without_subnet)
     with_subnet = self.link_df(f, 5, retain_index=True)
     assert set(with_subnet.particle) == set((0, 1, 2))
Beispiel #22
0
    def test_quadrature_sum(self):
        """A simple test to check whether the subnet linker adds
        distances in quadrature (as in Crocker-Grier)."""
        def subnet_test(epsilon):
            """Returns 2 features in 2 frames, which represent a special
            case when the subnet linker adds distances in quadrature. With
            epsilon=0, subnet linking is degenerate. Therefore
            linking should differ for positive and negative epsilon."""
            return pd.DataFrame([(0, 10, 30), (0, 10, 0),
                                 (1, 0, 20), (1, 30, 20 + epsilon)],
                         columns=['frame', 'x', 'y'])

        trpos = self.link(subnet_test(1), 30)
        expected = subnet_test(1)
        expected['particle'] = np.array([0, 1, 1, 0])
        assert_traj_equal(trpos, expected)

        trneg = self.link(subnet_test(-1), 30)
        expected = subnet_test(-1)
        expected['particle'] = np.array([0, 1, 0, 1])
        assert_traj_equal(trneg, expected)
Beispiel #23
0
 def test_multiple_lost_subnet(self):
     shape = (24, 48)
     #  (subnet 1, a-c) g (subnet 2, d-f)
     # left
     expected = pd.DataFrame({'x': [8, 10, 16, 32, 40, 38, 23],
                              'y': [8, 16, 8, 8, 8, 16, 8],
                              'frame': [0, 1, 0, 0, 0, 1, 1],
                              'particle': [0, 0, 1, 2, 3, 3, 1]})
     for n in range(3):
         for remove in itertools.combinations(range(3), n):
             actual = self.link(expected, shape=shape, remove=remove)
             assert_traj_equal(actual, expected)
     # right
     expected = pd.DataFrame({'x': [8, 10, 16, 32, 40, 38, 25],
                              'y': [8, 16, 8, 8, 8, 16, 8],
                              'frame': [0, 1, 0, 0, 0, 1, 1],
                              'particle': [0, 0, 1, 2, 3, 3, 2]})
     for n in range(3):
         for remove in itertools.combinations(range(3), n):
             actual = self.link(expected, shape=shape, remove=remove)
             assert_traj_equal(actual, expected)
Beispiel #24
0
    def test_memory_on_one_gap(self):
        N = 5
        Y = 2
        # Begin second feature one frame later than the first, so the particle labeling (0, 1) is
        # established and not arbitrary.
        a = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        b = DataFrame({'x': np.arange(1, N), 'y': Y + np.ones(N - 1), 'frame': np.arange(1, N)})
        a = a.drop(3).reset_index(drop=True)
        f = pd.concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.array([0, 0, 0, 0]), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        expected.reset_index(drop=True, inplace=True)
        actual = self.link_df(f, 5, memory=1)
        assert_traj_equal(actual, expected)

        # Sort rows by frame (normal use)
        actual = self.link_df(pandas_sort(f, 'frame'), 5, memory=1)
        assert_traj_equal(actual, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5, memory=1)
        assert_traj_equal(actual, expected)
Beispiel #25
0
    def test_two_isolated_steppers_one_gapped(self):
        N = 5
        Y = 25
        # Begin second feature one frame later than the first, 
        # so the particle labeling (0, 1) is established and not arbitrary.
        a = DataFrame({'x': np.arange(N), 'y': np.ones(N), 
                      'frame': np.arange(N)})
        a = a.drop(3).reset_index(drop=True)
        b = DataFrame({'x': np.arange(1, N), 'y': Y + np.ones(N - 1), 
                      'frame': np.arange(1, N)})
        f = pd.concat([a, b])
        expected = f.copy()
        expected['particle'] = np.concatenate([np.array([0, 0, 0, 2]), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        expected.reset_index(drop=True, inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        # link_df_iter() tests not performed, because hash_size is
        # not knowable from the first frame alone.

        # Sort rows by frame (normal use)
        actual = self.link_df(pandas_sort(f, 'frame'), 5)
        assert_traj_equal(actual, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5)
        assert_traj_equal(actual, expected)
Beispiel #26
0
 def test_two_single_overlap(self):
     shape = (16, 40)
     # a --> b  c --> d    : b-c overlap
     expected = DataFrame({'x': [8, 16, 24, 32], 'y': [8, 8, 8, 8],
                           'frame': [0, 1, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
     # a --> b  d <-- c    : b-d overlap
     expected = DataFrame({'x': [8, 16, 24, 32], 'y': [8, 8, 8, 8],
                           'frame': [0, 1, 1, 0], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
     # b <-- a  d --> c    : a-d overlap
     expected = DataFrame({'x': [8, 16, 24, 32], 'y': [8, 8, 8, 8],
                           'frame': [1, 0, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
Beispiel #27
0
 def test_two_triple_overlap(self):
     shape = (24, 32)
     # a --> b
     #     c --> d    # a-c, b-c, and b-d overlap
     expected = DataFrame({'x': [8, 16, 16, 24], 'y': [8, 8, 16, 16],
                           'frame': [0, 1, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
     # a --> b
     #     d <-- c    # a-d, b-d, and b-c overlap
     expected = DataFrame({'x': [8, 16, 16, 24], 'y': [8, 8, 16, 16],
                           'frame': [0, 1, 1, 0], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
     # b <-- a
     #     c -- > d    # b-c, a-c, and a-d overlap
     expected = DataFrame({'x': [8, 16, 16, 24], 'y': [8, 8, 16, 16],
                           'frame': [1, 0, 0, 1], 'particle': [0, 0, 1, 1]})
     for remove in [[], [0], [1], [0, 1]]:
         actual = self.link(expected, shape=shape, remove=remove)
         assert_traj_equal(actual, expected)
    def test_nearby_continuous_random_walks(self):
        # Two 2D random walks
        np.random.seed(0)
        N = 30
        Y = 250
        M = 20 # margin, because negative values raise OutOfHash
        a = DataFrame({'x': M + random_walk(N),
                       'y': M + random_walk(N),
                       'frame': np.arange(N)})
        b = DataFrame({'x': M + random_walk(N - 1),
                       'y': M + Y + random_walk(N - 1),
                       'frame': np.arange(1, N)})
        f = pandas_concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.zeros(N), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual = self.link_df_iter(f, 5, hash_size=(2*M, 2*M + Y))
        assert_traj_equal(actual, expected)

        # Several 2D random walks
        np.random.seed(0)
        initial_positions = [(10, 11), (10, 18), (14, 15), (20, 21), (13, 13),
                             (10, 10), (17, 19)]
        import itertools
        c = itertools.count()
        def walk(x, y):
            i = next(c)
            return DataFrame({'x': x + random_walk(N - i),
                              'y': y + random_walk(N - i),
                              'frame': np.arange(i, N)})
        f = pandas_concat([walk(*pos) for pos in initial_positions])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([i*np.ones(N - i) for i in range(len(initial_positions))])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual = self.link_df_iter(f, 5, hash_size=(2*M, 2*M))
        assert_traj_equal(actual, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5)
        assert_traj_equal(actual, expected)
        actual = self.link_df_iter(f1, 5, hash_size=(2*M, 2*M))
        assert_traj_equal(actual, expected)
    def test_two_nearby_steppers_one_gapped(self):
        N = 5
        Y = 2
        # Begin second feature one frame later than the first, so the particle labeling (0, 1) is
        # established and not arbitrary.
        a = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        b = DataFrame({'x': np.arange(1, N), 'y': Y + np.ones(N - 1), 'frame': np.arange(1, N)})
        a = a.drop(3).reset_index(drop=True)
        f = pandas_concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.array([0, 0, 0, 2]), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        expected.reset_index(drop=True, inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(f, 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        # Sort rows by frame (normal use)
        actual = self.link_df(pandas_sort(f, 'frame'), 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(pandas_sort(f, 'frame'), 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(f1, 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)
    def test_two_nearby_steppers(self):
        N = 5
        Y = 2
        # Begin second feature one frame later than the first, so the particle labeling (0, 1) is
        # established and not arbitrary.
        a = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        b = DataFrame({'x': np.arange(1, N), 'y': Y + np.ones(N - 1), 'frame': np.arange(1, N)})
        f = pandas_concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.zeros(N), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(f, 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        # Sort rows by frame (normal use)
        actual = self.link_df(pandas_sort(f, 'frame'), 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(pandas_sort(f, 'frame'), 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(f1, 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        if self.do_diagnostics:
            assert 'diag_subnet' in self.diag.columns
            assert 'diag_subnet_size' in self.diag.columns
            # Except for frame in which they appear, all particles should have
            # been labeled with a search_range
            assert not any(self.diag['diag_search_range'][
                               actual_iter.frame > 1].isnull())
            # The number of loop iterations is reported by the numba linker only
            if self.linker_opts['link_strategy'] == 'numba':
                assert 'diag_subnet_iterations' in self.diag.columns
    def test_two_isolated_steppers(self):
        N = 5
        Y = 25
        # Begin second feature one frame later than the first, so the particle labeling (0, 1) is
        # established and not arbitrary.
        a = DataFrame({'x': np.arange(N), 'y': np.ones(N), 'frame': np.arange(N)})
        b = DataFrame({'x': np.arange(1, N), 'y': Y + np.ones(N - 1), 'frame': np.arange(1, N)})
        f = pandas_concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.zeros(N), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(f, 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        # Sort rows by frame (normal use)
        actual = self.link_df(pandas_sort(f, 'frame'), 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(pandas_sort(f, 'frame'), 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5)
        assert_traj_equal(actual, expected)
        actual_iter = self.link_df_iter(f1, 5, hash_size=(50, 50))
        assert_traj_equal(actual_iter, expected)
Beispiel #32
0
    def test_nearby_continuous_random_walks(self):
        # Two 2D random walks
        np.random.seed(0)
        N = 30
        Y = 250
        M = 20  # margin, because negative values raise OutOfHash
        a = DataFrame({
            'x': M + random_walk(N),
            'y': M + random_walk(N),
            'frame': np.arange(N)
        })
        b = DataFrame({
            'x': M + random_walk(N - 1),
            'y': M + Y + random_walk(N - 1),
            'frame': np.arange(1, N)
        })
        f = pandas_concat([a, b])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate([np.zeros(N), np.ones(N - 1)])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual = self.link_df_iter(f, 5, hash_size=(2 * M, 2 * M + Y))
        assert_traj_equal(actual, expected)

        # Several 2D random walks
        np.random.seed(0)
        initial_positions = [(10, 11), (10, 18), (14, 15), (20, 21), (13, 13),
                             (10, 10), (17, 19)]
        import itertools
        c = itertools.count()

        def walk(x, y):
            i = next(c)
            return DataFrame({
                'x': x + random_walk(N - i),
                'y': y + random_walk(N - i),
                'frame': np.arange(i, N)
            })

        f = pandas_concat([walk(*pos) for pos in initial_positions])
        expected = f.copy().reset_index(drop=True)
        expected['particle'] = np.concatenate(
            [i * np.ones(N - i) for i in range(len(initial_positions))])
        pandas_sort(expected, ['particle', 'frame'], inplace=True)
        actual = self.link_df(f, 5)
        assert_traj_equal(actual, expected)
        actual = self.link_df_iter(f, 5, hash_size=(2 * M, 2 * M))
        assert_traj_equal(actual, expected)

        # Shuffle rows (crazy!)
        np.random.seed(0)
        f1 = f.reset_index(drop=True)
        f1.reindex(np.random.permutation(f1.index))
        actual = self.link_df(f1, 5)
        assert_traj_equal(actual, expected)
        actual = self.link_df_iter(f1, 5, hash_size=(2 * M, 2 * M))
        assert_traj_equal(actual, expected)