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
7 changes: 4 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ jobs:
fail-fast: false
matrix:
version:
- '1.10'
- 'min'
- '1'
os:
- ubuntu-latest
arch:
- x64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
Expand All @@ -40,6 +40,7 @@ jobs:
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v5
with:
file: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
10 changes: 7 additions & 3 deletions .github/workflows/Documenter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ jobs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- uses: julia-actions/cache@v2
- name: Install HolyLab Registry
run: julia -e 'using Pkg; Pkg.Registry.add([RegistrySpec(name="General"),RegistrySpec(url="https://github.com/HolyLab/HolyLabRegistry")]);'
- uses: julia-actions/julia-buildpkg@latest
run: julia -e 'using Pkg; Pkg.Registry.add([RegistrySpec(name="General"), RegistrySpec(url="https://github.com/HolyLab/HolyLabRegistry")])'
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-docdeploy@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,5 @@ jobs:
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
# Edit the following line to reflect the actual name of the GitHub Secret containing your private key
ssh: ${{ secrets.DOCUMENTER_KEY }}
# ssh: ${{ secrets.NAME_OF_MY_SSH_PRIVATE_KEY_SECRET }}
token: ${{ secrets.TAGBOT_TOKEN }}
registry: HolyLab/HolyLabRegistry
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@
docs/build
docs/site
Manifest.toml
Manifest-v*.toml
docs/Manifest.toml
docs/Manifest-v*.toml
*.jl.cov
*.jl.*.cov
*.jl.mem
18 changes: 9 additions & 9 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "BlockRegistration"
uuid = "96be3cfc-dfc9-41f0-9424-fd41ed36fd5e"
author = ["Tim Holy <tim.holy@gmail.com", "Cody Greer <codyjgreer@gmail.com>"]
version = "0.2.3"
version = "1.0.0"

[deps]
CachedInterpolations = "b9709bfb-d23d-5560-8276-8c35c4b76823"
Expand All @@ -15,15 +15,15 @@ RegisterOptimize = "b981a1b5-4587-53b0-9c3d-454c648f6f8d"
RegisterPenalty = "464fa2a9-b19c-5c59-8698-f58c971f971e"

[compat]
CachedInterpolations = "0.1"
CenterIndexedArrays = "0.2"
CachedInterpolations = "1"
CenterIndexedArrays = "1"
Reexport = "1"
RegisterCore = "0.2.2"
RegisterDeformation = "0.3, 0.4"
RegisterFit = "0.1, 0.2"
RegisterHindsight = "0.1, 0.2"
RegisterOptimize = "0.3"
RegisterPenalty = "0.2, 0.3"
RegisterCore = "1"
RegisterDeformation = "1"
RegisterFit = "1"
RegisterHindsight = "1"
RegisterOptimize = "1"
RegisterPenalty = "1"
julia = "1.10"

[extras]
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# BlockRegistration.jl

