Skip to content

Commit

Permalink
Imageruler revamp (#30)
Browse files Browse the repository at this point in the history
* Redo packaging using pyproject.toml and src layout (#1)

* Redo package

* Fix version number v0.1.0

* Formatting

* Docstring darglint

* Update imports

* Formatting

---------

Co-authored-by: Martin Schubert <[email protected]>

* Add py.typed

* Switch to tometrics algorithm

* Add mypy dep

* Add scipy dep

* Fix reference filename

* Type annotation

* Reference design readme

* Add docs deps

* Fix eof

* Fix naming

* Version updated from v0.1.0 to v0.2.0

* Add to_designs notebook

* Add skimage docs dep

* Add skimage docs dep

* Fix authorship in docs

* cleanup

* Notebook for ignore schemes

* Cleanup

* Fix module docstring

* Fix some typos

* Add performance comment

---------

Co-authored-by: Martin Schubert <[email protected]>
  • Loading branch information
mfschubert and Martin Schubert authored Mar 28, 2024
1 parent d77c0af commit 8820c26
Show file tree
Hide file tree
Showing 35 changed files with 3,889 additions and 1,958 deletions.
22 changes: 22 additions & 0 deletions .bumpversion.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[tool.bumpversion]
current_version = "v0.2.0"
commit = true
commit_args = "--no-verify"
tag = true
tag_name = "{new_version}"
allow_dirty = true
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\.(?P<dev>dev)\\d+\\+[-_a-zA-Z0-9]+)?"
serialize = [
"v{major}.{minor}.{patch}.{dev}{distance_to_latest_tag}+{short_branch_name}",
"v{major}.{minor}.{patch}"
]
message = "Version updated from {current_version} to {new_version}"

[[tool.bumpversion.files]]
filename = "pyproject.toml"

[[tool.bumpversion.files]]
filename = "README.md"

[[tool.bumpversion.files]]
filename = "src/imageruler/__init__.py"
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/" # Location of package manifests
schedule:
interval: "daily"

- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
79 changes: 79 additions & 0 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: CI

on:
pull_request:
push:
branches:
- main
schedule:
- cron: "0 13 * * 1" # Every Monday at 9AM EST

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
cache-dependency-path: pyproject.toml

- name: Test pre-commit hooks
run: |
python -m pip install --upgrade pip
pip install pre-commit
pre-commit run -a
validate-types-and-docstrings:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
cache-dependency-path: pyproject.toml

- name: Setup environment
run: |
python -m pip install --upgrade pip
pip install ".[tests,dev]"
- name: mypy type validation
run: |
mypy src
mypy imageruler
- name: darglint docstring validation
run: |
darglint src --strictness=short --ignore-raise=ValueError
darglint imageruler --strictness=short --ignore-raise=ValueError
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
cache-dependency-path: pyproject.toml

- name: Setup environment
run: |
python -m pip install --upgrade pip
pip install ".[tests,dev]"
- name: Run Python tests
run: |
pytest --cov=imageruler tests
43 changes: 0 additions & 43 deletions .github/workflows/ci-build.yml

This file was deleted.

32 changes: 32 additions & 0 deletions .github/workflows/cli_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI

on:
pull_request:
push:
branches:
- main
schedule:
- cron: "0 13 * * 1" # Every Monday at 9AM EST

jobs:
example:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
cache-dependency-path: pyproject.toml

- name: Setup environment
run: |
python -m pip install --upgrade pip
pip install ".[tests,dev,examples]"
- name: Run program on reference design
run: |
python imageruler reference_designs/Rasmus70nm.csv
51 changes: 51 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Sphinx docs to gh-pages

on:
push:
branches:
- main
workflow_dispatch:

jobs:
build-docs:
runs-on: ubuntu-latest
name: Sphinx docs to gh-pages
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
cache-dependency-path: pyproject.toml

- name: Setup environment
run: |
python -m pip install --upgrade pip
pip install ".[tests,dev,docs]"
- name: docs
run: jb build docs

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "./docs/_build/html/"

deploy-docs:
needs: build-docs
permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
28 changes: 28 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Release PyPI

on:
push:
tags: "v*"

jobs:
release_pypi:
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.x
cache-dependency-path: pyproject.toml
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build setuptools twine wheel
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python -m build
twine upload dist/*
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,4 @@ dmypy.json
cython_debug/

# PyCharm
.idea/
.idea/
55 changes: 55 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: mixed-line-ending
- id: name-tests-test
args: ["--pytest-test-first"]
- id: trailing-whitespace

# Black formatting
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black

# Upgrade python syntax
- repo: https://github.com/asottile/pyupgrade
rev: v3.10.1
hooks:
- id: pyupgrade
args: [--py37-plus, --keep-runtime-typing]

# Validate shell scripts
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.9.0.5
hooks:
- id: shellcheck

# Security linter
- repo: https://github.com/PyCQA/bandit
rev: 1.7.5
hooks:
- id: bandit
args: [--exit-zero]
exclude: ^tests/

# Linter
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.287
hooks:
- id: ruff
exclude: ^tests/

# Strip whitespace from notebooks.
- repo: https://github.com/kynan/nbstripout
rev: 0.6.0
hooks:
- id: nbstripout
3 changes: 1 addition & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[![Build Status](https://github.com/NanoComp/imageruler/workflows/CI/badge.svg)](https://github.com/NanoComp/imageruler/actions)
`v0.2.0`

Imageruler is a free Python program to compute the minimum length scale of binary images which are typically designs produced by topology optimization. The algorithm is described in Section 2 of [J. Optical Society of America B, Vol. 42, pp. A161-A176 (2024)](https://opg.optica.org/josab/abstract.cfm?uri=josab-41-2-A161) and is based on morphological transformations implemented using [OpenCV](https://github.com/opencv/opencv). Imageruler also supports 1d binary images.

Expand All @@ -21,4 +22,4 @@ For a 1d binary image, the algorithm simply finds the minimum length among all s

## Note on Accuracy

The accuracy of the minimum length scale computed by Imageruler is limited by the finite resolution of the input image. A fundamental feature is that length scales smaller than a single pixel cannot be measured. Also, in certain situations, length scales of a few pixels may be indistinguishable from discretization artifacts such as the "staircasing" of curved surfaces. As an example, a sharp 90° corner corresponds to a length scale (radius of curvature) of *zero* at infinite resolution. However, at a finite resolution, a sharp corner is indistinguishable from one that is rounded with a radius of curvature of a few pixels. Imageruler will therefore return a length scale proportional to the pixel size rather than zero. In general, the measured length scale should be viewed as having an "error bar" on the few-pixel level.
The accuracy of the minimum length scale computed by Imageruler is limited by the finite resolution of the input image. A fundamental feature is that length scales smaller than a single pixel cannot be measured. Also, in certain situations, length scales of a few pixels may be indistinguishable from discretization artifacts such as the "staircasing" of curved surfaces. As an example, a sharp 90° corner corresponds to a length scale (radius of curvature) of *zero* at infinite resolution. However, at a finite resolution, a sharp corner is indistinguishable from one that is rounded with a radius of curvature of a few pixels. Imageruler will therefore return a length scale proportional to the pixel size rather than zero. In general, the measured length scale should be viewed as having an "error bar" on the few-pixel level.
Loading

0 comments on commit 8820c26

Please sign in to comment.