csi_images.csi_images API documentation

# csi_images.csi_images

View Source

      1import numpy as np
      2import pandas as pd
      3from skimage.measure import regionprops_table
      4
      5
      6def extract_mask_info(
      7    mask: np.ndarray,
      8    images: list[np.ndarray] = None,
      9    image_labels: list[str] = None,
     10    properties: list[str] = None,
     11) -> pd.DataFrame:
     12    """
     13    Extracts events from a mask. Originated from @vishnu
     14    :param mask: mask to extract events from
     15    :param images: list of intensity images to extract from
     16    :param image_labels: list of labels for images
     17    :param properties: list of properties to extract in addition to the defaults:
     18    label, centroid, axis_major_length. See
     19    https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops
     20    for additional properties.
     21    :return: pd.DataFrame with columns: id, x, y, size, or an empty DataFrame
     22    """
     23    # Return empty if the mask is empty
     24    if np.max(mask) == 0:
     25        return pd.DataFrame()
     26    # Reshape any intensity images
     27    if images is not None:
     28        if isinstance(images, list):
     29            images = np.stack(images, axis=-1)
     30        if image_labels is not None and len(image_labels) != images.shape[-1]:
     31            raise ValueError("Number of image labels must match number of images.")
     32    # Accumulate any extra properties
     33    base_properties = ["label", "centroid", "axis_major_length"]
     34    if properties is not None:
     35        properties = base_properties + properties
     36    else:
     37        properties = base_properties
     38
     39    # Use skimage.measure.regionprops_table to compute properties
     40    info = pd.DataFrame(
     41        regionprops_table(mask, intensity_image=images, properties=properties)
     42    )
     43
     44    # Rename columns to match desired output
     45    info = info.rename(
     46        columns={
     47            "label": "id",
     48            "centroid-0": "y",
     49            "centroid-1": "x",
     50            "axis_major_length": "size",
     51        },
     52    )
     53    renamings = {}
     54    for column in info.columns:
     55        for i in range(len(image_labels)):
     56            suffix = f"-{i}"
     57            if column.endswith(suffix):
     58                renamings[column] = f"{image_labels[i]}_{column[:-len(suffix)]}"
     59    info = info.rename(columns=renamings)
     60
     61    return info
     62
     63
     64def make_rgb(
     65    images: list[np.ndarray], colors=list[tuple[float, float, float]]
     66) -> np.ndarray:
     67    """
     68    Combine multiple channels into a single RGB image.
     69    :param images: list of numpy arrays representing the channels.
     70    :param colors: list of RGB tuples for each channel.
     71    :return:
     72    """
     73    if len(images) == 0:
     74        raise ValueError("No images provided.")
     75    if len(colors) == 0:
     76        raise ValueError("No colors provided.")
     77    if len(images) != len(colors):
     78        raise ValueError("Number of images and colors must match.")
     79    if not all([isinstance(image, np.ndarray) for image in images]):
     80        raise ValueError("Images must be numpy arrays.")
     81    if not all([len(c) == 3 for c in colors]):
     82        raise ValueError("Colors must be RGB tuples.")
     83
     84    # Create an output with same shape and larger type to avoid overflow
     85    dims = images[0].shape
     86    dtype = images[0].dtype
     87    if dtype not in [np.uint8, np.uint16]:
     88        raise ValueError("Image dtype must be uint8 or uint16.")
     89    rgb = np.zeros((*dims, 3), dtype=np.uint16 if dtype == np.uint8 else np.uint32)
     90
     91    # Combine images with colors (can also be thought of as gains)
     92    for image, color in zip(images, colors):
     93        if image.shape != dims:
     94            raise ValueError("All images must have the same shape.")
     95        if image.dtype != dtype:
     96            raise ValueError("All images must have the same dtype.")
     97        rgb[..., 0] += (image * color[0]).astype(rgb.dtype)
     98        rgb[..., 1] += (image * color[1]).astype(rgb.dtype)
     99        rgb[..., 2] += (image * color[2]).astype(rgb.dtype)
    100
    101    # Cut off any overflow and convert back to original dtype
    102    rgb = np.clip(rgb, np.iinfo(dtype).min, np.iinfo(dtype).max).astype(dtype)
    103    return rgb

