Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mobie/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""Lorem ipsum
"""

from .image_data import add_image, add_bdv_image
from .open_organelle import add_open_organelle_data
from .registration import add_registered_source
Expand Down
6 changes: 4 additions & 2 deletions mobie/experimental.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""@private
"""
import warnings

import numpy as np
Expand Down Expand Up @@ -114,7 +116,7 @@ def create_slice_grid(
):
"""Create a grid that aligns n slices of a source shifted so that each n-th slice is aligned with the origin.

Arguments:
Args:
dataset_folder [str] -
source [str] -
n_slices [int] -
Expand Down Expand Up @@ -161,7 +163,7 @@ def create_slice_grid_with_reference_view(
The reference view will be used to derive initial transformation, display settigns and
other view specific parameters, unless over-written by a more explicit parameter.

Arguments:
Args:
dataset_folder [str] -
source [str] -
reference_view [str] -
Expand Down
Empty file removed mobie/export_data/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions mobie/htm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""Functionality for creating MoBIE projects with high throughput microscopy (HTM) / high content microscopy data.
"""

from .data_import import add_images, add_segmentations
from .grid_views import add_plate_grid_view, get_merged_plate_grid_view
from .utils import compute_contrast_limits
106 changes: 87 additions & 19 deletions mobie/htm/data_import.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Functionality for creating sources from high content microscopy data.
"""
import multiprocessing
import os
from typing import List, Optional, Sequence

import luigi
import cluster_tools.utils.volume_utils as vu
Expand Down Expand Up @@ -84,12 +87,44 @@ def _add_sources(dataset_folder, source_names, paths,
table_folder=table_folder, view={})


def add_images(files, root,
dataset_name, image_names,
resolution, scale_factors, chunks,
key=None, file_format="ome.zarr",
tmp_folder=None, target="local", max_jobs=multiprocessing.cpu_count(),
unit="micrometer", is_default_dataset=False, is2d=None):
def add_images(
files: Sequence[str],
root: str,
dataset_name: str,
image_names: Sequence[str],
resolution: Sequence[float],
scale_factors: List[List[int]],
chunks: Sequence[int],
key: Optional[str] = None,
file_format: str = "ome.zarr",
tmp_folder: Optional[str] = None,
target: str = "local",
max_jobs: int = multiprocessing.cpu_count(),
unit: str = "micrometer",
is_default_dataset: bool = False,
is2d: Optional[bool] = None,
) -> None:
"""Add images from a high-content microscopy experiment to a MoBIE dataset.

Args:
files: The input image files.
root: The root directory of the MoBIE project.
dataset_name: The name of the MoBIE dataset.
image_names: The names of the images.
resolution: The resolution in physical units.
scale_factors: The scale factors to use for downsampling the data.
chunks: The chunk size for the internal data format.
key: The key / internal file path for the input image data.
This is only required for hdf5, n5, zarr data; but not for tif or simlar.
file_format: The internal file format to use.
tmp_folder: The temporary folder for data conversion.
target: The computational target.
max_jobs: The number of jobs for parallelization.
unit: The physical unit of the coordinate system.
is_default_dataset: Whether this is the default dataset.
Only relevant if the dataset will be created.
is2d: Whether this is a 2D datasets.
"""
assert len(files) == len(image_names), f"{len(files)}, {len(image_names)}"

# require the dataset
Expand All @@ -107,17 +142,49 @@ def add_images(files, root,

# add metadata for all the images
if source_names:
_add_sources(os.path.join(root, dataset_name), source_names, metadata_paths,
file_format, "image")


def add_segmentations(files, root,
dataset_name, segmentation_names,
resolution, scale_factors, chunks,
key=None, file_format="ome.zarr",
tmp_folder=None, target="local", max_jobs=multiprocessing.cpu_count(),
add_default_tables=True, unit="micrometer",
is_default_dataset=False, is2d=None):
_add_sources(os.path.join(root, dataset_name), source_names, metadata_paths, file_format, "image")


def add_segmentations(
files: Sequence[str],
root: str,
dataset_name: str,
segmentation_names: Sequence[str],
resolution: Sequence[float],
scale_factors: List[List[int]],
chunks: Sequence[int],
key: Optional[str] = None,
file_format: str = "ome.zarr",
tmp_folder: Optional[str] = None,
target: str = "local",
max_jobs: int = multiprocessing.cpu_count(),
add_default_tables: bool = True,
unit: str = "micrometer",
is_default_dataset: bool = False,
is2d: Optional[bool] = None,
) -> None:
"""Add segmentation data for a high-content microscopy experiment to a MoBIE dataset.

