Skip to content

Commit

Permalink
🌼
Browse files Browse the repository at this point in the history
  • Loading branch information
jennydaman committed Feb 18, 2022
1 parent 822a535 commit fae9e7b
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 123 deletions.
18 changes: 10 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# Python version can be changed, e.g.
# FROM python:3.8
# FROM docker.io/fnndsc/conda:python3.10.2-cuda11.6.0
FROM docker.io/python:3.10.2-slim-buster
FROM docker.io/fnndsc/mni-conda-base:civet2.1.1-python3.10.2

LABEL org.opencontainers.image.authors="FNNDSC <[email protected]>" \
org.opencontainers.image.title="ChRIS Plugin Title" \
org.opencontainers.image.description="A ChRIS ds plugin that..."
org.opencontainers.image.title="ep-skimage-mcubes-mni" \
org.opencontainers.image.description="A ChRIS ds plugin wrapper around scikit-image's implementation of marching-cubes"

WORKDIR /usr/local/src/app
WORKDIR /usr/local/src/ep-skimage-mcubes-mni

# Install binary Python packages using conda, but install
# nibabel using pip for ppc64le support

RUN conda install -y -c conda-forge h5py=3.6.0 scikit-image=0.19.1

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .
RUN pip install .

CMD ["commandname", "--help"]
CMD ["skimc", "--help"]
87 changes: 7 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,82 +1,9 @@
# _ChRIS_ ds Plugin Template
# ep-skimage-mcubes-mni

