Coder Social home page Coder Social logo

livecellx's Introduction

LivecellX

Supported Python versions Development Status Documentation Status

LivecellX is a comprehensive deep learning live-cell analysis framework written in Python, designed specifically for segmenting, tracking, and analyzing single-cell trajectories in live-cell imaging datasets.

High-level abstract

single-cell; segmentation; correction; tracking; morphology; dynamics; biological process detection

Correct segmentation network

We address incorrect segmentation cases, particularly over-segmentation and under-segmentation cases, using a correction segmentation network (CSN) that follows a whole-image level segmentation provided by deep learning segmentation methods. The CSN framework simplifies the data collection process through active learning and a human-in-the-loop approach. To the best of our knowledge, we are providing the community with the first microscopy imaging correct segmentation dataset for over- and under- segmentation.

LivecellAction: biological process classification and detection based on deep learning

We provide a tool for users to annotate live-cell imaging datasets in Napari, and generate videos for deep learning training on video related tasks based on CNN or vision transformer based models.

To classify biological processes, we design a framework to classify and detect biological processes. We show case how to apply this framework by applying it to the single-cell mitosis trajectory classification task. Our framework achieves near-perfect detection accuracy, exceeding 99.99%, on label-free live-cell mitosis classification task. You can follow our Jupyter notebooks in ./notebooks to reproduce our results and apply the pretrained models to detect mitosis events in your dataset. This framework can be applied to other biological processes. The models we include and benchmark in our paper: temporal segment netowrks, timeSformer, visual transformer (ViT) and resnet50. We designed a programming interface to apply trained models to our single cell trajectory data structures.

For more information, installation instructions, and tutorials, please visit our official documentation.

Note: This repository is in a pre-alpha stage. While it currently showcases basic use-cases like image segmentation and cell tracking, our complete version is slated for release in Dec. 2023 alongside our manuscript and live-cell imaging annotated dataset. In the meantime, you may explore our previous pipeline repository maintained by Xing Lab.

Installation

General Requirements

If you encounter issues related to lap and numpy, or numba and numpy, please install numpy first, then lap. Follow the error messages to resolve any version conflicts between numba and numpy.

pip install -r requirements.txt
pip install -r napari_requirements.txt
pip install -e .  # -e option allows for an editable installation, useful for development

Pytorch and torchvision

Please refer to Pytorch Official Website to receive most recent installation instructions. Here we simply provide two examples used in our cases.

Install via pip:

conda install pytorch torchvision -c pytorch

On our 2080Ti/3090/4090 workstations and CUDA 11.7:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia

check if you are using cuda (refer to pytorch docs for TPU or other devices):

torch.cuda.is_available(), torch.cuda.current_device(), torch.cuda.device_count()

Detectron2 (optional)

Please refer to latest detectron2 documentation to install detectron2 for segmentation if you cannot build from source with the following commands.

Prebuilt (Easier and preferred by us):
https://detectron2.readthedocs.io/en/latest/tutorials/install.html#install-pre-built-detectron2-linux-only

Build from source:
https://detectron2.readthedocs.io/en/latest/tutorials/install.html#build-detectron2-from-source

git clone https://github.com/facebookresearch/detectron2.git
python -m pip install -e detectron2

For {avi, mp4} movie generation, ffmpeg is required. Conda installation cmd we used shown below. For other installation methods, please refer to the ffmpeg official website.

conda install -c conda-forge ffmpeg

Precommit [Dev]

pip install pre-commit
pre-commit install

livecellx's People

Contributors

dummyindex avatar mandyzhou807 avatar yajushikhurana avatar

Stargazers

 avatar  avatar Simen Chen avatar Gaohan avatar  avatar Yanshuo Chen avatar  avatar  avatar  avatar

Watchers

Shaoyi Zhang avatar  avatar  avatar Simen Chen avatar

Forkers

yuyoko

livecellx's Issues

SctOperator: add new single cell