Args:
files: The input segmentation files.
root: The root directory of the MoBIE project.
dataset_name: The name of the MoBIE dataset.
segmentation_names: The names of the segmentations.
resolution: The resolution in physical units.
scale_factors: The scale factors to use for downsampling the data.
chunks: The chunk size for the internal data format.
key: The key / internal file path for the input image data.
This is only required for hdf5, n5, zarr data; but not for tif or simlar.
file_format: The internal file format to use.
tmp_folder: The temporary folder for data conversion.
target: The computational target.
max_jobs: The number of jobs for parallelization.
add_default_tables: Whether to create the default segmentation tables.
unit: The physical unit of the coordinate system.
is_default_dataset: Whether this is the default dataset.
Only relevant if the dataset will be created.
is2d: Whether this is a 2D datasets.
"""
assert len(files) == len(segmentation_names)

# require the dataset
Expand All @@ -144,5 +211,6 @@ def add_segmentations(files, root,

# add metadata for all the images
if source_names:
_add_sources(os.path.join(root, dataset_name), source_names, metadata_paths,
file_format, "segmentation", table_folders)
_add_sources(
os.path.join(root, dataset_name), source_names, metadata_paths, file_format, "segmentation", table_folders
)
64 changes: 55 additions & 9 deletions mobie/htm/grid_views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""Functionality to create grid views for high content microscopy data.
"""
import os
from typing import Callable, Dict, Sequence, Optional

import mobie
import numpy as np
Expand Down Expand Up @@ -67,6 +70,8 @@ def get_transformed_plate_grid_view(metadata, source_prefixes,
well_to_position=None, name_filter=None,
sites_visible=True, wells_visible=True,
add_region_displays=True):
"""@private
"""
assert len(source_prefixes) == len(source_types) == len(source_settings)
this_sources, site_names = _get_sources_and_site_names(metadata, source_prefixes,
source_name_to_site_name, name_filter)
Expand Down Expand Up @@ -152,6 +157,8 @@ def get_merged_plate_grid_view(metadata, source_prefixes, source_types,
well_to_position=None, name_filter=None,
sites_visible=True, wells_visible=True,
add_region_displays=True):
"""@private
"""
assert len(source_prefixes) == len(source_types) == len(source_settings)
this_sources, site_names = _get_sources_and_site_names(metadata, source_prefixes,
source_name_to_site_name, name_filter)
Expand Down Expand Up @@ -313,15 +320,54 @@ def _require_table_source(ds_folder, metadata, table, name):
return metadata, name


