cellprofiler-library-nightly 5.0.0.dev496__tar.gz → 5.0.0.dev501__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 (93) hide show
  1. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/PKG-INFO +1 -1
  2. cellprofiler_library_nightly-5.0.0.dev501/cellprofiler_library/__init__.py +1 -0
  3. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/_version.py +3 -3
  4. cellprofiler_library_nightly-5.0.0.dev501/cellprofiler_library/measurement_model.py +154 -0
  5. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_measurecolocalization.py +28 -28
  6. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library_nightly.egg-info/PKG-INFO +1 -1
  7. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library_nightly.egg-info/SOURCES.txt +1 -0
  8. cellprofiler_library_nightly-5.0.0.dev496/cellprofiler_library/opts/__init__.py +0 -0
  9. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/LICENSE +0 -0
  10. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/README.md +0 -0
  11. {cellprofiler_library_nightly-5.0.0.dev496/cellprofiler_library → cellprofiler_library_nightly-5.0.0.dev501/cellprofiler_library/functions}/__init__.py +0 -0
  12. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/functions/file_processing.py +0 -0
  13. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/functions/image_processing.py +0 -0
  14. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/functions/measurement.py +0 -0
  15. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/functions/object_processing.py +0 -0
  16. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/functions/segmentation.py +0 -0
  17. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/__init__.py +0 -0
  18. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_closing.py +0 -0
  19. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_colortogray.py +0 -0
  20. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_combineobjects.py +0 -0
  21. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_convertimagetoobjects.py +0 -0
  22. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_convertobjectstoimage.py +0 -0
  23. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_correctilluminationapply.py +0 -0
  24. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_crop.py +0 -0
  25. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_dilateimage.py +0 -0
  26. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_dilateobjects.py +0 -0
  27. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_enhanceedges.py +0 -0
  28. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_enhanceorsuppressfeatures.py +0 -0
  29. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_erodeimage.py +0 -0
  30. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_erodeobjects.py +0 -0
  31. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_expandorshrinkobjects.py +0 -0
  32. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_fillobjects.py +0 -0
  33. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_flipandrotate.py +0 -0
  34. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_gaussianfilter.py +0 -0
  35. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_graytocolor.py +0 -0
  36. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_identifyprimaryobjects.py +0 -0
  37. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_identifysecondaryobjects.py +0 -0
  38. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_identifytertiaryobjects.py +0 -0
  39. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_imagemath.py +0 -0
  40. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_measureimageoverlap.py +0 -0
  41. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_measureobjectsizeshape.py +0 -0
  42. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_medialaxis.py +0 -0
  43. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_medianfilter.py +0 -0
  44. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_morph.py +0 -0
  45. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_morphologicalskeleton.py +0 -0
  46. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_opening.py +0 -0
  47. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_overlayobjects.py +0 -0
  48. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_overlayoutlines.py +0 -0
  49. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_reducenoise.py +0 -0
  50. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_removeholes.py +0 -0
  51. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_resize.py +0 -0
  52. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_savecroppedobjects.py +0 -0
  53. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_shrinktoobjectcenters.py +0 -0
  54. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_smooth.py +0 -0
  55. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_threshold.py +0 -0
  56. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/modules/_watershed.py +0 -0
  57. {cellprofiler_library_nightly-5.0.0.dev496/cellprofiler_library/functions → cellprofiler_library_nightly-5.0.0.dev501/cellprofiler_library/opts}/__init__.py +0 -0
  58. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/colortogray.py +0 -0
  59. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/convertimagetoobjects.py +0 -0
  60. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/convertobjectstoimage.py +0 -0
  61. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/correctilluminationapply.py +0 -0
  62. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/crop.py +0 -0
  63. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/dilateimage.py +0 -0
  64. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/dilateobjects.py +0 -0
  65. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/enhanceedges.py +0 -0
  66. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/enhanceorsuppressfeatures.py +0 -0
  67. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/erodeimage.py +0 -0
  68. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/erodeobjects.py +0 -0
  69. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/flipandrotate.py +0 -0
  70. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/graytocolor.py +0 -0
  71. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/identifyprimaryobjects.py +0 -0
  72. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/identifysecondaryobjects.py +0 -0
  73. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/identifytertiaryobjects.py +0 -0
  74. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/imagemath.py +0 -0
  75. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/measurecolocalization.py +0 -0
  76. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/measureimageoverlap.py +0 -0
  77. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/morph.py +0 -0
  78. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/objectsizeshapefeatures.py +0 -0
  79. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/overlayoutlines.py +0 -0
  80. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/removeholes.py +0 -0
  81. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/resize.py +0 -0
  82. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/shrinktoobjectcenters.py +0 -0
  83. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/smooth.py +0 -0
  84. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/structuring_elements.py +0 -0
  85. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/opts/threshold.py +0 -0
  86. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/py.typed +0 -0
  87. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library/types.py +0 -0
  88. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library_nightly.egg-info/dependency_links.txt +0 -0
  89. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library_nightly.egg-info/requires.txt +0 -0
  90. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/cellprofiler_library_nightly.egg-info/top_level.txt +0 -0
  91. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/environment.yml +0 -0
  92. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/pyproject.toml +0 -0
  93. {cellprofiler_library_nightly-5.0.0.dev496 → cellprofiler_library_nightly-5.0.0.dev501}/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.dev496
