cellprofiler-library-nightly 5.0.0.dev454__tar.gz → 5.0.0.dev462__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/PKG-INFO +1 -1
  2. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/_version.py +3 -3
  3. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/functions/image_processing.py +155 -3
  4. cellprofiler_library_nightly-5.0.0.dev462/cellprofiler_library/modules/_imagemath.py +64 -0
  5. cellprofiler_library_nightly-5.0.0.dev462/cellprofiler_library/opts/imagemath.py +30 -0
  6. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library_nightly.egg-info/PKG-INFO +1 -1
  7. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library_nightly.egg-info/SOURCES.txt +2 -0
  8. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/LICENSE +0 -0
  9. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/README.md +0 -0
  10. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/__init__.py +0 -0
  11. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/functions/__init__.py +0 -0
  12. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/functions/file_processing.py +0 -0
  13. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/functions/measurement.py +0 -0
  14. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/functions/object_processing.py +0 -0
  15. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/functions/segmentation.py +0 -0
  16. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/__init__.py +0 -0
  17. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_closing.py +0 -0
  18. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_colortogray.py +0 -0
  19. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_combineobjects.py +0 -0
  20. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
  21. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
  22. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
  23. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_crop.py +0 -0
  24. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_dilateimage.py +0 -0
  25. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_dilateobjects.py +0 -0
  26. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_enhanceedges.py +0 -0
  27. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
  28. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_erodeimage.py +0 -0
  29. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_erodeobjects.py +0 -0
  30. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
  31. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_fillobjects.py +0 -0
  32. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
  33. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
  34. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
  35. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
  36. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
  37. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
  38. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_medialaxis.py +0 -0
  39. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_medianfilter.py +0 -0
  40. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_morph.py +0 -0
  41. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
  42. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_opening.py +0 -0
  43. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_overlayobjects.py +0 -0
  44. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
  45. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_reducenoise.py +0 -0
  46. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_removeholes.py +0 -0
  47. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_resize.py +0 -0
  48. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
  49. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
  50. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_threshold.py +0 -0
  51. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/modules/_watershed.py +0 -0
  52. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/__init__.py +0 -0
  53. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/colortogray.py +0 -0
  54. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
  55. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
  56. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
  57. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/crop.py +0 -0
  58. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/dilateimage.py +0 -0
  59. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/dilateobjects.py +0 -0
  60. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
  61. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/erodeimage.py +0 -0
  62. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/erodeobjects.py +0 -0
  63. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
  64. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
  65. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
  66. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
  67. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/morph.py +0 -0
  68. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
  69. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/overlayoutlines.py +0 -0
  70. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/removeholes.py +0 -0
  71. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/resize.py +0 -0
  72. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
  73. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/structuring_elements.py +0 -0
  74. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/opts/threshold.py +0 -0
  75. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/py.typed +0 -0
  76. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library/types.py +0 -0
  77. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
  78. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
  79. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
  80. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/environment.yml +0 -0
  81. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/pyproject.toml +0 -0
  82. {cellprofiler_library_nightly-5.0.0.dev454 → cellprofiler_library_nightly-5.0.0.dev462}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev454
3
+ Version: 5.0.0.dev462
4
4
  Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
5
5
  Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
6
6
  Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '5.0.0.dev454'
32
- __version_tuple__ = version_tuple = (5, 0, 0, 'dev454')
31
+ __version__ = version = '5.0.0.dev462'
32
+ __version_tuple__ = version_tuple = (5, 0, 0, 'dev462')
33
33
 
34
- __commit_id__ = commit_id = 'g957fa6e04'
34
+ __commit_id__ = commit_id = 'g8dcb1b2d8'
@@ -1,8 +1,10 @@
1
1
  import numpy
2
+ from numpy import isscalar as _isscalar
2
3
  import skimage.color
3
4
  import skimage.morphology
4
5
  import skimage.segmentation
5
6
  import skimage.util
7
+ from skimage.util import invert as _invert
6
8
  import skimage.transform
7
9
  import skimage
8
10
  import skimage.restoration
@@ -13,16 +15,20 @@ import scipy
13
15
  import scipy.interpolate
14
16
  import matplotlib
15
17
  import math
