Skip to content
Open
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
2 changes: 1 addition & 1 deletion formats/image-dimension-stacking-tool/.bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.2
current_version = 0.2.0-dev0
commit = True
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+)(?P<dev>\d+))?
Expand Down
38 changes: 19 additions & 19 deletions formats/image-dimension-stacking-tool/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
# Image dimension stacking(0.1.2)
# Image dimension stacking(0.2.0-dev0)

This plugin leverages the [filepattern](https://filepattern2.readthedocs.io/en/latest/Home.html) library and employs the filepattern `groupBy` functionality to enable the matching of image filenames, facilitating their stacking into multi-dimensional images.

The filepattern must include the variables `c`, `t`, and `z`. If all these variables are present in the pattern, the plugin will group images according to the order `z, c, t`. If only one variable is present in the file pattern, the plugin will group images according to that variable.


Currently, the plugin supports the following dimensions and user can choose the relevant variable for the `groupBy` input argument.
1. `tubhiswt_z{z:d+}_c{c:d+}_t{t:d+}.ome.tif`\
Images are grouped based on `z` variable
2. `tubhiswt_.*_.*_t{t:d+}.ome.tif`\
Images are grouped based on `t` variable
3. `00001_01_{c:d+}.ome.tif`\
Images are grouped based on `c` variable

#### Note:

1. `tubhiswt_z{z:d+}_c{c:d+}_t{t:d+}.ome.tif`: Images are grouped based on `z` variable
2. `tubhiswt_.*_.*_t{t:d+}.ome.tif`: Images are grouped based on `t` variable
3. `00001_01_{c:d+}.ome.tif`: Images are grouped based on `c` variable

## Note:

Filename patterns may consist of any other filepattern variables, combined with other valid regular expression arguments, excluding the `groupBy` variable.

For more information on WIPP, visit the
Expand All @@ -33,18 +31,20 @@ contents of `plugin.json` into the pop-up window and submit.

This plugin takes three input argument and one output argument:

| Name | Description | I/O | Type |
|---------------|-------------------------|--------|--------|
| `--inpDir` | Input image collection | Input | Collection |
| `--filePattern` | Pattern to parse image files | Input | String |
| `--outDir` | Output image collection | Output | Collection |
| `--preview` | Generate a JSON file to view outputs | Output | Boolean |
| Name | Description | I/O | Type |
| --------------- | ------------------------------------ | ------ | ---------- |
| `--inpDir` | Input image collection | Input | Collection |
| `--filePattern` | Pattern to parse image files | Input | String |
| `--axis` | Dimension to stack images | Input | String |
| `--outDir` | Output image collection | Output | Collection |
| `--preview` | Generate a JSON file to view outputs | Output | Boolean |

### Run the Docker Container
## Run the Docker Container

```bash
docker run -v /path/to/data:/data polusai/image-dimension-stacking-plugin:0.1.2-dev \
--inpDir "Path/To/Data" \
docker run -v /path/to/data:/data polusai/image-dimension-stacking-plugin:0.2.0-dev0-dev \
--inpDir "path/to/data" \
--filePattern "tubhiswt_C1-z{z:d+}.ome.tif" \
--axis "z" \
--outDir "Path/To/Output/Dir"
```
2 changes: 1 addition & 1 deletion formats/image-dimension-stacking-tool/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.2
0.2.0-dev0
15 changes: 13 additions & 2 deletions formats/image-dimension-stacking-tool/ict.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
author:
- Nick Schaub
- Hamdah Shafqat Abbasi
- Najib Ishaq
contact: nick.schaub@nih.gov
container: polusai/image-dimension-stacking-tool:0.1.2
container: polusai/image-dimension-stacking-tool:0.2.0-dev0
description: Stacking of image dimensions (c, z, t) to create a multidimensional image.
entrypoint: python3 -m polus.images.formats.image_dimension_stacking
inputs:
Expand All @@ -18,6 +19,12 @@ inputs:
name: filePattern
required: true
type: string
- description: The axis to stack the images on. One of 'c', 'z', or 't'.
format:
- string
name: axis
required: true
type: string
- description: Generate an output preview
format:
- boolean
Expand All @@ -44,8 +51,12 @@ ui:
key: inputs.filePattern
title: Filename pattern
type: text
- description: The axis to stack the images on. One of 'c', 'z', or 't'.
key: inputs.axis
title: Axis
type: text
- description: Generate an output preview
key: inputs.preview
title: Generate preview
type: boolean
version: 0.1.2-dev0
version: 0.2.0-dev0-dev0
18 changes: 16 additions & 2 deletions formats/image-dimension-stacking-tool/plugin.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "Image Dimension Stacking",
"version": "0.1.2",
"version": "0.2.0-dev0",
"title": "Stacking of image dimensions (c, z, t) to create a multidimensional image.",
"description": "Stacking of image dimensions (c, z, t) to create a multidimensional image.",
"author": "Nick Schaub (nick.schaub@nih.gov), Hamdah Shafqat Abbasi (hamdahshafqat.abbasi@nih.gov)",
"institution": "National Center for Advancing Translational Sciences, National Institutes of Health",
"repository": "https://github.com/PolusAI/image-tools",
"website": "https://ncats.nih.gov/preclinical/core/informatics",
"containerId": "polusai/image-dimension-stacking-tool:0.1.2",
"containerId": "polusai/image-dimension-stacking-tool:0.2.0-dev0",
"baseCommand": [
"python3",
"-m",
Expand All @@ -26,6 +26,13 @@
"description": "Filename pattern used to separate data.",
"required": "True"
},
"axis": {
"type": "string",
"title": "Axis",
"description": "Axis to stack. One of 'c', 'z', 't'.",
"required": "False",
"default": "z"
},
"preview": {
"type": "boolean",
"title": "Preview",
Expand All @@ -52,6 +59,13 @@
"description": "Filename pattern used to separate data.",
"required": "True"
},
"axis": {
"type": "string",
"title": "Axis",
"description": "Axis to stack. One of 'c', 'z', 't'.",
"required": "False",
"default": "z"
},
"preview": {
"type": "boolean",
"title": "Preview example output of this plugin",
Expand Down
20 changes: 8 additions & 12 deletions formats/image-dimension-stacking-tool/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "polus-images-formats-image-dimension-stacking"
version = "0.1.2"
version = "0.2.0-dev0"
description = "Stacking multi-dimensional images"
authors = [
"Nick Schaub <nick.schaub@nih.gov>",
Expand All @@ -12,24 +12,20 @@ packages = [{include = "polus", from = "src"}]

[tool.poetry.dependencies]
python = ">=3.9,<3.12"
bfio = {version = "2.4.1", extras = ["all"]}
bfio = {version = "2.4.3", extras = ["all"]}
typer = "^0.7.0"
tqdm = "^4.66.1"
filepattern = "^2.0.4"
pydantic = "^1.10.4"
preadator="0.4.0.dev2"
numpy = "<2.0.0"
numpy = ">=2.0,<2.1"

[tool.poetry.group.dev.dependencies]
bump2version = "^1.0.1"
flake8 = "^6.0.0"
pre-commit = "^3.2.1"
flake8-docstrings = "^1.7.0"
black = "^23.3.0"
mypy = "^1.1.1"
pytest = "^7.2.2"
ruff = "^0.0.270"
scikit-image = "^0.22.0"
pytest = "^8.3.2"
pytest-sugar = "^1.0.0"
pytest-xdist = "^3.6.1"
scikit-image = "^0.24.0"
scipy = "<1.14"

[build-system]
requires = ["poetry-core"]
Expand Down
4 changes: 3 additions & 1 deletion formats/image-dimension-stacking-tool/run-plugin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ datapath=$(readlink --canonicalize ../data)

# Inputs
inpDir=/data/path_to_files

filePattern="tubhiswt_z{z:d+}_c{c:d+}_t{t:d+}.ome.tif"
axis="Z"

# Output paths
outDir=/data/path_to_output

Expand All @@ -19,4 +20,5 @@ docker run --mount type=bind,source=${datapath},target=/data/ \
polusai/image-dimension-stacking-plugin:${version} \
--inpDir ${inpDir} \
--filePattern ${filePattern} \
--axis ${axis} \
--outDir ${outDir}
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
"""Image dimension stacking package."""

__version__ = "0.1.2"
from . import utils
from .dimension_stacking import copy_stack
from .dimension_stacking import write_stack

__version__ = "0.2.0-dev0"

__all__ = [
"utils",
"copy_stack",
"write_stack",
"__version__",
]
Original file line number Diff line number Diff line change
@@ -1,110 +1,105 @@
"""Image dimension stacking package."""

import json
import logging
import os
import pathlib
import warnings
from os import environ
from pathlib import Path
from typing import Any

import filepattern as fp
import polus.images.formats.image_dimension_stacking.dimension_stacking as st
import filepattern
import tqdm
import typer
from polus.images.formats.image_dimension_stacking import copy_stack
from polus.images.formats.image_dimension_stacking import utils
from polus.images.formats.image_dimension_stacking import write_stack

warnings.filterwarnings("ignore")

logging.basicConfig(
format="%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s",
datefmt="%d-%b-%y %H:%M:%S",
)
POLUS_LOG = getattr(logging, environ.get("POLUS_LOG", "INFO"))
logger = logging.getLogger("polus.plugins.formats.image_dimension_stacking")
POLUS_LOG = getattr(logging, os.environ.get("POLUS_LOG", "INFO"))
logger = logging.getLogger("polus.images.formats.image_dimension_stacking")
logger.setLevel(POLUS_LOG)
logging.getLogger("bfio").setLevel(POLUS_LOG)


app = typer.Typer(help="Stack multi dimensional image into single image.")


def generate_preview(out_dir: Path, file_pattern: str) -> None:
"""Generate preview of the plugin outputs."""
with Path.open(Path(out_dir, "preview.json"), "w") as jfile:
out_json: dict[str, Any] = {
"filepattern": file_pattern,
"outDir": [],
}

fps = fp.FilePattern(out_dir, file_pattern)
out_name = fps.output_name()
out_json["outDir"].append(out_name)
json.dump(out_json, jfile, indent=2)
app = typer.Typer()


@app.command()
def main(
inp_dir: Path = typer.Option(
inp_dir: pathlib.Path = typer.Option(
...,
"--inpDir",
"-i",
help="Path to input directory containing binary images.",
exists=True,
readable=True,
resolve_path=True,
file_okay=False,
dir_okay=True,
),
file_pattern: str = typer.Option(
".*",
...,
"--filePattern",
"-f",
help="Filename pattern used to separate data.",
),
out_dir: Path = typer.Option(
axis: utils.StackableAxis = typer.Option(
utils.StackableAxis.Z,
"--axis",
help="Axis to stack images along.",
),
out_dir: pathlib.Path = typer.Option(
...,
"--outDir",
"-o",
help="Output collection.",
exists=True,
writable=True,
resolve_path=True,
file_okay=False,
dir_okay=True,
),
preview: bool = typer.Option(
False,
"--preview",
"-p",
help="Generate preview of expected outputs.",
),
) -> None:
"""Image dimension stacking plugin."""
logger.info(f"--inpDir: {inp_dir}")
logger.info(f"--filePattern: {file_pattern}")
logger.info(f"--outDir: {out_dir}")

if not inp_dir.exists():
msg = "inpDir does not exist"
raise ValueError(msg, inp_dir)

if not out_dir.exists():
msg = "outDir does not exist"
raise ValueError(msg, out_dir)

fps = fp.FilePattern(inp_dir, file_pattern)
list_val = ["c", "t", "z"]
variables = sorted([f for f in fps.get_variables() if f in list_val])

if len(variables) == 0:
msg = "Could not detect c, t or z variables in a pattern"
"""Image dimension stacking tool."""
# Get the file pattern
fp = filepattern.FilePattern(inp_dir, file_pattern)
variables = fp.get_variables()

# Check if the axis is present among the variables
if axis.value not in variables:
msg = f"Axis {axis} not present among the variables {variables}."
logger.error(msg)
raise ValueError(msg)

if variables == list_val or variables == ["z"]:
group_by = "z"

if variables == ["c", "t"] or variables == ["c"]:
group_by = "c"
# Collect the files into groups to stack
groups: dict[pathlib.Path, list[pathlib.Path]] = {}

if variables == ["t"]:
group_by = "t"
# Group the files by all variables except the axis
group_by = [v for v in variables if v != axis.value]
for _, files in fp(group_by=group_by):
out_path = out_dir / fp.output_name(files)
groups[out_path] = [p for _, [p] in files]

if preview:
generate_preview(out_dir=out_dir, file_pattern=file_pattern)

st.dimension_stacking(
inp_dir=inp_dir,
file_pattern=file_pattern,
group_by=group_by,
out_dir=out_dir,
)
with (out_dir / "preview.json").open("w") as f:
preview_data = {"outDir": [str(p) for p in groups]}
json.dump(preview_data, f, indent=2)
return

# TODO: Use some parallelism here
for out_path, inp_paths in tqdm.tqdm(
groups.items(),
desc="Stacking groups",
total=len(groups),
):
if str(out_path).endswith(".ome.zarr"):
copy_stack(inp_paths, axis, out_path)
else:
write_stack(inp_paths, axis, out_path)


if __name__ == "__main__":
Expand Down
Loading