[![Build Status](https://magnum.travis-ci.com/HolyLab/BlockRegistration.svg?token=su2Bzyut6KvcqmScAAsj&branch=master)](https://magnum.travis-ci.com/HolyLab/BlockRegistration.jl)
[![CI](https://github.com/HolyLab/BlockRegistration.jl/actions/workflows/CI.yml/badge.svg)](https://github.com/HolyLab/BlockRegistration.jl/actions/workflows/CI.yml)
[![Coverage](https://codecov.io/gh/HolyLab/BlockRegistration.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/HolyLab/BlockRegistration.jl)

BlockRegistration is designed to perform non-rigid image registration---specifically, motion correction---for a time series of images.
BlockRegistration works on images/movies with an arbitrary number of spatial dimensions and a single temporal dimension.
Expand All @@ -10,4 +11,5 @@ it prioritizes speed above all else.
BlockRegistration is written in the [Julia programming language](https://julialang.org/).
Installation is greatly facilitated by using the [HolyLabRegistry](https://github.com/HolyLab/HolyLabRegistry#usage); see the documentation link below for details and demonstrations.

[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://HolyLab.github.io/BlockRegistration.jl/stable)
[![docs-stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://HolyLab.github.io/BlockRegistration.jl/stable)
[![docs-dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://HolyLab.github.io/BlockRegistration.jl/dev)
27 changes: 25 additions & 2 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
[deps]
AxisArrays = "39de3d68-74b9-583c-8d2d-e117c070f3a9"
BlockRegistration = "96be3cfc-dfc9-41f0-9424-fd41ed36fd5e"
CenterIndexedArrays = "46a7138f-0d70-54e1-8ada-fb8296f91f24"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
RegisterDeformation = "c19381b7-cf49-59d7-881c-50dfbd227eaf"
RegisterMismatch = "3c0dd727-6833-5f5d-a1e8-c0d421935c74"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[compat]
CenterIndexedArrays = "0.2"
Documenter = "~0.24"
AxisArrays = "0.4"
CenterIndexedArrays = "1"
Documenter = "1"
FileIO = "1"
ImageCore = "0.10"
Images = "0.26"
Interpolations = "0.15"
ProgressMeter = "1"
RegisterDeformation = "1"
RegisterMismatch = "1"
StaticArrays = "1"
TestImages = "1"
Unitful = "1"
6 changes: 3 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using Documenter, BlockRegistration

makedocs(
modules = [BlockRegistration],
clean = false,
checkdocs = :exports,
format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
sitename = "BlockRegistration.jl",
authors = "Timothy E. Holy",
Expand All @@ -11,11 +11,11 @@ makedocs(
"Home" => "index.md",
"cookbook.md",
"details.md",
"improving.md", # TODO: move more from leftovers.md
# "whole_experiment.md",
"improving.md",
],
)

deploydocs(
repo = "github.com/HolyLab/BlockRegistration.jl.git",
devbranch = "master",
)
14 changes: 5 additions & 9 deletions docs/src/cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

For practical use with large images you might prefer the "stack-by-stack registration"
section of
[BlockRegistrationScheduler](https://github.com/HolyLab/BlockRegistrationScheduler).
[BlockRegistrationScheduler](https://github.com/HolyLab/BlockRegistrationScheduler.jl).
If you're using the scheduler, many parts of the rest of this cookbook
do not apply.
However, if your goal is to learn the internals, it's easier and more informative to start with BlockRegistration.

Let's start with a simple two-dimensional demonstration.
The code below is heavily annotated to explain what each step does.

```jldoctest cookbook; filter=[r"Planning.*", r"Progress.*"]
```julia
using FileIO, Images, Unitful, StaticArrays, ProgressMeter
using AxisArrays: Axis, AxisArray
using BlockRegistration
Expand Down Expand Up @@ -99,8 +99,9 @@ Qs = Array{Any}(undef, gridsize)
ap = AffinePenalty(nodes, first(λrange))

# Now loop over each timeslice
# (In practice, wrap the `for` with `@showprogress 1` to display a progress bar)
ϕs, λs, errs = [], [], [] # storage for results (the deformation, chosen λ, and resid for each timeslice)
@showprogress 1 for tidx in axes(img, Axis{:time})
for tidx in axes(img, Axis{:time})
moving = view(img, timeaxis(img)(tidx))

# Compute the mismatch for all deformations that are piecewise-constant
Expand Down Expand Up @@ -142,11 +143,6 @@ ap = AffinePenalty(nodes, first(λrange))
push!(errs, mismatch)
end

all(errs .< 0.03)

# output

true
```

If you prefer, you can put everything after the parameter settings
Expand All @@ -165,7 +161,7 @@ end

But if you're testing this on the small demo in `"test/gen2d.jl"`, we can do it in memory:

```jldoctest cookbook; filter="\".*"
```julia
# Allocate storage for the warped image
imgw = similar(img, Gray{Float32}); # eltype needs to be able to store NaN
for i = 1:nimages(img)
Expand Down
2 changes: 1 addition & 1 deletion docs/src/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ the mismatch between images is represented using an array where each element cor
From the demo in the [cookbook](@ref), we can select a particular moving image,
compute the mismatch, and visualize it:

```jldoctest cookbook
```julia
moving = img[:,:,1]
mms = mismatch_apertures(fixed, moving, aperture_centers, aperture_width, mxshift)
# Turn the mismatch from NumDenom to a plain ratio (see RegisterCore docs)
Expand Down
8 changes: 4 additions & 4 deletions docs/src/improving.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ with a fixed value of `λ = 1e-6`, we seem to do somewhat better on that trouble
It is possible to use the solution as an initializer to iteratively improve the alignment.
The idea is that

```jldoctest cookbook
```julia
moving = img[:,:,end]
ϕ1 = ϕs[end]
movw1 = warp(moving, ϕ1)
Expand All @@ -30,7 +30,7 @@ movw1 = warp(moving, ϕ1)
represents a closer match to `fixed` than `moving` itself; we can then calculate
a `ϕ2` that aligns `movw1` to `fixed` and then compose them:

```jldoctest cookbook
```julia
mms = mismatch_apertures(fixed, movw1, aperture_centers, aperture_width, mxshift)
for i in eachindex(mms)
E0[i], cs[i], Qs[i] = qfit(mms[i], thresh; opt=false)
Expand All @@ -41,7 +41,7 @@ mmis = interpolate_mm!(mms)

`ϕ2` should approximately align `movw1` to fixed, and consequently

```jldoctest cookbook
```julia
using Interpolations
ϕtot = interpolate(ϕ1)(ϕ2)
```
Expand Down Expand Up @@ -82,7 +82,7 @@ More conventional registration frameworks directly model the mismatch associated
`moving(ϕ(x))` and perform descent on `ϕ`.
[RegisterHindsight](https://github.com/HolyLab/RegisterHindsight.jl) lets you optimize `ϕ` in this manner:

```jldoctest cookbook
```julia
moving, ϕ0, λ = img[:,:,end], ϕs[end], λs[end]
ϕ = interpolate!(copy(ϕ0)) # not the same as `interpolate(ϕ0)`, see docs
ap = AffinePenalty(ϕ.nodes, λ/100) # note /100! `auto_λ` often seems to choose high
Expand Down
10 changes: 8 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ BlockRegistration is written in the [Julia programming language](https://juliala
## Installation

If you don't already have it, add [HolyLabRegistry](https://github.com/HolyLab/HolyLabRegistry#usage) as a registry.
Then from [package mode](https://julialang.github.io/Pkg.jl/v1/getting-started/) just do
Then from [package mode](https://pkgdocs.julialang.org/v1/getting-started/) just do

```julia
pkg> add BlockRegistration RegisterMismatch
Expand All @@ -31,7 +31,7 @@ pkg> add BlockRegistration RegisterMismatch
If you have GPUs available, you may also want to add `RegisterMismatchCuda`.
This requires that you have nvidia drivers installed on your system.

See also [BlockRegistrationScheduler](https://github.com/HolyLab/BlockRegistrationScheduler), which allows you to parallelize registration across worker processes.
See also [BlockRegistrationScheduler](https://github.com/HolyLab/BlockRegistrationScheduler.jl), which allows you to parallelize registration across worker processes.
It works for both CPU (`RegisterMismatch`) and GPU (`RegisterMismatchCuda`),
though for GPU you need a dedicated GPU card for each worker process.

Expand Down Expand Up @@ -71,3 +71,9 @@ its own documentation.
Given that "published" documentation is still a bit sparse,
also consider looking at the code in each package's
`test/` folder as an example of how to use these modules.

## Reference

```@docs
BlockRegistration
```
14 changes: 14 additions & 0 deletions src/BlockRegistration.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
"""
BlockRegistration

Umbrella package for block-based image registration. Re-exports all symbols from:

- `CenterIndexedArrays`: arrays with centered (zero-based) indexing
- `CachedInterpolations`: memoized interpolation objects
- `RegisterCore`: core data structures (`MismatchArray`, `NumDenom`) and preprocessing (`PreprocessSNF`, `highpass`)
- `RegisterDeformation`: deformation fields (`GridDeformation`), warping, and time-series utilities
- `RegisterFit`: mismatch fitting (`qfit`, `mms2fit!`) and affine extraction
- `RegisterOptimize`: full optimization loop (`RegisterOptimize.optimize!`) and penalty auto-tuning
- `RegisterPenalty`: regularization penalties (`AffinePenalty`, `DeformationPenalty`)
- `RegisterHindsight`: retrospective correction utilities
"""
module BlockRegistration

using Reexport
Expand Down
Loading