3
+ Version: 5.0.0.dev501
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>
@@ -0,0 +1 @@
1
+ from .measurement_model import LibraryMeasurements
@@ -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.dev496'
32
- __version_tuple__ = version_tuple = (5, 0, 0, 'dev496')
31
+ __version__ = version = '5.0.0.dev501'
32
+ __version_tuple__ = version_tuple = (5, 0, 0, 'dev501')
33
33
 
34
- __commit_id__ = commit_id = 'g8d098d2ce'
34
+ __commit_id__ = commit_id = 'gb8fc0acf1'
@@ -0,0 +1,154 @@
1
+ from typing import Any, Dict, List
2
+ from pydantic import BaseModel, Field, ConfigDict
3
+
4
+ class LibraryMeasurements(BaseModel):
5
+ """
6
+ A Pydantic implementation mirroring CellProfiler's Measurements class functionality.
7
+
8
+ This class represents measurements for a single image set context, designed to be
9
+ constructed from and serializable to the "Primitive Dictionary" contract.
10
+ """
11
+ model_config = ConfigDict(
12
+ arbitrary_types_allowed=True,
13
+ populate_by_name=True
14
+ )
15
+
16
+ # Primary data structures matching the MDC contract
17
+ image: Dict[str, Any] = Field(default_factory=dict)
18
+ objects: Dict[str, Dict[str, Any]] = Field(default_factory=dict)
19
+
20
+ # Additional storage for full Measurements compatibility (e.g. Experiment metadata)
21
+ experiment: Dict[str, Any] = Field(default_factory=dict)
22
+
23
+ # Placeholder for relationships if needed in the future
24
+ relationships: List[Dict[str, Any]] = Field(default_factory=list)
25
+
26
+ def add_measurement(self, object_name: str, feature_name: str, data: Any):
27
+ """
28
+ Add a measurement. Mirrors Measurements.add_measurement.
29
+
30
+ Args:
31
+ object_name: Name of the object (e.g., 'Image', 'Nuclei').
32
+ feature_name: Name of the feature (e.g., 'AreaShape_Area').
33
+ data: The value to store (float, string, or numpy array).
34
+ """
35
+ if object_name == "Experiment":
36
+ self.experiment[feature_name] = data
37
+ elif object_name == "Image":
38
+ self.image[feature_name] = data
39
+ else:
40
+ if object_name not in self.objects:
41
+ self.objects[object_name] = {}
42
+ self.objects[object_name][feature_name] = data
43
+
44
+ def get_measurement(self, object_name: str, feature_name: str) -> Any:
45
+ """
46
+ Get a measurement. Mirrors Measurements.get_measurement.
47
+ """
48
+ if object_name == "Experiment":
49
+ return self.experiment.get(feature_name)
50
+ elif object_name == "Image":
51
+ return self.image.get(feature_name)
52
+ else:
53
+ return self.objects.get(object_name, {}).get(feature_name)
54
+
55
+ def add_image_measurement(self, feature_name: str, data: Any):
56
+ """Helper to add an image measurement."""
57
+ self.add_measurement("Image", feature_name, data)
58
+
59
+ def add_experiment_measurement(self, feature_name: str, data: Any):
60
+ """Helper to add an experiment measurement."""
61
+ self.add_measurement("Experiment", feature_name, data)
62
+
63
+ def get_experiment_measurement(self, feature_name: str) -> Any:
64
+ """Helper to get an experiment measurement."""
65
+ return self.get_measurement("Experiment", feature_name)
66
+
67
+ def get_object_names(self) -> List[str]:
68
+ """Return a list of all object names (including Image and Experiment if present)."""
69
+ names = list(self.objects.keys())
70
+ if self.image:
71
+ names = ["Image"] + names
72
+ if self.experiment:
73
+ names = ["Experiment"] + names
74
+ return names
75
+
76
+ def get_feature_names(self, object_name: str) -> List[str]:
77
+ """Return feature names for a specific object."""
78
+ if object_name == "Experiment":
79
+ return list(self.experiment.keys())
80
+ elif object_name == "Image":
81
+ return list(self.image.keys())
82
+ else:
83
+ return list(self.objects.get(object_name, {}).keys())
84
+
85
+ def has_feature(self, object_name: str, feature_name: str) -> bool:
86
+ """Check if a feature exists."""
87
+ if object_name == "Experiment":
88
+ return feature_name in self.experiment
89
+ elif object_name == "Image":
90
+ return feature_name in self.image
91
+ else:
92
+ return feature_name in self.objects.get(object_name, {})
93
+
94
+ def __getitem__(self, key):
95
+ """Support dict-style access: m['Image', 'Count_Cells']"""
96
+ if isinstance(key, tuple):
97
+ assert len(key) == 2
98
+ return self.get_measurement(*key)
99
+ raise KeyError("Invalid key format. Expected (Object, Feature)")
100
+
101
+ def __setitem__(self, key, value):
102
+ """Support dict-style assignment: m['Image', 'Count_Cells'] = 5"""
103
+ if isinstance(key, tuple):
104
+ assert len(key) == 2
105
+ self.add_measurement(*key, value)
106
+ else:
107
+ raise KeyError("Invalid key format. Expected (Object, Feature)")
108
+
109
+ def to_dict(self) -> Dict[str, Any]:
110
+ """
111
+ Serialize to the primitive dictionary format required by the refactoring contract.
112
+ """
113
+ return self.model_dump(exclude_none=True)
114
+
115
+ def merge(self, other: 'LibraryMeasurements') -> 'LibraryMeasurements':
116
+ """
117
+ Merge this LibraryMeasurements object with another one, returning a new instance.
118
+
119
+ Collision resolution:
120
+ - Image measurements: 'other' overwrites 'self'
121
+ - Experiment measurements: 'other' overwrites 'self'
122
+ - Object measurements: Merged by object name. Within an object, 'other' features overwrite 'self'.
123
+ - Relationships: Concatenated
124
+
125
+ Args:
126
+ other: Another LibraryMeasurements instance
127
+
128
+ Returns:
129
+ A new LibraryMeasurements instance containing merged data
130
+ """
131
+ # Create deep copies of dictionaries to avoid side effects
132
+ new_image = self.image.copy()
133
+ new_image.update(other.image)
134
+
135
+ new_experiment = self.experiment.copy()
136
+ new_experiment.update(other.experiment)
137
+
138
+ new_objects = {}
139
+ # Merge objects
140
+ all_objects = set(self.objects.keys()) | set(other.objects.keys())
141
+ for obj_name in all_objects:
142
+ obj_measurements = self.objects.get(obj_name, {}).copy()
143
+ obj_measurements.update(other.objects.get(obj_name, {}))
144
+ new_objects[obj_name] = obj_measurements
145
+
146
+ # Concatenate relationships
147
+ new_relationships = self.relationships + other.relationships
148
+
149
+ return LibraryMeasurements(
150
+ image=new_image,
151
+ objects=new_objects,
152
+ experiment=new_experiment,
153
+ relationships=new_relationships
154
+ )
@@ -1,11 +1,12 @@
1
1
  import numpy as np
