Skip to content

Commit

Permalink
Merge pull request #225 from dzenanz/master
Browse files Browse the repository at this point in the history
  • Loading branch information
dzenanz authored Apr 22, 2024
2 parents 53f0970 + 91eccc5 commit 1959142
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Right
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
# clang 9.0 AllowAllArgumentsOnNextLine: true
Expand Down
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# http://EditorConfig.org
# https://EditorConfig.org

# top-most EditorConfig file
root = true
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/build-test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ on: [push,pull_request]

jobs:
cxx-build-workflow:
uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@246883ef3828fc00219145aeec9efa67b9889d0b
uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@b223658f3ab10680ab2ec3286d070b9601ea6ef1
with:
cmake-options: "Module_Montage_BUILD_EXAMPLES:BOOL=ON"

python-build-workflow:
uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@246883ef3828fc00219145aeec9efa67b9889d0b
uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@b223658f3ab10680ab2ec3286d070b9601ea6ef1
with:
manylinux-platforms: '["_2_28-x64","2014-x64"]'
test-notebooks: true
secrets:
pypi_password: ${{ secrets.pypi_password }}
3 changes: 2 additions & 1 deletion .github/workflows/clang-format-linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3

- uses: InsightSoftwareConsortium/ITKClangFormatLinterAction@master
21 changes: 21 additions & 0 deletions include/itkTileMontage.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,24 @@ class ITK_TEMPLATE_EXPORT TileMontage : public ProcessObject
return static_cast<TransformOutputType *>(this->GetOutput(this->nDIndexToLinearIndex(position)))->Get();
}

/** Reliability of each tile, highest normalized to 1.0. */
using TileReliabilities = std::vector<float>;

/** Tile reliability, from 0.0 (lowest) to 1.0 (highest).
* This can be used to judge successfulness of registration to adjacent tiles. */
itkGetConstReferenceMacro(TileReliabilities, TileReliabilities);
float
GetTileReliability(DataObjectPointerArraySizeType linearIndex) const
{
return m_TileReliabilities[linearIndex];
}
float
GetTileReliability(TileIndexType nDIndex) const
{
DataObjectPointerArraySizeType linearIndex = nDIndexToLinearIndex(nDIndex);
return GetTileReliability(linearIndex);
}

protected:
TileMontage();
~TileMontage() override = default;
Expand Down Expand Up @@ -241,6 +259,8 @@ class ITK_TEMPLATE_EXPORT TileMontage : public ProcessObject
nDIndexToLinearIndex(TileIndexType nDIndex) const;
TileIndexType
LinearIndexTonDIndex(DataObjectPointerArraySizeType linearIndex) const;
DataObjectPointerArraySizeType
ReferenceLinearIndex(DataObjectPointerArraySizeType candidateIndex) const;

/** Register a pair of images with given indices. Handles FFTcaching. */
void
Expand Down Expand Up @@ -301,6 +321,7 @@ class ITK_TEMPLATE_EXPORT TileMontage : public ProcessObject
std::vector<OffsetVector> m_TransformCandidates; // to adjacent tiles
std::vector<ConfidencesType> m_CandidateConfidences;
std::vector<TranslationOffset> m_CurrentAdjustments;
std::vector<float> m_TileReliabilities;

typename PCMOptimizerType::PeakInterpolationMethodEnum m_PeakInterpolationMethod =
PCMOptimizerType::PeakInterpolationMethodEnum::Parabolic;
Expand Down
83 changes: 78 additions & 5 deletions include/itkTileMontage.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ TileMontage<TImageType, TCoordinate>::SetMontageSize(SizeType montageSize)
m_FFTCache.resize(m_LinearMontageSize);
m_Tiles.resize(m_LinearMontageSize);
m_CurrentAdjustments.resize(m_LinearMontageSize);
m_TileReliabilities.resize(m_LinearMontageSize);
m_TransformCandidates.resize(ImageDimension * m_LinearMontageSize); // adjacency along each dimension
m_CandidateConfidences.resize(ImageDimension * m_LinearMontageSize);
this->Modified();
Expand Down Expand Up @@ -230,6 +231,19 @@ TileMontage<TImageType, TCoordinate>::LinearIndexTonDIndex(DataObject::DataObjec
return ind;
}

