Skip to content

Commit 517f0f4

Browse files
authored
Merge pull request #29 from Leengit/manual_formatting
STYLE: Add trailing semicolons to itk macro invocations. STYLE: Remove extra spaces adjacent to parentheses. ENH: Bump ITK version to 5.2.1.post1. ENH: Bump ITKColorNormalization version to 0.1.6. DOC: Update README.md to indicate supported Python versions 3.6-3.9. DOC: Update README.md to use black Python formatting.
2 parents d557dba + 82dfe8d commit 517f0f4

File tree

7 files changed

+65
-61
lines changed

7 files changed

+65
-61
lines changed

.github/workflows/build-test-package.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ jobs:
136136
matrix:
137137
python-version: [36, 37, 38, 39]
138138
include:
139-
- itk-python-git-tag: "v5.2.0"
139+
- itk-python-git-tag: "v5.2.1"
140140

141141
steps:
142142
- uses: actions/checkout@v2
@@ -172,7 +172,7 @@ jobs:
172172
max-parallel: 2
173173
matrix:
174174
include:
175-
- itk-python-git-tag: "v5.2.0"
175+
- itk-python-git-tag: "v5.2.1"
176176

177177
steps:
178178
- uses: actions/checkout@v2
@@ -208,7 +208,7 @@ jobs:
208208
matrix:
209209
python-version-minor: [6, 7, 8, 9]
210210
include:
211-
- itk-python-git-tag: "v5.2.0"
211+
- itk-python-git-tag: "v5.2.1"
212212

213213
steps:
214214
- name: Get specific version of CMake, Ninja

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ We have set up a demonstration of this using [Binder](www.mybinder.org) that any
2222