2
2
  from numpy.typing import NDArray
3
- from typing import List, Tuple, Annotated, Optional, Dict, Union
3
+ from typing import List, Tuple, Annotated, Optional, Union
4
4
  from pydantic import validate_call, ConfigDict, BeforeValidator, Field
5
5
  from cellprofiler_library.functions.measurement import measure_correlation_and_slope_from_objects, measure_manders_coefficient_from_objects, measure_rwc_coefficient_from_objects, measure_overlap_coefficient_from_objects, measure_costes_coefficient_from_objects, get_thresholded_images_and_counts, measure_correlation_and_slope, measure_manders_coefficient, measure_rwc_coefficient, measure_overlap_coefficient, measure_costes_coefficient
6
6
  from cellprofiler_library.opts.measurecolocalization import TemplateMeasurementFormat, MeasurementType
7
7
  from cellprofiler_library.types import ImageGrayscale, ImageGrayscaleMask, Pixel, ObjectLabel, ObjectSegmentation, ImageAny, ImageAnyMask
8
8
  from cellprofiler_library.opts.measurecolocalization import CostesMethod
9
+ from cellprofiler_library.measurement_model import LibraryMeasurements
9
10
  from cellprofiler_library.functions.image_processing import crop_image_similarly
10
11
  from cellprofiler_library.functions.object_processing import size_similarly, object_crop_image_similarly