template <typename TImageType, typename TCoordinate>
auto
TileMontage<TImageType, TCoordinate>::ReferenceLinearIndex(DataObjectPointerArraySizeType candidateIndex) const
-> DataObjectPointerArraySizeType
{
SizeValueType linIndex = candidateIndex % m_LinearMontageSize;
TileIndexType currentIndex = this->LinearIndexTonDIndex(linIndex);
TileIndexType referenceIndex = currentIndex;
unsigned dim = candidateIndex / m_LinearMontageSize;
referenceIndex[dim] = currentIndex[dim] - 1;
return this->nDIndexToLinearIndex(referenceIndex);
}

template <typename TImageType, typename TCoordinate>
void
TileMontage<TImageType, TCoordinate>::RegisterPair(TileIndexType fixed, TileIndexType moving)
Expand Down Expand Up @@ -421,11 +435,7 @@ TileMontage<TImageType, TCoordinate>::OptimizeTiles()
if (!m_TransformCandidates[i].empty())
{
SizeValueType linIndex = i % m_LinearMontageSize;
TileIndexType currentIndex = this->LinearIndexTonDIndex(linIndex);
TileIndexType referenceIndex = currentIndex;
unsigned dim = i / m_LinearMontageSize;
referenceIndex[dim] = currentIndex[dim] - 1;
SizeValueType refLinearIndex = this->nDIndexToLinearIndex(referenceIndex);
SizeValueType refLinearIndex = this->ReferenceLinearIndex(i);

// construct equation: -c*refLinearIndex + c*linIndex = c*candidateOffset, c=confidence
const float & confidence = m_CandidateConfidences[i][0];
Expand Down Expand Up @@ -526,6 +536,8 @@ TileMontage<TImageType, TCoordinate>::OptimizeTiles()
std::cout << "\nresiduals:\n";
}

m_TileReliabilities.clear();
m_TileReliabilities.resize(m_LinearMontageSize, 0.0); // reset all to zero
for (SizeValueType i = 0; i < m_NumberOfPairs; i++)
{
TCoordinate residual = 0;
Expand Down Expand Up @@ -569,6 +581,67 @@ TileMontage<TImageType, TCoordinate>::OptimizeTiles()
maxCost = cost;
maxIndex = i;
}

// accumulate costs into tile reliabilities
SizeValueType linIndex = candidateIndex % m_LinearMontageSize;
SizeValueType refLinearIndex = this->ReferenceLinearIndex(candidateIndex);
m_TileReliabilities[linIndex] += cost;
m_TileReliabilities[refLinearIndex] += cost;
}
if (this->GetDebug())
{
std::cout << std::endl;
}