def add_plate_grid_view(ds_folder, view_name, menu_name,
source_prefixes, source_types, source_settings,
source_name_to_site_name,
site_name_to_well_name,
site_table=None, well_table=None,
well_to_position=None, name_filter=None,
sites_visible=True, wells_visible=True,
add_region_displays=True,
use_transformed_grid=False):
def add_plate_grid_view(
ds_folder: str,
view_name: str,
menu_name: str,
source_prefixes: Sequence[str],
source_types: Sequence[str],
source_settings: Sequence[Dict],
source_name_to_site_name: Callable,
site_name_to_well_name: Callable,
site_table: Optional[str] = None,
well_table: Optional[str] = None,
well_to_position: Optional[Dict] = None,
name_filter: Optional[Callable] = None,
sites_visible: bool = True,
wells_visible: bool = True,
add_region_displays: bool = True,
use_transformed_grid: bool = False,
) -> None:
"""Add a grid view that describes a plate layout for a high content microscopy experiment.

MoBIE assumes that high content microscopy data is organized in sites, corresponding to individual
image locations, and wells, which may contain multiple sites. For example, a typical plate layout
is a 96 well plate, which contains 9 sites (a 3 x 3 grid) per well. For such a plate, the typical
site and well names are 'A01' (well name) and 'A01-1' (well and site name). When using this function,
you have to pass 'source_name_to_site_name', which extracts the site name (e.g. 'A01-1') from the source name
and `site_name_to_well_name`, which extracts the well name from the site name.

Args:
ds_folder: The folder of the MoBIE dataset where this view will be added.
view_name: The name of the view.
menu_name: The name of the menu where the view will be added.
source_prefixes: The prefixes of the sources that will be added to this view.
Each prefix will be mapped to a separate group of images in the view.
source_types: The respective source types of the prefixes. Must be of the same length as 'source_prefixes'.
source_settings: The settings for the source views. Must be of the same length as 'source_prefixes'.
source_name_to_site_name: A function that maps each source name to their site name.
site_name_to_well_name: A function that maps each site to their well name.
site_table: An optional path for a table that contains site-level information.
well_table: An optional path for a table that contains well-level information.
well_to_position: An optional dictionary that maps each well to a global position.
If not given, the wells will be placed on an ordinary grid.
name_filter: An optional function to filter out sources that should not be added to the view.
sites_visible: Whether the site overlay is visible by default.
wells_visible: Whether the well overlay is visible by default.
add_region_displays: Whether to add the region displays for sites and wells.
use_transformed_grid: Whether to use the transformed grid or merged grid transformation of MoBIE.
The transformed gird enables more flexible transformations, but is less efficient than the merged one.
"""
metadata = mobie.metadata.read_dataset_metadata(ds_folder)

if site_table is None and add_region_displays:
Expand Down
5 changes: 4 additions & 1 deletion mobie/htm/table_impl.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#! /bin/python

"""@private
"""

import os
import sys
import json
Expand All @@ -21,7 +24,7 @@
#

class TableImplBase(luigi.Task):
""" table_impl base class
"""table_impl base class
"""

task_name = "table_impl"
Expand Down
27 changes: 24 additions & 3 deletions mobie/htm/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Helper functions for the high content microscopy functionality.
"""
import json
import os
from concurrent import futures
from typing import List, Optional

import numpy as np
from elf.io import open_file
Expand All @@ -9,8 +12,26 @@


def compute_contrast_limits(
source_prefix, dataset_folder, lower_percentile, upper_percentile, n_threads, cache_path=None
):
source_prefix: str,
dataset_folder: str,
lower_percentile: float,
upper_percentile: float,
n_threads: int,
cache_path: Optional[str] = None,
) -> List[float]:
"""Compute the contrast limits for images of a high content microscopy screen.

Args:
source_prefix: The source prefix for selecting the images to use for contrast limit computation.
dataset_folder: The folder of the MoBIE dataset.
lower_percentile: The lower percentile for computing the contrast limit.
upper_precentile: The upper percentile for computing the contrast limit.
n_threads: The number of threads to use in the computation.
cache_path: An optional path for caching the compuation result.

Returns:
The upper and lower contrast limit.
"""
if cache_path is not None and os.path.exists(cache_path):
with open(cache_path) as f:
return json.load(f)
Expand All @@ -25,7 +46,7 @@ def compute_clim_im(source_name):
data = f["s0"][:]
cmin = np.percentile(data, lower_percentile)
cmax = np.percentile(data, upper_percentile)
return cmin, cmax
return [cmin, cmax]

source_names = [name for name in sources.keys() if name.startswith(source_prefix)]
with futures.ThreadPoolExecutor(n_threads) as tp:
Expand Down
Loading