11
12
 
@@ -121,14 +122,14 @@ def run_image_pair_images(
121
122
  costes_method: Annotated[Optional[CostesMethod], Field(description="")] = CostesMethod.FAST,
122
123
  ) -> Annotated[
123
124
  Tuple[
124
- Dict[str, np.float64],
125
+ LibraryMeasurements,
125
126
  List[Tuple[str, str, str, str, str]]
126
127
  ], Field(description="List of measurement results and a dictionary of measurements with precise values")]:
127
128
  """Calculate the correlation between the pixels of two images"""
128
129
 
129
130
 
130
131
  summary: List[Tuple[str, str, str, str, str]] = []
131
- measurements: Dict[str, np.float64] = {}
132
+ measurements = LibraryMeasurements()
132
133
  corr = np.float64(np.NaN)
133
134
  slope = np.float64(np.NaN)
134
135
  C1 = np.float64(np.NaN)
@@ -210,22 +211,22 @@ def run_image_pair_images(
210
211
  costes_measurement_2 = TemplateMeasurementFormat.COSTES_FORMAT % (im2_name, im1_name)
211
212
 
212
213
  if MeasurementType.CORRELATION in measurement_types:
213
- measurements[corr_measurement] = corr
214
- measurements[slope_measurement] = slope
214
+ measurements.add_image_measurement(corr_measurement, corr)
215
+ measurements.add_image_measurement(slope_measurement, slope)
215
216
  if MeasurementType.OVERLAP in measurement_types:
216
- measurements[overlap_measurement] = overlap
217
- measurements[k_measurement_1] = K1
218
- measurements[k_measurement_2] = K2
217
+ measurements.add_image_measurement(overlap_measurement, overlap)
218
+ measurements.add_image_measurement(k_measurement_1, K1)
219
+ measurements.add_image_measurement(k_measurement_2, K2)
219
220
 
220
221
  if MeasurementType.MANDERS in measurement_types:
221
- measurements[manders_measurement_1] = M1
222
- measurements[manders_measurement_2] = M2
222
+ measurements.add_image_measurement(manders_measurement_1, M1)
223
+ measurements.add_image_measurement(manders_measurement_2, M2)
223
224
  if MeasurementType.RWC in measurement_types:
224
- measurements[rwc_measurement_1] = RWC1
225
- measurements[rwc_measurement_2] = RWC2
225
+ measurements.add_image_measurement(rwc_measurement_1, RWC1)
226
+ measurements.add_image_measurement(rwc_measurement_2, RWC2)
226
227
  if MeasurementType.COSTES in measurement_types:
227
- measurements[costes_measurement_1] = C1
228
- measurements[costes_measurement_2] = C2
228
+ measurements.add_image_measurement(costes_measurement_1, C1)
229
+ measurements.add_image_measurement(costes_measurement_2, C2)
229
230
 
230
231
  return measurements, summary
231
232
 
@@ -259,7 +260,7 @@ def run_image_pair_objects(
259
260
  im2_scale: Annotated[Optional[Union[float, int]], Field(description="Second image scale for costes thresholding")]=None,
260
261
  costes_method: Annotated[Optional[CostesMethod], Field(description="Costes method for costes thresholding")]=CostesMethod.FAST
261
262
  ) -> Tuple[
262
- Dict[str, NDArray[np.float64]],
263
+ LibraryMeasurements,
263
264
  List[Tuple[str, str, str, str, str]]
264
265
  ]:
265
266
  if MeasurementType.COSTES in measurement_types:
@@ -346,41 +347,40 @@ def run_image_pair_objects(
346
347
  summary += __get_object_result_array((im2_name, im1_name, object_name), "Manders coeff (Costes)", C2)
347
348
 
348
349
 
349
- measurements: Dict[str, NDArray[np.float64]] = {}
350
+ measurements = LibraryMeasurements()
351
+
350
352
  if MeasurementType.CORRELATION in measurement_types:
351
353
  measurement = TemplateMeasurementFormat.CORRELATION_FORMAT % (im1_name, im2_name)
352
- measurements[measurement] = corr
354
+ measurements.add_measurement(object_name, measurement, corr)
353
355
  if MeasurementType.MANDERS in measurement_types:
354
356
  manders_measurement_1 = TemplateMeasurementFormat.MANDERS_FORMAT % (im1_name, im2_name)
355
357
  manders_measurement_2 = TemplateMeasurementFormat.MANDERS_FORMAT % (im2_name, im1_name)
356
358
 
357
- measurements[manders_measurement_1] = M1
358
- measurements[manders_measurement_2] = M2
359
+ measurements.add_measurement(object_name, manders_measurement_1, M1)
360
+ measurements.add_measurement(object_name, manders_measurement_2, M2)
359
361
 
360
362
  if MeasurementType.RWC in measurement_types:
361
363
  rwc_measurement_1 = TemplateMeasurementFormat.RWC_FORMAT % (im1_name, im2_name)
362
364
  rwc_measurement_2 = TemplateMeasurementFormat.RWC_FORMAT % (im2_name, im1_name)
363
365
 
364
- measurements[rwc_measurement_1] = RWC1
365
- measurements[rwc_measurement_2] = RWC2
366
+ measurements.add_measurement(object_name, rwc_measurement_1, RWC1)
367
+ measurements.add_measurement(object_name, rwc_measurement_2, RWC2)
366
368
 
367
369
  if MeasurementType.OVERLAP in measurement_types:
368
370
  overlap_measurement = TemplateMeasurementFormat.OVERLAP_FORMAT % (im1_name, im2_name)
369
371
  k_measurement_1 = TemplateMeasurementFormat.K_FORMAT % (im1_name, im2_name)
370
372
  k_measurement_2 = TemplateMeasurementFormat.K_FORMAT % (im2_name, im1_name)
371
373
 
372
- measurements[overlap_measurement] = overlap
373
- measurements[k_measurement_1] = K1
374
- measurements[k_measurement_2] = K2
374
+ measurements.add_measurement(object_name, overlap_measurement, overlap)
375
+ measurements.add_measurement(object_name, k_measurement_1, K1)
376
+ measurements.add_measurement(object_name, k_measurement_2, K2)
375
377
 
376
378
  if MeasurementType.COSTES in measurement_types:
377
379
  costes_measurement_1 = TemplateMeasurementFormat.COSTES_FORMAT % (im1_name, im2_name)
378
380
  costes_measurement_2 = TemplateMeasurementFormat.COSTES_FORMAT % (im2_name, im1_name)
379
381
 
380
- measurements[costes_measurement_1] = C1
381
- measurements[costes_measurement_2] = C2
382
-
383
- if n_objects == 0:
382
+ measurements.add_measurement(object_name, costes_measurement_1, C1)
383
+ measurements.add_measurement(object_name, costes_measurement_2, C2)
384
384
  col_order_1 = (im1_name, im2_name, object_name)
385
385
  summary += [
386
386
  (*col_order_1, "Mean correlation", "-"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cellprofiler-library-nightly
3
- Version: 5.0.0.dev496
3
+ Version: 5.0.0.dev501
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>
@@ -4,6 +4,7 @@ environment.yml
4
4
  pyproject.toml
5
5
  cellprofiler_library/__init__.py
6
6
  cellprofiler_library/_version.py
7
+ cellprofiler_library/measurement_model.py
7
8
  cellprofiler_library/py.typed
8
9
  cellprofiler_library/types.py
9
10
  cellprofiler_library/functions/__init__.py