// now convert costs into reliabilities
float minReliabilityCost = std::numeric_limits<float>::max();
float maxReliabilityCost = 0.0;
// first divide by number of registrations
for (SizeValueType i = 0; i < m_LinearMontageSize; ++i)
{
TileIndexType nDIndex = LinearIndexTonDIndex(i);
unsigned regCount = 2 * Dimension; // for tiles in the middle
// now reduce this by one for each dimension's edge this finds itself on
for (unsigned d = 0; d < Dimension; ++d)
{
if (nDIndex[d] == 0 || nDIndex[d] == m_MontageSize[d] - 1)
{
--regCount;
}
}
assert(regCount >= 1); // every tile must have participated in at least on registration
m_TileReliabilities[i] /= regCount;
if (m_TileReliabilities[i] < minReliabilityCost)
{
minReliabilityCost = m_TileReliabilities[i];
}
if (m_TileReliabilities[i] > maxReliabilityCost)
{
maxReliabilityCost = m_TileReliabilities[i];
}
}
if (this->GetDebug())
{
std::cout << "Reliabilities:";
}
// now transform costs into (0.0, 1.0] reliability range
for (SizeValueType i = 0; i < m_LinearMontageSize; ++i)
{
// map minReliabilityCost to 1.0 reliability; map maxReliabilityCost to near zero (min/max)
float sourceRange = maxReliabilityCost - minReliabilityCost;
float newMin = minReliabilityCost / maxReliabilityCost;
float targetRange = 1.0 - newMin;
float fraction = (maxReliabilityCost - m_TileReliabilities[i]) / sourceRange;
m_TileReliabilities[i] = newMin + fraction * (targetRange);
if (this->GetDebug())
{
if (i % m_MontageSize[0] == 0)
{
std::cout << '\n';
}
std::cout << std::fixed << std::setprecision(4);
std::cout << " " << std::setw(6) << m_TileReliabilities[i];
}
}
if (this->GetDebug())
{
Expand Down
112 changes: 112 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[build-system]
requires = ["scikit-build-core"]
build-backend = "scikit_build_core.build"

[project]
name = "itk-montage"
version = "0.8.2"
description = "Montaging for microscopy imaging files."
readme = "README.md"
license = {file = "LICENSE"}
authors = [
{ name = "Dženan Zukić", email = "[email protected]" },
{ name = "Matt McCormick", email = "[email protected]" },
]
keywords = [
"itk",
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: Healthcare Industry",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Apache Software License",
"Operating System :: Android",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX",
"Operating System :: Unix",
"Programming Language :: C++",
"Programming Language :: Python",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Information Analysis",
"Topic :: Scientific/Engineering :: Medical Science Apps.",
"Topic :: Software Development :: Libraries",
]
requires-python = ">=3.8"
dependencies = [
"itk-core>=5.4rc4",
"itk-filtering>=5.4rc4",
"itk-io>=5.4rc4",
"numpy",
]

[project.urls]
Download = "https://github.com/InsightSoftwareConsortium/ITKMontage"
Homepage = "https://github.com/InsightSoftwareConsortium/ITKMontage"

[tool.scikit-build]
# The versions of CMake to allow. If CMake is not present on the system or does
# not pass this specifier, it will be downloaded via PyPI if possible. An empty
# string will disable this check.
cmake.version = ">=3.16.3"

# A list of args to pass to CMake when configuring the project. Setting this in
# config or envvar will override toml. See also ``cmake.define``.
cmake.args = []

# A table of defines to pass to CMake when configuring the project. Additive.
cmake.define = {}

# Verbose printout when building.
cmake.verbose = true

# The build type to use when building the project. Valid options are: "Debug",
# "Release", "RelWithDebInfo", "MinSizeRel", "", etc.
cmake.build-type = "Release"

# The source directory to use when building the project. Currently only affects
# the native builder (not the setuptools plugin).
cmake.source-dir = "."

# The versions of Ninja to allow. If Ninja is not present on the system or does
# not pass this specifier, it will be downloaded via PyPI if possible. An empty
# string will disable this check.
ninja.version = ">=1.11"

# The logging level to display, "DEBUG", "INFO", "WARNING", and "ERROR" are
# possible options.
logging.level = "INFO"

# Files to include in the SDist even if they are skipped by default. Supports
# gitignore syntax.
sdist.include = []

# Files to exclude from the SDist even if they are included by default. Supports
# gitignore syntax.
sdist.exclude = []

# A list of license files to include in the wheel. Supports glob patterns.
wheel.license-files = ["LICEN[CS]E*",]

# Target the platlib or the purelib. If not set, the default is to target the
# platlib if wheel.cmake is true, and the purelib otherwise.
wheel.platlib = "false"

# If CMake is less than this value, backport a copy of FindPython. Set to 0
# disable this, or the empty string.
backport.find-python = "3.26.1"

# Select the editable mode to use. Can be "redirect" (default) or "inplace".
editable.mode = "redirect"

# Rebuild the project when the package is imported. The build-directory must be
# set.
editable.rebuild = false

# If set, this will provide a method for scikit-build-core backward compatibility.
minimum-version = "0.8.2"

# The build directory. Defaults to a temporary directory, but can be set.
build-dir = "build/{wheel_tag}"
56 changes: 0 additions & 56 deletions setup.py

This file was deleted.

0 comments on commit 1959142

Please sign in to comment.