docstr: Calculate per-object correlations between intensities in two images
docstr_tok: ["Calculate","per-object","correlations","between","intensities","in","two","images"]
code: def run_image_pair_objects(
      self, workspace, first_image_name, second_image_name, object_name
  ):
      """Calculate per-object correlations between intensities in two images"""
      first_image = workspace.image_set.get_image(
          first_image_name, must_be_grayscale=True
      )
      second_image = workspace.image_set.get_image(
          second_image_name, must_be_grayscale=True
      )
      objects = workspace.object_set.get_objects(object_name)
      #
      # Crop both images to the size of the labels matrix
      #
      labels = objects.segmented
      try:
          first_pixels = objects.crop_image_similarly(
              first_image.pixel_data
          )
          first_mask = objects.crop_image_similarly(first_image.mask)
      except ValueError:
          first_pixels, m1 = size_similarly(
              labels, first_image.pixel_data
          )
          first_mask, m1 = size_similarly(labels, first_image.mask)
          first_mask[~m1] = False
      try:
          second_pixels = objects.crop_image_similarly(
              second_image.pixel_data
          )
          second_mask = objects.crop_image_similarly(second_image.mask)
      except ValueError:
          second_pixels, m1 = size_similarly(
              labels, second_image.pixel_data
          )
          second_mask, m1 = size_similarly(labels, second_image.mask)
          second_mask[~m1] = False
      mask = (labels > 0) & first_mask & second_mask
      first_pixels = first_pixels[mask]
      second_pixels = second_pixels[mask]
      labels = labels[mask]
      result = []
      first_pixel_data = first_image.pixel_data
      first_mask = first_image.mask
      first_pixel_count = numpy.product(first_pixel_data.shape)
      second_pixel_data = second_image.pixel_data
      second_mask = second_image.mask
      second_pixel_count = numpy.product(second_pixel_data.shape)
      #
      # Crop the larger image similarly to the smaller one
      #
      if first_pixel_count < second_pixel_count:
          second_pixel_data = first_image.crop_image_similarly(
              second_pixel_data
          )
          second_mask = first_image.crop_image_similarly(second_mask)
      elif second_pixel_count < first_pixel_count:
          first_pixel_data = second_image.crop_image_similarly(
              first_pixel_data
          )
          first_mask = second_image.crop_image_similarly(first_mask)
      mask = (
          first_mask
          & second_mask
          & (~numpy.isnan(first_pixel_data))
          & (~numpy.isnan(second_pixel_data))
      )
      if numpy.any(mask):
          fi = first_pixel_data[mask]
          si = second_pixel_data[mask]
  
      n_objects = objects.count
      # Handle case when both images for the correlation are completely masked out
  
      if n_objects == 0:
          corr = numpy.zeros((0,))
          overlap = numpy.zeros((0,))
          K1 = numpy.zeros((0,))
          K2 = numpy.zeros((0,))
          M1 = numpy.zeros((0,))
          M2 = numpy.zeros((0,))
          RWC1 = numpy.zeros((0,))
          RWC2 = numpy.zeros((0,))
          C1 = numpy.zeros((0,))
          C2 = numpy.zeros((0,))
      elif numpy.where(mask)[0].__len__() == 0:
          corr = numpy.zeros((n_objects,))
          corr[:] = numpy.NaN
          overlap = K1 = K2 = M1 = M2 = RWC1 = RWC2 = C1 = C2 = corr
      else:
          lrange = numpy.arange(n_objects, dtype=numpy.int32) + 1
  
          if self.do_corr_and_slope:
              #
              # The correlation is sum((x-mean(x))(y-mean(y)) /
              #                         ((n-1) * std(x) *std(y)))
              #
  
              mean1 = fix(
                  scipy.ndimage.mean(first_pixels, labels, lrange)
              )
              mean2 = fix(
                  scipy.ndimage.mean(second_pixels, labels, lrange)
              )
              #
              # Calculate the standard deviation times the population.
              #
              std1 = numpy.sqrt(
                  fix(
                      scipy.ndimage.sum(
                          (first_pixels - mean1[labels - 1]) ** 2,
                          labels,
                          lrange,
                      )
                  )
              )
              std2 = numpy.sqrt(
                  fix(
                      scipy.ndimage.sum(
                          (second_pixels - mean2[labels - 1]) ** 2,
                          labels,
                          lrange,
                      )
                  )
              )
              x = first_pixels - mean1[labels - 1]  # x - mean(x)
              y = second_pixels - mean2[labels - 1]  # y - mean(y)
              corr = fix(
                  scipy.ndimage.sum(
                      x * y / (std1[labels - 1] * std2[labels - 1]),
                      labels,
                      lrange,
                  )
              )
              # Explicitly set the correlation to NaN for masked objects
              corr[
                  scipy.ndimage.sum(1, labels, lrange) == 0
              ] = numpy.NaN
              result += [
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Mean Correlation coeff",
                      "%.3f" % numpy.mean(corr),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Median Correlation coeff",
                      "%.3f" % numpy.median(corr),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Min Correlation coeff",
                      "%.3f" % numpy.min(corr),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Max Correlation coeff",
                      "%.3f" % numpy.max(corr),
                  ],
              ]
  
          if any((self.do_manders, self.do_rwc, self.do_overlap)):
              # Threshold as percentage of maximum intensity of objects in each channel
              tff = (self.thr.value / 100) * fix(
                  scipy.ndimage.maximum(first_pixels, labels, lrange)
              )
              tss = (self.thr.value / 100) * fix(
                  scipy.ndimage.maximum(second_pixels, labels, lrange)
              )
  
              combined_thresh = (first_pixels >= tff[labels - 1]) & (
                  second_pixels >= tss[labels - 1]
              )
              fi_thresh = first_pixels[combined_thresh]
              si_thresh = second_pixels[combined_thresh]
              tot_fi_thr = scipy.ndimage.sum(
                  first_pixels[first_pixels >= tff[labels - 1]],
                  labels[first_pixels >= tff[labels - 1]],
                  lrange,
              )
              tot_si_thr = scipy.ndimage.sum(
                  second_pixels[second_pixels >= tss[labels - 1]],
                  labels[second_pixels >= tss[labels - 1]],
                  lrange,
              )
  
          if self.do_manders:
              # Manders Coefficient
              M1 = numpy.zeros(len(lrange))
              M2 = numpy.zeros(len(lrange))
  
              if numpy.any(combined_thresh):
                  M1 = numpy.array(
                      scipy.ndimage.sum(
                          fi_thresh, labels[combined_thresh], lrange
                      )
                  ) / numpy.array(tot_fi_thr)
                  M2 = numpy.array(
                      scipy.ndimage.sum(
                          si_thresh, labels[combined_thresh], lrange
                      )
                  ) / numpy.array(tot_si_thr)
              result += [
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Mean Manders coeff",
                      "%.3f" % numpy.mean(M1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Median Manders coeff",
                      "%.3f" % numpy.median(M1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Min Manders coeff",
                      "%.3f" % numpy.min(M1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Max Manders coeff",
                      "%.3f" % numpy.max(M1),
                  ],
              ]
              result += [
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Mean Manders coeff",
                      "%.3f" % numpy.mean(M2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Median Manders coeff",
                      "%.3f" % numpy.median(M2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Min Manders coeff",
                      "%.3f" % numpy.min(M2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Max Manders coeff",
                      "%.3f" % numpy.max(M2),
                  ],
              ]
  
          if self.do_rwc:
              # RWC Coefficient
              RWC1 = numpy.zeros(len(lrange))
              RWC2 = numpy.zeros(len(lrange))
              [Rank1] = numpy.lexsort(([labels], [first_pixels]))
              [Rank2] = numpy.lexsort(([labels], [second_pixels]))
              Rank1_U = numpy.hstack(
                  [
                      [False],
                      first_pixels[Rank1[:-1]]
                      != first_pixels[Rank1[1:]],
                  ]
              )
              Rank2_U = numpy.hstack(
                  [
                      [False],
                      second_pixels[Rank2[:-1]]
                      != second_pixels[Rank2[1:]],
                  ]
              )
              Rank1_S = numpy.cumsum(Rank1_U)
              Rank2_S = numpy.cumsum(Rank2_U)
              Rank_im1 = numpy.zeros(first_pixels.shape, dtype=int)
              Rank_im2 = numpy.zeros(second_pixels.shape, dtype=int)
              Rank_im1[Rank1] = Rank1_S
              Rank_im2[Rank2] = Rank2_S
  
              R = max(Rank_im1.max(), Rank_im2.max()) + 1
              Di = abs(Rank_im1 - Rank_im2)
              weight = (R - Di) * 1.0 / R
              weight_thresh = weight[combined_thresh]
  
              if numpy.any(combined_thresh):
                  RWC1 = numpy.array(
                      scipy.ndimage.sum(
                          fi_thresh * weight_thresh,
                          labels[combined_thresh],
                          lrange,
                      )
                  ) / numpy.array(tot_fi_thr)
                  RWC2 = numpy.array(
                      scipy.ndimage.sum(
                          si_thresh * weight_thresh,
                          labels[combined_thresh],
                          lrange,
                      )
                  ) / numpy.array(tot_si_thr)
  
              result += [
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Mean RWC coeff",
                      "%.3f" % numpy.mean(RWC1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Median RWC coeff",
                      "%.3f" % numpy.median(RWC1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Min RWC coeff",
                      "%.3f" % numpy.min(RWC1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Max RWC coeff",
                      "%.3f" % numpy.max(RWC1),
                  ],
              ]
              result += [
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Mean RWC coeff",
                      "%.3f" % numpy.mean(RWC2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Median RWC coeff",
                      "%.3f" % numpy.median(RWC2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Min RWC coeff",
                      "%.3f" % numpy.min(RWC2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Max RWC coeff",
                      "%.3f" % numpy.max(RWC2),
                  ],
              ]
  
          if self.do_overlap:
              # Overlap Coefficient
              if numpy.any(combined_thresh):
                  fpsq = scipy.ndimage.sum(
                      first_pixels[combined_thresh] ** 2,
                      labels[combined_thresh],
                      lrange,
                  )
                  spsq = scipy.ndimage.sum(
                      second_pixels[combined_thresh] ** 2,
                      labels[combined_thresh],
                      lrange,
                  )
                  pdt = numpy.sqrt(
                      numpy.array(fpsq) * numpy.array(spsq)
                  )
  
                  overlap = fix(
                      scipy.ndimage.sum(
                          first_pixels[combined_thresh]
                          * second_pixels[combined_thresh],
                          labels[combined_thresh],
                          lrange,
                      )
                      / pdt
                  )
                  K1 = fix(
                      (
                          scipy.ndimage.sum(
                              first_pixels[combined_thresh]
                              * second_pixels[combined_thresh],
                              labels[combined_thresh],
                              lrange,
                          )
                      )
                      / (numpy.array(fpsq))
                  )
                  K2 = fix(
                      scipy.ndimage.sum(
                          first_pixels[combined_thresh]
                          * second_pixels[combined_thresh],
                          labels[combined_thresh],
                          lrange,
                      )
                      / numpy.array(spsq)
                  )
              else:
                  overlap = K1 = K2 = numpy.zeros(len(lrange))
              result += [
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Mean Overlap coeff",
                      "%.3f" % numpy.mean(overlap),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Median Overlap coeff",
                      "%.3f" % numpy.median(overlap),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Min Overlap coeff",
                      "%.3f" % numpy.min(overlap),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Max Overlap coeff",
                      "%.3f" % numpy.max(overlap),
                  ],
              ]
  
          if self.do_costes:
              # Orthogonal Regression for Costes' automated threshold
              scale = get_scale(first_image.scale, second_image.scale)
  
              if self.fast_costes == M_FASTER:
                  thr_fi_c, thr_si_c = self.bisection_costes(
                      fi, si, scale
                  )
              else:
                  thr_fi_c, thr_si_c = self.linear_costes(fi, si, scale)
  
              # Costes' thershold for entire image is applied to each object
              fi_above_thr = first_pixels > thr_fi_c
              si_above_thr = second_pixels > thr_si_c
              combined_thresh_c = fi_above_thr & si_above_thr
              fi_thresh_c = first_pixels[combined_thresh_c]
              si_thresh_c = second_pixels[combined_thresh_c]
              if numpy.any(fi_above_thr):
                  tot_fi_thr_c = scipy.ndimage.sum(
                      first_pixels[first_pixels >= thr_fi_c],
                      labels[first_pixels >= thr_fi_c],
                      lrange,
                  )
              else:
                  tot_fi_thr_c = numpy.zeros(len(lrange))
              if numpy.any(si_above_thr):
                  tot_si_thr_c = scipy.ndimage.sum(
                      second_pixels[second_pixels >= thr_si_c],
                      labels[second_pixels >= thr_si_c],
                      lrange,
                  )
              else:
                  tot_si_thr_c = numpy.zeros(len(lrange))
  
              # Costes Automated Threshold
              C1 = numpy.zeros(len(lrange))
              C2 = numpy.zeros(len(lrange))
              if numpy.any(combined_thresh_c):
                  C1 = numpy.array(
                      scipy.ndimage.sum(
                          fi_thresh_c, labels[combined_thresh_c], lrange
                      )
                  ) / numpy.array(tot_fi_thr_c)
                  C2 = numpy.array(
                      scipy.ndimage.sum(
                          si_thresh_c, labels[combined_thresh_c], lrange
                      )
                  ) / numpy.array(tot_si_thr_c)
              result += [
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Mean Manders coeff (Costes)",
                      "%.3f" % numpy.mean(C1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Median Manders coeff (Costes)",
                      "%.3f" % numpy.median(C1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Min Manders coeff (Costes)",
                      "%.3f" % numpy.min(C1),
                  ],
                  [
                      first_image_name,
                      second_image_name,
                      object_name,
                      "Max Manders coeff (Costes)",
                      "%.3f" % numpy.max(C1),
                  ],
              ]
              result += [
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Mean Manders coeff (Costes)",
                      "%.3f" % numpy.mean(C2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Median Manders coeff (Costes)",
                      "%.3f" % numpy.median(C2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Min Manders coeff (Costes)",
                      "%.3f" % numpy.min(C2),
                  ],
                  [
                      second_image_name,
                      first_image_name,
                      object_name,
                      "Max Manders coeff (Costes)",
                      "%.3f" % numpy.max(C2),
                  ],
              ]
  
      if self.do_corr_and_slope:
          measurement = "Correlation_Correlation_%s_%s" % (
              first_image_name,
              second_image_name,
          )
          workspace.measurements.add_measurement(
              object_name, measurement, corr
          )
      if self.do_manders:
          manders_measurement_1 = F_MANDERS_FORMAT % (
              first_image_name,
              second_image_name,
          )
          manders_measurement_2 = F_MANDERS_FORMAT % (
              second_image_name,
              first_image_name,
          )
          workspace.measurements.add_measurement(
              object_name, manders_measurement_1, M1
          )
          workspace.measurements.add_measurement(
              object_name, manders_measurement_2, M2
          )
      if self.do_rwc:
          rwc_measurement_1 = F_RWC_FORMAT % (
              first_image_name,
              second_image_name,
          )
          rwc_measurement_2 = F_RWC_FORMAT % (
              second_image_name,
              first_image_name,
          )
          workspace.measurements.add_measurement(
              object_name, rwc_measurement_1, RWC1
          )
          workspace.measurements.add_measurement(
              object_name, rwc_measurement_2, RWC2
          )
      if self.do_overlap:
          overlap_measurement = F_OVERLAP_FORMAT % (
              first_image_name,
              second_image_name,
          )
          k_measurement_1 = F_K_FORMAT % (
              first_image_name,
              second_image_name,
          )
          k_measurement_2 = F_K_FORMAT % (
              second_image_name,
              first_image_name,
          )
          workspace.measurements.add_measurement(
              object_name, overlap_measurement, overlap
          )
          workspace.measurements.add_measurement(
              object_name, k_measurement_1, K1
          )
          workspace.measurements.add_measurement(
              object_name, k_measurement_2, K2
          )
      if self.do_costes:
          costes_measurement_1 = F_COSTES_FORMAT % (
              first_image_name,
              second_image_name,
          )
          costes_measurement_2 = F_COSTES_FORMAT % (
              second_image_name,
              first_image_name,
          )
          workspace.measurements.add_measurement(
              object_name, costes_measurement_1, C1
          )
          workspace.measurements.add_measurement(
              object_name, costes_measurement_2, C2
          )
  
      if n_objects == 0:
          return [
              [
                  first_image_name,
                  second_image_name,
                  object_name,
                  "Mean correlation",
                  "-",
              ],
              [
                  first_image_name,
                  second_image_name,
                  object_name,
                  "Median correlation",
                  "-",
              ],
              [
                  first_image_name,
                  second_image_name,
                  object_name,
                  "Min correlation",
                  "-",
              ],
              [
                  first_image_name,
                  second_image_name,
                  object_name,
                  "Max correlation",
                  "-",
              ],
          ]
      else:
          return result
  
imports: import numpy
  import scipy.ndimage
  import scipy.stats
  from cellprofiler_core.constants.measurement import COLTYPE_FLOAT
  from cellprofiler_core.module import Module
  from cellprofiler_core.setting import Divider, Binary, ValidationError
  from cellprofiler_core.setting.choice import Choice
  from cellprofiler_core.setting.subscriber import LabelListSubscriber, ImageListSubscriber
  from cellprofiler_core.setting.text import Float
  from cellprofiler_core.utilities.core.object import size_similarly
  from centrosome.cpmorphology import fixup_scipy_ndimage_result
  from scipy.linalg import lstsq
label_desc: Use image node_id 11 for calling the MeasureColocalization obj's underlying member method code with example usage: obj.run_image_pair_objects(workspace, first_image_name, second_image_name, object_name) and returns: list, result