コード例 #1
0
ファイル: roi.py プロジェクト: CLVestergaard/TRamWAy
 def crop(self, r, df):
     n_space_cols = len([col for col in 'xyz' if col in df.columns])
     for regions in self.unit_region.values():
         if len(regions) < r:
             r -= len(regions)
         else:
             if isinstance(regions[r], (pt.Polytope, pt.Region)):
                 raise NotImplementedError
             else:
                 _min, _max = regions[r]
                 if n_space_cols < _min.size:
                     assert _min.size == n_space_cols + 1
                     df = df[(_min[-1] <= df['t']) & (df['t'] <= _max[-1])]
                     df = crop(df, np.r_[_min[:-1], _max[:-1] - _min[:-1]])
                 else:
                     df = crop(df, np.r_[_min, _max - _min])
             return df
コード例 #2
0
ファイル: roi.py プロジェクト: CLVestergaard/TRamWAy
 def crop(self, r, df):
     n_space_cols = len([col for col in 'xyz' if col in df.columns])
     loc_indices = set()
     df_r = None
     for u in self.group[r]:
         if isinstance(self.unit_region[u], (pt.Polytope, pt.Region)):
             raise NotImplementedError
         else:
             _min, _max = self.unit_region[u]
             if n_space_cols < _min.size:
                 assert _min.size == n_space_cols + 1
                 df_u = df[(_min[-1] <= df['t']) & (df['t'] <= _max[-1])]
                 df_u = crop(df_u, np.r_[_min[:-1], _max[:-1] - _min[:-1]])
             else:
                 df_u = crop(df, np.r_[_min, _max - _min])
         if df_r is None:
             df_r = df_u
         else:
             df_r = pd.merge(df_r, df_u, how='outer')
     return df_r
コード例 #3
0
ファイル: roi.py プロジェクト: DecBayComp/TRamWAy
 def crop(self, r, df, **kwargs):
     kwargs["preserve_index"] = True
     n_space_cols = len([col for col in "xyz" if col in df.columns])
     loc_indices = set()
     df_r = None
     for u in self.group[r]:
         if isinstance(self.unit_region[u], (pt.Polytope, pt.Region)):
             raise NotImplementedError
         else:
             _min, _max = self.unit_region[u]
             if n_space_cols < _min.size:
                 assert _min.size == n_space_cols + 1
                 df_u = df[(_min[-1] <= df["t"]) & (df["t"] <= _max[-1])]
                 df_u = crop(df_u, np.r_[_min[:-1], _max[:-1] - _min[:-1]], **kwargs)
             else:
                 df_u = crop(df, np.r_[_min, _max - _min], **kwargs)
         if df_r is None:
             df_r = df_u
         else:
             df_r = pd.merge(df_r, df_u, how="outer")
     return reindex_trajectories(df_r.sort_values(by=["n", "t"]))
コード例 #4
0
ファイル: crop.py プロジェクト: DecBayComp/TRamWAy
def cropping_utility():
    import argparse

    parser = argparse.ArgumentParser(prog="crop",
                                     description="crop 2D trajectories")
    parser.add_argument(
        "--columns",
        help="input trajectory file column names (comma-separated list)")
    parser.add_argument("-q",
                        "--quiet",
                        action="store_true",
                        help="do not ask to overwrite the file")
    parser.add_argument("input_file", help="path to input trajectory file")
    parser.add_argument("bounding_box",
                        help="bounding box as left,bottom,right,top")
    parser.add_argument("output_file",
                        nargs="?",
                        help="path to output trajectory file")
    args = parser.parse_args()

    bounding_box = np.array([float(x) for x in args.bounding_box.split(",")])
    dim = int(round(float(bounding_box.size) * 0.5))
    bounding_box[dim:] -= bounding_box[:dim]

    load_kwargs = {}
    if args.columns:
        load_kwargs["columns"] = args.columns.split(",")
    trajectories = load_xyt(args.input_file, **load_kwargs)

    cropped_trajectories = crop(trajectories, bounding_box.tolist())

    if args.output_file:
        output_file = args.output_file
    else:
        output_file = args.input_file
        if not args.quiet:
            invite = "overwrite file '{}': [N/y] ".format(output_file)
            try:
                answer = raw_input(invite)  # Py2
            except NameError:
                answer = input(invite)
            if not (answer and answer[0].lower() == "y"):
                return

    cropped_trajectories.to_csv(output_file, sep="\t", index=False)