18
+ from typing import Any, Optional, Tuple, Callable, Union, List, cast, Dict, TypeVar
16
19
  from numpy.typing import NDArray
17
- import centrosome.filter
18
- from typing import Any, Optional, Tuple, Callable, Union, List, TypeVar
19
20
  from cellprofiler_library.types import ImageGrayscale, ImageGrayscaleMask, Image2DColor, Image2DGrayscale, ImageAny, ImageAnyMask, ObjectSegmentation, Image2D, Image2DMask, StructuringElement, ObjectLabelSet, ImageColor, ImageBinaryMask
20
21
  from cellprofiler_library.opts import threshold as Threshold
21
22
  from cellprofiler_library.opts.enhanceorsuppressfeatures import SpeckleAccuracy, NeuriteMethod
22
23
  from cellprofiler_library.opts.overlayoutlines import BrightnessMode
23
24
  from cellprofiler_library.opts.crop import RemovalMethod
24
25
  from cellprofiler_library.opts.structuring_elements import StructuringElementShape2D, StructuringElementShape3D
25
- from ..opts.resize import ResizingMethod, DimensionMethod, InterpolationMethod
26
+ from cellprofiler_library.opts.resize import ResizingMethod, DimensionMethod, InterpolationMethod
27
+ from cellprofiler_library.opts.imagemath import Operator
28
+
29
+ # TODO: python_latest - remove this if later skimage versions update types
30
+ invert = cast(Callable[[ImageAny], ImageAny], _invert)
31
+ isscalar = cast(Callable[[Optional[ImageAny]], bool], _isscalar)
26
32
 
27
33
  T = TypeVar("T", bound=ImageAny)
28
34
  MorphImageT = TypeVar("Union[ImageGrayscale, ImageGrayscaleMask]", bound=Union[ImageGrayscale, ImageGrayscaleMask])
@@ -1702,3 +1708,149 @@ def fill_holes(image: ImageAny, diameter: float) -> ImageAny:
1702
1708
  size = numpy.pi * factor
1703
1709
 
1704
1710
  return skimage.morphology.remove_small_holes(image, size)
