def compute_averaged_quantities(body_parts_tracking: dict) -> dict:
    """
        For some things like orientation average across body parts to reduce noise
    """

    # import matplotlib.pyplot as plt

    def unwrap(x):
        return np.degrees(np.unwrap(np.radians(x)))

    # get data
    body = pd.DataFrame(body_parts_tracking["body"]).interpolate(axis=0)
    tail_base = pd.DataFrame(
        body_parts_tracking["tail_base"]).interpolate(axis=0)

    # get speed & acceleration
    results = dict(speed=body.bp_speed.values.copy())
    results["acceleration"] = derivative(results["speed"])

    # get direction of movement
    path = Path(body.x, body.y).smooth()
    results["theta"] = path.theta
    results["thetadot"] = path.thetadot  # deg/s
    results["thetadotdot"] = path.thetadotdot  # in deg / s^2

    # compute orientation of the body
    results["orientation"] = orientation(tail_base.x, tail_base.y, body.x,
                                         body.y)

    # compute angular velocity in deg/s
    results["angular_velocity"] = (angular_derivative(results["orientation"]) *
                                   60)  # in deg/s

    return results
Beispiel #2
0
def average_xy_trajectory(paths: List[Path], rescale: bool = False) -> Path:
    '''
        Computes the average XY trajectory from a set of paths,
        rescaling them in time if necessary
    '''
    if rescale:
        paths = time_rescale(paths)

    X = np.mean(np.vstack([path.x for path in paths]), 0)
    Y = np.mean(np.vstack([path.y for path in paths]), 0)

    return Path(X, Y)
Beispiel #3
0
def BSpline(
    x: np.ndarray,
    y: np.ndarray,
    n_path_points: int = 500,
    degree=3,
    cut: float = 0.06,
    fps: int = 60,
) -> Path:
    ipl_t = np.linspace(0.0, len(x) - 1, len(x))
    spl_i_x = scipy_interpolate.make_interp_spline(ipl_t, x, k=degree)
    spl_i_y = scipy_interpolate.make_interp_spline(ipl_t, y, k=degree)

    travel = np.linspace(0.0, len(x) - 1, n_path_points)

    if cut:
        cut = int(cut * n_path_points)
        return Path(spl_i_x(travel)[cut:-cut],
                    spl_i_y(travel)[cut:-cut],
                    fps=fps)
    else:
        return Path(spl_i_x(travel), spl_i_y(travel), fps=fps)
def fit_best_trace(
    control_points: dict,
    center_line: Path,
    k: int,
    angle_cost: float = 1,
    length_cost: float = 1,
) -> Tuple[Path, Path]:
    """
        Fits a best trace through the arena based on the cost for length and angle.
        It returns a Path with the best trace and one with the best trace in the track's coordinates
        system
    """
    node_values = compute_nodes_values(control_points,
                                       k,
                                       angle_cost=angle_cost,
                                       length_cost=length_cost)

    n = 1
    prev = 0
    node = int(k / 2)
    trace = [node]
    while n < len(node_values) - 1:
        # get the next best node, at this node and coming from the previous
        next_best = node_values[n][node].next_best_node[prev]
        prev = node
        node = int(next_best)
        trace.append(node)

        n += 1

    trace_path = Path(
        [control_points[n][v].x for n, v in enumerate(trace)],
        [control_points[n][v].y for n, v in enumerate(trace)],
    )
    trace_to_track = TCS.path_to_track_coordinates_system(
        center_line, trace_path)

    return trace_path, trace_to_track
def process_body_part(
    bp_data: dict,
    M: np.ndarray,
    likelihood_th: float = 0.95,
    cm_per_px: float = 1,
) -> dict:
    # register to CMM
    x, y = register(bp_data["x"], bp_data["y"], M)

    # scale to go px -> cm
    x *= cm_per_px
    y *= cm_per_px

    # remove low confidence intervals
    like = bp_data["likelihood"]
    x[like < likelihood_th] = np.nan
    y[like < likelihood_th] = np.nan

    # interpolate nans
    xy = data_utils.interpolate_nans(x=x, y=y)
    x, y = np.array(list(xy["x"].values())), np.array(list(xy["y"].values()))

    # median filter pass
    x = data_utils.convolve_with_gaussian(x, kernel_width=5)
    y = data_utils.convolve_with_gaussian(y, kernel_width=5)

    # compute speed
    speed = Path(x, y, fps=60).speed  # in cm/s

    # make sure there are no nans
    results = dict(x=x, y=y, bp_speed=speed)
    for k, var in results.items():
        if np.any(np.isnan(var)):
            raise ValueError(f"Found NANs in {k}")

    return results
