Skip to content

Commit

Permalink
Bump version number for 3.5.0 release.
Browse files Browse the repository at this point in the history
  • Loading branch information
crisluengo committed Jun 18, 2024
1 parent 3afa432 commit 2f0a016
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 231 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ project(DIPlib)

# The version number and latest copyright year. Update these values here, they're used all throughout the project.
set(PROJECT_VERSION_MAJOR "3")
set(PROJECT_VERSION_MINOR "4")
set(PROJECT_VERSION_PATCH "3")
set(PROJECT_VERSION_MINOR "5")
set(PROJECT_VERSION_PATCH "0")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(DIP_COPYRIGHT_YEAR "2024")

Expand Down
292 changes: 292 additions & 0 deletions changelogs/diplib_3.5.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
---
layout: post
title: "Changes DIPlib 3.5.0"
---

## Changes to *DIPlib*

### New functionality

- Added `dip::OutputBuffer` as a virtual base class, and `dip::SimpleOutputBuffer` and `dip::FixedOutputBuffer`
as specific instances. These are used to handle a buffer that a JPEG or PNG file can be written into by
`dip::ImageWriteJPEG()` and `dip::ImageWritePNG()`.

- Added `dip::Framework::Projection()` as a public function. Previously it was a private library function for internal
use only. This framework function simplifies the creation of projection operations, and forms the basis of
functions such as `dip::Mean()` and `dip::Maximum()`.

- Added macros `DIP_PARALLEL_ERROR_DECLARE`, `DIP_PARALLEL_ERROR_START` and `DIP_PARALLEL_ERROR_END`
to simplify writing parallel code with OpenMP that properly handles exceptions.

- Added an operator to convert `dip::Units` to `bool`. The units object will test false if it's unitless.

- Added `dip::Quartiles()`.

- Added `dip::Measurement::IteratorFeature::AsImage()` and `AsScalarImage()`.

- Added `dip::Histogram::OptimalConfiguration()` and `OptimalConfigurationWithFullRange()`, which make it possible
to configure the histogram to use the Freedman--Diaconis rule to choose the bin size.

- Added `dip::LabelMap`, a class that holds labels (object IDs) and can map them to new values. The mapping can be
applied to a labeled image or to a `dip::Measurement` object. You can also index into a `dip::Measurement`
object with a `dip::LabelMap`.

- Added comparison operators for `dip::Measurement::IteratorFeature`. They return a `dip::LabelMap`.

- Added `dip::UnionFind::Size()`.

- Added `dip::IsOnEdge()`.

- Added an overload to `dip::GaussianMixtureModel()` that takes a 1D histogram as input.

### Changed functionality

- The `compressionLevel` argument to `dip::ImageWritePNG()` changed from `dip::uint` to `dip::sint`, allowing for
-1 to configure the deflate algorithm to use RLE instead of its default strategy. For some images this option
can lead to smaller files, and for some images to much faster compression.

- The versions of `dip::ImageWriteJPEG()` and `dip::ImageWritePNG()` that write to a memory buffer now take
a version of a `dip::OutputBuffer` object to write to. Overloaded versions of these two functions maintain
the previous syntax where the buffer is created internally and returned to the caller.

- `dip::Framework::Projection()` is now parallelized. All projection functions (for example `dip::Mean()` and
`dip::Maximum()`) now can use multithreading for faster computation if the output has at least one dimension.
For example, the mean value of each image row can be computed in parallel, but the mean value over the whole
image is still not computed in parallel.

- `dip::PairCorrelation()`, `dip::ProbabilisticPairCorrelation()`, `dip::Semivariogram()`, and `dip::ChordLength()`
Have been parallelized for `"random"` sampling.

- `dip::GrowRegionsWeighted()` with a `dip::Metric` parameter has been deprecated. The new version of the function
uses the fast marching algorithm in the grey-weighted distance transform. If both `grey` and `mask` are not
forged, `dip::EuclideanDistanceTransform()` is called instead of `dip::GreyWeightedDistanceTransform()`.
This makes the function efficient for when isotropic growing is required. And the function now has a new float
parameter, `distance` that determines how far the regions are grown.

- `dip::ImageRead()` throws a `dip::RunTimeError` instead of a `dip::ParameterError` if the file doesn't exist
or is of an unrecognized type.

- `dip::GetOptimalDFTSize()` has a new argument `maxFactor` that determines what the largest factor for the output
integer can be. Valid values are 5, 7 and 11. A new function `dip::MaxFactor()` will give the appropriate value
depending on whether a real or complex-valued transform is being computed, and what FFT implementation is being
used. When using *PocketFFT*, this function can now also return much larger values than before.

- `dip::OptimalFourierTransformSize()`, which depends on `dip::GetOptimalDFTSize()` (see the bullet point above
this one) has a new argument `purpose` that can be either `"real"` or `"complex"`, and uses the new
`dip::MaxFactor()` to fill in the `maxFactor` argument.