2323
[![PyPI Version](https://img.shields.io/pypi/v/itk-spcn.svg)](https://pypi.python.org/pypi/itk-spcn)
2424

25-
ITKColorNormalization and all its dependencies can be easily installed with [Python wheels](https://blog.kitware.com/itk-is-on-pypi-pip-install-itk-is-here/). Wheels have been generated for macOS, Linux, and Windows and several versions of Python, 3.5, 3.6, 3.7, and 3.8. If you do not want the installation to be to your current Python environment, you should first create and activate a [Python virtual environment (venv)](https://docs.python.org/3/tutorial/venv.html) to work in. Then, run the following from the command-line:
25+
ITKColorNormalization and all its dependencies can be easily installed with [Python wheels](https://blog.kitware.com/itk-is-on-pypi-pip-install-itk-is-here/). Wheels have been generated for macOS, Linux, and Windows and several versions of Python, 3.6, 3.7, 3.8, and 3.9. If you do not want the installation to be to your current Python environment, you should first create and activate a [Python virtual environment (venv)](https://docs.python.org/3/tutorial/venv.html) to work in. Then, run the following from the command-line:
2626

2727
```shell-script
2828
pip install itk-spcn
@@ -32,8 +32,9 @@ Launch `python`, import the itk package, and set variable names for the input im
3232

3333
```python
3434
import itk
35-
input_image_filename = 'path/to/image_to_be_normalized'
36-
reference_image_filename = 'path/to/image_to_be_used_as_color_reference'
35+
36+
input_image_filename = "path/to/image_to_be_normalized"
37+
reference_image_filename = "path/to/image_to_be_used_as_color_reference"
3738
```
3839

3940
## Usage in Python
@@ -62,7 +63,8 @@ eager_normalized_image = itk.structure_preserving_color_normalization_filter(
6263
input_image,
6364
reference_image,
6465
color_index_suppressed_by_hematoxylin=0,
65-
color_index_suppressed_by_eosin=1)
66+
color_index_suppressed_by_eosin=1,
67+
)
6668

6769
itk.imwrite(eager_normalized_image, output_image_filename)
6870
```
@@ -75,7 +77,9 @@ Alternatively, you can use the ITK pipeline infrastructure that waits until a ca
7577
input_reader = itk.ImageFileReader.New(FileName=input_image_filename)
7678
reference_reader = itk.ImageFileReader.New(FileName=reference_image_filename)
7779

78-
spcn_filter = itk.StructurePreservingColorNormalizationFilter.New(Input=input_reader.GetOutput())
80+
spcn_filter = itk.StructurePreservingColorNormalizationFilter.New(
81+
Input=input_reader.GetOutput()
82+
)
7983
spcn_filter.SetColorIndexSuppressedByHematoxylin(0)
8084
spcn_filter.SetColorIndexSuppressedByEosin(1)
8185
spcn_filter.SetInput(0, input_reader.GetOutput())

include/itkStructurePreservingColorNormalizationFilter.h

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -108,24 +108,25 @@ class StructurePreservingColorNormalizationFilter : public ImageToImageFilter<TI
108108
* Otherwise, set ColorIndexSuppressedByHematoxylin to the index in
109109
* the array of colors that indicates the color most suppressed by
110110
* hematoxylin. */
111-
itkGetMacro(ColorIndexSuppressedByHematoxylin, Eigen::Index)
112-
itkSetMacro(ColorIndexSuppressedByHematoxylin, Eigen::Index)
113-
114-
/** If the pixel type is RGB or RGBA then
115-
* ColorIndexSuppressedByEosin defaults to 1, indicating green.
116-
* Otherwise, set ColorIndexSuppressedByEosin to the index in the
117-
* array of colors that indicates the color most suppressed by
118-
* eosin. */
119-
itkGetMacro(ColorIndexSuppressedByEosin, Eigen::Index) itkSetMacro(ColorIndexSuppressedByEosin, Eigen::Index)
120-
121-
// This algorithm is defined for H&E (Hematoxylin (blue) and
122-
// Eosin (pink)), which is a total of 2 stains. However, this
123-
// approach could in theory work in other circumstances. In that
124-
// case it might be better to have NumberOfStains be a template
125-
// parameter or a setable class member.
126-
127-
/** Hematoxylin and eosin; there are two stains supported. */
128-
static constexpr SizeValueType NumberOfStains{ 2 };
111+
itkGetMacro(ColorIndexSuppressedByHematoxylin, Eigen::Index);
112+
itkSetMacro(ColorIndexSuppressedByHematoxylin, Eigen::Index);
113+
114+
/** If the pixel type is RGB or RGBA then
115+
* ColorIndexSuppressedByEosin defaults to 1, indicating green.
116+
* Otherwise, set ColorIndexSuppressedByEosin to the index in the
117+
* array of colors that indicates the color most suppressed by
118+
* eosin. */
119+
itkGetMacro(ColorIndexSuppressedByEosin, Eigen::Index);
120+
itkSetMacro(ColorIndexSuppressedByEosin, Eigen::Index);
121+
122+
// This algorithm is defined for H&E (Hematoxylin (blue) and
123+
// Eosin (pink)), which is a total of 2 stains. However, this
124+
// approach could in theory work in other circumstances. In that
125+
// case it might be better to have NumberOfStains be a template
126+
// parameter or a setable class member.
127+
128+
/** Hematoxylin and eosin; there are two stains supported. */
129+
static constexpr SizeValueType NumberOfStains{ 2 };
129130
/** For Virtanen's non-negative matrix factorization algorithm. */
130131
static constexpr SizeValueType maxNumberOfIterations{ 0 };
131132
/** Select a subset of the pixels if the image has more than this */
@@ -406,7 +407,7 @@ class StructurePreservingColorNormalizationFilter : public ImageToImageFilter<TI
406407
private:
407408
#ifdef ITK_USE_CONCEPT_CHECKING
408409
// Add concept checking such as
409-
// itkConceptMacro( FloatingPointPixel, ( Concept::IsFloatingPoint< typename ImageType::PixelType > ) );
410+
// itkConceptMacro(FloatingPointPixel, (Concept::IsFloatingPoint<typename ImageType::PixelType>));
410411
#endif
411412
};
412413

include/itkStructurePreservingColorNormalizationFilter.hxx

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ StructurePreservingColorNormalizationFilter<TImage>::StructurePreservingColorNor
3434
, m_ColorIndexSuppressedByEosin(Self::PixelHelper<PixelType>::ColorIndexSuppressedByEosin)
3535
{
3636
// The number of colors had better be at least 3 or be unknown
37-
// ( which is indicated with the value -1 ).
37+
// (which is indicated with the value -1).
3838
static_assert(2 / PixelHelper<PixelType>::NumberOfColors < 1, "Images need at least 3 colors");
3939
}
4040

@@ -67,8 +67,8 @@ StructurePreservingColorNormalizationFilter<TImage>::GenerateInputRequestedRegio
6767
// Call the superclass' implementation of this method
6868
Superclass::GenerateInputRequestedRegion();
6969

70-
// Get pointers to the input image ( to be normalized ) and
71-
// reference image.
70+
// Get pointers to the input image (to be normalized) and reference
71+
// image.
7272
ImageType * inputImage = const_cast<ImageType *>(this->GetInput(0));
7373
ImageType * referenceImage = const_cast<ImageType *>(this->GetInput(1));
7474

@@ -143,7 +143,7 @@ StructurePreservingColorNormalizationFilter<TImage>::BeforeThreadedGenerateData(
143143
RegionConstIterator refIt{ m_Reference, m_Reference->GetRequestedRegion() };
144144
refIt.GoToBegin();
145145
itkAssertOrThrowMacro(m_NumberOfColors == refIt.Get().Size(),
146-
"The ( cached ) reference image needs its number of colors to be exactly the same as the "
146+
"The (cached) reference image needs its number of colors to be exactly the same as the "
147147
"input image to be normalized");
148148
}
149149
}
@@ -155,7 +155,7 @@ StructurePreservingColorNormalizationFilter<TImage>::BeforeThreadedGenerateData(
155155
// we failed
156156
itkAssertOrThrowMacro(
157157
m_Input != nullptr,
158-
"The image to be normalized could not be processed; does it have white, blue, and pink pixels?")
158+
"The image to be normalized could not be processed; does it have white, blue, and pink pixels?");
159159
}
160160
m_Input = inputImage;
161161

@@ -178,7 +178,7 @@ StructurePreservingColorNormalizationFilter<TImage>::BeforeThreadedGenerateData(
178178
// we failed
179179
m_Reference = nullptr;
180180
itkAssertOrThrowMacro(m_Reference != nullptr,
181-
"The reference image could not be processed; does it have white, blue, and pink pixels?")
181+
"The reference image could not be processed; does it have white, blue, and pink pixels?");
182182
}
183183
}
184184
m_Reference = referenceImage;
@@ -194,7 +194,6 @@ StructurePreservingColorNormalizationFilter<TImage>::BeforeThreadedGenerateData(
194194
m_ReferenceH.row(0) = referenceHOriginal.row(1);
195195
m_ReferenceH.row(1) = referenceHOriginal.row(0);
196196
}
197-
198197
itkAssertOrThrowMacro((m_InputH * m_ReferenceH.transpose()).determinant() > CalcElementType(0),
199198
"Hematoxylin and Eosin are getting mixed up; failed");
200199
}
@@ -205,8 +204,8 @@ void
205204
StructurePreservingColorNormalizationFilter<TImage>::DynamicThreadedGenerateData(const RegionType & outputRegion)
206205
{
207206
ImageType * const outputImage = this->GetOutput();
208-
itkAssertOrThrowMacro(outputImage != nullptr, "An output image needs to be supplied")
209-
RegionIterator outIt{ outputImage, outputRegion };
207+
itkAssertOrThrowMacro(outputImage != nullptr, "An output image needs to be supplied");
208+
RegionIterator outIt{ outputImage, outputRegion };
210209

211210
this->NMFsToImage(m_InputH, m_InputUnstainedPixel, m_ReferenceH, m_ReferenceUnstainedPixel, outIt);
212211
}
@@ -254,7 +253,7 @@ StructurePreservingColorNormalizationFilter<TImage>::ImageToNMF(RegionConstItera
254253
}
255254

