scikit-image
304 строки · 12.0 Кб
1import numpy as np2from scipy.stats import pearsonr3
4from .._shared.utils import check_shape_equality, as_binary_ndarray5
6__all__ = [7'pearson_corr_coeff',8'manders_coloc_coeff',9'manders_overlap_coeff',10'intersection_coeff',11]
12
13
14def pearson_corr_coeff(image0, image1, mask=None):15r"""Calculate Pearson's Correlation Coefficient between pixel intensities16in channels.
17
18Parameters
19----------
20image0 : (M, N) ndarray
21Image of channel A.
22image1 : (M, N) ndarray
23Image of channel 2 to be correlated with channel B.
24Must have same dimensions as `image0`.
25mask : (M, N) ndarray of dtype bool, optional
26Only `image0` and `image1` pixels within this region of interest mask
27are included in the calculation. Must have same dimensions as `image0`.
28
29Returns
30-------
31pcc : float
32Pearson's correlation coefficient of the pixel intensities between
33the two images, within the mask if provided.
34p-value : float
35Two-tailed p-value.
36
37Notes
38-----
39Pearson's Correlation Coefficient (PCC) measures the linear correlation
40between the pixel intensities of the two images. Its value ranges from -1
41for perfect linear anti-correlation to +1 for perfect linear correlation.
42The calculation of the p-value assumes that the intensities of pixels in
43each input image are normally distributed.
44
45Scipy's implementation of Pearson's correlation coefficient is used. Please
46refer to it for further information and caveats [1]_.
47
48.. math::
49r = \frac{\sum (A_i - m_A_i) (B_i - m_B_i)}
50{\sqrt{\sum (A_i - m_A_i)^2 \sum (B_i - m_B_i)^2}}
51
52where
53:math:`A_i` is the value of the :math:`i^{th}` pixel in `image0`
54:math:`B_i` is the value of the :math:`i^{th}` pixel in `image1`,
55:math:`m_A_i` is the mean of the pixel values in `image0`
56:math:`m_B_i` is the mean of the pixel values in `image1`
57
58A low PCC value does not necessarily mean that there is no correlation
59between the two channel intensities, just that there is no linear
60correlation. You may wish to plot the pixel intensities of each of the two
61channels in a 2D scatterplot and use Spearman's rank correlation if a
62non-linear correlation is visually identified [2]_. Also consider if you
63are interested in correlation or co-occurence, in which case a method
64involving segmentation masks (e.g. MCC or intersection coefficient) may be
65more suitable [3]_ [4]_.
66
67Providing the mask of only relevant sections of the image (e.g., cells, or
68particular cellular compartments) and removing noise is important as the
69PCC is sensitive to these measures [3]_ [4]_.
70
71References
72----------
73.. [1] https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html # noqa
74.. [2] https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.spearmanr.html # noqa
75.. [3] Dunn, K. W., Kamocka, M. M., & McDonald, J. H. (2011). A practical
76guide to evaluating colocalization in biological microscopy.
77American journal of physiology. Cell physiology, 300(4), C723–C742.
78https://doi.org/10.1152/ajpcell.00462.2010
79.. [4] Bolte, S. and Cordelières, F.P. (2006), A guided tour into
80subcellular colocalization analysis in light microscopy. Journal of
81Microscopy, 224: 213-232.
82https://doi.org/10.1111/j.1365-2818.2006.01706.x
83"""
84image0 = np.asarray(image0)85image1 = np.asarray(image1)86if mask is not None:87mask = as_binary_ndarray(mask, variable_name="mask")88check_shape_equality(image0, image1, mask)89image0 = image0[mask]90image1 = image1[mask]91else:92check_shape_equality(image0, image1)93# scipy pearsonr function only takes flattened arrays94image0 = image0.reshape(-1)95image1 = image1.reshape(-1)96
97return tuple(float(v) for v in pearsonr(image0, image1))98
99
100def manders_coloc_coeff(image0, image1_mask, mask=None):101r"""Manders' colocalization coefficient between two channels.102
103Parameters
104----------
105image0 : (M, N) ndarray
106Image of channel A. All pixel values should be non-negative.
107image1_mask : (M, N) ndarray of dtype bool
108Binary mask with segmented regions of interest in channel B.
109Must have same dimensions as `image0`.
110mask : (M, N) ndarray of dtype bool, optional
111Only `image0` pixel values within this region of interest mask are
112included in the calculation.
113Must have same dimensions as `image0`.
114
115Returns
116-------
117mcc : float
118Manders' colocalization coefficient.
119
120Notes
121-----
122Manders' Colocalization Coefficient (MCC) is the fraction of total
123intensity of a certain channel (channel A) that is within the segmented
124region of a second channel (channel B) [1]_. It ranges from 0 for no
125colocalisation to 1 for complete colocalization. It is also referred to
126as M1 and M2.
127
128MCC is commonly used to measure the colocalization of a particular protein
129in a subceullar compartment. Typically a segmentation mask for channel B
130is generated by setting a threshold that the pixel values must be above
131to be included in the MCC calculation. In this implementation,
132the channel B mask is provided as the argument `image1_mask`, allowing
133the exact segmentation method to be decided by the user beforehand.
134
135The implemented equation is:
136
137.. math::
138r = \frac{\sum A_{i,coloc}}{\sum A_i}
139
140where
141:math:`A_i` is the value of the :math:`i^{th}` pixel in `image0`
142:math:`A_{i,coloc} = A_i` if :math:`Bmask_i > 0`
143:math:`Bmask_i` is the value of the :math:`i^{th}` pixel in
144`mask`
145
146MCC is sensitive to noise, with diffuse signal in the first channel
147inflating its value. Images should be processed to remove out of focus and
148background light before the MCC is calculated [2]_.
149
150References
151----------
152.. [1] Manders, E.M.M., Verbeek, F.J. and Aten, J.A. (1993), Measurement of
153co-localization of objects in dual-colour confocal images. Journal
154of Microscopy, 169: 375-382.
155https://doi.org/10.1111/j.1365-2818.1993.tb03313.x
156https://imagej.net/media/manders.pdf
157.. [2] Dunn, K. W., Kamocka, M. M., & McDonald, J. H. (2011). A practical
158guide to evaluating colocalization in biological microscopy.
159American journal of physiology. Cell physiology, 300(4), C723–C742.
160https://doi.org/10.1152/ajpcell.00462.2010
161
162"""
163image0 = np.asarray(image0)164image1_mask = as_binary_ndarray(image1_mask, variable_name="image1_mask")165if mask is not None:166mask = as_binary_ndarray(mask, variable_name="mask")167check_shape_equality(image0, image1_mask, mask)168image0 = image0[mask]169image1_mask = image1_mask[mask]170else:171check_shape_equality(image0, image1_mask)172# check non-negative image173if image0.min() < 0:174raise ValueError("image contains negative values")175
176sum = np.sum(image0)177if sum == 0:178return 0179return np.sum(image0 * image1_mask) / sum180
181
182def manders_overlap_coeff(image0, image1, mask=None):183r"""Manders' overlap coefficient184
185Parameters
186----------
187image0 : (M, N) ndarray
188Image of channel A. All pixel values should be non-negative.
189image1 : (M, N) ndarray
190Image of channel B. All pixel values should be non-negative.
191Must have same dimensions as `image0`
192mask : (M, N) ndarray of dtype bool, optional
193Only `image0` and `image1` pixel values within this region of interest
194mask are included in the calculation.
195Must have ♣same dimensions as `image0`.
196
197Returns
198-------
199moc: float
200Manders' Overlap Coefficient of pixel intensities between the two
201images.
202
203Notes
204-----
205Manders' Overlap Coefficient (MOC) is given by the equation [1]_:
206
207.. math::
208r = \frac{\sum A_i B_i}{\sqrt{\sum A_i^2 \sum B_i^2}}
209
210where
211:math:`A_i` is the value of the :math:`i^{th}` pixel in `image0`
212:math:`B_i` is the value of the :math:`i^{th}` pixel in `image1`
213
214It ranges between 0 for no colocalization and 1 for complete colocalization
215of all pixels.
216
217MOC does not take into account pixel intensities, just the fraction of
218pixels that have positive values for both channels[2]_ [3]_. Its usefulness
219has been criticized as it changes in response to differences in both
220co-occurence and correlation and so a particular MOC value could indicate
221a wide range of colocalization patterns [4]_ [5]_.
222
223References
224----------
225.. [1] Manders, E.M.M., Verbeek, F.J. and Aten, J.A. (1993), Measurement of
226co-localization of objects in dual-colour confocal images. Journal
227of Microscopy, 169: 375-382.
228https://doi.org/10.1111/j.1365-2818.1993.tb03313.x
229https://imagej.net/media/manders.pdf
230.. [2] Dunn, K. W., Kamocka, M. M., & McDonald, J. H. (2011). A practical
231guide to evaluating colocalization in biological microscopy.
232American journal of physiology. Cell physiology, 300(4), C723–C742.
233https://doi.org/10.1152/ajpcell.00462.2010
234.. [3] Bolte, S. and Cordelières, F.P. (2006), A guided tour into
235subcellular colocalization analysis in light microscopy. Journal of
236Microscopy, 224: 213-232.
237https://doi.org/10.1111/j.1365-2818.2006.01
238.. [4] Adler J, Parmryd I. (2010), Quantifying colocalization by
239correlation: the Pearson correlation coefficient is
240superior to the Mander's overlap coefficient. Cytometry A.
241Aug;77(8):733-42.https://doi.org/10.1002/cyto.a.20896
242.. [5] Adler, J, Parmryd, I. Quantifying colocalization: The case for
243discarding the Manders overlap coefficient. Cytometry. 2021; 99:
244910– 920. https://doi.org/10.1002/cyto.a.24336
245
246"""
247image0 = np.asarray(image0)248image1 = np.asarray(image1)249if mask is not None:250mask = as_binary_ndarray(mask, variable_name="mask")251check_shape_equality(image0, image1, mask)252image0 = image0[mask]253image1 = image1[mask]254else:255check_shape_equality(image0, image1)256
257# check non-negative image258if image0.min() < 0:259raise ValueError("image0 contains negative values")260if image1.min() < 0:261raise ValueError("image1 contains negative values")262
263denom = (np.sum(np.square(image0)) * (np.sum(np.square(image1)))) ** 0.5264return np.sum(np.multiply(image0, image1)) / denom265
266
267def intersection_coeff(image0_mask, image1_mask, mask=None):268r"""Fraction of a channel's segmented binary mask that overlaps with a269second channel's segmented binary mask.
270
271Parameters
272----------
273image0_mask : (M, N) ndarray of dtype bool
274Image mask of channel A.
275image1_mask : (M, N) ndarray of dtype bool
276Image mask of channel B.
277Must have same dimensions as `image0_mask`.
278mask : (M, N) ndarray of dtype bool, optional
279Only `image0_mask` and `image1_mask` pixels within this region of
280interest
281mask are included in the calculation.
282Must have same dimensions as `image0_mask`.
283
284Returns
285-------
286Intersection coefficient, float
287Fraction of `image0_mask` that overlaps with `image1_mask`.
288
289"""
290image0_mask = as_binary_ndarray(image0_mask, variable_name="image0_mask")291image1_mask = as_binary_ndarray(image1_mask, variable_name="image1_mask")292if mask is not None:293mask = as_binary_ndarray(mask, variable_name="mask")294check_shape_equality(image0_mask, image1_mask, mask)295image0_mask = image0_mask[mask]296image1_mask = image1_mask[mask]297else:298check_shape_equality(image0_mask, image1_mask)299
300nonzero_image0 = np.count_nonzero(image0_mask)301if nonzero_image0 == 0:302return 0303nonzero_joint = np.count_nonzero(np.logical_and(image0_mask, image1_mask))304return nonzero_joint / nonzero_image0305