diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1cf61d..d01d6ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: build: name: Build if: github.event_name == 'push' || github.event_name == 'release' - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 # A local registry helps us reuse the built image between steps services: @@ -33,7 +33,7 @@ jobs: - name: Get git tag id: git_info if: startsWith(github.ref, 'refs/tags/') - run: echo "::set-output name=tag::${GITHUB_REF##*/}" + run: echo "tag=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT - name: Get project info id: determine env: @@ -42,49 +42,45 @@ jobs: repo="${GITHUB_REPOSITORY,,}" # to lower case # if build triggered by tag, use tag name tag="${git_tag:-latest}" - # if tag is a version number prefixed by 'v', remove the 'v' if [[ "$tag" =~ ^v[0-9].* ]]; then tag="${tag:1}" fi - dock_image=$repo:$tag echo $dock_image - echo "::set-output name=dock_image::$dock_image" - echo "::set-output name=repo::$repo" - - - uses: actions/checkout@v2 + echo "dock_image=$dock_image" >> $GITHUB_OUTPUT + echo "repo=$repo" >> $GITHUB_OUTPUT + - uses: actions/checkout@v3 # QEMU is used for non-x86_64 builds - - uses: docker/setup-qemu-action@v1 + - uses: docker/setup-qemu-action@v2 # buildx adds additional features to docker build - - uses: docker/setup-buildx-action@v1 + - uses: docker/setup-buildx-action@v2 with: driver-opts: network=host # cache slightly improves rebuild time - name: Cache Docker layers - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx- - - name: Login to DockerHub id: dockerhub_login - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to GitHub Container Registry - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 id: docker_build with: context: . @@ -105,10 +101,9 @@ jobs: dock_image=${{ steps.determine.outputs.dock_image }} docker run --rm localhost:5000/$dock_image chris_plugin_info > /tmp/description.json jq < /tmp/description.json # pretty print in log - echo "::set-output name=title::$(jq -r '.title' < /tmp/description.json)" - + echo "title=$(jq -r '.title' < /tmp/description.json)" >> $GITHUB_OUTPUT - name: Update DockerHub description - uses: peter-evans/dockerhub-description@v2 + uses: peter-evans/dockerhub-description@v3 continue-on-error: true # it is not crucial that this works with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -118,7 +113,7 @@ jobs: repository: ${{ steps.determine.outputs.repo }} - name: Upload to ChRIS Store - if: github.event_name == 'release' + if: steps.git_info.outcome != 'skipped' uses: FNNDSC/chrisstore-action@master with: descriptor_file: /tmp/description.json diff --git a/README.md b/README.md index 57e072b..ba74941 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Fetal CP Surface Extraction -[![Version](https://img.shields.io/docker/v/fnndsc/pl-fetal-cp-surface-extract?sort=semver)](https://hub.docker.com/r/fnndsc/pl-fetal-cp-surface-extract) -[![MIT License](https://img.shields.io/github/license/fnndsc/pl-fetal-cp-surface-extract)](https://github.com/FNNDSC/pl-fetal-cp-surface-extract/blob/main/LICENSE) -[![ci](https://github.com/FNNDSC/pl-fetal-cp-surface-extract/actions/workflows/ci.yml/badge.svg)](https://github.com/FNNDSC/pl-fetal-cp-surface-extract/actions/workflows/ci.yml) +[![Version](https://img.shields.io/docker/v/fnndsc/pl-fetal-surface-extract?sort=semver)](https://hub.docker.com/r/fnndsc/pl-fetal-surface-extract) +[![MIT License](https://img.shields.io/github/license/fnndsc/pl-fetal-surface-extract)](https://github.com/FNNDSC/pl-fetal-surface-extract/blob/main/LICENSE) +[![ci](https://github.com/FNNDSC/pl-fetal-surface-extract/actions/workflows/ci.yml/badge.svg)](https://github.com/FNNDSC/pl-fetal-surface-extract/actions/workflows/ci.yml) Fetal brain cortical plate surface extraction using CIVET marching-cubes (`sphere_mesh`). @@ -10,7 +10,7 @@ Fetal brain cortical plate surface extraction using CIVET marching-cubes (`spher ## Abstract -`pl-fetal-cp-surface-extract` consumes binary volumetric `.mnc` brain masks to produce +`pl-fetal-surface-extract` consumes binary volumetric `.mnc` brain masks to produce surfaces as `.obj` files with standard connectivity (81,920 triangles). This program is suitable for targeting the **inner cortical plate** surface (gray-white matter boundary) of high-quality human fetal brain MRI segmentation for subjects between 23-35 gestational @@ -21,11 +21,21 @@ weeks of age. Polygonal surface mesh representations of brain hemispheres are useful for measuring cortical thickness, image registration, and quantitative regional analysis. -## Marching Cubes +## Surface Extraction Algorithm + +1. Preprocess mask using `mincmorph` to fill in disconnected voxels (improve mask quality) +2. Marching-cubes -> spherical topology surface mesh with unknown number of triangles +3. Calculate distance error +4. _If_ maximum distance error is too large, _then_ redo marching-cubes with subsampling +5. Sphere-to-sphere interpolation -> resample mesh to standard connectivity of 81,920 triangles, preserving morphology +6. Calculate smoothness error +7. Run `adapt_object_mesh` to achieve desired smoothness. Number of iterations is predicted by a regression + +### Marching Cubes We have evaluated two implementations of marching-cubes: -- [scikit-image](https://github.com/FNNDSC/pl-fetal-cp-surface-extract) +- [scikit-image](https://github.com/FNNDSC/pl-fetal-surface-extract) - [CIVET](https://github.com/FNNDSC/ep-sphere_mesh) We found that CIVET's implementation of the marching-cubes algorithm, `sphere_mesh`, is @@ -33,17 +43,7 @@ We found that CIVET's implementation of the marching-cubes algorithm, `sphere_me than scikit-image's implementation, which requires FWHM blurring of the volume. Moreover, `sphere_mesh` guarantees a spherical topology. -## Surface Extraction Algorithm - -1. Preprocess mask using `mincmorph` to fill in disconnected voxels (improve mask quality) -2. Marching-cubes -> spherical topology surface mesh with unknown number of triangles -3. Calculate distance error -4. _If_ maximum distance error is too large, _then_ redo marching-cubes with subsampling -5. Sphere-to-sphere interpolation -> resample mesh to standard connectivity of 81,920 triangles, preserving morphology -6. Calculate smoothness error -7. Run `adapt_object_mesh` to achieve desired smoothness. Number of iterations is predicted by a regression model - -### Estimation of: How much smoothing? +### How much Smoothing? Estimation We developed a model which predicts the number of `adapt_object_mesh` smoothing iterations necessary, given a desired smoothness error threshold. The model was created from the experiment described here: @@ -55,7 +55,7 @@ The model was created from the experiment described here: 1. https://github.com/FNNDSC/ep-premc-mincmorph 2. https://github.com/FNNDSC/pl-nums2mask 3. https://github.com/FNNDSC/pl-subdiv-minc TODO -4. pl-fetal-cp-surface-extract +4. pl-fetal-surface-extract 5. pl-extracted-surface-asp TODO