Napari version: '0.4.17'

  1. Starting with 0 cells
  2. add one single cell, draw a contour and save
  3. the new shape does not show up in the napari UI; if users check the values in the notebook (sct_operator.shape_layer), everything looks fine, including napari shape_layer's data, face_color
  4. If users switch dimensions forth and back ONCE, the shape shows upKe worked on this issue and reviewed code. However, no clues for now. Adding refresh() does not work either.

SctOperator: daughter/mother relation after connecting/disconnecting

Describe the bug
From Gauhan:
"Find a potential bug:
While correcting the traj level, if first label the mother-daughter relation, then do the 'connect' or 'disconnect' to one daughter traj. The information in the mother_traj's 'daughter' set is not be updated. As the saved 'daughter_traj' id no longer in the traj_collection, so while doing 'inflate_other_trajectories' will lead to error. "

To Reproduce
Steps to reproduce the behavior:
Create Napari UI for sctc
create mother/daughter cell relation
delete or disconnect mother or daughter trajectories -> mother/daughter cell info not updated in related trajectories
save/load sctc

UI: show mother daughter IDs in cells

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Mitosis detection data prep: float infinity bug

`---------------------------------------------------------------------------
RemoteTraceback Traceback (most recent call last)
RemoteTraceback:
"""
Traceback (most recent call last):
File "c:\Users\dummy\anaconda3\envs\livecell-work\lib\multiprocessing\pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "D:\LiveCellTracker-dev\livecell_tracker\core\parallel.py", line 8, in wrap_func
return func(*args)
File "D:\LiveCellTracker-dev\livecell_tracker\core\sc_video_utils.py", line 26, in gen_mp4s_helper
video_frames, video_frame_masks = video_frames_and_masks_from_sample(sample, padding_pixels=padding_pixels)
File "D:\LiveCellTracker-dev\livecell_tracker\core\sc_video_utils.py", line 189, in video_frames_and_masks_from_sample
largest_bbox = [int(x) for x in largest_bbox]
File "D:\LiveCellTracker-dev\livecell_tracker\core\sc_video_utils.py", line 189, in
largest_bbox = [int(x) for x in largest_bbox]
OverflowError: cannot convert float infinity to integer
"""

The above exception was the direct cause of the following exception:

OverflowError Traceback (most recent call last)
Cell In[29], line 17
1 # # for debug
2 # train_class2samples = {key: value[:5] for key, value in all_class2samples.items()}
3 # test_class2samples = {key: value[:5] for key, value in all_class2samples.items()}
4 # padding_pixels = [20]
7 train_sample_info_df = gen_class2sample_samples(
8 train_class2samples,
9 train_class2sample_extra_info,
(...)
15 prefix="train",
16 )
---> 17 test_sample_info_df = gen_class2sample_samples(
18 test_class2samples,
19 test_class2sample_extra_info,
20 data_dir,
21 class_labels,
22 padding_pixels=padding_pixels,
23 frame_types=frame_types,
24 fps=fps,
25 prefix="test",
26 )
28 train_sample_info_df.to_csv(
29 data_dir / f"train_data.txt",
30 index=False,
31 header=False,
32 sep=" ",
33 )
34 test_sample_info_df.to_csv(
35 data_dir / f"test_data.txt",
36 index=False,
37 header=False,
38 sep=" ",
39 )

File D:\LiveCellTracker-dev\livecell_tracker\core\sc_video_utils.py:110, in gen_class2sample_samples(class2samples, class2sample_extra_info, data_dir, class_labels, padding_pixels, fps, frame_types, prefix)
108 video_frames_samples_info = class2sample_extra_info[class_label]
109 for padding_pixel in padding_pixels:
--> 110 frametype2paths, res_extra_info = gen_samples_mp4s(
111 video_frames_samples,
112 video_frames_samples_info,
113 class_label,
114 output_dir,
115 padding_pixels=padding_pixel,
116 fps=fps,
117 prefix=prefix,
118 )
119 for selected_frame_type in frame_types:
120 # mmaction_df = mmaction_df.append(pd.DataFrame([(str(path.name), class_labels.index(class_label), padding_pixel, selected_frame_type) for path in res_paths[selected_frame_type]], columns=["path", "label_index", "padding_pixels", "frame_type"]), ignore_index=True)
121 sample_info_df = pd.concat(
122 [
123 sample_info_df,
(...)
140 ]
141 )

File D:\LiveCellTracker-dev\livecell_tracker\core\sc_video_utils.py:88, in gen_samples_mp4s(sc_samples, samples_info_list, class_label, output_dir, fps, padding_pixels, prefix)
85 type2paths["combined"].append(combined_output_file)
87 res_extra_info.append(extra_sample_info)
---> 88 parallelize(gen_mp4s_helper, helper_input_args)
89 return type2paths, res_extra_info

File D:\LiveCellTracker-dev\livecell_tracker\core\parallel.py:16, in parallelize(func, inputs, cores)
14 pool = Pool(processes=cores)
15 outputs = []
---> 16 for output in tqdm.tqdm(pool.imap_unordered(partial(wrap_func, func), inputs), total=len(inputs)):
17 outputs.append(output)
18 pool.close()

File c:\Users\dummy\anaconda3\envs\livecell-work\lib\site-packages\tqdm\std.py:1195, in tqdm.iter(self)
1192 time = self._time
1194 try:
-> 1195 for obj in iterable:
1196 yield obj
1197 # Update and possibly print the progressbar.
1198 # Note: does not call self.update(1) for speed optimisation.

File c:\Users\dummy\anaconda3\envs\livecell-work\lib\multiprocessing\pool.py:870, in IMapIterator.next(self, timeout)
868 if success:
869 return value
--> 870 raise value

OverflowError: cannot convert float infinity to integer`

