text: import numpy as np
  from stainlib.utils.stain_utils import ABCStainExtractor, is_uint8_image
  from stainlib.utils.stain_utils import normalize_matrix_rows, convert_RGB_to_OD, LuminosityThresholdTissueLocator
  
  class MacenkoStainExtractor(ABCStainExtractor):
      @staticmethod
      def get_stain_matrix(I, luminosity_threshold=0.8, angular_percentile=99):
          """
          Stain matrix estimation via method of:
          M. Macenko et al. 'A method for normalizing histology slides for quantitative analysis'
          :param I: Image RGB uint8.
          :param luminosity_threshold:
          :param angular_percentile:
          :return:
          """
          assert is_uint8_image(I), "Image should be RGB uint8."
          # Convert to OD and ignore background
          tissue_mask = LuminosityThresholdTissueLocator.get_tissue_mask(I, luminosity_threshold=luminosity_threshold).reshape((-1,))
          OD = convert_RGB_to_OD(I).reshape((-1, 3))
          OD = OD[tissue_mask]
          # Eigenvectors of cov in OD space (orthogonal as cov symmetric)
          _, V = np.linalg.eigh(np.cov(OD, rowvar=False))
          # The two principle eigenvectors
          V = V[:, [2, 1]]
          # Make sure vectors are pointing the right way
          if V[0, 0] < 0: V[:, 0] *= -1
          if V[0, 1] < 0: V[:, 1] *= -1
          # Project on this basis.
          That = np.dot(OD, V)
          # Angular coordinates with repect to the principle, orthogonal eigenvectors
          phi = np.arctan2(That[:, 1], That[:, 0])
          # Min and max angles
          minPhi = np.percentile(phi, 100 - angular_percentile)
          maxPhi = np.percentile(phi, angular_percentile)
          # the two principle colors
          v1 = np.dot(V, np.array([np.cos(minPhi), np.sin(minPhi)]))
          v2 = np.dot(V, np.array([np.cos(maxPhi), np.sin(maxPhi)]))
          # Order of H and E.
          # H first row.
          if v1[0] > v2[0]:
              HE = np.array([v1, v2])
          else:
              HE = np.array([v2, v1])
          return normalize_matrix_rows(HE)