<!--
[![Version](https://img.shields.io/docker/v/fnndsc/pl-appname?sort=semver)](https://hub.docker.com/r/fnndsc/pl-appname)
[![MIT License](https://img.shields.io/github/license/fnndsc/pl-appname)](https://github.com/FNNDSC/pl-appname/blob/main/LICENSE)
[![Build](https://github.com/FNNDSC/pl-appname/actions/workflows/ci.yml/badge.svg)](https://github.com/FNNDSC/pl-appname/actions)
-->
[![Version](https://img.shields.io/docker/v/fnndsc/ep-skimage-mcubes-mni?sort=semver)](https://hub.docker.com/r/fnndsc/ep-skimage-mcubes-mni)
[![MIT License](https://img.shields.io/github/license/fnndsc/ep-skimage-mcubes-mni)](https://github.com/FNNDSC/ep-skimage-mcubes-mni/blob/main/LICENSE)
[![Build](https://github.com/FNNDSC/ep-skimage-mcubes-mni/actions/workflows/ci.yml/badge.svg)](https://github.com/FNNDSC/ep-skimage-mcubes-mni/actions)


This is a minimal template repository for _ChRIS_ _ds_ plugin applications.
For a more comprehensive boilerplate, use

https://github.com/fnndsc/cookiecutter-chrisapp

## How to Use This Template

1. Click "Use this template"
2. Clone the newly created repository
3. Replace placeholder text

```shell
function replace () {
find . -type f -not -path '*/\.*/*' -not -path '*/\venv/*' -exec sed -i -e "s/$1/$2/" '{}' \;
}

replace commandname my_command_name
replace pl-appname pl-my-plugin-name
replace fnndsc my_username
```

### Template Examples

Here are some good, complete examples of _ChRIS_ plugins created from this template.

- https://github.com/FNNDSC/pl-nums2mask
- https://github.com/FNNDSC/pl-nii2mnc-u8

Advanced users can `cp -rv .github/workflows` into their own repositories to enable
automatic builds.

## Abstract

PROGRAMNAME is a [_ChRIS_](https://chrisproject.org/)
_ds_ plugin which takes in ... as input files and
creates ... as output files.

## Usage

```shell
singularity exec docker://fnndsc/pl-appname commandname [--args values...] input/ output/
```

## Examples

```shell
mkdir incoming/ outgoing/
mv some.dat other.dat incoming/
singularity exec docker://fnndsc/pl-appname:latest commandname [--args] incoming/ outgoing/
```

## Development

### Building

```shell
docker build -t localhost/fnndsc/pl-appname .
```

### Get JSON Representation

```shell
docker run --rm localhost/fnndsc/pl-appname chris_plugin_info > MyProgram.json
```

### Local Test Run

```shell
docker run --rm -it --userns=host -u $(id -u):$(id -g) \
-v $PWD/app.py:/usr/local/lib/python3.10/site-packages/app.py:ro \
-v $PWD/in:/incoming:ro -v $PWD/out:/outgoing:rw -w /outgoing \
localhost/fnndsc/pl-appname commandname /incoming /outgoing
```
`ep-skimage-mcubes-mni` is a _ChRIS_ _ds_ plugin that performs the
[marching-cubes](https://scikit-image.org/docs/stable/auto_examples/edges/plot_marching_cubes.html)
algorithm on binary `.mnc` masks, producing surfaces in the `.obj` file format.
26 changes: 0 additions & 26 deletions app.py

This file was deleted.

4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
chris_plugin~=0.0.10
pybicpl~=0.3.0
numpy~=1.22.2
nibabel~=3.2.2
loguru~=0.6.0
18 changes: 9 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from setuptools import setup

setup(
name = 'chris-plugin-template',
name = 'ep-skimage-mcubes-mni',
version = '1.0.0',
description = 'A ChRIS DS plugin template',
author = 'FNNDSC',
author_email = '[email protected]',
url = 'https://github.com/FNNDSC/python-chrisapp-template',
py_modules = ['app'],
install_requires = ['chris_plugin'],
description = 'Marching-cubes implementation from scikit-image',
author = 'Jennings Zhang',
author_email = '[email protected]',
url = 'https://github.com/jennydaman/ep-skimage-mcubes-mni',
py_modules = ['skimc'],
install_requires = ['chris_plugin', 'pybicpl', 'nibabel', 'scikit-image', 'h5py', 'loguru'],
license = 'MIT',
python_requires = '>=3.8.2',
python_requires = '>=3.10.2',
entry_points = {
'console_scripts': [
'commandname = app:main'
'skimc = skimc:main'
]
},
classifiers = [
Expand Down
70 changes: 70 additions & 0 deletions skimc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python

import os
import nibabel as nib
from nibabel.affines import apply_affine
from skimage import measure
from bicpl import PolygonObj

from pathlib import Path
from argparse import ArgumentParser, Namespace
from concurrent.futures import ThreadPoolExecutor
from loguru import logger
from chris_plugin import chris_plugin, PathMapper

parser = ArgumentParser(description='cli description')
parser.add_argument('--spacing', default='1,1,1',
help='Voxel spacing in spatial dimensions corresponding'
' to numpy array indexing dimensions (M, N, P).')
parser.add_argument('-s', '--step-size', default=1, type=int,
help='Step size in voxels. '
'Larger steps yield faster but coarser results. '
'The result will always be topologically correct though.')
parser.add_argument('-m', '--method', default='lewiner',
choices=('lewiner', 'lorensen'),
help='Specify which of Lewiner et al. or Lorensen et al.'
' method will be used.')
parser.add_argument('-p', '--pattern', default='**/*.mnc',
help='pattern for file names to include')


def mcubes(mask_path: Path, surface_path: Path,
spacing: tuple[float, float, float],
step_size: int,
method: str):
mask = nib.load(mask_path)
data = mask.get_fdata()
verts, faces, normals, values = measure.marching_cubes(
data, spacing=spacing, step_size=step_size, method=method, allow_degenerate=False
)
transformed_verts = apply_affine(mask.affine, verts)
obj = PolygonObj.from_data(transformed_verts, faces, normals)
obj.save(surface_path)
logger.info('Completed: {} => {}', mask_path, surface_path)


@chris_plugin(
parser=parser,
title='Scikit-Image Marching Cubes',
category='Surface Extraction',
min_memory_limit='200Mi',
min_cpu_limit='1000m',
)
def main(options: Namespace, inputdir: Path, outputdir: Path):
spacing = tuple(float(n) for n in options.spacing.split(','))

logger.info('scikit-image marching_cubes: spacing={} step_size={} method={}',
spacing, options.step_size, options.method)

results = []
with ThreadPoolExecutor(max_workers=len(os.sched_getaffinity(0))) as pool:
mapper = PathMapper(inputdir, outputdir, glob=options.pattern, suffix='.obj')
for mnc, obj in mapper:
results.append(pool.submit(mcubes, mnc, obj, spacing, options.step_size, options.method))

for future in results:
future.exception()


if __name__ == '__main__':
main()

0 comments on commit fae9e7b

Please sign in to comment.