SctOperator: deletion + restore operation

  1. select deletion
  2. move contour in trajectories layer
  3. click delete
  4. restoration cannot recover the contour position because interval states of sct_operator is messed up. The self.original_* attributes are incorrect and set to the positions moved by the users.

Kernal crashed after running napari(sct_opeartor) on Ubuntu 20.04.6 LTS.

Describe the bug
While running 'tutorial_create_sct_operator_interval' under Ubuntu 20.04.6 LTS, after calling sct_opeartor kernal crashed. While tutorial from napari website works well. If under the same notebook, run napari website tutorial first then call sct_operator, issue solved.

To Reproduce
Steps to reproduce the behavior:
Part 1; error:

  1. Go to notebook "tutorial_create_sct_operator_interval"
  2. Run all
  3. See error
WARNING: QObject::moveToThread: Current thread (0x9564f60) is not the object's thread (0x9c71050).
Cannot move to target thread (0x9564f60)

WARNING: Could not load the Qt platform plugin "xcb" in "/home/gay17/anaconda3/envs/livecell/lib/python3.10/site-packages/cv2/qt/plugins" even though it was found.

The Kernel crashed while executing code in the the current cell or a previous cell. Please review the code in the cell(s) to identify a possible cause of the failure. Click [here](https://aka.ms/vscodeJupyterKernelCrash) for more info. View Jupyter [log](command:jupyter.viewOutput) for further details.

Part 2; solution:

  1. Go to notebook "tutorial_create_sct_operator_interval"
  2. Run napari website tutorial first, then close the GUI. Code attached:
# import sample data
from skimage.data import cells3d

import napari

# create a `Viewer` and `Image` layer here
viewer, image_layer = napari.imshow(cells3d())

# print shape of image datas
print(image_layer.data.shape)

# start the event loop and show the viewer
napari.run()
  1. See napari GUI

Desktop

  • OS: Ubuntu
  • Version: 20.04.6 LTS

UI: connect/disconnect and load -> mother/daughter cell info not updated

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Fix bug: napari add_shapes complain when the input shapes is an empty array

Napari version: '0.4.17'

IndexError                                Traceback (most recent call last)
Cell In[12], line 6
      2 span_interval = 10
      3 # viewer = create_scs_edit_viewer_by_interval(single_cells, img_dataset=dic_dataset, span_interval = 10, viewer = None)
      4 
      5 # manual segmentation
----> 6 viewer = create_scs_edit_viewer_by_interval([], img_dataset=dic_dataset, span_interval = 10, viewer = None)
      7 # for i in range(0, len(single_cells), span_interval):
      8 #     sct_operator = create_scs_edit_viewer(single_cells, img_dataset = dic_dataset, viewer = viewer, time_span=(i, i+span_interval))
      9 #     # set slice to the first frame of the span
     10 #     viewer.dims.set_point(0, i)
     11 #     # viewer.show(block=True)
     12 #     input("Press Enter to continue...")

File [D:\LiveCellTracker-dev\livecell_tracker\core\sct_operator.py:838](file:///D:/LiveCellTracker-dev/livecell_tracker/core/sct_operator.py:838), in create_scs_edit_viewer_by_interval(single_cells, img_dataset, span_interval, viewer, clear_prev_batch)
    835 def create_scs_edit_viewer_by_interval(single_cells, img_dataset: LiveCellImageDataset, span_interval=10, viewer=None, clear_prev_batch=True):
    836     # TODO: a potential bug is that the slice index is not the same concept as the time. A solution is to add time frame to shape properties
    837     # Here for now we assume indices represents timeframes
--> 838     sct_operator = create_scs_edit_viewer(
    839         single_cells, img_dataset=img_dataset, viewer=viewer, time_span=(0, span_interval)
    840     )
    841     viewer = sct_operator.viewer
    842     tmp_points_data_layer_key = "_lcx_sct_cur_idx"

File [D:\LiveCellTracker-dev\livecell_tracker\core\sct_operator.py:822](file:///D:/LiveCellTracker-dev/livecell_tracker/core/sct_operator.py:822), in create_scs_edit_viewer(single_cells, img_dataset, viewer, time_span)
    819 temp_sc_trajs_for_correct = create_sctc_from_scs(single_cells)
    821 # Create an SctOperator instance for editing the SingleCellStatic objects
--> 822 sct_operator = create_scts_operator_viewer(temp_sc_trajs_for_correct, img_dataset, viewer, time_span)
    823 return sct_operator

File [D:\LiveCellTracker-dev\livecell_tracker\core\sct_operator.py:791](file:///D:/LiveCellTracker-dev/livecell_tracker/core/sct_operator.py:791), in create_scts_operator_viewer(sctc, img_dataset, viewer, time_span)
    788     else:
    789         viewer = napari.Viewer()
--> 791 shape_layer = NapariVisualizer.gen_trajectories_shapes(sctc, viewer, contour_sample_num=20)
    792 shape_layer.mode = "select"
    793 sct_operator = SctOperator(sctc, shape_layer, viewer, img_dataset=img_dataset, time_span=time_span)

File [D:\LiveCellTracker-dev\livecell_tracker\core\napari_visualizer.py:64](file:///D:/LiveCellTracker-dev/livecell_tracker/core/napari_visualizer.py:64), in NapariVisualizer.gen_trajectories_shapes(trajectories, viewer, bbox, contour_sample_num, viewer_kwargs, text_parameters, layer_name)
     62 # Track ID can be UUID, so we need to map it to an integer
     63 track_value_indices = [idx for idx, v in enumerate(track_ids)]
---> 64 shape_layer = viewer.add_shapes(
     65     # all_shapes if len(all_shapes) > 0 else None,
     66     all_shapes,
     67     properties=properties,
     68     face_color=NapariVisualizer.map_colors(track_value_indices),
     69     face_colormap="viridis",
     70     shape_type="polygon",
     71     text=text_parameters,
     72     name=layer_name,
     73     **viewer_kwargs
     74 )
     75 return shape_layer

File [c:\Users\dummy\anaconda3\envs\livecell-work\lib\site-packages\napari\components\viewer_model.py:4](file:///C:/Users/dummy/anaconda3/envs/livecell-work/lib/site-packages/napari/components/viewer_model.py:4), in add_shapes(self, data, ndim, features, properties, property_choices, text, shape_type, edge_width, edge_color, edge_color_cycle, edge_colormap, edge_contrast_limits, face_color, face_color_cycle, face_colormap, face_contrast_limits, z_index, name, metadata, scale, translate, rotate, shear, affine, opacity, blending, visible, cache, experimental_clipping_planes)
      1 from __future__ import annotations
      3 import inspect
----> 4 import itertools
      5 import os
      6 import warnings

File [c:\Users\dummy\anaconda3\envs\livecell-work\lib\site-packages\napari\layers\shapes\shapes.py:408](file:///C:/Users/dummy/anaconda3/envs/livecell-work/lib/site-packages/napari/layers/shapes/shapes.py:408), in Shapes.__init__(self, data, ndim, features, properties, property_choices, text, shape_type, edge_width, edge_color, edge_color_cycle, edge_colormap, edge_contrast_limits, face_color, face_color_cycle, face_colormap, face_contrast_limits, z_index, name, metadata, scale, translate, rotate, shear, affine, opacity, blending, visible, cache, experimental_clipping_planes)
    406 else:
    407     data, shape_type = extract_shape_type(data, shape_type)
--> 408     data_ndim = get_shape_ndim(data)
    409     if ndim is not None and ndim != data_ndim:
    410         raise ValueError(
    411             trans._(
    412                 "Shape dimensions must be equal to ndim",
    413                 deferred=True,
    414             )
    415         )

File [c:\Users\dummy\anaconda3\envs\livecell-work\lib\site-packages\napari\layers\shapes\_shapes_utils.py:1062](file:///C:/Users/dummy/anaconda3/envs/livecell-work/lib/site-packages/napari/layers/shapes/_shapes_utils.py:1062), in get_shape_ndim(data)
   1060     ndim = np.array(data).shape[2]
   1061 # just one shape
-> 1062 elif np.array(data[0]).ndim == 1:
   1063     ndim = np.array(data).shape[1]
   1064 # list of different shapes
   1065 else:

IndexError: list index out of range

SctOperator: after adding a new single cell, napari Shapes cannot load text's track_id issue

Napari version: '0.4.18'
Describe the bug

[c:\Users\dummy\anaconda3\envs\livecell-work\lib\site-packages\napari\layers\utils\style_encoding.py:258](file:///C:/Users/dummy/anaconda3/envs/livecell-work/lib/site-packages/napari/layers/utils/style_encoding.py:258): RuntimeWarning: Applying the encoding failed. Using the safe fallback value instead.
  warnings.warn(
[c:\Users\dummy\anaconda3\envs\livecell-work\lib\site-packages\napari\layers\utils\style_encoding.py:258](file:///C:/Users/dummy/anaconda3/envs/livecell-work/lib/site-packages/napari/layers/utils/style_encoding.py:258): RuntimeWarning: Applying the encoding failed. Using the safe fallback value instead.
  warnings.warn(

And the warning is from:

    def _call_safely(self, features: Any) -> StyleArray:
        """Calls this without raising encoding errors, warning instead."""
        try:
            array = self(features)
        except (KeyError, ValueError):
            warnings.warn(
                trans._(
                    'Applying the encoding failed. Using the safe fallback value instead.',
                    deferred=True,
                ),
                category=RuntimeWarning,
            )
            shape = (features.shape[0], *self.fallback.shape)
            array = np.broadcast_to(self.fallback, shape)
        return array

To fix the problem, I tried:
shape_layer.text = "{track_id}" works;
shape_layer.text = "{status}" works;
shape_layer.text = "{track_id}\n{status}" works;
shape_layer.text = "{track_id:0.0f}\n{status}" works;
shape_layer.text = "{track_id:d}" does not work
shape_layer.text = "{track_id:d}\n{status}" does not work;

To Reproduce
Steps to reproduce the behavior:

  1. Go to Napari UI, created by create_sctc_edit_viewer_by_interval
  2. Click on "add new sc"
  3. Remove sc seg operator
  4. there is no text for each single cell in trajectories layer now

Expected behavior
Texts showing track_id and status should remain there after adding a new single cell.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):
Windows 10

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.