:orphan: Source: bactoscoop/omni.py ========================== .. raw:: html
  1# -*- coding: utf-8 -*-
     2"""
     3Created on Mon May 15 16:08:02 2023
     4
     5@author: Bart Steemans. Govers Lab.
     6"""
     7
     8from cellpose_omni import models, core, io
     9from cellpose_omni import models
    10from cellpose_omni.models import MODEL_NAMES
    11from numbers import Integral
    12
    13
    14class Omnipose:
    15
    16    def __init__(self, imgs, paths):
    17
    18        self.imgs = imgs
    19        self.files = paths
    20        self.use_GPU = core.use_gpu()
    21        self.masks = None
    22        self.flows = None
    23        self.selected_imgs = []
    24        self.selected_files = []
    25        self.model = None
    26        print(f">>> GPU activated? {self.use_GPU}")
    27
    28    def load_models(self, model_name):
    29        """
    30        Load the desired omnipose model.
    31
    32        """
    33        if self.model is None:
    34            self.model = models.CellposeModel(gpu=self.use_GPU, model_type=model_name)
    35
    36    def process(self, n=(0,), mask_thresh=1, minsize=300):
    37        """
    38        Segment the raw images and get their masks.
    39
    40        """
    41        chans = [0, 0]  # th is means segment based on first channel, no second channel
    42        mask_threshold = mask_thresh  # negative = mask becomes larger, positive = mask becomes thinner
    43        verbose = 0  # turn on if you want to see more output
    44        use_gpu = self.use_GPU  # defined above
    45        transparency = True  # transparency in flow output
    46        rescale = (
    47            None  # give this a number if you need to upscale or downscale your images
    48        )
    49        omni = True  # we can turn off Omnipose mask reconstruction, not advised
    50        flow_threshold = 0.0  # default is .4, but only needed if there are spurious masks to clean up; slows down output
    51        resample = (
    52            True  # whether or not to run dynamics on rescaled grid or original grid
    53        )
    54        batch_size = 1
    55        niter = None
    56        # diamter: too small -> oversegmentation, too large -> undersegmentation
    57        # if diameter = None, the diam will be estimated (in images from test-set )
    58        self.masks = None
    59        self.flows = None
    60        self.selected_imgs = []
    61        self.selected_files = []
    62        if len(self.imgs) != len(self.files):
    63            raise ValueError("Image and filename counts do not match")
    64        indices = list(range(len(self.imgs))) if n is None else list(n)
    65        if not indices:
    66            raise ValueError("At least one image must be selected for segmentation")
    67        if len(set(indices)) != len(indices) or any(
    68            not isinstance(i, Integral) or isinstance(i, bool)
    69            or i < 0 or i >= len(self.imgs) for i in indices
    70        ):
    71            raise ValueError("Segmentation indices must be unique valid image positions")
    72        self.selected_imgs = [self.imgs[i] for i in indices]
    73        self.selected_files = [self.files[i] for i in indices]
    74        self.masks, self.flows, styles = self.model.eval(
    75            self.selected_imgs,
    76            niter=niter,
    77            channels=chans,
    78            rescale=rescale,
    79            mask_threshold=mask_threshold,
    80            transparency=transparency,
    81            flow_threshold=flow_threshold,
    82            omni=omni,
    83            resample=resample,
    84            cluster=True,
    85            verbose=verbose,
    86            diameter=None,
    87            min_size=minsize,
    88            batch_size=batch_size,
    89        )
    90
    91    def save_masks(self):
    92        """
    93        Save the segmentation masks.
    94
    95        """
    96        if self.masks is None or self.flows is None:
    97            raise RuntimeError("Run process() successfully before saving masks")
    98        if len(self.masks) != len(self.selected_imgs) or len(self.flows) != len(self.selected_imgs):
    99            raise ValueError("Segmentation results do not match selected images")
   100        io.save_masks(
   101            self.selected_imgs,
   102            self.masks,
   103            self.flows,
   104            self.selected_files,
   105            png=False,
   106            tif=True,  # whether to use PNG or TIF format
   107            suffix="",  # suffix to add to files if needed
   108            save_flows=False,  # saves both RGB depiction as *_flows.png and the raw components as *_dP.tif
   109            save_outlines=False,  # save outline images
   110            dir_above=0,  # save output in the image directory or in the directory above (at the level of the image directory)
   111            in_folders=True,  # save output in folders (recommended)
   112            save_txt=False,  # txt file for outlines in imageJ
   113            save_ncolor=False,
   114        )  # save ncolor version of masks for visualization and editing
   115
   116    def compiled_process(self, n, mask_thresh, minsize):
   117        """
   118        Sequentially process and save the masks in one method.
   119        """
   120        self.process(n, mask_thresh, minsize)
   121        self.save_masks()