From 59e93cf736936dc88271fc8a92c82ca8e6b4bd5a Mon Sep 17 00:00:00 2001 From: <> Date: Fri, 21 Jun 2024 13:15:35 +0000 Subject: [PATCH] Deployed ffe82e2 with MkDocs version: 1.6.0 --- faq/index.html | 20 ++++++++++++++ index.html | 55 +++++++++++++++++++++++++++++++++++---- search/search_index.json | 2 +- sitemap.xml | 16 ++++++------ sitemap.xml.gz | Bin 279 -> 279 bytes 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/faq/index.html b/faq/index.html index fa3926c..2f4e26f 100644 --- a/faq/index.html +++ b/faq/index.html @@ -496,6 +496,15 @@ + + +
  • + + + Can I use it locally on the laptop or PC? + + +
  • @@ -568,6 +577,15 @@ + + +
  • + + + Can I use it locally on the laptop or PC? + + +
  • @@ -606,6 +624,8 @@

    viz.orthogonal and v

    Make sure to run %matplotlib widget alongwith other library

    How models.track_fibres works ?

    models.track_fibres either requires detected coordinates coords or normalized volume vol. It is suggested to use both if calculated coords available during smoothening to avoid re-compute.

    +

    Can I use it locally on the laptop or PC?

    +

    Yes, this library works locally and does not need very high computing power to use it. Load depends on memory size of data which you are going to use.

    FAQ will be updated based on user experiences diff --git a/index.html b/index.html index 80cd11d..17a47bc 100644 --- a/index.html +++ b/index.html @@ -640,20 +640,65 @@

    FibreTracker

    A python library to track fibre in a volume

    💻 Getting Started

    Create a new environment (highly recommended)

    -
    conda create -n fibretracker python=3.11
    +
    +Miniconda installation and setup +

    Miniconda is a free lightweight installer for conda.

    +

    Here are commands to quickly setup the conda. For reference, you can also use installation link

    +
    +
    +
    +

    Following commands will install the latest 64-bit version and delete the installer. To install different version change the .exe version to desired version in the curl command line.

    +

    curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -o miniconda.exe
    +start /wait "" miniconda.exe /S
    +del miniconda.exe
    +
    +After successful installation, search and open "Ananconda prompt (miniconda3)".

    +
    +
    +

    Following commands will install the latest 64-bit version and delete the installer. To install different version change the .sh version to desired version in the curl command line.

    +
    mkdir -p ~/miniconda3
    +curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o ~/miniconda3/miniconda.sh
    +bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
    +rm -rf ~/miniconda3/miniconda.sh
    +
    +

    After successful installation, initialize your miniconda (in general, it is intialized; just close the current terminal and open a new terminal). If not, following commands initialize for bash and zsh shells :

    +
    ~/miniconda3/bin/conda init bash
    +~/miniconda3/bin/conda init zsh
    +
    +
    +
    +

    Following commands will install the latest 64-bit version and delete the installer. To install different version change the .sh version to desired version in the wget command line.

    +
    mkdir -p ~/miniconda3
    +wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
    +bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
    +rm -rf ~/miniconda3/miniconda.sh
    +
    +

    After installing, initialize your newly-installed Miniconda (in general, it is initialized; just close the current terminal and open a new terminal). If not, following commands initialize for bash and zsh shells:

    +
    ~/miniconda3/bin/conda init bash
    +~/miniconda3/bin/conda init zsh
    +
    +
    +
    +
    +
    +

    Once installed, create the environment

    +
    conda create -n fibretracker python=3.11
     

    Activate the environment by running

    -
    conda activate fibretracker
    +
    conda activate fibretracker
     

    To read .txm file, install dxchange using conda [install before fibretracker module to avoid version conflicts and related error]

    -
    conda install -c conda-forge dxchange
    +
    conda install -c conda-forge dxchange
     

    Install the FibreTracker tool using pip

    -
    pip install fibretracker
    +
    pip install fibretracker
    +
    +

    Open jupyter notebook and create a new notebook

    +
    jupyter notebook
     

    Go to Example and run the notebook with fibretracker enviroment

    Data

    -

    Following are the dataset on which fibre tracking is tested on 250 slices

    +

    Following are the dataset for which fibre tracking is tested on 250 slices

    • Mock and UD [link] - UD-01_FoV_2_B2_recon.txm Mock-01_FoV_2_B2_recon.txm
    • diff --git a/search/search_index.json b/search/search_index.json index 5026e71..25a9e34 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"FibreTracker","text":"

      A python library to track fibre in a volume

      "},{"location":"#getting-started","title":"\ud83d\udcbb Getting Started","text":"

      Create a new environment (highly recommended)

      conda create -n fibretracker python=3.11\n

      Activate the environment by running

      conda activate fibretracker\n

      To read .txm file, install dxchange using conda [install before fibretracker module to avoid version conflicts and related error]

      conda install -c conda-forge dxchange\n

      Install the FibreTracker tool using pip

      pip install fibretracker\n

      Go to Example and run the notebook with fibretracker enviroment

      "},{"location":"#data","title":"Data","text":"

      Following are the dataset on which fibre tracking is tested on 250 slices

      • Mock and UD [link] - UD-01_FoV_2_B2_recon.txm Mock-01_FoV_2_B2_recon.txm
      • GFRP [link] - GFRP_Initial.zip
      • XCT Low-Res [link] - XCT_L.zip
      "},{"location":"#license","title":"License","text":"

      fibretracker was created by Kumari Pooja. It is licensed under the terms of the MIT license.

      "},{"location":"#credits","title":"Credits","text":"

      This work is supported by the RELIANCE doctoral network via the Marie Sk\u0142odowska-Curie Actions HORIZON-MSCA-2021-DN- 01. Project no: 101073040

      Project based on the cookiecutter data science project template. #cookiecutterdatascience

      "},{"location":"CHANGELOG/","title":"Versions History","text":""},{"location":"CHANGELOG/#v010-20062024","title":"v0.1.0 (20/06/2024)","text":"
      • First release of fibretracker!
      "},{"location":"detector/","title":"Documention for fibre detection","text":"

      To detect fibre centre in a slice

      "},{"location":"detector/#fibretracker.models","title":"fibretracker.models","text":""},{"location":"detector/#fibretracker.models.get_fibre_coords","title":"fibretracker.models.get_fibre_coords","text":"
      get_fibre_coords(vol, std=2.5, min_distance=3, threshold_abs=0.4, weighted_avg=False, window_size=10, apply_filter=False)\n

      Get list of fibres centre coordinates in a volume using blob detector

      Parameters:

      Name Type Description Default vol ndarray

      input volume

      required std float

      standard deviation of the Gaussian filter

      2.5 min_distance int

      minimum distance between fibres

      3 threshold_abs float

      threshold value for the peak from the background

      0.4 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

      Returns:

      Name Type Description coords List(array)

      List of fibres centre coordinates in the volume

      Example
      import fibretracker as ft\n\nvol = ft.detector.get_fib_coords(vol, std=2.5, min_distance=3, threshold_abs=0.4)\n
      Source code in fibretracker/models/detector.py
      def get_fibre_coords(\n        vol: np.ndarray, \n        std: float=2.5, \n        min_distance: int=3, \n        threshold_abs: float=0.4,\n        weighted_avg: bool=False,\n        window_size: int=10,\n        apply_filter: bool=False,\n        ):\n    ''' Get list of fibres centre coordinates in a volume using blob detector\n\n    Args:\n        vol: input volume\n        std: standard deviation of the Gaussian filter\n        min_distance: minimum distance between fibres\n        threshold_abs: threshold value for the peak from the background\n        weighted_avg: whether to apply weighted average to the detected coordinates\n        window_size: size of the neighbourhood window around the peak\n        apply_filter: whether to apply Gaussian filter to the window\n\n    Returns:\n        coords (List(nd.array)): List of fibres centre coordinates in the volume\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.detector.get_fib_coords(vol, std=2.5, min_distance=3, threshold_abs=0.4)\n        ```\n\n    '''\n    coords = []\n    for i, im in enumerate(vol):\n        coord = blob_centre_detector(im, std=std, min_distance=min_distance, threshold_abs=threshold_abs)\n        if weighted_avg:\n            coord = avg_fibre_coord(coord, im, window_size=window_size, apply_filter=apply_filter, std=std)\n        coords.append(np.stack([coord[:,1], coord[:,0], np.ones(len(coord)) * i], axis=1))\n        print(f'Detecting coordinates - slice: {i+1}/{len(vol)}', end='\\r')\n    print(' ' * len(f'Detecting coordinates - slice: {i+1}/{len(vol)}'), end='\\r')\n    return coords\n
      "},{"location":"detector/#fibretracker.models.blob_centre_detector","title":"fibretracker.models.blob_centre_detector","text":"
      blob_centre_detector(im, std=2.5, min_distance=3, threshold_abs=0.4)\n

      Predict coordinates of fibres centre in a volume slice using blob detector

      Parameters:

      Name Type Description Default im ndarray

      input image

      required std float

      standard deviation of the Gaussian filter

      2.5 min_distance int

      minimum distance between peaks

      3 threshold_abs float

      threshold value for the peak from the background

      0.4

      Returns:

      Name Type Description pred_coords ndarray

      predicted coordinates of the fibre centre

      Example
      import fibretracker as ft\n\nvol = ft.detector.blob_centre_detector(im, std=2.5, min_distance=3, threshold_abs=0.4)\n
      Source code in fibretracker/models/detector.py
      def blob_centre_detector(\n        im: np.ndarray, \n        std: float=2.5, \n        min_distance: int=3, \n        threshold_abs: float=0.4\n        ):\n    ''' Predict coordinates of fibres centre in a volume slice using blob detector\n\n    Args: \n        im: input image\n        std: standard deviation of the Gaussian filter\n        min_distance: minimum distance between peaks\n        threshold_abs: threshold value for the peak from the background\n\n    Returns: \n        pred_coords (np.ndarray): predicted coordinates of the fibre centre\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.detector.blob_centre_detector(im, std=2.5, min_distance=3, threshold_abs=0.4)\n        ```\n\n    '''\n    g = gauss_filter(std)[0]\n    im_g = scipy.ndimage.convolve(scipy.ndimage.convolve(im, g), g.T)\n    pred_coords = skimage.feature.peak_local_max(im_g, min_distance=min_distance, threshold_abs=threshold_abs)\n    return pred_coords\n
      "},{"location":"detector/#fibretracker.models.gauss_filter","title":"fibretracker.models.gauss_filter","text":"
      gauss_filter(std)\n

      Generate a 1D Gaussian filter and its derivatives

      Parameters:

      Name Type Description Default std float

      standard deviation of the Gaussian filter

      required

      Returns:

      Name Type Description g ndarray

      1D Gaussian filter

      dg ndarray

      derivative of the Gaussian filter

      ddg ndarray

      second derivative of the Gaussian filter

      Example
      import fibretracker as ft\n\nvol = ft.detector.gauss_filter(std=2.5)\n
      Source code in fibretracker/models/detector.py
      def gauss_filter(\n        std: float\n        ):\n    ''' Generate a 1D Gaussian filter and its derivatives\n\n    Args: \n        std: standard deviation of the Gaussian filter\n\n    Returns:\n        g (np.ndarray): 1D Gaussian filter\n        dg (np.ndarray): derivative of the Gaussian filter\n        ddg (np.ndarray): second derivative of the Gaussian filter\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.detector.gauss_filter(std=2.5)\n        ```\n\n    '''\n    x = np.arange(-np.ceil(5*std), np.ceil(5*std) + 1)[:,None]\n    g = np.exp(-x**2/(2*std**2))\n    g /= np.sum(g)\n    dg = -x/std**2 * g\n    ddg = -g/std**2 -x/std**2 * dg\n    return g, dg, ddg\n
      "},{"location":"detector/#fibretracker.models.avg_fibre_coord","title":"fibretracker.models.avg_fibre_coord","text":"
      avg_fibre_coord(pred_coord, im, window_size=10, apply_filter=False, std=None)\n

      Recompute the fibre centre in a slice using weighted average of peak neighbourhood

      Parameters:

      Name Type Description Default pred_coord ndarray

      predicted coordinates of the peaks

      required im ndarray

      input image

      required window_size int

      size of the neighbourhood window around the peak

      10 apply_filter bool

      whether to apply Gaussian filter to the window

      False std Optional[float]

      standard deviation of the Gaussian filter

      None

      Returns:

      Name Type Description coords ndarray

      recomputed fibre centre coordinates in the slice with weighted average

      Example
      import fibretracker as ft\n\navg_coord = ft.detector.avg_fib_coord(pred_coord, im, window_size)\n
      Source code in fibretracker/models/detector.py
      def avg_fibre_coord(\n        pred_coord: np.ndarray, \n        im: np.ndarray, \n        window_size: int = 10,\n        apply_filter: bool = False,\n        std: Optional[float] = None\n        ):\n    ''' Recompute the fibre centre in a slice using weighted average of peak neighbourhood\n\n    Args: \n        pred_coord: predicted coordinates of the peaks\n        im: input image\n        window_size: size of the neighbourhood window around the peak\n        apply_filter: whether to apply Gaussian filter to the window\n        std: standard deviation of the Gaussian filter\n\n    Returns:\n        coords (np.ndarray): recomputed fibre centre coordinates in the slice with weighted average\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        avg_coord = ft.detector.avg_fib_coord(pred_coord, im, window_size)\n        ```\n\n    '''\n    coords = []\n    for coord in pred_coord:\n        x, y = coord\n        window = im[x-window_size//2:x+window_size//2+1, y-window_size//2:y+window_size//2+1]\n        # Apply Gaussian filter to the window\n        if apply_filter:\n            if std is not None:\n                g = gauss_filter(std)[0]\n            else:\n                g = gauss_filter(std=2.5)[0]\n            window = scipy.ndimage.convolve(scipy.ndimage.convolve(window, g), g.T)\n        x_coords, y_coords = np.meshgrid(range(x-window_size//2, x+window_size//2+1), range(y-window_size//2, y+window_size//2+1))\n        weighted_x = np.sum(window * x_coords) / np.sum(window)\n        weighted_y = np.sum(window * y_coords) / np.sum(window)\n        coords.append([weighted_x, weighted_y])\n    return np.array(coords)\n
      "},{"location":"faq/","title":"Frequently Asked Questions","text":""},{"location":"faq/#vizorthogonal-and-vizslicer-are-not-showing-output","title":"viz.orthogonal and viz.slicer are not showing output","text":"

      Make sure to run %matplotlib widget alongwith other library

      "},{"location":"faq/#how-modelstrack_fibres-works","title":"How models.track_fibres works ?","text":"

      models.track_fibres either requires detected coordinates coords or normalized volume vol. It is suggested to use both if calculated coords available during smoothening to avoid re-compute.

      FAQ will be updated based on user experiences"},{"location":"io/","title":"Data input and output","text":"

      Dealing with volumetric data can be done by fibretracker for the most common image formats available.

      Currently, it is possible to directly load tiff, h5, nii,txm and common PIL formats using one single function.

      "},{"location":"io/#fibretracker.io","title":"fibretracker.io","text":""},{"location":"io/#fibretracker.io.load","title":"fibretracker.io.load","text":"
      load(path, dataset_name=None, return_metadata=False, contains=None, force_load=False, dim_order=(2, 1, 0), **kwargs)\n

      Load data from the specified file or directory.

      Parameters:

      Name Type Description Default path str or PathLike

      The path to the file or directory.

      required dataset_name str

      Specifies the name of the dataset to be loaded in case multiple dataset exist within the same file. Default is None (only for HDF5 files)

      None return_metadata bool

      Specifies whether to return metadata or not. Default is False (only for HDF5 and TXRM/TXM/XRM files)

      False contains str

      Specifies a part of the name that is common for the TIFF file stack to be loaded (only for TIFF stacks). Default is None.

      None force_load bool

      If the file size exceeds available memory, a MemoryError is raised. If force_load is True, the error is changed to warning and the loader tries to load it anyway. Default is False.

      False dim_order tuple

      The order of the dimensions in the volume for .vol files. Default is (2,1,0) which corresponds to (z,y,x)

      (2, 1, 0) **kwargs

      Additional keyword arguments to be passed

      {}

      Returns:

      Name Type Description vol ndarray

      The loaded volume If return_metadata=True and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns tuple (volume, metadata).

      Raises:

      Type Description MemoryError

      if the given file size exceeds available memory

      Example

      # Load volume from a single file\nimport fibretracker as ft\n\nvol = ft.io.load(data_path)\n
      # Load a stack of TIFF files as a volume\nimport fibretracker as ft\n\nvol = ft.io.load(data_path, contains='.tif')\n

      Source code in fibretracker/io/read_file.py
      def load(\n    path,\n    dataset_name=None,\n    return_metadata=False,\n    contains=None,\n    force_load: bool = False,\n    dim_order=(2, 1, 0),\n    **kwargs,\n):\n    \"\"\"\n    Load data from the specified file or directory.\n\n    Args:\n        path (str or os.PathLike): The path to the file or directory.\n        dataset_name (str, optional): Specifies the name of the dataset to be loaded\n            in case multiple dataset exist within the same file. Default is None (only for HDF5 files)\n        return_metadata (bool, optional): Specifies whether to return metadata or not. Default is False (only for HDF5 and TXRM/TXM/XRM files)\n        contains (str, optional): Specifies a part of the name that is common for the TIFF file stack to be loaded (only for TIFF stacks).\n            Default is None.\n        force_load (bool, optional): If the file size exceeds available memory, a MemoryError is raised.\n            If force_load is True, the error is changed to warning and the loader tries to load it anyway. Default is False.\n        dim_order (tuple, optional): The order of the dimensions in the volume for .vol files. Default is (2,1,0) which corresponds to (z,y,x)\n        **kwargs: Additional keyword arguments to be passed\n        to the DataLoader constructor.\n\n    Returns:\n        vol (numpy.ndarray): The loaded volume\n            If `return_metadata=True` and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns `tuple` (volume, metadata).\n\n    Raises:\n        MemoryError: if the given file size exceeds available memory\n\n    Example:\n        ```python\n        # Load volume from a single file\n        import fibretracker as ft\n\n        vol = ft.io.load(data_path)\n        ```\n        ```python\n        # Load a stack of TIFF files as a volume\n        import fibretracker as ft\n\n        vol = ft.io.load(data_path, contains='.tif')\n        ```\n\n    \"\"\"\n\n    loader = DataLoader(\n        dataset_name=dataset_name,\n        return_metadata=return_metadata,\n        contains=contains,\n        force_load=force_load,\n        dim_order=dim_order,\n        **kwargs,\n    )\n\n    data = loader.load(path)\n\n    return data\n
      "},{"location":"io/#fibretracker.io.normalize","title":"fibretracker.io.normalize","text":"
      normalize(vol)\n

      Normalize the volume to the range [0, 1] using min-max scaling.

      Parameters:

      Name Type Description Default vol ndarray

      The volume to normalize.

      required

      Returns:

      Name Type Description norm_vol ndarray

      The normalized volume.

      Example
      import fibretracker as ft\n\nnorm_vol = ft.io.normalize(vol)\n
      Source code in fibretracker/io/read_file.py
      def normalize(\n        vol: np.ndarray\n        ):\n    \"\"\"Normalize the volume to the range [0, 1] using min-max scaling.\n\n    Args:\n        vol (numpy.ndarray): The volume to normalize.\n\n    Returns:\n        norm_vol (numpy.ndarray): The normalized volume.\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        norm_vol = ft.io.normalize(vol)\n        ```\n    \"\"\"\n    norm_vol = (vol - np.min(vol)) / (np.max(vol) - np.min(vol))\n    return norm_vol\n
      "},{"location":"tracker/","title":"For tracking file","text":"

      To detect fibre centre in a slice

      "},{"location":"tracker/#fibretracker.models","title":"fibretracker.models","text":""},{"location":"tracker/#fibretracker.models.track_fibres","title":"fibretracker.models.track_fibres","text":"
      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)\n

      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\n\nvol = ft.io.load(\"path/to/volume.txm\")\nv = ft.io.normalize(vol)\ncoords = ft.models.get_fibre_coords(v)\ntracks = ft.models.track_fibres(coords=coords)\n
      import fibretracker as ft\n\nvol = ft.io.load(\"path/to/volume.txm\")\nv = ft.io.normalize(vol)\ncoords = ft.models.get_fibre_coords(v)\ntracks = ft.models.track_fibres(vol=v, coords=coords, smoothtrack_gaussian=True, sigma=3) # Smoothened tracks using Gaussian\n

      Source code in fibretracker/models/tracker.py
      def track_fibres(\n        vol: Optional[np.ndarray]=None,\n        max_jump: int=5, \n        max_skip: int=5, \n        momentum: float=0.1, \n        track_min_length: int=5,\n        coords: Optional[List[np.ndarray]]=None,\n        std: float=2.5,\n        min_distance: int=5,\n        threshold_abs: float=0.5,\n        weighted_avg: bool=False,\n        window_size: int=10,\n        apply_filter: bool=False,\n        smoothtrack_gaussian: bool=False,\n        sigma: float=3,\n        smoothtrack_watershed: bool=False,\n        threshold: Optional[float]=None\n        ):\n    '''Tracks fibers throughout the volume\n\n        Args:\n            vol (np.ndarray, optional): 3D volume.\n            max_jump (int, optional): Maximum distance between detected points in two consecutive frames. Threshold in pixels.\n            max_skip (int, optional): Maximum number of frames along one track where no points are detected.\n            momentum (float, optional): Parameter in the range [0;1] that gives momentum to the tracking direction.\n            track_min_length (int, optional): Minimum number of points in a track.\n            coords (list, optional): List of numpy arrays with row and column indices of detected points. One per slice, which\n                                        means that z is gives as the index of the list.\n            std (float, optional): Standard deviation of the Gaussian filter.\n            min_distance (int, optional): Minimum distance between fibres.\n            threshold_abs (float, optional): Threshold value for the peak from the background.\n            weighted_avg (bool, optional): Whether to apply weighted average to the detected coordinates.\n            window_size (int, optional): Size of the neighbourhood window around the peak.\n            apply_filter (bool, optional): Whether to apply Gaussian filter to the window.\n            smoothtrack_gaussian (bool, optional): Whether to smooth tracks using Gaussian.\n            sigma (float, optional): Sigma value for Gaussian filter.\n            smoothtrack_watershed (bool, optional): Whether to smooth tracks using watershed.\n            threshold (float, optional): Threshold value for watershed.\n\n        Returns:\n            tracks (List[np.ndarray]): List of arrays of shape (n_points, 3) - each list contains coordinates of tracked fibers.\n\n        Example:\n            ```python\n            import fibretracker as ft\n\n            vol = ft.io.load(\"path/to/volume.txm\")\n            v = ft.io.normalize(vol)\n            coords = ft.models.get_fibre_coords(v)\n            tracks = ft.models.track_fibres(coords=coords)\n            ```\n            ```python\n            import fibretracker as ft\n\n            vol = ft.io.load(\"path/to/volume.txm\")\n            v = ft.io.normalize(vol)\n            coords = ft.models.get_fibre_coords(v)\n            tracks = ft.models.track_fibres(vol=v, coords=coords, smoothtrack_gaussian=True, sigma=3) # Smoothened tracks using Gaussian\n            ```\n\n\n    '''\n\n    fib_tracker = TrackPoints(max_jump=max_jump, max_skip=max_skip,\n                        momentum=momentum, track_min_length=track_min_length)\n\n    if coords is None:\n        coords = get_fibre_coords(vol, std=std, min_distance=min_distance, threshold_abs=threshold_abs, \n                                weighted_avg=weighted_avg, window_size=window_size, apply_filter=apply_filter)\n\n    tracks, _ = fib_tracker(coords)\n    if smoothtrack_gaussian:\n        print('Smoothing tracks using Gaussian')\n        tracks_smooth = []\n        for track in tracks:\n            tracks_smooth.append(gaussian_filter1d(track, sigma=sigma, axis=0))\n\n        return tracks_smooth\n\n    elif smoothtrack_watershed and vol is not None:\n        print('Smoothing tracks using watershed...')\n        tracks_filled = fib_tracker.fill_tracks(tracks)\n        if threshold is None:\n            threshold = threshold_otsu(vol[len(vol)//2])\n        V_thres = vol > threshold\n        V_dist = -distance_transform_edt(V_thres)\n        V_coords = np.zeros(vol.shape)\n        for i, track in enumerate(tracks_filled):\n            for point in track:\n                V_coords[int(point[2]), int(point[1]), int(point[0])] = i + 1\n        V_ws = watershed(V_dist, markers=V_coords.astype(int))*V_thres\n        print('Watershed volume created.')\n        n_fibers = V_ws.max()\n        tracks_smooth = [[] for i in range(n_fibers)]\n\n        for i, v_ws in enumerate(V_ws):\n            props = regionprops(v_ws)\n            for prop in props:\n                tracks_smooth[prop.label-1].append(list(prop.centroid[::-1]) + [i])\n            print(f'Smoothing tracks - iteration: {i+1}/{len(V_ws)}', end='\\r')\n\n        for i in range(n_fibers):\n            tracks_smooth[i] = np.array(tracks_smooth[i])\n\n        return tracks_smooth\n\n    else:\n        return tracks\n
      "},{"location":"viz/","title":"Visualise detected centre and tracked fibre","text":"

      To visualise volume accross the slice, detected centres and tracked fibre

      "},{"location":"viz/#fibretracker.viz","title":"fibretracker.viz","text":""},{"location":"viz/#fibretracker.viz.orthogonal","title":"fibretracker.viz.orthogonal","text":"
      orthogonal(vol, cmap='gray', img_height=5, img_width=5)\n

      Interactive widget for visualizing orthogonal slices of a 3D volume.

      Parameters:

      Name Type Description Default vol ndarray or Tensor

      The 3D volume to be sliced.

      required cmap str

      Specifies the color map for the image. Defaults to \"gray\".

      'gray' img_height(int, optional

      Height of the figure.

      required img_width(int, optional

      Width of the figure.

      required

      Returns:

      Name Type Description orthogonal_obj HBox

      The interactive widget for visualizing orthogonal slices of a 3D volume.

      Example

      import fibretracker as ft\n\nvol = ft.io.load(\"path/to/volume.txm\")\nft.viz.orthogonal(vol, cmap=\"gray\")\n

      Source code in fibretracker/viz/visualize.py
      def orthogonal(\n    vol: np.ndarray,\n    cmap: str = \"gray\",\n    img_height: int = 5,\n    img_width: int = 5\n)-> widgets.HBox:\n    \"\"\"Interactive widget for visualizing orthogonal slices of a 3D volume.\n\n    Args:\n        vol (np.ndarray or torch.Tensor): The 3D volume to be sliced.\n        cmap (str, optional): Specifies the color map for the image. Defaults to \"gray\".\n        img_height(int, optional): Height of the figure.\n        img_width(int, optional): Width of the figure.\n\n    Returns:\n        orthogonal_obj (widgets.HBox): The interactive widget for visualizing orthogonal slices of a 3D volume.\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.io.load(\"path/to/volume.txm\")\n        ft.viz.orthogonal(vol, cmap=\"gray\")\n        ```\n        ![viz orthogonal](figures/viz-orthogonal.gif)\n    \"\"\"\n\n    fig, ax = plt.subplots(1, 3, figsize=(3*img_width, img_height))\n    ax[0].axis(\"off\")\n    ax[1].axis(\"off\")\n    ax[2].axis(\"off\")\n\n    def _slice(slice_idx_z, slice_idx_y, slice_idx_x):\n        slice_img_z = vol.take(slice_idx_z, axis=0)\n        slice_img_y = vol.take(slice_idx_y, axis=1)\n        slice_img_x = vol.take(slice_idx_x, axis=2)\n\n        ax[0].imshow(slice_img_z, cmap=cmap)\n        ax[0].set_aspect('equal')\n        ax[1].imshow(slice_img_y, cmap=cmap)\n        ax[1].set_aspect('equal')\n        ax[2].imshow(slice_img_x, cmap=cmap)\n        ax[2].set_aspect('equal')\n\n    slice_slider_z = widgets.IntSlider(\n        value=vol.shape[0] // 2,\n        min=0,\n        max=vol.shape[0] - 1,\n        description=\"Z\",\n        continuous_update=True,\n    )\n\n    slice_slider_y = widgets.IntSlider(\n        value=vol.shape[1] // 2,\n        min=0,\n        max=vol.shape[1] - 1,\n        description=\"Y\",\n        continuous_update=True,\n    )\n\n    slice_slider_x = widgets.IntSlider(\n        value=vol.shape[2] // 2,\n        min=0,\n        max=vol.shape[2] - 1,\n        description=\"X\",\n        continuous_update=True,\n    )\n\n    slicer_obj = interactive(_slice, slice_idx_z=slice_slider_z, slice_idx_y=slice_slider_y, slice_idx_x=slice_slider_x)\n\n    # Create a horizontal box for the sliders\n    hbox = widgets.HBox([slicer_obj.children[0], slicer_obj.children[1], slicer_obj.children[2]], layout=widgets.Layout(align_items=\"stretch\", justify_content=\"center\", align_content=\"center\", justify_items=\"center\", justify_self=\"center\", align_self=\"center\", width=\"100%\"))\n\n    # Replace the sliders in the interactive widget with the horizontal box\n    slicer_obj.children = (hbox,) + slicer_obj.children[3:]\n\n    return slicer_obj\n
      "},{"location":"viz/#fibretracker.viz.slicer","title":"fibretracker.viz.slicer","text":"
      slicer(vol, detect_coords=None, mark_size=None, axis=0, cmap='gray', img_height=5, img_width=5)\n

      Interactive widget for visualizing slices of a 3D volume and fibres centre if provided.

      Parameters:

      Name Type Description Default vol ndarray

      The 3D volume to be sliced.

      required detect_coords list

      List of coordinates of detected fibres. Defaults to None.

      None mark_size int

      Size of the marker for detected fibres. Defaults to None.

      None axis int

      Specifies the axis, or dimension, along which to slice. Defaults to 0.

      0 cmap str

      Specifies the color map for the image. Defaults to \"gray\".

      'gray' img_height int

      Height of the figure. Defaults to 5.

      5 img_width int

      Width of the figure. Defaults to 5.

      5

      Returns:

      Name Type Description slicer_obj interactive

      The interactive widget for visualizing slices of a 3D volume.

      Example

      import fibretracker as ft\n\n# Load the volume and visualize the slices\nvol = ft.io.load(\"path/to/volume.txm\")\nft.viz.slicer(vol)\n

      import fibretracker as ft\n\n# Load the volume and detected coordinates\nvol = ft.io.load(\"path/to/volume.txm\")\nvol = ft.io.normalize(vol)\nvol = vol[100:350] # 250 slices along the z-axis\ndetect_coords = ft.models.get_fibre_coords(vol)\nft.viz.slicer(vol, detect_coords=detect_coords, mark_size=4)\n

      Source code in fibretracker/viz/visualize.py
      def slicer(\n    vol: np.ndarray,\n    detect_coords: Optional[List[np.ndarray]] = None,\n    mark_size: Optional[int] = None,\n    axis: int = 0,\n    cmap: str = \"gray\",\n    img_height: int = 5,\n    img_width: int = 5, \n) -> widgets.interactive:\n    \"\"\"Interactive widget for visualizing slices of a 3D volume and fibres centre if provided.\n\n    Args:\n        vol (np.ndarray): The 3D volume to be sliced.\n        detect_coords (list, optional): List of coordinates of detected fibres. Defaults to None.\n        mark_size (int, optional): Size of the marker for detected fibres. Defaults to None.\n        axis (int, optional): Specifies the axis, or dimension, along which to slice. Defaults to 0.\n        cmap (str, optional): Specifies the color map for the image. Defaults to \"gray\".\n        img_height (int, optional): Height of the figure. Defaults to 5.\n        img_width (int, optional): Width of the figure. Defaults to 5.\n\n    Returns:\n        slicer_obj (widgets.interactive): The interactive widget for visualizing slices of a 3D volume.\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        # Load the volume and visualize the slices\n        vol = ft.io.load(\"path/to/volume.txm\")\n        ft.viz.slicer(vol)\n        ```\n        ![viz slicer](figures/viz-slicer.gif)\n\n        ```python\n        import fibretracker as ft\n\n        # Load the volume and detected coordinates\n        vol = ft.io.load(\"path/to/volume.txm\")\n        vol = ft.io.normalize(vol)\n        vol = vol[100:350] # 250 slices along the z-axis\n        detect_coords = ft.models.get_fibre_coords(vol)\n        ft.viz.slicer(vol, detect_coords=detect_coords, mark_size=4)\n        ```\n\n        ![viz slicer](figures/viz-slicer_detector.gif)\n\n    \"\"\"\n\n    if detect_coords is None:\n        fig, ax = plt.subplots(figsize=(img_width, img_height))\n        ax.axis(\"off\")\n    else:\n        fig, ax = plt.subplots(1, 2, figsize=(2*img_width, img_height), sharex=True, sharey=True, gridspec_kw={'wspace': 0})\n        ax[0].axis(\"off\")\n        ax[1].axis(\"off\")\n\n    def _slice(slice_idx):\n        slice_img = vol.take(slice_idx, axis=axis)\n        if detect_coords is not None:\n            [l.remove() for l in ax[1].lines]\n            ax[0].imshow(slice_img, cmap=cmap)\n            ax[1].imshow(slice_img, cmap=cmap)\n            if mark_size is not None:\n                ax[1].plot(detect_coords[slice_idx][:, 0], detect_coords[slice_idx][:, 1], 'rx', markersize=mark_size)\n            else:\n                ax[1].plot(detect_coords[slice_idx][:, 0], detect_coords[slice_idx][:, 1], 'rx', markersize=3)\n        else:\n            ax.imshow(slice_img, cmap=cmap)\n\n    def on_release(event):\n        if detect_coords is not None:\n            xlim = ax[0].get_xlim()\n            ylim = ax[0].get_ylim()\n            ax[1].set_xlim(xlim)\n            ax[1].set_ylim(ylim)\n        else:\n            xlim = ax.get_xlim()\n            ylim = ax.get_ylim()\n\n    slice_slider = widgets.IntSlider(\n        value=vol.shape[axis] // 2,\n        min=0,\n        max=vol.shape[axis] - 1,\n        description=\"Slice\",\n        continuous_update=True,\n    )\n\n    slice_slider.style.description_width = 'middle'  # Set the width of the description to fit the larger font size\n    slice_slider.style.handle_color = 'blue'  # Optional: Change the handle color\n    slice_slider.style.font_size = '150px'  \n\n    fig.canvas.mpl_connect('button_release_event', on_release)\n    slicer_obj = interactive(_slice, slice_idx = slice_slider)\n\n    return slicer_obj\n
      "},{"location":"viz/#fibretracker.viz.plot_tracks","title":"fibretracker.viz.plot_tracks","text":"
      plot_tracks(tracks, grid=False)\n

      Plot tracks of fibres detected in the volume

      Parameters:

      Name Type Description Default tracks List[ndarray]

      List of arrays of shape (n_points, 3)

      required grid bool

      Whether to show grid in the plot

      False

      Returns:

      Name Type Description fig Figure

      matplotlib figure object

      Example
      import fibretracker as ft\n\n# Load the volume and detected coordinates\nvol = ft.io.load(\"path/to/volume.txm\")\nvol = ft.io.normalize(vol)\nvol = vol[100:350] # 250 slices along the z-axis\ndetect_coords = ft.models.get_fibre_coords(vol)\ntracks_gauss = ft.models.track_fibres(coords=detect_coords, smoothtrack_gaussian=True)\nft.viz.plot_tracks(tracks_gauss)\n

      Source code in fibretracker/viz/plotting.py
      def plot_tracks(\n        tracks: List[np.ndarray],\n        grid: bool = False,):\n\n    '''Plot tracks of fibres detected in the volume\n\n    Args:\n        tracks: List of arrays of shape (n_points, 3)\n        grid: Whether to show grid in the plot\n\n    Returns:\n        fig (matplotlib.figure.Figure): matplotlib figure object\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        # Load the volume and detected coordinates\n        vol = ft.io.load(\"path/to/volume.txm\")\n        vol = ft.io.normalize(vol)\n        vol = vol[100:350] # 250 slices along the z-axis\n        detect_coords = ft.models.get_fibre_coords(vol)\n        tracks_gauss = ft.models.track_fibres(coords=detect_coords, smoothtrack_gaussian=True)\n        ft.viz.plot_tracks(tracks_gauss)\n        ```\n\n        ![viz tracks](figures/tracks_gauss.gif)\n\n\n    '''\n    fig, ax = plt.subplots(figsize=(10, 10))\n    ax = fig.add_subplot(projection='3d')\n    for track in tracks:\n        ax.plot(track[:,0], track[:,1], track[:,2])\n    ax.grid(grid)\n    ax.set_aspect('equal')\n\n    plt.show()\n    return fig\n
      "},{"location":"notebooks/fibre_tracking/","title":"Example","text":"In\u00a0[1]: Copied!
      %matplotlib widget\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport fibretracker as ft\n
      %matplotlib widget import numpy as np import matplotlib.pyplot as plt import fibretracker as ft In\u00a0[2]: Copied!
      data_path = '/Users/pooja/Documents/PhD_work/ICPR_docs/data/Mock_UD_GFRP_data/UD-01_FoV_2_B2_recon.txm'\ndata_path1 = 'data/Mock_UD_GFRP_data/Mock-01_FoV_2_B2_recon.txm'\ndata_path2 = 'data/Mock_UD_GFRP_data/GFRP'\ndata_path3 = 'data/Mock_UD_GFRP_data/XCT_LR'\n\nV_UD = ft.io.load(data_path)\n# V_Mock = ft.io.load(data_path1)\n# V_GFRP = ft.io.load(data_path2, contains='.tif')\n# V_XCTLR = ft.io.load(data_path3, contains='.tif')\n\nV_norm = ft.io.normalize(V_UD).astype(float)\n
      data_path = '/Users/pooja/Documents/PhD_work/ICPR_docs/data/Mock_UD_GFRP_data/UD-01_FoV_2_B2_recon.txm' data_path1 = 'data/Mock_UD_GFRP_data/Mock-01_FoV_2_B2_recon.txm' data_path2 = 'data/Mock_UD_GFRP_data/GFRP' data_path3 = 'data/Mock_UD_GFRP_data/XCT_LR' V_UD = ft.io.load(data_path) # V_Mock = ft.io.load(data_path1) # V_GFRP = ft.io.load(data_path2, contains='.tif') # V_XCTLR = ft.io.load(data_path3, contains='.tif') V_norm = ft.io.normalize(V_UD).astype(float)
      astropy module not found\n
      In\u00a0[3]: Copied!
      ft.viz.slicer(V_norm, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.slicer(V_norm, img_height=7, img_width=7, cmap='gray') Out[3]:
      interactive(children=(IntSlider(value=499, description='Slice', max=998, style=SliderStyle(description_width='\u2026
      Figure In\u00a0[4]: Copied!
      V_tmp = V_norm[100:350, V_norm.shape[1]//2 - 250:V_norm.shape[1]//2 + 250, V_norm.shape[2]//2 - 250:V_norm.shape[2]//2 + 250]\n
      V_tmp = V_norm[100:350, V_norm.shape[1]//2 - 250:V_norm.shape[1]//2 + 250, V_norm.shape[2]//2 - 250:V_norm.shape[2]//2 + 250] In\u00a0[5]: Copied!
      ft.viz.slicer(V_tmp, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.slicer(V_tmp, img_height=7, img_width=7, cmap='gray') Out[5]:
      interactive(children=(IntSlider(value=125, description='Slice', max=249, style=SliderStyle(description_width='\u2026
      Figure In\u00a0[6]: Copied!
      ft.viz.orthogonal(V_tmp, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.orthogonal(V_tmp, img_height=7, img_width=7, cmap='gray') Out[6]:
      interactive(children=(HBox(children=(IntSlider(value=125, description='Z', max=249), IntSlider(value=250, desc\u2026
      Figure In\u00a0[7]: Copied!
      n_bins = int(255*(V_tmp.max() - V_tmp.min()) + 1)\nhist, bins = np.histogram(V_tmp, bins=n_bins)\nbin_width = bins[1] - bins[0]\nfig, ax = plt.subplots(1, figsize=(5, 5))\nax.bar(bins[:-1], hist, width=bin_width)\nax.set_xlabel('Intensity')\nax.set_ylabel('Frequency')\nax.set_title('Histogram of UD section volume')\nplt.show()\n
      n_bins = int(255*(V_tmp.max() - V_tmp.min()) + 1) hist, bins = np.histogram(V_tmp, bins=n_bins) bin_width = bins[1] - bins[0] fig, ax = plt.subplots(1, figsize=(5, 5)) ax.bar(bins[:-1], hist, width=bin_width) ax.set_xlabel('Intensity') ax.set_ylabel('Frequency') ax.set_title('Histogram of UD section volume') plt.show() Figure In\u00a0[9]: Copied!
      coords = ft.models.get_fibre_coords(V_tmp, std=2.5, min_distance=3, threshold_abs=0.6)\n
      coords = ft.models.get_fibre_coords(V_tmp, std=2.5, min_distance=3, threshold_abs=0.6)
                                            \r
      In\u00a0[10]: Copied!
      ft.viz.slicer(V_tmp, detect_coords=coords, mark_size=3, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.slicer(V_tmp, detect_coords=coords, mark_size=3, img_height=7, img_width=7, cmap='gray') Out[10]:
      interactive(children=(IntSlider(value=125, description='Slice', max=249, style=SliderStyle(description_width='\u2026
      Figure In\u00a0[11]: Copied!
      # fibre can be tracked either directly from the volume or from the detected coordinates, or both[to avoid coordinate detection again]\n\ntracks = ft.models.track_fibres(coords=coords)\ntracks_gauss = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_gaussian=True, sigma=2)\ntracks_ws = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_watershed=True, threshold=0.6)\n\n# tracks = ft.models.track_fibres(V_tmp, smoothtrack_watershed=True, threshold=0.5)\n# tracks = ft.models.track_fibres(V_tmp, smoothtrack_gaussian=True)\n# tracks = ft.models.track_fibres(coords=coords)\n# tracks = ft.models.track_fibres(coords=coords, smoothtrack_gaussian=True)\n
      # fibre can be tracked either directly from the volume or from the detected coordinates, or both[to avoid coordinate detection again] tracks = ft.models.track_fibres(coords=coords) tracks_gauss = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_gaussian=True, sigma=2) tracks_ws = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_watershed=True, threshold=0.6) # tracks = ft.models.track_fibres(V_tmp, smoothtrack_watershed=True, threshold=0.5) # tracks = ft.models.track_fibres(V_tmp, smoothtrack_gaussian=True) # tracks = ft.models.track_fibres(coords=coords) # tracks = ft.models.track_fibres(coords=coords, smoothtrack_gaussian=True)
      Smoothing tracks using Gaussian       \nSmoothing tracks using watershed...   \nWatershed volume created.\nSmoothing tracks - iteration: 250/250\r
      In\u00a0[12]: Copied!
      ft.viz.plot_tracks(tracks)\n
      ft.viz.plot_tracks(tracks) Figure Out[12]:
      (<Figure size 1000x1000 with 2 Axes>, <Axes3D: >)
      In\u00a0[13]: Copied!
      ft.viz.plot_tracks(tracks_gauss)\n
      ft.viz.plot_tracks(tracks_gauss) Figure Out[13]:
      (<Figure size 1000x1000 with 2 Axes>, <Axes3D: >)
      In\u00a0[14]: Copied!
      ft.viz.plot_tracks(tracks_ws)\n
      ft.viz.plot_tracks(tracks_ws) Figure Out[14]:
      (<Figure size 1000x1000 with 2 Axes>, <Axes3D: >)
      "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"FibreTracker","text":"

      A python library to track fibre in a volume

      "},{"location":"#getting-started","title":"\ud83d\udcbb Getting Started","text":"

      Create a new environment (highly recommended)

      Miniconda installation and setup

      Miniconda is a free lightweight installer for conda.

      Here are commands to quickly setup the conda. For reference, you can also use installation link

      WindowsmacOSLinux

      Following commands will install the latest 64-bit version and delete the installer. To install different version change the .exe version to desired version in the curl command line.

      curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -o miniconda.exe\nstart /wait \"\" miniconda.exe /S\ndel miniconda.exe\n
      After successful installation, search and open \"Ananconda prompt (miniconda3)\".

      Following commands will install the latest 64-bit version and delete the installer. To install different version change the .sh version to desired version in the curl command line.

      mkdir -p ~/miniconda3\ncurl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o ~/miniconda3/miniconda.sh\nbash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3\nrm -rf ~/miniconda3/miniconda.sh\n

      After successful installation, initialize your miniconda (in general, it is intialized; just close the current terminal and open a new terminal). If not, following commands initialize for bash and zsh shells :

      ~/miniconda3/bin/conda init bash\n~/miniconda3/bin/conda init zsh\n

      Following commands will install the latest 64-bit version and delete the installer. To install different version change the .sh version to desired version in the wget command line.

      mkdir -p ~/miniconda3\nwget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh\nbash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3\nrm -rf ~/miniconda3/miniconda.sh\n

      After installing, initialize your newly-installed Miniconda (in general, it is initialized; just close the current terminal and open a new terminal). If not, following commands initialize for bash and zsh shells:

      ~/miniconda3/bin/conda init bash\n~/miniconda3/bin/conda init zsh\n

      Once installed, create the environment

      conda create -n fibretracker python=3.11\n

      Activate the environment by running

      conda activate fibretracker\n

      To read .txm file, install dxchange using conda [install before fibretracker module to avoid version conflicts and related error]

      conda install -c conda-forge dxchange\n

      Install the FibreTracker tool using pip

      pip install fibretracker\n

      Open jupyter notebook and create a new notebook

      jupyter notebook\n

      Go to Example and run the notebook with fibretracker enviroment

      "},{"location":"#data","title":"Data","text":"

      Following are the dataset for which fibre tracking is tested on 250 slices

      • Mock and UD [link] - UD-01_FoV_2_B2_recon.txm Mock-01_FoV_2_B2_recon.txm
      • GFRP [link] - GFRP_Initial.zip
      • XCT Low-Res [link] - XCT_L.zip
      "},{"location":"#license","title":"License","text":"

      fibretracker was created by Kumari Pooja. It is licensed under the terms of the MIT license.

      "},{"location":"#credits","title":"Credits","text":"

      This work is supported by the RELIANCE doctoral network via the Marie Sk\u0142odowska-Curie Actions HORIZON-MSCA-2021-DN- 01. Project no: 101073040

      Project based on the cookiecutter data science project template. #cookiecutterdatascience

      "},{"location":"CHANGELOG/","title":"Versions History","text":""},{"location":"CHANGELOG/#v010-20062024","title":"v0.1.0 (20/06/2024)","text":"
      • First release of fibretracker!
      "},{"location":"detector/","title":"Documention for fibre detection","text":"

      To detect fibre centre in a slice

      "},{"location":"detector/#fibretracker.models","title":"fibretracker.models","text":""},{"location":"detector/#fibretracker.models.get_fibre_coords","title":"fibretracker.models.get_fibre_coords","text":"
      get_fibre_coords(vol, std=2.5, min_distance=3, threshold_abs=0.4, weighted_avg=False, window_size=10, apply_filter=False)\n

      Get list of fibres centre coordinates in a volume using blob detector

      Parameters:

      Name Type Description Default vol ndarray

      input volume

      required std float

      standard deviation of the Gaussian filter

      2.5 min_distance int

      minimum distance between fibres

      3 threshold_abs float

      threshold value for the peak from the background

      0.4 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

      Returns:

      Name Type Description coords List(array)

      List of fibres centre coordinates in the volume

      Example
      import fibretracker as ft\n\nvol = ft.detector.get_fib_coords(vol, std=2.5, min_distance=3, threshold_abs=0.4)\n
      Source code in fibretracker/models/detector.py
      def get_fibre_coords(\n        vol: np.ndarray, \n        std: float=2.5, \n        min_distance: int=3, \n        threshold_abs: float=0.4,\n        weighted_avg: bool=False,\n        window_size: int=10,\n        apply_filter: bool=False,\n        ):\n    ''' Get list of fibres centre coordinates in a volume using blob detector\n\n    Args:\n        vol: input volume\n        std: standard deviation of the Gaussian filter\n        min_distance: minimum distance between fibres\n        threshold_abs: threshold value for the peak from the background\n        weighted_avg: whether to apply weighted average to the detected coordinates\n        window_size: size of the neighbourhood window around the peak\n        apply_filter: whether to apply Gaussian filter to the window\n\n    Returns:\n        coords (List(nd.array)): List of fibres centre coordinates in the volume\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.detector.get_fib_coords(vol, std=2.5, min_distance=3, threshold_abs=0.4)\n        ```\n\n    '''\n    coords = []\n    for i, im in enumerate(vol):\n        coord = blob_centre_detector(im, std=std, min_distance=min_distance, threshold_abs=threshold_abs)\n        if weighted_avg:\n            coord = avg_fibre_coord(coord, im, window_size=window_size, apply_filter=apply_filter, std=std)\n        coords.append(np.stack([coord[:,1], coord[:,0], np.ones(len(coord)) * i], axis=1))\n        print(f'Detecting coordinates - slice: {i+1}/{len(vol)}', end='\\r')\n    print(' ' * len(f'Detecting coordinates - slice: {i+1}/{len(vol)}'), end='\\r')\n    return coords\n
      "},{"location":"detector/#fibretracker.models.blob_centre_detector","title":"fibretracker.models.blob_centre_detector","text":"
      blob_centre_detector(im, std=2.5, min_distance=3, threshold_abs=0.4)\n

      Predict coordinates of fibres centre in a volume slice using blob detector

      Parameters:

      Name Type Description Default im ndarray

      input image

      required std float

      standard deviation of the Gaussian filter

      2.5 min_distance int

      minimum distance between peaks

      3 threshold_abs float

      threshold value for the peak from the background

      0.4

      Returns:

      Name Type Description pred_coords ndarray

      predicted coordinates of the fibre centre

      Example
      import fibretracker as ft\n\nvol = ft.detector.blob_centre_detector(im, std=2.5, min_distance=3, threshold_abs=0.4)\n
      Source code in fibretracker/models/detector.py
      def blob_centre_detector(\n        im: np.ndarray, \n        std: float=2.5, \n        min_distance: int=3, \n        threshold_abs: float=0.4\n        ):\n    ''' Predict coordinates of fibres centre in a volume slice using blob detector\n\n    Args: \n        im: input image\n        std: standard deviation of the Gaussian filter\n        min_distance: minimum distance between peaks\n        threshold_abs: threshold value for the peak from the background\n\n    Returns: \n        pred_coords (np.ndarray): predicted coordinates of the fibre centre\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.detector.blob_centre_detector(im, std=2.5, min_distance=3, threshold_abs=0.4)\n        ```\n\n    '''\n    g = gauss_filter(std)[0]\n    im_g = scipy.ndimage.convolve(scipy.ndimage.convolve(im, g), g.T)\n    pred_coords = skimage.feature.peak_local_max(im_g, min_distance=min_distance, threshold_abs=threshold_abs)\n    return pred_coords\n
      "},{"location":"detector/#fibretracker.models.gauss_filter","title":"fibretracker.models.gauss_filter","text":"
      gauss_filter(std)\n

      Generate a 1D Gaussian filter and its derivatives

      Parameters:

      Name Type Description Default std float

      standard deviation of the Gaussian filter

      required

      Returns:

      Name Type Description g ndarray

      1D Gaussian filter

      dg ndarray

      derivative of the Gaussian filter

      ddg ndarray

      second derivative of the Gaussian filter

      Example
      import fibretracker as ft\n\nvol = ft.detector.gauss_filter(std=2.5)\n
      Source code in fibretracker/models/detector.py
      def gauss_filter(\n        std: float\n        ):\n    ''' Generate a 1D Gaussian filter and its derivatives\n\n    Args: \n        std: standard deviation of the Gaussian filter\n\n    Returns:\n        g (np.ndarray): 1D Gaussian filter\n        dg (np.ndarray): derivative of the Gaussian filter\n        ddg (np.ndarray): second derivative of the Gaussian filter\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.detector.gauss_filter(std=2.5)\n        ```\n\n    '''\n    x = np.arange(-np.ceil(5*std), np.ceil(5*std) + 1)[:,None]\n    g = np.exp(-x**2/(2*std**2))\n    g /= np.sum(g)\n    dg = -x/std**2 * g\n    ddg = -g/std**2 -x/std**2 * dg\n    return g, dg, ddg\n
      "},{"location":"detector/#fibretracker.models.avg_fibre_coord","title":"fibretracker.models.avg_fibre_coord","text":"
      avg_fibre_coord(pred_coord, im, window_size=10, apply_filter=False, std=None)\n

      Recompute the fibre centre in a slice using weighted average of peak neighbourhood

      Parameters:

      Name Type Description Default pred_coord ndarray

      predicted coordinates of the peaks

      required im ndarray

      input image

      required window_size int

      size of the neighbourhood window around the peak

      10 apply_filter bool

      whether to apply Gaussian filter to the window

      False std Optional[float]

      standard deviation of the Gaussian filter

      None

      Returns:

      Name Type Description coords ndarray

      recomputed fibre centre coordinates in the slice with weighted average

      Example
      import fibretracker as ft\n\navg_coord = ft.detector.avg_fib_coord(pred_coord, im, window_size)\n
      Source code in fibretracker/models/detector.py
      def avg_fibre_coord(\n        pred_coord: np.ndarray, \n        im: np.ndarray, \n        window_size: int = 10,\n        apply_filter: bool = False,\n        std: Optional[float] = None\n        ):\n    ''' Recompute the fibre centre in a slice using weighted average of peak neighbourhood\n\n    Args: \n        pred_coord: predicted coordinates of the peaks\n        im: input image\n        window_size: size of the neighbourhood window around the peak\n        apply_filter: whether to apply Gaussian filter to the window\n        std: standard deviation of the Gaussian filter\n\n    Returns:\n        coords (np.ndarray): recomputed fibre centre coordinates in the slice with weighted average\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        avg_coord = ft.detector.avg_fib_coord(pred_coord, im, window_size)\n        ```\n\n    '''\n    coords = []\n    for coord in pred_coord:\n        x, y = coord\n        window = im[x-window_size//2:x+window_size//2+1, y-window_size//2:y+window_size//2+1]\n        # Apply Gaussian filter to the window\n        if apply_filter:\n            if std is not None:\n                g = gauss_filter(std)[0]\n            else:\n                g = gauss_filter(std=2.5)[0]\n            window = scipy.ndimage.convolve(scipy.ndimage.convolve(window, g), g.T)\n        x_coords, y_coords = np.meshgrid(range(x-window_size//2, x+window_size//2+1), range(y-window_size//2, y+window_size//2+1))\n        weighted_x = np.sum(window * x_coords) / np.sum(window)\n        weighted_y = np.sum(window * y_coords) / np.sum(window)\n        coords.append([weighted_x, weighted_y])\n    return np.array(coords)\n
      "},{"location":"faq/","title":"Frequently Asked Questions","text":""},{"location":"faq/#vizorthogonal-and-vizslicer-are-not-showing-output","title":"viz.orthogonal and viz.slicer are not showing output","text":"

      Make sure to run %matplotlib widget alongwith other library

      "},{"location":"faq/#how-modelstrack_fibres-works","title":"How models.track_fibres works ?","text":"

      models.track_fibres either requires detected coordinates coords or normalized volume vol. It is suggested to use both if calculated coords available during smoothening to avoid re-compute.

      "},{"location":"faq/#can-i-use-it-locally-on-the-laptop-or-pc","title":"Can I use it locally on the laptop or PC?","text":"

      Yes, this library works locally and does not need very high computing power to use it. Load depends on memory size of data which you are going to use.

      FAQ will be updated based on user experiences"},{"location":"io/","title":"Data input and output","text":"

      Dealing with volumetric data can be done by fibretracker for the most common image formats available.

      Currently, it is possible to directly load tiff, h5, nii,txm and common PIL formats using one single function.

      "},{"location":"io/#fibretracker.io","title":"fibretracker.io","text":""},{"location":"io/#fibretracker.io.load","title":"fibretracker.io.load","text":"
      load(path, dataset_name=None, return_metadata=False, contains=None, force_load=False, dim_order=(2, 1, 0), **kwargs)\n

      Load data from the specified file or directory.

      Parameters:

      Name Type Description Default path str or PathLike

      The path to the file or directory.

      required dataset_name str

      Specifies the name of the dataset to be loaded in case multiple dataset exist within the same file. Default is None (only for HDF5 files)

      None return_metadata bool

      Specifies whether to return metadata or not. Default is False (only for HDF5 and TXRM/TXM/XRM files)

      False contains str

      Specifies a part of the name that is common for the TIFF file stack to be loaded (only for TIFF stacks). Default is None.

      None force_load bool

      If the file size exceeds available memory, a MemoryError is raised. If force_load is True, the error is changed to warning and the loader tries to load it anyway. Default is False.

      False dim_order tuple

      The order of the dimensions in the volume for .vol files. Default is (2,1,0) which corresponds to (z,y,x)

      (2, 1, 0) **kwargs

      Additional keyword arguments to be passed

      {}

      Returns:

      Name Type Description vol ndarray

      The loaded volume If return_metadata=True and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns tuple (volume, metadata).

      Raises:

      Type Description MemoryError

      if the given file size exceeds available memory

      Example

      # Load volume from a single file\nimport fibretracker as ft\n\nvol = ft.io.load(data_path)\n
      # Load a stack of TIFF files as a volume\nimport fibretracker as ft\n\nvol = ft.io.load(data_path, contains='.tif')\n

      Source code in fibretracker/io/read_file.py
      def load(\n    path,\n    dataset_name=None,\n    return_metadata=False,\n    contains=None,\n    force_load: bool = False,\n    dim_order=(2, 1, 0),\n    **kwargs,\n):\n    \"\"\"\n    Load data from the specified file or directory.\n\n    Args:\n        path (str or os.PathLike): The path to the file or directory.\n        dataset_name (str, optional): Specifies the name of the dataset to be loaded\n            in case multiple dataset exist within the same file. Default is None (only for HDF5 files)\n        return_metadata (bool, optional): Specifies whether to return metadata or not. Default is False (only for HDF5 and TXRM/TXM/XRM files)\n        contains (str, optional): Specifies a part of the name that is common for the TIFF file stack to be loaded (only for TIFF stacks).\n            Default is None.\n        force_load (bool, optional): If the file size exceeds available memory, a MemoryError is raised.\n            If force_load is True, the error is changed to warning and the loader tries to load it anyway. Default is False.\n        dim_order (tuple, optional): The order of the dimensions in the volume for .vol files. Default is (2,1,0) which corresponds to (z,y,x)\n        **kwargs: Additional keyword arguments to be passed\n        to the DataLoader constructor.\n\n    Returns:\n        vol (numpy.ndarray): The loaded volume\n            If `return_metadata=True` and file format is either HDF5, NIfTI or TXRM/TXM/XRM, returns `tuple` (volume, metadata).\n\n    Raises:\n        MemoryError: if the given file size exceeds available memory\n\n    Example:\n        ```python\n        # Load volume from a single file\n        import fibretracker as ft\n\n        vol = ft.io.load(data_path)\n        ```\n        ```python\n        # Load a stack of TIFF files as a volume\n        import fibretracker as ft\n\n        vol = ft.io.load(data_path, contains='.tif')\n        ```\n\n    \"\"\"\n\n    loader = DataLoader(\n        dataset_name=dataset_name,\n        return_metadata=return_metadata,\n        contains=contains,\n        force_load=force_load,\n        dim_order=dim_order,\n        **kwargs,\n    )\n\n    data = loader.load(path)\n\n    return data\n
      "},{"location":"io/#fibretracker.io.normalize","title":"fibretracker.io.normalize","text":"
      normalize(vol)\n

      Normalize the volume to the range [0, 1] using min-max scaling.

      Parameters:

      Name Type Description Default vol ndarray

      The volume to normalize.

      required

      Returns:

      Name Type Description norm_vol ndarray

      The normalized volume.

      Example
      import fibretracker as ft\n\nnorm_vol = ft.io.normalize(vol)\n
      Source code in fibretracker/io/read_file.py
      def normalize(\n        vol: np.ndarray\n        ):\n    \"\"\"Normalize the volume to the range [0, 1] using min-max scaling.\n\n    Args:\n        vol (numpy.ndarray): The volume to normalize.\n\n    Returns:\n        norm_vol (numpy.ndarray): The normalized volume.\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        norm_vol = ft.io.normalize(vol)\n        ```\n    \"\"\"\n    norm_vol = (vol - np.min(vol)) / (np.max(vol) - np.min(vol))\n    return norm_vol\n
      "},{"location":"tracker/","title":"For tracking file","text":"

      To detect fibre centre in a slice

      "},{"location":"tracker/#fibretracker.models","title":"fibretracker.models","text":""},{"location":"tracker/#fibretracker.models.track_fibres","title":"fibretracker.models.track_fibres","text":"
      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)\n

      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\n\nvol = ft.io.load(\"path/to/volume.txm\")\nv = ft.io.normalize(vol)\ncoords = ft.models.get_fibre_coords(v)\ntracks = ft.models.track_fibres(coords=coords)\n
      import fibretracker as ft\n\nvol = ft.io.load(\"path/to/volume.txm\")\nv = ft.io.normalize(vol)\ncoords = ft.models.get_fibre_coords(v)\ntracks = ft.models.track_fibres(vol=v, coords=coords, smoothtrack_gaussian=True, sigma=3) # Smoothened tracks using Gaussian\n

      Source code in fibretracker/models/tracker.py
      def track_fibres(\n        vol: Optional[np.ndarray]=None,\n        max_jump: int=5, \n        max_skip: int=5, \n        momentum: float=0.1, \n        track_min_length: int=5,\n        coords: Optional[List[np.ndarray]]=None,\n        std: float=2.5,\n        min_distance: int=5,\n        threshold_abs: float=0.5,\n        weighted_avg: bool=False,\n        window_size: int=10,\n        apply_filter: bool=False,\n        smoothtrack_gaussian: bool=False,\n        sigma: float=3,\n        smoothtrack_watershed: bool=False,\n        threshold: Optional[float]=None\n        ):\n    '''Tracks fibers throughout the volume\n\n        Args:\n            vol (np.ndarray, optional): 3D volume.\n            max_jump (int, optional): Maximum distance between detected points in two consecutive frames. Threshold in pixels.\n            max_skip (int, optional): Maximum number of frames along one track where no points are detected.\n            momentum (float, optional): Parameter in the range [0;1] that gives momentum to the tracking direction.\n            track_min_length (int, optional): Minimum number of points in a track.\n            coords (list, optional): List of numpy arrays with row and column indices of detected points. One per slice, which\n                                        means that z is gives as the index of the list.\n            std (float, optional): Standard deviation of the Gaussian filter.\n            min_distance (int, optional): Minimum distance between fibres.\n            threshold_abs (float, optional): Threshold value for the peak from the background.\n            weighted_avg (bool, optional): Whether to apply weighted average to the detected coordinates.\n            window_size (int, optional): Size of the neighbourhood window around the peak.\n            apply_filter (bool, optional): Whether to apply Gaussian filter to the window.\n            smoothtrack_gaussian (bool, optional): Whether to smooth tracks using Gaussian.\n            sigma (float, optional): Sigma value for Gaussian filter.\n            smoothtrack_watershed (bool, optional): Whether to smooth tracks using watershed.\n            threshold (float, optional): Threshold value for watershed.\n\n        Returns:\n            tracks (List[np.ndarray]): List of arrays of shape (n_points, 3) - each list contains coordinates of tracked fibers.\n\n        Example:\n            ```python\n            import fibretracker as ft\n\n            vol = ft.io.load(\"path/to/volume.txm\")\n            v = ft.io.normalize(vol)\n            coords = ft.models.get_fibre_coords(v)\n            tracks = ft.models.track_fibres(coords=coords)\n            ```\n            ```python\n            import fibretracker as ft\n\n            vol = ft.io.load(\"path/to/volume.txm\")\n            v = ft.io.normalize(vol)\n            coords = ft.models.get_fibre_coords(v)\n            tracks = ft.models.track_fibres(vol=v, coords=coords, smoothtrack_gaussian=True, sigma=3) # Smoothened tracks using Gaussian\n            ```\n\n\n    '''\n\n    fib_tracker = TrackPoints(max_jump=max_jump, max_skip=max_skip,\n                        momentum=momentum, track_min_length=track_min_length)\n\n    if coords is None:\n        coords = get_fibre_coords(vol, std=std, min_distance=min_distance, threshold_abs=threshold_abs, \n                                weighted_avg=weighted_avg, window_size=window_size, apply_filter=apply_filter)\n\n    tracks, _ = fib_tracker(coords)\n    if smoothtrack_gaussian:\n        print('Smoothing tracks using Gaussian')\n        tracks_smooth = []\n        for track in tracks:\n            tracks_smooth.append(gaussian_filter1d(track, sigma=sigma, axis=0))\n\n        return tracks_smooth\n\n    elif smoothtrack_watershed and vol is not None:\n        print('Smoothing tracks using watershed...')\n        tracks_filled = fib_tracker.fill_tracks(tracks)\n        if threshold is None:\n            threshold = threshold_otsu(vol[len(vol)//2])\n        V_thres = vol > threshold\n        V_dist = -distance_transform_edt(V_thres)\n        V_coords = np.zeros(vol.shape)\n        for i, track in enumerate(tracks_filled):\n            for point in track:\n                V_coords[int(point[2]), int(point[1]), int(point[0])] = i + 1\n        V_ws = watershed(V_dist, markers=V_coords.astype(int))*V_thres\n        print('Watershed volume created.')\n        n_fibers = V_ws.max()\n        tracks_smooth = [[] for i in range(n_fibers)]\n\n        for i, v_ws in enumerate(V_ws):\n            props = regionprops(v_ws)\n            for prop in props:\n                tracks_smooth[prop.label-1].append(list(prop.centroid[::-1]) + [i])\n            print(f'Smoothing tracks - iteration: {i+1}/{len(V_ws)}', end='\\r')\n\n        for i in range(n_fibers):\n            tracks_smooth[i] = np.array(tracks_smooth[i])\n\n        return tracks_smooth\n\n    else:\n        return tracks\n
      "},{"location":"viz/","title":"Visualise detected centre and tracked fibre","text":"

      To visualise volume accross the slice, detected centres and tracked fibre

      "},{"location":"viz/#fibretracker.viz","title":"fibretracker.viz","text":""},{"location":"viz/#fibretracker.viz.orthogonal","title":"fibretracker.viz.orthogonal","text":"
      orthogonal(vol, cmap='gray', img_height=5, img_width=5)\n

      Interactive widget for visualizing orthogonal slices of a 3D volume.

      Parameters:

      Name Type Description Default vol ndarray or Tensor

      The 3D volume to be sliced.

      required cmap str

      Specifies the color map for the image. Defaults to \"gray\".

      'gray' img_height(int, optional

      Height of the figure.

      required img_width(int, optional

      Width of the figure.

      required

      Returns:

      Name Type Description orthogonal_obj HBox

      The interactive widget for visualizing orthogonal slices of a 3D volume.

      Example

      import fibretracker as ft\n\nvol = ft.io.load(\"path/to/volume.txm\")\nft.viz.orthogonal(vol, cmap=\"gray\")\n

      Source code in fibretracker/viz/visualize.py
      def orthogonal(\n    vol: np.ndarray,\n    cmap: str = \"gray\",\n    img_height: int = 5,\n    img_width: int = 5\n)-> widgets.HBox:\n    \"\"\"Interactive widget for visualizing orthogonal slices of a 3D volume.\n\n    Args:\n        vol (np.ndarray or torch.Tensor): The 3D volume to be sliced.\n        cmap (str, optional): Specifies the color map for the image. Defaults to \"gray\".\n        img_height(int, optional): Height of the figure.\n        img_width(int, optional): Width of the figure.\n\n    Returns:\n        orthogonal_obj (widgets.HBox): The interactive widget for visualizing orthogonal slices of a 3D volume.\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        vol = ft.io.load(\"path/to/volume.txm\")\n        ft.viz.orthogonal(vol, cmap=\"gray\")\n        ```\n        ![viz orthogonal](figures/viz-orthogonal.gif)\n    \"\"\"\n\n    fig, ax = plt.subplots(1, 3, figsize=(3*img_width, img_height))\n    ax[0].axis(\"off\")\n    ax[1].axis(\"off\")\n    ax[2].axis(\"off\")\n\n    def _slice(slice_idx_z, slice_idx_y, slice_idx_x):\n        slice_img_z = vol.take(slice_idx_z, axis=0)\n        slice_img_y = vol.take(slice_idx_y, axis=1)\n        slice_img_x = vol.take(slice_idx_x, axis=2)\n\n        ax[0].imshow(slice_img_z, cmap=cmap)\n        ax[0].set_aspect('equal')\n        ax[1].imshow(slice_img_y, cmap=cmap)\n        ax[1].set_aspect('equal')\n        ax[2].imshow(slice_img_x, cmap=cmap)\n        ax[2].set_aspect('equal')\n\n    slice_slider_z = widgets.IntSlider(\n        value=vol.shape[0] // 2,\n        min=0,\n        max=vol.shape[0] - 1,\n        description=\"Z\",\n        continuous_update=True,\n    )\n\n    slice_slider_y = widgets.IntSlider(\n        value=vol.shape[1] // 2,\n        min=0,\n        max=vol.shape[1] - 1,\n        description=\"Y\",\n        continuous_update=True,\n    )\n\n    slice_slider_x = widgets.IntSlider(\n        value=vol.shape[2] // 2,\n        min=0,\n        max=vol.shape[2] - 1,\n        description=\"X\",\n        continuous_update=True,\n    )\n\n    slicer_obj = interactive(_slice, slice_idx_z=slice_slider_z, slice_idx_y=slice_slider_y, slice_idx_x=slice_slider_x)\n\n    # Create a horizontal box for the sliders\n    hbox = widgets.HBox([slicer_obj.children[0], slicer_obj.children[1], slicer_obj.children[2]], layout=widgets.Layout(align_items=\"stretch\", justify_content=\"center\", align_content=\"center\", justify_items=\"center\", justify_self=\"center\", align_self=\"center\", width=\"100%\"))\n\n    # Replace the sliders in the interactive widget with the horizontal box\n    slicer_obj.children = (hbox,) + slicer_obj.children[3:]\n\n    return slicer_obj\n
      "},{"location":"viz/#fibretracker.viz.slicer","title":"fibretracker.viz.slicer","text":"
      slicer(vol, detect_coords=None, mark_size=None, axis=0, cmap='gray', img_height=5, img_width=5)\n

      Interactive widget for visualizing slices of a 3D volume and fibres centre if provided.

      Parameters:

      Name Type Description Default vol ndarray

      The 3D volume to be sliced.

      required detect_coords list

      List of coordinates of detected fibres. Defaults to None.

      None mark_size int

      Size of the marker for detected fibres. Defaults to None.

      None axis int

      Specifies the axis, or dimension, along which to slice. Defaults to 0.

      0 cmap str

      Specifies the color map for the image. Defaults to \"gray\".

      'gray' img_height int

      Height of the figure. Defaults to 5.

      5 img_width int

      Width of the figure. Defaults to 5.

      5

      Returns:

      Name Type Description slicer_obj interactive

      The interactive widget for visualizing slices of a 3D volume.

      Example

      import fibretracker as ft\n\n# Load the volume and visualize the slices\nvol = ft.io.load(\"path/to/volume.txm\")\nft.viz.slicer(vol)\n

      import fibretracker as ft\n\n# Load the volume and detected coordinates\nvol = ft.io.load(\"path/to/volume.txm\")\nvol = ft.io.normalize(vol)\nvol = vol[100:350] # 250 slices along the z-axis\ndetect_coords = ft.models.get_fibre_coords(vol)\nft.viz.slicer(vol, detect_coords=detect_coords, mark_size=4)\n

      Source code in fibretracker/viz/visualize.py
      def slicer(\n    vol: np.ndarray,\n    detect_coords: Optional[List[np.ndarray]] = None,\n    mark_size: Optional[int] = None,\n    axis: int = 0,\n    cmap: str = \"gray\",\n    img_height: int = 5,\n    img_width: int = 5, \n) -> widgets.interactive:\n    \"\"\"Interactive widget for visualizing slices of a 3D volume and fibres centre if provided.\n\n    Args:\n        vol (np.ndarray): The 3D volume to be sliced.\n        detect_coords (list, optional): List of coordinates of detected fibres. Defaults to None.\n        mark_size (int, optional): Size of the marker for detected fibres. Defaults to None.\n        axis (int, optional): Specifies the axis, or dimension, along which to slice. Defaults to 0.\n        cmap (str, optional): Specifies the color map for the image. Defaults to \"gray\".\n        img_height (int, optional): Height of the figure. Defaults to 5.\n        img_width (int, optional): Width of the figure. Defaults to 5.\n\n    Returns:\n        slicer_obj (widgets.interactive): The interactive widget for visualizing slices of a 3D volume.\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        # Load the volume and visualize the slices\n        vol = ft.io.load(\"path/to/volume.txm\")\n        ft.viz.slicer(vol)\n        ```\n        ![viz slicer](figures/viz-slicer.gif)\n\n        ```python\n        import fibretracker as ft\n\n        # Load the volume and detected coordinates\n        vol = ft.io.load(\"path/to/volume.txm\")\n        vol = ft.io.normalize(vol)\n        vol = vol[100:350] # 250 slices along the z-axis\n        detect_coords = ft.models.get_fibre_coords(vol)\n        ft.viz.slicer(vol, detect_coords=detect_coords, mark_size=4)\n        ```\n\n        ![viz slicer](figures/viz-slicer_detector.gif)\n\n    \"\"\"\n\n    if detect_coords is None:\n        fig, ax = plt.subplots(figsize=(img_width, img_height))\n        ax.axis(\"off\")\n    else:\n        fig, ax = plt.subplots(1, 2, figsize=(2*img_width, img_height), sharex=True, sharey=True, gridspec_kw={'wspace': 0})\n        ax[0].axis(\"off\")\n        ax[1].axis(\"off\")\n\n    def _slice(slice_idx):\n        slice_img = vol.take(slice_idx, axis=axis)\n        if detect_coords is not None:\n            [l.remove() for l in ax[1].lines]\n            ax[0].imshow(slice_img, cmap=cmap)\n            ax[1].imshow(slice_img, cmap=cmap)\n            if mark_size is not None:\n                ax[1].plot(detect_coords[slice_idx][:, 0], detect_coords[slice_idx][:, 1], 'rx', markersize=mark_size)\n            else:\n                ax[1].plot(detect_coords[slice_idx][:, 0], detect_coords[slice_idx][:, 1], 'rx', markersize=3)\n        else:\n            ax.imshow(slice_img, cmap=cmap)\n\n    def on_release(event):\n        if detect_coords is not None:\n            xlim = ax[0].get_xlim()\n            ylim = ax[0].get_ylim()\n            ax[1].set_xlim(xlim)\n            ax[1].set_ylim(ylim)\n        else:\n            xlim = ax.get_xlim()\n            ylim = ax.get_ylim()\n\n    slice_slider = widgets.IntSlider(\n        value=vol.shape[axis] // 2,\n        min=0,\n        max=vol.shape[axis] - 1,\n        description=\"Slice\",\n        continuous_update=True,\n    )\n\n    slice_slider.style.description_width = 'middle'  # Set the width of the description to fit the larger font size\n    slice_slider.style.handle_color = 'blue'  # Optional: Change the handle color\n    slice_slider.style.font_size = '150px'  \n\n    fig.canvas.mpl_connect('button_release_event', on_release)\n    slicer_obj = interactive(_slice, slice_idx = slice_slider)\n\n    return slicer_obj\n
      "},{"location":"viz/#fibretracker.viz.plot_tracks","title":"fibretracker.viz.plot_tracks","text":"
      plot_tracks(tracks, grid=False)\n

      Plot tracks of fibres detected in the volume

      Parameters:

      Name Type Description Default tracks List[ndarray]

      List of arrays of shape (n_points, 3)

      required grid bool

      Whether to show grid in the plot

      False

      Returns:

      Name Type Description fig Figure

      matplotlib figure object

      Example
      import fibretracker as ft\n\n# Load the volume and detected coordinates\nvol = ft.io.load(\"path/to/volume.txm\")\nvol = ft.io.normalize(vol)\nvol = vol[100:350] # 250 slices along the z-axis\ndetect_coords = ft.models.get_fibre_coords(vol)\ntracks_gauss = ft.models.track_fibres(coords=detect_coords, smoothtrack_gaussian=True)\nft.viz.plot_tracks(tracks_gauss)\n

      Source code in fibretracker/viz/plotting.py
      def plot_tracks(\n        tracks: List[np.ndarray],\n        grid: bool = False,):\n\n    '''Plot tracks of fibres detected in the volume\n\n    Args:\n        tracks: List of arrays of shape (n_points, 3)\n        grid: Whether to show grid in the plot\n\n    Returns:\n        fig (matplotlib.figure.Figure): matplotlib figure object\n\n    Example:\n        ```python\n        import fibretracker as ft\n\n        # Load the volume and detected coordinates\n        vol = ft.io.load(\"path/to/volume.txm\")\n        vol = ft.io.normalize(vol)\n        vol = vol[100:350] # 250 slices along the z-axis\n        detect_coords = ft.models.get_fibre_coords(vol)\n        tracks_gauss = ft.models.track_fibres(coords=detect_coords, smoothtrack_gaussian=True)\n        ft.viz.plot_tracks(tracks_gauss)\n        ```\n\n        ![viz tracks](figures/tracks_gauss.gif)\n\n\n    '''\n    fig, ax = plt.subplots(figsize=(10, 10))\n    ax = fig.add_subplot(projection='3d')\n    for track in tracks:\n        ax.plot(track[:,0], track[:,1], track[:,2])\n    ax.grid(grid)\n    ax.set_aspect('equal')\n\n    plt.show()\n    return fig\n
      "},{"location":"notebooks/fibre_tracking/","title":"Example","text":"In\u00a0[1]: Copied!
      %matplotlib widget\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport fibretracker as ft\n
      %matplotlib widget import numpy as np import matplotlib.pyplot as plt import fibretracker as ft In\u00a0[2]: Copied!
      data_path = '/Users/pooja/Documents/PhD_work/ICPR_docs/data/Mock_UD_GFRP_data/UD-01_FoV_2_B2_recon.txm'\ndata_path1 = 'data/Mock_UD_GFRP_data/Mock-01_FoV_2_B2_recon.txm'\ndata_path2 = 'data/Mock_UD_GFRP_data/GFRP'\ndata_path3 = 'data/Mock_UD_GFRP_data/XCT_LR'\n\nV_UD = ft.io.load(data_path)\n# V_Mock = ft.io.load(data_path1)\n# V_GFRP = ft.io.load(data_path2, contains='.tif')\n# V_XCTLR = ft.io.load(data_path3, contains='.tif')\n\nV_norm = ft.io.normalize(V_UD).astype(float)\n
      data_path = '/Users/pooja/Documents/PhD_work/ICPR_docs/data/Mock_UD_GFRP_data/UD-01_FoV_2_B2_recon.txm' data_path1 = 'data/Mock_UD_GFRP_data/Mock-01_FoV_2_B2_recon.txm' data_path2 = 'data/Mock_UD_GFRP_data/GFRP' data_path3 = 'data/Mock_UD_GFRP_data/XCT_LR' V_UD = ft.io.load(data_path) # V_Mock = ft.io.load(data_path1) # V_GFRP = ft.io.load(data_path2, contains='.tif') # V_XCTLR = ft.io.load(data_path3, contains='.tif') V_norm = ft.io.normalize(V_UD).astype(float)
      astropy module not found\n
      In\u00a0[3]: Copied!
      ft.viz.slicer(V_norm, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.slicer(V_norm, img_height=7, img_width=7, cmap='gray') Out[3]:
      interactive(children=(IntSlider(value=499, description='Slice', max=998, style=SliderStyle(description_width='\u2026
      Figure In\u00a0[4]: Copied!
      V_tmp = V_norm[100:350, V_norm.shape[1]//2 - 250:V_norm.shape[1]//2 + 250, V_norm.shape[2]//2 - 250:V_norm.shape[2]//2 + 250]\n
      V_tmp = V_norm[100:350, V_norm.shape[1]//2 - 250:V_norm.shape[1]//2 + 250, V_norm.shape[2]//2 - 250:V_norm.shape[2]//2 + 250] In\u00a0[5]: Copied!
      ft.viz.slicer(V_tmp, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.slicer(V_tmp, img_height=7, img_width=7, cmap='gray') Out[5]:
      interactive(children=(IntSlider(value=125, description='Slice', max=249, style=SliderStyle(description_width='\u2026
      Figure In\u00a0[6]: Copied!
      ft.viz.orthogonal(V_tmp, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.orthogonal(V_tmp, img_height=7, img_width=7, cmap='gray') Out[6]:
      interactive(children=(HBox(children=(IntSlider(value=125, description='Z', max=249), IntSlider(value=250, desc\u2026
      Figure In\u00a0[7]: Copied!
      n_bins = int(255*(V_tmp.max() - V_tmp.min()) + 1)\nhist, bins = np.histogram(V_tmp, bins=n_bins)\nbin_width = bins[1] - bins[0]\nfig, ax = plt.subplots(1, figsize=(5, 5))\nax.bar(bins[:-1], hist, width=bin_width)\nax.set_xlabel('Intensity')\nax.set_ylabel('Frequency')\nax.set_title('Histogram of UD section volume')\nplt.show()\n
      n_bins = int(255*(V_tmp.max() - V_tmp.min()) + 1) hist, bins = np.histogram(V_tmp, bins=n_bins) bin_width = bins[1] - bins[0] fig, ax = plt.subplots(1, figsize=(5, 5)) ax.bar(bins[:-1], hist, width=bin_width) ax.set_xlabel('Intensity') ax.set_ylabel('Frequency') ax.set_title('Histogram of UD section volume') plt.show() Figure In\u00a0[9]: Copied!
      coords = ft.models.get_fibre_coords(V_tmp, std=2.5, min_distance=3, threshold_abs=0.6)\n
      coords = ft.models.get_fibre_coords(V_tmp, std=2.5, min_distance=3, threshold_abs=0.6)
                                            \r
      In\u00a0[10]: Copied!
      ft.viz.slicer(V_tmp, detect_coords=coords, mark_size=3, img_height=7, img_width=7, cmap='gray')\n
      ft.viz.slicer(V_tmp, detect_coords=coords, mark_size=3, img_height=7, img_width=7, cmap='gray') Out[10]:
      interactive(children=(IntSlider(value=125, description='Slice', max=249, style=SliderStyle(description_width='\u2026
      Figure In\u00a0[11]: Copied!
      # fibre can be tracked either directly from the volume or from the detected coordinates, or both[to avoid coordinate detection again]\n\ntracks = ft.models.track_fibres(coords=coords)\ntracks_gauss = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_gaussian=True, sigma=2)\ntracks_ws = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_watershed=True, threshold=0.6)\n\n# tracks = ft.models.track_fibres(V_tmp, smoothtrack_watershed=True, threshold=0.5)\n# tracks = ft.models.track_fibres(V_tmp, smoothtrack_gaussian=True)\n# tracks = ft.models.track_fibres(coords=coords)\n# tracks = ft.models.track_fibres(coords=coords, smoothtrack_gaussian=True)\n
      # fibre can be tracked either directly from the volume or from the detected coordinates, or both[to avoid coordinate detection again] tracks = ft.models.track_fibres(coords=coords) tracks_gauss = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_gaussian=True, sigma=2) tracks_ws = ft.models.track_fibres(V_tmp, coords=coords, smoothtrack_watershed=True, threshold=0.6) # tracks = ft.models.track_fibres(V_tmp, smoothtrack_watershed=True, threshold=0.5) # tracks = ft.models.track_fibres(V_tmp, smoothtrack_gaussian=True) # tracks = ft.models.track_fibres(coords=coords) # tracks = ft.models.track_fibres(coords=coords, smoothtrack_gaussian=True)
      Smoothing tracks using Gaussian       \nSmoothing tracks using watershed...   \nWatershed volume created.\nSmoothing tracks - iteration: 250/250\r
      In\u00a0[12]: Copied!
      ft.viz.plot_tracks(tracks)\n
      ft.viz.plot_tracks(tracks) Figure Out[12]:
      (<Figure size 1000x1000 with 2 Axes>, <Axes3D: >)
      In\u00a0[13]: Copied!
      ft.viz.plot_tracks(tracks_gauss)\n
      ft.viz.plot_tracks(tracks_gauss) Figure Out[13]:
      (<Figure size 1000x1000 with 2 Axes>, <Axes3D: >)
      In\u00a0[14]: Copied!
      ft.viz.plot_tracks(tracks_ws)\n
      ft.viz.plot_tracks(tracks_ws) Figure Out[14]:
      (<Figure size 1000x1000 with 2 Axes>, <Axes3D: >)
      "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index eacbc5b..4f17efb 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,42 +2,42 @@ https://ndpooja.github.io/fibretracker/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/CHANGELOG/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/detector/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/faq/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/io/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/tracker/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/viz/ - 2024-06-20 + 2024-06-21 daily https://ndpooja.github.io/fibretracker/notebooks/fibre_tracking/ - 2024-06-20 + 2024-06-21 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 5924c1cc3dfc3765a81799e8be35b39329f2934c..584c8baa57aaf46266b4327abc9646a3f0202890 100644 GIT binary patch delta 260 zcmV+f0sH=!0+#{@ABzYGfWmZ<2OWR9MMR~|BBJX-^rB};lW7~b&2*FOR{iy+?IOJ| zLY+%8kC(^CKqlLKwoP;d>ol62tZ70bFcOtERZiYsAL1*r;j8Rm8wWlLX5(^Fd*9tK z*7rSi+CwWkN6}Wy$vQNSokW(Vh`H=(}%`lTcOmmhT0--~B7=%GN|xk-K>^{^!W9(+8)^5s9P KLG$RW1pol7$$?z} delta 260 zcmV+f0sH=!0+#{@ABzYG0C97X2OWQE5m9NgETZc{^rB};lWCjXHq%YATlLqQwu|&G zLY+%8kC(^CKqgy%v`usZ>ol62T+oC>U?eJSs+_#NKE&5#%~#pcHV%9g%*N%U_P)Di ztnYj3w1-x7j-suYlXYkuJBuu#H-xXEP(#3U8!Ky2@*%~A7^6DGouHNW^|5rI8d<3e z3*HL32g@=xnCEYW^DQc#Ch29IT*YY;EN5+IleI7vlok$L3Eg~VY^F?5?1$