Beispiel #6
0
from data import paths
from data.data_structures import LocomotionBout
import draw
from data.dbase._tracking import calc_angular_velocity
from kinematics.msd import MSD
from kinematics import time
from geometry import Path

from matplotlib import rc

rc("font", **{"family": "sans-serif", "sans-serif": ["Helvetica"]})
rc("text", usetex=False)

folder = Path(
    # r"/Users/federicoclaudi/Dropbox (UCL)/Rotation_vte/Presentations/Presentations/Fiete lab"
    r'D:\Dropbox (UCL)\Rotation_vte\Presentations\Presentations\Fiete lab'
)
recorder.start(
    base_folder=folder.parent, folder_name=folder.name, timestamp=False
)

"""
    Fit MSD model to turn trajectories in mice
"""

# %%
# load and clean roi crossings
ROI = "T3"
MIN_DUR = 1.3

_bouts = pd.read_hdf(
Beispiel #7
0
 def fit(self) -> Path:
     for i in range(len(self.waypoints) - 1):
         self.fit_segment(self.waypoints[i], self.waypoints[i + 1])
     return Path(self.x, self.y, self.theta)
def animate_one(ROI: str, crossing_id: int, FPS: int):
    scale = 1 / 30  # to scale velocity vectors
    save_folder = (paths.analysis_folder / "behavior" /
                   "roi_crossings_animations")

    # ----------------------------------- prep ----------------------------------- #
    # load tracking
    bouts = pd.read_hdf(paths.analysis_folder / "behavior" / "roi_crossings" /
                        f"{ROI}_crossings.h5")
    bout = bouts.sort_values("duration").iloc[crossing_id]
    logger.info(f"Animating bout {crossing_id} - {round(bout.duration, 2)}s")
    # tracking: dict = ROICrossing.get_crossing_tracking(bout.crossing_id)

    # generate a path from tracking
    path = Path(bout.x, bout.y)

    # create fig and start camera
    if ROI == "T4":
        f = plt.figure(figsize=(12, 12))
    elif "S" in ROI:
        f = plt.figure(figsize=(8, 14))
    else:
        f = plt.figure(figsize=(5, 14))

    axes = f.subplot_mosaic("""
            AA
            AA
            BB
        """)
    camera = Camera(f)

    # ----------------------------------- plot ----------------------------------- #
    n_interpolated_frames = int(60 / FPS)
    n_frames = len(bout.x) - 1
    trajectory = GrowingPath()
    for frame in track(range(n_frames), total=n_frames):
        # repeat each frame N times interpolating between frames
        for interpol in np.linspace(0, 1, n_interpolated_frames):
            # get interpolated quantities
            x = interpolate_at_frame(path.x, frame, interpol)
            y = interpolate_at_frame(path.y, frame, interpol)
            speed = interpolate_at_frame(path.speed, frame, interpol)

            trajectory.update(x, y, speed=speed)

            # time elapsed
            _time = (np.arange(len(trajectory.speed)) / n_interpolated_frames /
                     60)

            # plot the arena
            draw.ROI(ROI, set_ax=True, shade=False, ax=axes["A"])

            # plot tracking so far
            draw.Tracking(trajectory.x, trajectory.y, lw=3, ax=axes["A"])
            draw.Dot(x, y, s=50, ax=axes["A"])

            # plot speed and velocity vectors
            draw.Arrow(
                x,
                y,
                interpolate_at_frame(path.velocity.angle,
                                     frame,
                                     interpol,
                                     method="step"),
                L=scale *
                interpolate_at_frame(path.velocity.magnitude, frame, interpol),
                color=colors.velocity,
                outline=True,
                width=2,
                ax=axes["A"],
            )
            draw.Arrow(
                x,
                y,
                path.acceleration.angle[frame],
                L=4 * scale * path.acceleration.magnitude[frame],
                color=colors.acceleration,
                outline=True,
                width=2,
                ax=axes["A"],
                zorder=200,
            )

            # plot speed trace
            axes["B"].fill_between(_time,
                                   0,
                                   trajectory.speed,
                                   alpha=0.5,
                                   color=colors.speed)
            axes["B"].plot(_time, trajectory.speed, lw=4, color=colors.speed)

            axes["A"].set(title=f"{ROI} - crossing: {crossing_id}")
            axes["B"].set(xlabel="time (s)", ylabel="speed (cm/s)")
            camera.snap()

    # ------------------------------- video creation ------------------------------- #
    save_path = save_folder / f"{ROI}_{bout.crossing_id}.mp4"
    logger.info(f"Saving animation @: '{save_path}'")
    animation = camera.animate(interval=1000 / FPS)
    animation.save(save_path, fps=FPS)
    logger.info("Done!")

    plt.cla()
    plt.close(f)
    del camera
    del animation

    # ----------------------------------- plot ----------------------------------- #
    f = plot_roi_crossing(bout, step=4)
    recorder.add_figures(svg=False)
    plt.close(f)
Beispiel #9
0
def plot_roi_crossing(
    crossing: pd.Series,
    tracking: dict = None,
    step: int = 5,
    highlight: str = None,
    arrow_scale=0.5,
) -> plt.Figure:
    """
        Plots an entire ROI crossing, tracking, vectors and mouse
    """
    if highlight == "velocity":
        v_alpha, a_alpha = 1, 0.4
    elif highlight == "acceleration":
        v_alpha, a_alpha = 0.4, 1
    else:
        v_alpha, a_alpha = 1, 1

    # path = Path(
    #     convolve_with_gaussian(crossing.x, kernel_width=11),
    #     convolve_with_gaussian(crossing.y, kernel_width=11))
    path = Path(crossing.x, crossing.y)

    f = plt.figure(figsize=(20, 10))
    axes = f.subplot_mosaic(
        """
            AACC
            AADD
            BBEE
        """
    )
    f._save_name = (
        f"{crossing.roi}_{crossing.crossing_id}" + ""
        if highlight is None
        else highlight
    )

    # draw main crossing plot
    draw.ROI(crossing.roi, ax=axes["A"], set_ax=True)
    draw.Tracking(path.x, path.y, lw=0.5, color="k", ax=axes["A"])

    # draw velocity and acceleartion vectors
    draw.Arrows(
        path.x,
        path.y,
        path.velocity.angle,
        label="velocity",
        L=arrow_scale * path.velocity.magnitude / 30,
        step=step,
        color=colors.velocity,
        ax=axes["A"],
        outline=True,
        alpha=v_alpha,
    )

    draw.Arrows(
        path.x,
        path.y,
        path.acceleration.angle,
        label="acceleration",
        L=arrow_scale * 6 * path.acceleration.magnitude / 30,
        step=step,
        color=colors.acceleration,
        ax=axes["A"],
        outline=True,
        alpha=a_alpha,
    )

    draw.Tracking.scatter(
        path.x[::step], path.y[::step], color="k", ax=axes["A"], zorder=200,
    )

    # draw speed traces
    time = np.arange(len(path.speed)) / 60
    axes["B"].fill_between(time, 0, path.speed, alpha=0.5, color=colors.speed)
    axes["B"].plot(
        time, path.speed, lw=4, color=colors.speed,
    )

    if tracking is not None:
        for bp in PAWS:
            axes["C"].plot(
                tracking[bp]["bp_speed"], color=colors.bodyparts[bp], label=bp
            )
        axes["C"].plot(
            tracking["body"]["bp_speed"],
            color=colors.bodyparts["body"],
            label="body",
        )
        axes["C"].plot(
            np.mean(
                np.vstack(
                    [tracking[bp]["bp_speed"] for bp in PAWS if "h" in bp]
                ),
                0,
            ),
            color="k",
            label="mean",
        )

    # clean plots
    axes["A"].legend()
    axes["B"].set(xlabel="time (s)", ylabel="speed (cm/s)")
    axes["C"].legend()
    f.tight_layout()

    return f
Beispiel #10
0
ROI = "T1"

# load tracking
bouts = pd.read_hdf(
    f"/Users/federicoclaudi/Dropbox (UCL)/Rotation_vte/Locomotion/analysis/behavior/roi_crossings/{ROI}_crossings.h5"
)
selected_bouts = bouts.sample(6).reset_index()


# draw stuff
f, axes = plt.subplots(figsize=(18, 12), ncols=3, nrows=2)
axes = axes.flatten()

for i, bout in selected_bouts.iterrows():
    # generate a path from tracking
    path = Path(bout.x, bout.y)

    ax = axes[i]

    # draw arena and tracking
    draw.ROI(ROI, set_ax=True, shade=False, ax=ax)
    # draw.Tracking(bouts.x, bouts.y, alpha=0.5)

    # draw bout tracking and velocity/acceleration vectors
    # draw.Tracking.scatter(path.x, path.y, c=path.tangent.angle, cmap='bwr', vmin=-180, vmax=180)
    draw.Tracking(path.x, path.y, color=[0.6, 0.6, 0.6], lw=5, ax=ax)

    draw.Arrows(
        path.x,
        path.y,
        path.velocity.angle,
Beispiel #11
0
P = [0, 0.125, 1]
colors = make_palette(pink_dark, blue_dark, len(P))
traces = []
for n, p in enumerate(P):
    trace, _ = tp.fit_best_trace(
        control_points,
        center_line,
        K,
        angle_cost=p,
        length_cost=(1 - p) * 5e-3,
    )

    # draw best trace
    X = convolve_with_gaussian(trace.x, kernel_width=11)
    Y = convolve_with_gaussian(trace.y, kernel_width=11)
    traces.append(Path(X, Y))
    draw.Tracking(X, Y, color=colors[n], lw=3)

# %%
# ------------------------------- load tracking ------------------------------ #
_bouts = pd.read_hdf(paths.analysis_folder / "behavior" / "saved_data" /
                     f"complete_bouts.h5")
_bouts = _bouts.loc[_bouts.duration < 8]
print(f"Kept {len(_bouts)} bouts")

bouts = []
for i, bout in _bouts.iterrows():
    bouts.append(LocomotionBout(bout))

#  %%
# ----------------------------------- plot ----------------------------------- #
# %%
(
    left_line,
    center_line,
    right_line,
    left_to_track,
    center_to_track,
    right_to_track,
    control_points,
) = track.extract_track_from_image(
    points_spacing=1,
    restrict_extremities=False,
    apply_extra_spacing=False,
)

tracking = Path(tracking_db.x[fast], tracking_db.y[fast])
linearized = TCS.path_to_track_coordinates_system(center_line, tracking)

# %%
from fcutils.maths import derivative

unit = units.iloc[0]

spikes = np.zeros_like(tracking_db.x)
spikes[unit.spikes] = 1

direction = derivative(tracking_db.global_coord)
direction[direction > 0] = 1
direction[direction < 0] = -1

data = pd.DataFrame(
Beispiel #13
0
        set_ax=True,
        # img_path=r'C:\Users\Federico\Documents\GitHub\pysical_locomotion\draw\hairpin.png'
        img_path="/Users/federicoclaudi/Documents/Github/LocomotionControl/draw/hairpin.png",
    )

all_xy_vectors = {
    "velocity": {},
    "acceleration": {},
}  # stores vectors at each XY position, for averaging
scale_factor = {"velocity": 1 / 80, "acceleration": 1 / 5}
for vn, (vec_name, xy_vectors) in enumerate(all_xy_vectors.items()):
    ax = axes[vn]

    for n, (i, cross) in enumerate(bouts.iterrows()):

        path = Path(cross.x, cross.y)

        cross_bins = []
        for t, (x, y) in enumerate(zip(path.x.round(0), path.y.round(0))):
            if (x, y) in cross_bins:
                continue  # avoid repeated sampling of same location

            # add entry to dictionary
            if (x, y) not in xy_vectors.keys():
                xy_vectors[(x, y)] = []

            xy_vectors[(x, y)].append(path[vec_name][t])
            cross_bins.append((x, y))

    # draw stuff
    for (x, y), vecs in xy_vectors.items():