Skip to content

For tracking file

To detect fibre centre in a slice

fibretracker.models

fibretracker.models.track_fibres

track_fibres(vol=None, max_jump=5, max_skip=5, momentum=0.1, track_min_length=5, coords=None, std=2.5, min_distance=5, threshold_abs=0.5, weighted_avg=False, window_size=10, apply_filter=False, smoothtrack_gaussian=False, sigma=3, smoothtrack_watershed=False, threshold=None)

Tracks fibers throughout the volume

Parameters:

Name Type Description Default
vol ndarray

3D volume.

None
max_jump int

Maximum distance between detected points in two consecutive frames. Threshold in pixels.

5
max_skip int

Maximum number of frames along one track where no points are detected.

5
momentum float

Parameter in the range [0;1] that gives momentum to the tracking direction.

0.1
track_min_length int

Minimum number of points in a track.

5
coords list

List of numpy arrays with row and column indices of detected points. One per slice, which means that z is gives as the index of the list.

None
std float

Standard deviation of the Gaussian filter.

2.5
min_distance int

Minimum distance between fibres.

5
threshold_abs float

Threshold value for the peak from the background.

0.5
weighted_avg bool

Whether to apply weighted average to the detected coordinates.

False
window_size int

Size of the neighbourhood window around the peak.

10
apply_filter bool

Whether to apply Gaussian filter to the window.

False
smoothtrack_gaussian bool

Whether to smooth tracks using Gaussian.

False
sigma float

Sigma value for Gaussian filter.

3
smoothtrack_watershed bool

Whether to smooth tracks using watershed.

False
threshold float

Threshold value for watershed.

None

Returns:

Name Type Description
tracks List[ndarray]

List of arrays of shape (n_points, 3) - each list contains coordinates of tracked fibers.

Example

import fibretracker as ft

vol = ft.io.load("path/to/volume.txm")
v = ft.io.normalize(vol)
coords = ft.models.get_fibre_coords(v)
tracks = ft.models.track_fibres(coords=coords)
import fibretracker as ft

vol = ft.io.load("path/to/volume.txm")
v = ft.io.normalize(vol)
coords = ft.models.get_fibre_coords(v)
tracks = ft.models.track_fibres(vol=v, coords=coords, smoothtrack_gaussian=True, sigma=3) # Smoothened tracks using Gaussian

Source code in fibretracker/models/tracker.py
def track_fibres(
        vol: Optional[np.ndarray]=None,
        max_jump: int=5, 
        max_skip: int=5, 
        momentum: float=0.1, 
        track_min_length: int=5,
        coords: Optional[List[np.ndarray]]=None,
        std: float=2.5,
        min_distance: int=5,
        threshold_abs: float=0.5,
        weighted_avg: bool=False,
        window_size: int=10,
        apply_filter: bool=False,
        smoothtrack_gaussian: bool=False,
        sigma: float=3,
        smoothtrack_watershed: bool=False,
        threshold: Optional[float]=None
        ):
    '''Tracks fibers throughout the volume

        Args:
            vol (np.ndarray, optional): 3D volume.
            max_jump (int, optional): Maximum distance between detected points in two consecutive frames. Threshold in pixels.
            max_skip (int, optional): Maximum number of frames along one track where no points are detected.
            momentum (float, optional): Parameter in the range [0;1] that gives momentum to the tracking direction.
            track_min_length (int, optional): Minimum number of points in a track.
            coords (list, optional): List of numpy arrays with row and column indices of detected points. One per slice, which
                                        means that z is gives as the index of the list.
            std (float, optional): Standard deviation of the Gaussian filter.
            min_distance (int, optional): Minimum distance between fibres.
            threshold_abs (float, optional): Threshold value for the peak from the background.
            weighted_avg (bool, optional): Whether to apply weighted average to the detected coordinates.
            window_size (int, optional): Size of the neighbourhood window around the peak.
            apply_filter (bool, optional): Whether to apply Gaussian filter to the window.
            smoothtrack_gaussian (bool, optional): Whether to smooth tracks using Gaussian.
            sigma (float, optional): Sigma value for Gaussian filter.
            smoothtrack_watershed (bool, optional): Whether to smooth tracks using watershed.
            threshold (float, optional): Threshold value for watershed.

        Returns:
            tracks (List[np.ndarray]): List of arrays of shape (n_points, 3) - each list contains coordinates of tracked fibers.

        Example:
            ```python
            import fibretracker as ft

            vol = ft.io.load("path/to/volume.txm")
            v = ft.io.normalize(vol)
            coords = ft.models.get_fibre_coords(v)
            tracks = ft.models.track_fibres(coords=coords)
            ```
            ```python
            import fibretracker as ft

            vol = ft.io.load("path/to/volume.txm")
            v = ft.io.normalize(vol)
            coords = ft.models.get_fibre_coords(v)
            tracks = ft.models.track_fibres(vol=v, coords=coords, smoothtrack_gaussian=True, sigma=3) # Smoothened tracks using Gaussian
            ```


    '''

    fib_tracker = TrackPoints(max_jump=max_jump, max_skip=max_skip,
                        momentum=momentum, track_min_length=track_min_length)

    if coords is None:
        coords = get_fibre_coords(vol, std=std, min_distance=min_distance, threshold_abs=threshold_abs, 
                                weighted_avg=weighted_avg, window_size=window_size, apply_filter=apply_filter)

    tracks, _ = fib_tracker(coords)
    if smoothtrack_gaussian:
        print('Smoothing tracks using Gaussian')
        tracks_smooth = []
        for track in tracks:
            tracks_smooth.append(gaussian_filter1d(track, sigma=sigma, axis=0))

        return tracks_smooth

    elif smoothtrack_watershed and vol is not None:
        print('Smoothing tracks using watershed...')
        tracks_filled = fib_tracker.fill_tracks(tracks)
        if threshold is None:
            threshold = threshold_otsu(vol[len(vol)//2])
        V_thres = vol > threshold
        V_dist = -distance_transform_edt(V_thres)
        V_coords = np.zeros(vol.shape)
        for i, track in enumerate(tracks_filled):
            for point in track:
                V_coords[int(point[2]), int(point[1]), int(point[0])] = i + 1
        V_ws = watershed(V_dist, markers=V_coords.astype(int))*V_thres
        print('Watershed volume created.')
        n_fibers = V_ws.max()
        tracks_smooth = [[] for i in range(n_fibers)]

        for i, v_ws in enumerate(V_ws):
            props = regionprops(v_ws)
            for prop in props:
                tracks_smooth[prop.label-1].append(list(prop.centroid[::-1]) + [i])
            print(f'Smoothing tracks - iteration: {i+1}/{len(V_ws)}', end='\r')

        for i in range(n_fibers):
            tracks_smooth[i] = np.array(tracks_smooth[i])

        return tracks_smooth

    else:
        return tracks