1711
+
1712
+ ################################################################################
1713
+ # ImageMath
1714
+ ################################################################################
1715
+
1716
+ def imagemath_apply_on_image(
1717
+ output_pixel_data: ImageAny,
1718
+ pd: ImageAny,
1719
+ comparitor: ImageAny,
1720
+ op: Callable[[ImageAny, ImageAny], ImageAny],
1721
+ opval: Operator,
1722
+ ) -> ImageAny:
1723
+ assert isinstance(output_pixel_data, numpy.ndarray), "output_pixel_data must be a numpy array" # Pylance needs to understand this is a numpy array
1724
+ if not isscalar(pd) and output_pixel_data.ndim != pd.ndim:
1725
+ if output_pixel_data.ndim == 2:
1726
+ output_pixel_data = output_pixel_data[:, :, numpy.newaxis]
1727
+ if opval == Operator.EQUALS and not isscalar(comparitor):
1728
+ comparitor = comparitor[:, :, numpy.newaxis]
1729
+ if pd.ndim == 2:
1730
+ pd = pd[:, :, numpy.newaxis]
1731
+ if opval == Operator.EQUALS:
1732
+ output_pixel_data = output_pixel_data & (comparitor == pd)
1733
+ else:
1734
+ output_pixel_data = op(output_pixel_data, pd)
1735
+ return output_pixel_data
1736
+
1737
+
1738
+
1739
+ def imagemath_apply_binary_operation(
1740
+ opval: Operator,
1741
+ operands: List[Union[ImageAny, float]],
1742
+ masks: Optional[List[Optional[Union[ImageAnyMask, bool]]]],
1743
+ output_pixel_data: ImageAny,
1744
+ output_mask: Optional[ImageAnyMask],
1745
+ image_factors: Optional[List[float]], # TODO: can this be removed?
1746
+ ignore_mask: bool, # TODO: can this be removed?
1747
+ ) -> Tuple[
1748
+ ImageAny,
1749
+ Optional[ImageAnyMask],
1750
+ ]:
1751
+ #
1752
+ # Helper function to determine if logical operations should be used
1753
+ #
1754
+ def use_logical_operation(pixel_data: List[ImageAny]) -> bool:
1755
+ return all(
1756
+ [pd.dtype == bool for pd in pixel_data if not isscalar(pd)]
1757
+ )
1758
+
1759
+ #
1760
+ # Helper function for logical subtraction
1761
+ #
1762
+
1763
+ def logical_subtract(output_pixel_data: ImageAny, pd: ImageAny) -> ImageAny:
1764
+ output_pixel_data[pd] = False
1765
+ return output_pixel_data
1766
+
1767
+ comparitor = operands[0] # fix pylance error
1768
+ use_logical = use_logical_operation(operands)
1769
+ op_fn_dispatch: Dict[Operator, Callable[[ImageAny, ImageAny], ImageAny]] = {
1770
+ Operator.ADD: numpy.add,
1771
+ Operator.SUBTRACT: logical_subtract if use_logical else numpy.subtract,
1772
+ Operator.DIFFERENCE: numpy.logical_xor if use_logical else lambda x, y: numpy.abs(numpy.subtract(x, y)),
1773
+ Operator.MULTIPLY: numpy.logical_and if use_logical else numpy.multiply,
1774
+ Operator.MINIMUM: numpy.minimum,
1775
+ Operator.MAXIMUM: numpy.maximum,
1776
+ Operator.AVERAGE: numpy.add,
1777
+ Operator.MAXIMUM: numpy.maximum,
1778
+ Operator.AND: numpy.logical_and,
1779
+ Operator.OR: numpy.logical_or,
1780
+ Operator.EQUALS: numpy.equal,
1781
+ Operator.NONE: lambda x, y: x,
1782
+ Operator.DIVIDE: numpy.divide,
1783
+ }
1784
+ if opval not in op_fn_dispatch:
1785
+ raise NotImplementedError(f"Unimplemented operation: {opval}")
1786
+ #
1787
+ # Binary operations
1788
+ #
1789
+ op = op_fn_dispatch[opval]
1790
+
1791
+ #
1792
+ # Equals and Subtract operations need additional handling
1793
+ #
1794
+ if opval == Operator.EQUALS:
1795
+ output_pixel_data = numpy.ones(operands[0].shape, bool)
1796
+ comparitor = operands[0]
1797
+ elif opval == Operator.SUBTRACT and use_logical:
1798
+ output_pixel_data = operands[0].copy()
1799
+
1800
+
1801
+ # _masks is a list of Nones if masks is None. Fixes type warnings.
1802
+ if masks is None:
1803
+ masks = [None for _ in operands]
1804
+
1805
+ #
1806
+ # Apply the operation to each image in the list
1807
+ #
1808
+ for pd, mask in zip(operands[1:], masks[1:]):
1809
+ output_pixel_data = imagemath_apply_on_image(output_pixel_data, pd, comparitor, op, opval)
1810
+ if not ignore_mask:
1811
+ if output_mask is None:
1812
+ output_mask = mask
1813
+ elif mask is not None:
1814
+ output_mask = output_mask & mask
1815
+ #
1816
+ # Average operation needs additional handling
1817
+ #
1818
+ if opval == Operator.AVERAGE:
1819
+ if not use_logical:
1820
+ assert image_factors is not None, "image_factors must be provided for average operation"
1821
+ output_pixel_data /= sum(image_factors)
1822
+ return output_pixel_data, output_mask
1823
+
1824
+
1825
+ def imagemath_apply_unary_operation(
1826
+ opval: Operator,
1827
+ operands: List[Union[ImageAny, float]],
1828
+ masks: Optional[List[Optional[Union[ImageAnyMask, bool]]]],
1829
+ output_pixel_data: ImageAny,
1830
+ output_mask: Optional[ImageAnyMask],
1831
+ ignore_mask: bool,
1832
+ ) -> Tuple[
1833
+ ImageAny,
1834
+ Optional[ImageAnyMask],
1835
+ ]:
1836
+ if opval == Operator.STDEV:
1837
+ pixel_array = numpy.array(operands)
1838
+ output_pixel_data = numpy.std(pixel_array,axis=0)
1839
+ if not ignore_mask:
1840
+ mask_array = numpy.array(masks)
1841
+ output_mask = mask_array.all(axis=0)
1842
+ elif opval == Operator.INVERT:
1843
+ output_pixel_data = invert(output_pixel_data)
1844
+ elif opval == Operator.NOT:
1845
+ output_pixel_data = numpy.logical_not(output_pixel_data)
1846
+ elif opval == Operator.LOG_TRANSFORM:
1847
+ output_pixel_data = numpy.log2(output_pixel_data + 1)
1848
+ elif opval == Operator.LOG_TRANSFORM_LEGACY:
1849
+ output_pixel_data = numpy.log2(output_pixel_data)
1850
+ elif opval == Operator.NONE:
1851
+ output_pixel_data = output_pixel_data.copy()
1852
+ else:
1853
+ raise NotImplementedError(
1854
+ "The operation %s has not been implemented" % opval
1855
+ )
1856
+ return output_pixel_data, output_mask
@@ -0,0 +1,64 @@
1
+ import numpy
2
+ from typing import Callable, Optional, List, Tuple, cast, Union, Annotated
3
+ from numpy import isscalar as _isscalar
4
+ from pydantic import validate_call, ConfigDict, Field
5
+ from cellprofiler_library.opts.imagemath import Operator, BINARY_OUTPUT_OPS, UNARY_INPUT_OPS, BINARY_INPUT_OPS
6
+ from cellprofiler_library.types import ImageAny, ImageAnyMask
7
+ from cellprofiler_library.functions.image_processing import imagemath_apply_binary_operation, imagemath_apply_unary_operation
8
+ isscalar = cast(Callable[[Optional[ImageAny]], bool], _isscalar)
9
+
10
+
11
+ @validate_call(config=ConfigDict(arbitrary_types_allowed=True))
12
+ def image_math(
13
+ opval: Annotated[Operator, Field(description=" Operator to apply to the images or measurements")],
14
+ operands: Annotated[List[Union[ImageAny, float]], Field(description=" List of images and/or measurements to apply the operator to")],
15
+ masks: Annotated[Optional[List[Optional[Union[ImageAnyMask, bool]]]], Field(description=" List of masks for the images. Use `True` for measurement operands")],
16
+ output_pixel_data: Annotated[ImageAny, Field(description=" Output image or measurement")],
17
+ output_mask: Annotated[Optional[ImageAnyMask], Field(description=" Output mask")],
18
+ ignore_mask: Annotated[bool, Field(description=" Ignore the masks")],
19
+ image_factors: Annotated[Optional[List[float]], Field(description=" List of image factors to multiply the images by")],
20
+ exponent: Annotated[Optional[float], Field(description=" Exponent to raise the images by")],
21
+ after_factor: Annotated[Optional[float], Field(description=" Multiply the images by this value after the operation")],
22
+ addend: Annotated[Optional[float], Field(description=" Add this value to the images")],
23
+ truncate_low: Annotated[Optional[bool], Field(description=" Truncate the images below 0")],
24
+ truncate_high: Annotated[Optional[bool], Field(description=" Truncate the images above 0")],
25
+ replace_nan: Annotated[Optional[bool], Field(description=" Replace invalid values with 0")],
26
+ ) -> Tuple[
27
+ ImageAny, Optional[ImageAnyMask]
28
+ ]:
29
+ if opval in BINARY_INPUT_OPS:
30
+ output_pixel_data, output_mask = imagemath_apply_binary_operation(opval, operands, masks, output_pixel_data, output_mask, image_factors, ignore_mask)
31
+
32
+ elif opval in UNARY_INPUT_OPS:
33
+ output_pixel_data, output_mask = imagemath_apply_unary_operation(opval, operands, masks, output_pixel_data, output_mask, ignore_mask)
34
+
35
+ else:
36
+ raise NotImplementedError(
37
+ "The operation %s has not been implemented" % opval
38
+ )
39
+
40
+ # Check to see if there was a measurement & image w/o mask. If so
41
+ # set mask to none
42
+ if isscalar(output_mask):
43
+ output_mask = None
44
+ if opval not in BINARY_OUTPUT_OPS:
45
+ #
46
+ # Post-processing: exponent, multiply, add
47
+ #
48
+ if exponent is not None and exponent != 1:
49
+ output_pixel_data **= exponent
50
+ if after_factor is not None and after_factor != 1:
51
+ output_pixel_data *= after_factor
52
+ if addend is not None and addend != 0:
53
+ output_pixel_data += addend
54
+
55
+ #
56
+ # truncate values
57
+ #
58
+ if truncate_low:
59
+ output_pixel_data[output_pixel_data < 0] = 0
60
+ if truncate_high:
61
+ output_pixel_data[output_pixel_data > 1] = 1
62
+ if replace_nan:
63
+ output_pixel_data[numpy.isnan(output_pixel_data)] = 0
64
+ return output_pixel_data, output_mask
@@ -0,0 +1,30 @@
1
+ from enum import Enum
2
+
3
+ class Operator(str, Enum):
4
+ ADD = "Add"
5
+ SUBTRACT = "Subtract"
6
+ DIFFERENCE = "Absolute Difference"
7
+ MULTIPLY = "Multiply"
8
+ DIVIDE = "Divide"
9
+ AVERAGE = "Average"
10
+ MINIMUM = "Minimum"
11
+ MAXIMUM = "Maximum"
12
+ STDEV = "Standard Deviation"
13
+ INVERT = "Invert"
14
+ COMPLEMENT = "Complement"
15
+ LOG_TRANSFORM_LEGACY = "Log transform (legacy)"
16
+ LOG_TRANSFORM = "Log transform (base 2)"
17
+ NONE = "None"
18
+ OR = "Or"
19
+ AND = "And"
20
+ NOT = "Not"
21
+ EQUALS = "Equals"
22
+
23
+
24
+ class Operand(str, Enum):
25
+ IMAGE = "Image"
26
+ MEASUREMENT = "Measurement"
27
+
28
+ BINARY_OUTPUT_OPS = [Operator.AND, Operator.OR, Operator.NOT, Operator.EQUALS]
29
+ UNARY_INPUT_OPS = [Operator.STDEV, Operator.INVERT, Operator.NOT, Operator.LOG_TRANSFORM, Operator.LOG_TRANSFORM_LEGACY, Operator.NONE]
30
+ BINARY_INPUT_OPS = [Operator.ADD, Operator.SUBTRACT, Operator.DIFFERENCE, Operator.MULTIPLY, Operator.DIVIDE, Operator.AVERAGE, Operator.MAXIMUM, Operator.MINIMUM, Operator.AND, Operator.OR, Operator.EQUALS]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev454
3
+ Version: 5.0.0.dev462
4
4
  Summary: cellprofiler-library implements CellProfiler's image processing and mathematical code, and is usable as a standalone library