- `dip::GaussFT()` has a new parameter `boundaryCondition`, the default empty value gives the same behavior as
previously. `dip::Gauss()` now passes the boundary condition through to `dip::GaussFT()`.
See [issue #159](https://github.com/DIPlib/diplib/issues/159).

- The versions of `dip::IsodataThreshold()`, `dip::OtsuThreshold()`, `dip::MinimumErrorThreshold()`,
`dip::GaussianMixtureModelThreshold()`, `dip::TriangleThreshold()` and `dip::BackgroundThreshold()` that take an
image as input, now compute the histogram using the new `dip::Histogram::OptimalConfiguration()` configuration.
This generally makes them more precise. In some cases, the previous behavior was not correct.
See [issue #161](https://github.com/DIPlib/diplib/issues/161).
To reproduce the previous behavior, compute a histogram with default configuration (`dip::Histogram(image)`),
and pass this histogram to the equivalent threshold estimation function. This function will return a threshold
value that can be applied to the image using the comparison operator (`image > threshold`).

- `dip::EstimateNoiseVariance()` uses a potentially more precise threshold internally to exclude edges.

- Made more consistent use of `dip::LabelType`, and we're no longer accepting any label (or object ID) with a value
that doesn't fit in that type. *DIPlib* has always produced labeled images of this type, but it accepts any
unsigned integer image as a label image. Both internally and in the API, sometimes we used `dip::LabelType`
(32-bit unsigned integer), and sometimes we used `dip::uint` (system-dependent size integer, usually 64-bit).
We now consistently use `dip::LabelType` everywhere:

- If the input labeled image is of type `uint64`, any pixel value outside the `dip::LabelType` range will cause
an exception to the thrown. This is true for the measurement functionality and the functions in `regions.h`.

- Added a version of `dip::Measurement::SetObjectIDs()` that takes a `std::vector< dip::LabelType >` as input.

- `dip::ListObjectLabels()` is identical to `dip::GetObjectLabels()` (which is now deprecated), but it returns a
`std::vector< dip::LabelType >` instead of a `dip::UnsignedArray`. `dip::GetObjectLabels()` is deprecated.

- Added `dip::CastLabelType()`, which can be called with any unsigned integer as input, and the same value
as a `dip::LabelType`. If the value is too large to fit in that type, an exception is thrown.

- `dip::GetLabelBoundingBox()` with a `dip::uint` for the `objectID` parameter is deprecated,
it now needs to be a `dip::LabelType`.

- `dip::GetImageChainCodes()` with a `dip::UnsignedArray` for the `objectIDs` parameter is deprecated,
it now needs to be a `std::vector< dip::LabelType >`.

- `dip::ChainCode::objectID` is now of type `dip::LabelType`, was `dip::uint`.

- The measurement functions and data structures still use `dip::uint` for object IDs.

- `dip::ListObjectLabels()` adds an option to list only labels touching the image edge.

- `dip::EdgeObjectsRemove()` also works for labeled images.

- `dip::Image::View::Copy()` with an image as input now allows a 1-pixel input to be used. This behaves like
`dip::Image::View::Fill()` with a `dip::Image::Pixel` as input.

### Bug fixes

- `dip::PairCorrelation`, `dip::ProbabilisticPairCorrelation`, `dip::Semivariogram`, and `dip::ChordLength`
did not properly compute step sizes for `"grid"` sampling, effectively ignoring the value of `probes`
and using all pixels (as if `probes` were set to 0).

- Tensor indexing did not remove color space information as expected (bug introduced with the fix to the move
constructor in 3.4.3).

- `dip::Image::CheckIsMask()` didn't properly check for singleton-expandable masks, accepting masks of any size.

- `dip::FourierTransform()` threw an exception when the real-to-complex dimension had a size of 2.
See [issue #158](https://github.com/DIPlib/diplib/issues/158).

- A wrong assertion in internal code for `dip::FourierTransform()` made it impossible to inverse transform
a real-valued image under certain conditions, when *DIPlib* was built with assertions enabled (bug introduced
with the refactoring of the Fourier code in 3.4.0).

- The 2D parabola fitting function used in `dip::SubpixelLocation()`, `dip::SubpixelMaxima()` and
`dip::SubpixelMinima()`, with the `"parabolic"` and `"gaussian"` methods, was using wrong weights,
making the result not precise. The 3D case was not affected. The faster `"parabolic separable"` and
`"gaussian separable"` methods were also not affected.

### Updated dependencies

- Updated included header-only library *robin-map* to version 1.3.0. Assorted minor improvements.

- Updated included header-only library *pcg-cpp* to the current master branch (last updated 2022-04-08).
Assorted minor improvements.

- Updated bundled *pybind11* to version 2.12.0.

- Updated bundled library *PocketFFT* to the current master branch (last updated 2024-03-22).
This fixes a potential compilation problem on macOS.

### Build changes

- Minimum required version of *CMake* is now 3.12.




## Changes to *DIPimage*

### Changed functionality

- Added `'optimal'` to `diphist`, `diphist2` and `mdhistogram` as an option to choose an optimal bin size.

(See also changes to *DIPlib*.)

### Bug fixes

None, but see bugfixes to *DIPlib*.

### Build and installation changes

- Added the *CMake* option `DIP_JAVA_VERSION`, which can be important when building *DIPimage* for older versions
of MATLAB. The Java version must be equal or older than the version used by MATLAB. Running `version -java`
in MATLAB will tell you what version of Java it is using.

- Added the function `download_bioformats`, which does the same thing as `python -m diplib download_bioformats` in
*PyDIP*. This significantly simplifies the installation instructions for *Bio-Formats*.




## Changes to *PyDIP*

### New functionality

- Added bindings to `dip::GaussFIR()`, to complement `GaussIIR()` and `GaussFT()`. Though it is expected users will
keep using `dip.Gauss()` to access these various algorithms.

- Added bindings for `dip.Units.HasSameDimensions`, `dip.Units.IsDimensionless`, `dip.Units.IsPhysical`,
`dip.Units.AdjustThousands`, `dip.Units.Thousands`.

- Added `dip.Measurement.ToDataFrame()`, which converts the measurement results into a Pandas DataFrame.
This function will import NumPy and Pandas when used, these packages need to be installed.

- Added `dip.Measurement.MeasurementFeature.Subset()` (binding for `dip::Measurement::IteratorFeature::Subset()`)
and `dip.Measurement.FeatureValuesView()`.

- Added bindings for `dip.ColorSpaceManager.SetWhitePoint()`, as well as `dip.ColorSpaceManager.IlluminantA`,
`IlluminantD50`, `IlluminantD55`, `IlluminantD65` and `IlluminantE`.

- Added bindings for `dip.SeparableConvolution()`, `dip.SeparateFilter()` and the `dip.OneDimensionalFilter`
struct.

### Changed functionality

- The *DIPlib* exception classes are now properly bound. This changes the type of the exceptions raised by
the library in Python: `dip.Error` is the new base class, raised exceptions are either `dip.ParameterError`,
`dip.RunTimeError` or `dip.AssertionError`. `dip.Error` is derived from `Exception`.

- Made `diplib.PyDIPjavaio` more easily available as `diplib.javaio`. The new name matches the C++ library
namespace, and when imported properly loads the JVM before importing *PyDIPjavaio*. One can now:
```python
import diplib as dip
import diplib.javaio
image = dip.javaio.ImageReadJavaIO("foo")
```
`dip.ImageRead()` still automatically loads *PyDIPjavaio* on first use.

- `diplib.viewer` is no longer an alias, but a true submodule, like we did for `diplib.javaio`. This should
not change anything for the user, other than some IDEs having less trouble identifying the name.

- `dip.ImageRead()` and `dip.javaio.ImageReadJavaIO()` now also have a version that takes the output image
as a keyword-only argument `out`.

- All the functions named `dip.ImageRead...()` that have a keyword-only argument `out` now return the
`dip::FileInformation` structure (as a dict, just like `dip.ImageRead...Info()` does).

- Unitless `dip.Units` now test false.

- Moved `dip.MeasurementTool.MeasurementFeature` to `dip.Measurement.MeasurementFeature` and
`dip.MeasurementTool.MeasurementObject` to `dip.Measurement.MeasurementObject`.
They are the bindings to `dip::Measurement::IteratorFeature` and `dip::Measurement::IteratorObject` respectively.

(See also changes to *DIPlib*.)

### Bug fixes

- `dip.viewer.Show()` would cause Python to crash if given a raw image.

(See also bugfixes to *DIPlib*.)

### Updated dependencies

- Updated bundled *pybind11* to version 2.12.0.

### Build and installation changes

- The *CMake* option `PYTHON_EXECUTABLE` is no longer used, set `Python_EXECUTABLE` instead. The build script
will, for the time being, copy the value of the former to the latter if the former is set but the latter isn't.

- The *CMake* option `PYBIND11_PYTHON_VERSION` is no longer used. It was mentioned in the documentation, but
probably never really worked.

- Significantly improved the command to download *Bio-Formats*: `python -m diplib download_bioformats` now
has an optional argument `-u` to force an update of the existing library, and another one to specify
which verison to download. By default, it downloads whatever the latest version is, we no longer hard-code
a specific version number.




## Changes to *DIPviewer*

### Bug fixes

- Trying to display an image with wrong color space information would throw an exception. The image is now seen
as a generic tensor image.

- Continuous scrolling devices were way too sensitive when using GLFW, it was really hard to zoom in and out
of an image. (The fix works at least on macOS, let us know if this produces issues on other platforms.)




## Changes to *DIPjavaio*

### Changed functionality

- `dip::javaio::ImageReadJavaIO()` has an additional parameter `imageNumber` to select which image in a multi-image
file to read. The `dip::FileInformation` structure returned now correctly indicates how many images are in the file
in the `numberOfImages` element.
Loading

0 comments on commit 2f0a016

Please sign in to comment.