def extract_mask_info( mask: numpy.ndarray, images: list[numpy.ndarray] = None, image_labels: list[str] = None, properties: list[str] = None) -> pandas.core.frame.DataFrame: View Source

     7def extract_mask_info(
     8    mask: np.ndarray,
     9    images: list[np.ndarray] = None,
    10    image_labels: list[str] = None,
    11    properties: list[str] = None,
    12) -> pd.DataFrame:
    13    """
    14    Extracts events from a mask. Originated from @vishnu
    15    :param mask: mask to extract events from
    16    :param images: list of intensity images to extract from
    17    :param image_labels: list of labels for images
    18    :param properties: list of properties to extract in addition to the defaults:
    19    label, centroid, axis_major_length. See
    20    https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops
    21    for additional properties.
    22    :return: pd.DataFrame with columns: id, x, y, size, or an empty DataFrame
    23    """
    24    # Return empty if the mask is empty
    25    if np.max(mask) == 0:
    26        return pd.DataFrame()
    27    # Reshape any intensity images
    28    if images is not None:
    29        if isinstance(images, list):
    30            images = np.stack(images, axis=-1)
    31        if image_labels is not None and len(image_labels) != images.shape[-1]:
    32            raise ValueError("Number of image labels must match number of images.")
    33    # Accumulate any extra properties
    34    base_properties = ["label", "centroid", "axis_major_length"]
    35    if properties is not None:
    36        properties = base_properties + properties
    37    else:
    38        properties = base_properties
    39
    40    # Use skimage.measure.regionprops_table to compute properties
    41    info = pd.DataFrame(
    42        regionprops_table(mask, intensity_image=images, properties=properties)
    43    )
    44
    45    # Rename columns to match desired output
    46    info = info.rename(
    47        columns={
    48            "label": "id",
    49            "centroid-0": "y",
    50            "centroid-1": "x",
    51            "axis_major_length": "size",
    52        },
    53    )
    54    renamings = {}
    55    for column in info.columns:
    56        for i in range(len(image_labels)):
    57            suffix = f"-{i}"
    58            if column.endswith(suffix):
    59                renamings[column] = f"{image_labels[i]}_{column[:-len(suffix)]}"
    60    info = info.rename(columns=renamings)
    61
    62    return info

Extracts events from a mask. Originated from @vishnu

###### Parameters

- mask: mask to extract events from
- images: list of intensity images to extract from
- image_labels: list of labels for images
- properties: list of properties to extract in addition to the defaults: label, centroid, axis_major_length. See https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops for additional properties.

###### Returns

> pd.DataFrame with columns: id, x, y, size, or an empty DataFrame

def make_rgb( images: list[numpy.ndarray], colors=list[tuple[float, float, float]]) -> numpy.ndarray: View Source

     65def make_rgb(
     66    images: list[np.ndarray], colors=list[tuple[float, float, float]]
     67) -> np.ndarray:
     68    """
     69    Combine multiple channels into a single RGB image.
     70    :param images: list of numpy arrays representing the channels.
     71    :param colors: list of RGB tuples for each channel.
     72    :return:
     73    """
     74    if len(images) == 0:
     75        raise ValueError("No images provided.")
     76    if len(colors) == 0:
     77        raise ValueError("No colors provided.")
     78    if len(images) != len(colors):
     79        raise ValueError("Number of images and colors must match.")
     80    if not all([isinstance(image, np.ndarray) for image in images]):
     81        raise ValueError("Images must be numpy arrays.")
     82    if not all([len(c) == 3 for c in colors]):
     83        raise ValueError("Colors must be RGB tuples.")
     84
     85    # Create an output with same shape and larger type to avoid overflow
     86    dims = images[0].shape
     87    dtype = images[0].dtype
     88    if dtype not in [np.uint8, np.uint16]:
     89        raise ValueError("Image dtype must be uint8 or uint16.")
     90    rgb = np.zeros((*dims, 3), dtype=np.uint16 if dtype == np.uint8 else np.uint32)
     91
     92    # Combine images with colors (can also be thought of as gains)
     93    for image, color in zip(images, colors):
     94        if image.shape != dims:
     95            raise ValueError("All images must have the same shape.")
     96        if image.dtype != dtype:
     97            raise ValueError("All images must have the same dtype.")
     98        rgb[..., 0] += (image * color[0]).astype(rgb.dtype)
     99        rgb[..., 1] += (image * color[1]).astype(rgb.dtype)
    100        rgb[..., 2] += (image * color[2]).astype(rgb.dtype)
    101
    102    # Cut off any overflow and convert back to original dtype
    103    rgb = np.clip(rgb, np.iinfo(dtype).min, np.iinfo(dtype).max).astype(dtype)
    104    return rgb

Combine multiple channels into a single RGB image.

###### Parameters

- images: list of numpy arrays representing the channels.
- colors: list of RGB tuples for each channel.

###### Returns