コード例 #5
0
def cropping_utility():
    import argparse
    parser = argparse.ArgumentParser(prog='crop',
                                     description='crop 2D trajectories')
    parser.add_argument(
        '--columns',
        help="input trajectory file column names (comma-separated list)")
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help="do not ask to overwrite the file")
    parser.add_argument('input_file', help='path to input trajectory file')
    parser.add_argument('bounding_box',
                        help='bounding box as left,bottom,right,top')
    parser.add_argument('output_file',
                        nargs='?',
                        help='path to output trajectory file')
    args = parser.parse_args()

    bounding_box = np.array([float(x) for x in args.bounding_box.split(',')])
    dim = int(round(float(bounding_box.size) * .5))
    bounding_box[dim:] -= bounding_box[:dim]

    load_kwargs = {}
    if args.columns:
        load_kwargs['columns'] = args.columns.split(',')
    trajectories = load_xyt(args.input_file, **load_kwargs)

    cropped_trajectories = crop(trajectories, bounding_box.tolist())

    if args.output_file:
        output_file = args.output_file
    else:
        output_file = args.input_file
        if not args.quiet:
            invite = "overwrite file '{}': [N/y] ".format(output_file)
            try:
                answer = raw_input(invite)  # Py2
            except NameError:
                answer = input(invite)
            if not (answer and answer[0].lower() == 'y'):
                return

    cropped_trajectories.to_csv(output_file, sep='\t', index=False)