256255
// Rescale each row of matrixH so that the
257-
// ( 100-VeryDarkPercentileLevel ) value of each column of matrixW is
256+
// (100-VeryDarkPercentileLevel) value of each column of matrixW is
258257
// 1.0.
259258
// { std::ostringstream mesg; mesg << "matrixH before NormalizeMatrixH = " << std::endl << matrixH << std::endl;
260259
// std::cout << mesg.str() << std::flush; }
@@ -370,8 +369,8 @@ StructurePreservingColorNormalizationFilter<TImage>::MatrixToDistinguishers(cons
370369
{
371370
const CalcMatrixType normVStart{ matrixV };
372371

373-
// We will store the row ( pixel ) index of each distinguishing
374-
// pixel in firstPassDistinguisherIndices.
372+
// We will store the row (pixel) index of each distinguishing pixel
373+
// in firstPassDistinguisherIndices.
375374
std::array<int, NumberOfStains + 1> firstPassDistinguisherIndices{ -1 };
376375
SizeValueType numberOfDistinguishers{ 0 };
377376
Self::FirstPassDistinguishers(normVStart, firstPassDistinguisherIndices, numberOfDistinguishers);
@@ -399,7 +398,7 @@ StructurePreservingColorNormalizationFilter<TImage>::FirstPassDistinguishers(
399398
bool needToRecenterMatrix = true;
400399
while (numberOfDistinguishers <= NumberOfStains)
401400
{
402-
// Find the next distinguishing row ( pixel )
401+
// Find the next distinguishing row (pixel)
403402
firstPassDistinguisherIndices[numberOfDistinguishers] = Self::MatrixToOneDistinguisher(normV);
404403
// If we found a distinguisher and we have not yet found
405404
// NumberOfStains+1 of them, then look for the next distinguisher.
@@ -462,8 +461,8 @@ StructurePreservingColorNormalizationFilter<TImage>::SecondPassDistinguishers(
462461
// We have sent all distinguishers except self to the origin.
463462
// Whatever is far from the origin in the same direction as self
464463
// is a good replacement for self. We will take an average among
465-
// those that are at least 80% as far as the best. ( Note that
466-
// self could still be best, but not always. )
464+
// those that are at least 80% as far as the best. (Note that
465+
// self could still be best, but not always.)
467466
const CalcColVectorType dotProducts{ normV * normV.row(firstPassDistinguisherIndices[distinguisher]).transpose() };
468467
const CalcElementType threshold{ *std::max_element(Self::cbegin(dotProducts), Self::cend(dotProducts)) *
469468
SecondPassDistinguishersThreshold };
@@ -571,9 +570,9 @@ StructurePreservingColorNormalizationFilter<TImage>::DistinguishersToColors(Calc
571570
SizeValueType & hematoxylinIndex,
572571
SizeValueType & eosinIndex) const
573572
{
574-
// Figure out which, distinguishers are unstained ( highest
575-
// brightness ), hematoxylin ( suppresses red ), and eosin (
576-
// suppresses green ).
573+
// Figure out which, distinguishers are unstained (highest
574+
// brightness), hematoxylin (suppresses red), and eosin (suppresses
575+
// green).
577576
const CalcColVectorType lengths2{ distinguishers.rowwise().squaredNorm() };
578577
const CalcElementType * const unstainedIterator{ std::max_element(Self::cbegin(lengths2), Self::cend(lengths2)) };
579578
unstainedIndex = std::distance(Self::cbegin(lengths2), unstainedIterator);
@@ -601,8 +600,8 @@ StructurePreservingColorNormalizationFilter<TImage>::NormalizeMatrixH(const Calc
601600
const CalcColVectorType firstOnes{ CalcColVectorType::Constant(matrixDarkVIn.rows(), 1, 1.0) };
602601

603602
// Compute the VeryDarkPercentileLevel percentile of a stain's
604-
// negative( matrixW ) column. This a dark value due to its being the
605-
// ( 100 - VeryDarkPercentileLevel ) among quantities of stain.
603+
// negative(matrixW) column. This a dark value due to its being the
604+
// (100 - VeryDarkPercentileLevel) among quantities of stain.
606605
CalcRowVectorType logUnstainedCalcPixel = unstainedPixel.unaryExpr(CalcUnaryFunctionPointer(std::log));
607606
CalcMatrixType matrixDarkV{ matrixDarkVIn };
608607
matrixDarkV = (firstOnes * logUnstainedCalcPixel) - matrixDarkV.unaryExpr(CalcUnaryFunctionPointer(std::log));
@@ -836,8 +835,8 @@ StructurePreservingColorNormalizationFilter<TImage>::end(
836835
{
837836
itkAssertOrThrowMacro(std::distance(matrix.data(), &matrix(matrix.rows() - 1, matrix.cols() - 1)) + 1 ==
838837
matrix.size(),
839-
"Bad array stepping") return matrix.data() +
840-
matrix.size();
838+
"Bad array stepping");
839+
return matrix.data() + matrix.size();
841840
}
842841

843842
template <typename TImage>
@@ -848,8 +847,8 @@ StructurePreservingColorNormalizationFilter<TImage>::cend(
848847
{
849848
itkAssertOrThrowMacro(std::distance(matrix.data(), &matrix(matrix.rows() - 1, matrix.cols() - 1)) + 1 ==
850849
matrix.size(),
851-
"Bad array stepping") return matrix.data() +
852-
matrix.size();
850+
"Bad array stepping");
851+
return matrix.data() + matrix.size();
853852
}
854853

855854
#else
@@ -876,8 +875,8 @@ StructurePreservingColorNormalizationFilter<TImage>::end(TMatrix & matrix)
876875
{
877876
itkAssertOrThrowMacro(std::distance(matrix.data(), &matrix(matrix.rows() - 1, matrix.cols() - 1)) + 1 ==
878877
matrix.size(),
879-
"Bad array stepping") return matrix.data() +
880-
matrix.size();
878+
"Bad array stepping");
879+
return matrix.data() + matrix.size();
881880
}
882881

883882
template <typename TImage>
@@ -887,8 +886,8 @@ StructurePreservingColorNormalizationFilter<TImage>::cend(const TMatrix & matrix
887886
{
888887
itkAssertOrThrowMacro(std::distance(matrix.data(), &matrix(matrix.rows() - 1, matrix.cols() - 1)) + 1 ==
889888
matrix.size(),
890-
"Bad array stepping") return matrix.data() +
891-
matrix.size();
889+
"Bad array stepping");
890+
return matrix.data() + matrix.size();
892891
}
893892
#endif
894893

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
setup(
1818
name="itk-spcn",
19-
version="0.1.5",
19+
version="0.1.6",
2020
author="Lee Newberg",
2121
author_email="[email protected]",
2222
packages=["itk"],
@@ -46,5 +46,5 @@
4646
license="Apache",
4747
keywords="ITK InsightToolkit",
4848
url=r"https://github.com/InsightSoftwareConsortium/ITKColorNormalization/",
49-
install_requires=[r"itk>=5.2.0"],
49+
install_requires=[r"itk>=5.2.1.post1"],
5050
)

test/azure-pipelines.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
variables:
2-
ITKGitTag: v5.2.0
3-
ITKPythonGitTag: v5.2.0
2+
ITKGitTag: v5.2.1
3+
ITKPythonGitTag: v5.2.1
44
CMakeBuildType: Release
55

66
trigger:

test/itkStructurePreservingColorNormalizationFilterTest.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ itkStructurePreservingColorNormalizationFilterTest(int argc, char * argv[])
107107

108108
using FilterType = itk::StructurePreservingColorNormalizationFilter<ImageType>;
109109
FilterType::Pointer filter = FilterType::New();
110-
// filter->SetColorIndexSuppressedByHematoxylin( 0 );
111-
// filter->SetColorIndexSuppressedByEosin( 1 );
110+
// filter->SetColorIndexSuppressedByHematoxylin(0);
111+
// filter->SetColorIndexSuppressedByEosin(1);
112112

113113
ITK_EXERCISE_BASIC_OBJECT_METHODS(filter, StructurePreservingColorNormalizationFilter, ImageToImageFilter);
114114

0 commit comments

Comments
 (0)