5
5
  Author: Anne Carpenter, Thouis (Ray) Jones, Lee Kamentsky, Vebjorn Ljosa, David Logan, Mark Bray, Madison Swain-Bowden, Allen Goodman, Claire McQuinn, Alice Lucas, Callum Tromans-Coia
6
6
  Author-email: Beth Cimini <bcimini@broadinstitute.org>, David Stirling <dstirling@glencoesoftware.com>, Nodar Gogoberidze <ngogober@broadinstitute.org>
@@ -32,6 +32,7 @@ cellprofiler_library/modules/_gaussianfilter.py
32
32
  cellprofiler_library/modules/_identifyprimaryobjects.py
33
33
  cellprofiler_library/modules/_identifysecondaryobjects.py
34
34
  cellprofiler_library/modules/_identifytertiaryobjects.py
35
+ cellprofiler_library/modules/_imagemath.py
35
36
  cellprofiler_library/modules/_measureimageoverlap.py
36
37
  cellprofiler_library/modules/_measureobjectsizeshape.py
37
38
  cellprofiler_library/modules/_medialaxis.py
@@ -62,6 +63,7 @@ cellprofiler_library/opts/erodeobjects.py
62
63
  cellprofiler_library/opts/identifyprimaryobjects.py
63
64
  cellprofiler_library/opts/identifysecondaryobjects.py
64
65
  cellprofiler_library/opts/identifytertiaryobjects.py
66
+ cellprofiler_library/opts/imagemath.py
65
67
  cellprofiler_library/opts/measureimageoverlap.py
66
68
  cellprofiler_library/opts/morph.py
67
69
  cellprofiler_library/opts/objectsizeshapefeatures.py