コード例 #6
0
def random_walk(diffusivity=None,
                force=None,
                viscosity=None,
                drift=None,
                trajectory_mean_count=100,
                trajectory_count_sd=0,
                turnover=None,
                initial_trajectory_count=None,
                new_trajectory_count=None,
                lifetime_tau=None,
                lifetime=None,
                single=False,
                box=(0., 0., 1., 1.),
                duration=10.,
                time_step=.05,
                minor_step_count=99,
                reflect=False,
                full=False,
                count_outside_trajectories=None):
    """
    Generate random walks.

    Consider also the alternative generator
    :func:`~tramway.helper.simulation.categoricaltrap.random_walk_2d`.

    The `trajectory_mean_count` and `trajectory_count_sd` arguments are not compatible with
    the `initial_trajectory_count` and `new_trajectory_count` arguments.
    Use either pair of arguments.

    Arguments:

        diffusivity (callable or float): if callable, takes a coordinate vector
            (:class:`~numpy.ndarray`) and time (float),
            and returns the local diffusivity (float) in :math:`\mu m^2.s^{-1}`

        force (callable): takes a coordinate vector (:class:`~numpy.ndarray`) and time (float)
            and returns the local force vector (:class:`~numpy.ndarray`)

        viscosity (callable or float): if callable, takes a coordinate vector
            (:class:`~numpy.ndarray`) and time (float),
            and returns the local viscosity (float) that divides the local force;
            the default viscosity ensures equilibrium conditions

        drift (callable): takes a coordinate vector (:class:`~numpy.ndarray`) and time (float)
            if `force` is not defined,
            or the same two arguments plus the diffusivity (float) and force
            (:class:`~numpy.ndarray`) otherwise, and returns the local drift;
            this lets `viscosity` unevaluated

        trajectory_mean_count (int or float): average number of active trajectories at any time

        trajectory_count_sd (int or float): standard deviation of the number of active
            trajectories

        turnover (float): fraction of trajectories that will end at each time step;
            **deprecated**

        initial_trajectory_count (int): initial number of active trajectories

        new_trajectory_count (int or callable): number of newly generated trajectories;
            if `new_trajectory_count` is ``callable``, then it takes the time of a step as input
            and returns the count for this step as an ``int``

        lifetime_tau (float): trajectory lifetime constant in seconds

        lifetime (callable or float): trajectory lifetime in seconds;
            if `lifetime` is a ``float``, then it acts like `lifetime_tau`;
            if `lifetime` is ``callable``, then it takes as input the initial time of
            the trajectory

        single (bool): allow single-point trajectories

        box (array-like): origin and size of the space bounding box

        duration (float): duration of the simulation in seconds

        time_step (float): duration between two consecutive observations

        minor_step_count (int): number of intermediate unobserved steps

        reflect (bool): reflect the minor steps that would otherwise leave the bounding box

        full (bool): include locations that are outside the bounding box and times that are
            posterior to `duration`

        count_outside_trajectories (bool): include trajectories that have left the bounding box
            in determining the number of trajectories at each observation step;
            **deprecated**

    Returns:

        pandas.DataFrame: simulated trajectories with 'n' the trajectory index,
            't' the time and with other columns for location coordinates

    """
    if turnover is not None:
        warnings.warn('`turnover` is deprecated', DeprecationWarning)
    if count_outside_trajectories is False:
        warnings.warn('`count_outside_trajectories` is deprecated',
                      DeprecationWarning)
    _box = np.asarray(box)
    dim = int(_box.size / 2)
    support_lower_bound = _box[:dim]
    support_size = _box[dim:]
    support_upper_bound = support_lower_bound + support_size
    # default diffusivity and drift maps
    #def null_scalar_map(xy, t):
    #    return 0.
    #def null_vector_map(xy, t):
    #    return np.zeros((dim,))
    if callable(diffusivity):
        pass
    elif np.isscalar(diffusivity) and 0 < diffusivity:
        _D = diffusivity
        diffusivity = lambda x, t: _D
    else:
        raise ValueError('`diffusivity` must be callable or a positive float')
    if force and not callable(force):
        raise TypeError('`force` must be callable')
    if drift:
        _drift = drift
        if force:
            drift = lambda x, t, D: _drift(x, t, D, force(x, t))
        else:
            drift = lambda x, t, D: _drift(x, t)
    elif force:
        if viscosity is None:
            drift = lambda x, t, D: D * force(x, t)
        elif callable(viscosity):
            drift = lambda x, t, D: force(x, t) / viscosity(x, t)
        elif np.isscalar(viscosity) and 0 < viscosity:
            drift = lambda x, t, D: force(x, t) / viscosity
        else:
            raise ValueError(
                '`viscosity` must be callable or a positive float')
    else:
        drift = lambda x, t, D: 0
    #
    N = int(round(float(duration) / time_step))  # number of observed steps
    min_step_count = 1 if single else 2  # minimum number of observed steps per trajectory
    if callable(lifetime):
        lifetime_tau = None
    elif lifetime:
        lifetime_tau, lifetime = lifetime, None
    if lifetime_tau:
        trajectory_count_sd = None
    elif trajectory_count_sd:
        lifetime_tau = float(trajectory_count_sd) * time_step
    else:
        lifetime_tau = 4. * time_step
    # check
    if lifetime:
        assert callable(lifetime)
    else:
        assert bool(lifetime_tau)
    # number of trajectories at each time step
    K = None
    if new_trajectory_count is None:
        if trajectory_count_sd:
            K = np.rint(
                np.random.randn(N) * trajectory_count_sd +
                trajectory_mean_count).astype(int)
        else:
            K = np.full(N, trajectory_mean_count, dtype=int)
    elif initial_trajectory_count is None:
        warnings.warn(
            'in combination with `new_trajectory_count`, use `initial_trajectory_count` instead of `trajectory_mean_count`'
        )
        initial_trajectory_count = trajectory_mean_count
    k = np.zeros(N, dtype=int)
    # starting time and duration of the trajectories
    time_support = []
    t = 0.
    for i in range(N):
        t += time_step
        if K is None:
            if i == 0:
                k_new = initial_trajectory_count
            elif callable(new_trajectory_count):
                k_new = new_trajectory_count(t)
            else:
                k_new = new_trajectory_count
        else:
            k_new = K[i] - k[i]
        if k_new <= 0:
            if k_new != 0:
                print('{:d} excess trajectories at step {:d}'.format(
                    -k_new, i))
            continue
        if lifetime:
            _lifetime = np.array([lifetime(t) for j in range(k_new)])
        else:
            _lifetime = -np.log(1 - np.random.rand(k_new)) * lifetime_tau
        _lifetime = np.rint(_lifetime / time_step).astype(int) + 1
        _lifetime = _lifetime[min_step_count <= _lifetime]
        time_support.append((t, _lifetime))
        _lifetimes, _count = np.unique(_lifetime, return_counts=True)
        _lifetime = np.zeros(_lifetimes.max(), dtype=_count.dtype)
        _lifetime[_lifetimes - 1] = _count
        if K is not None:
            _count = np.flipud(np.cumsum(np.flipud(_lifetime)))
            k[i:min(i + _count.size, k.size
                    )] += _count[:min(k.size - i, _count.size)]
    #
    actual_time_step = time_step / float(minor_step_count + 1)
    total_location_count = sum(
        [np.sum(_lifetime) for _, _lifetime in time_support])
    # generate the trajectories
    N = np.empty((total_location_count, ), dtype=int)  # trajectory index
    X = np.empty((total_location_count, dim),
                 dtype=_box.dtype)  # spatial coordinates
    T = np.empty((total_location_count, ), dtype=float)  # time
    i, n = 0, 0
    for t0, lifetimes in time_support:
        k = lifetimes.size  # number of new trajectories at time t
        X0 = np.random.rand(
            k, dim) * support_size + support_lower_bound  # initial coordinates
        for x0, _lifetime in zip(X0, lifetimes):  # for each new trajectory
            n += 1
            N[i] = n
            X[i] = x = x0
            T[i] = t = t0
            i += 1
            # from here the main code (``not reflect``) is duplicated to reduce the number of if-tests
            if reflect:
                # duplicated code
                for j in range(1, _lifetime):
                    for _ in range(minor_step_count + 1):
                        D = diffusivity(x, t)
                        A = drift(x, t, D)
                        dx = actual_time_step * A + \
                            np.sqrt(actual_time_step * 2. * D) * np.random.randn(dim)
                        x = x + dx
                        # additional code
                        above = support_upper_bound < x
                        x[above] = 2 * support_upper_bound[above] - x[above]
                        below = x < support_lower_bound
                        if np.any(below & above):
                            raise NotImplementedError(
                                'the jump is so large that its reflection also exceeds the opposite bound'
                            )
                        x[below] = 2 * support_lower_bound[below] - x[below]
                        #
                        t = t + actual_time_step
                    t = t0 + j * time_step  # moderate numerical precision errors
                    N[i] = n
                    X[i] = x
                    T[i] = t
                    i += 1
            else:
                # reference code
                for j in range(1, _lifetime):
                    for _ in range(minor_step_count + 1):
                        D = diffusivity(x, t)
                        A = drift(x, t, D)
                        dx = actual_time_step * A + \
                            np.sqrt(actual_time_step * 2. * D) * np.random.randn(dim)
                        x = x + dx
                        t = t + actual_time_step
                    t = t0 + j * time_step  # moderate numerical precision errors
                    N[i] = n
                    X[i] = x
                    T[i] = t
                    i += 1
    # format the data as a dataframe
    columns = 'xyz'
    if dim <= 3:
        xcols = [d for d in columns[:dim]]
    else:
        xcols = ['x' + str(i) for i in range(dim)]
    points = pd.DataFrame(N, columns=['n']).join(pd.DataFrame(
        X, columns=xcols)).join(pd.DataFrame(T, columns=['t']))
    # post-process
    if not full:
        points = crop(points, _box)
        points = points.loc[points['t'] <= duration + time_step * .1]
        if not single:
            n, count = np.unique(points['n'].values, return_counts=True)
            n = n[count == 1]
            if n.size:
                points = points.loc[~points['n'].isin(n)]
        points.index = np.arange(points.shape[0])
    return points
コード例 #7
0
ファイル: __init__.py プロジェクト: xiang526/TRamWAy
 def crop(self, df=None):
     _min, _max = self._bounding_box
     if df is None:
         df = self._spt_data.dataframe
     return crop(df, np.r_[_min, _max - _min])