docstr: Compute the MMD based conditional test statistic, and perform a conditional permutation test to obtain a
  p-value representing the test statistic's extremity under the null hypothesis.
  
  Parameters
  ----------
  x
      Batch of instances.
  c
      Context associated with batch of instances.
  
  Returns
  -------
  p-value obtained from the conditional permutation test, the conditional MMD test statistic, the test         statistic threshold above which drift is flagged, and a tuple containing the coupling matrices         (W_{ref,ref}, W_{test,test}, W_{ref,test}).
docstr_tok: ["Compute","the","MMD","based","conditional","test","statistic",",","and","perform","a","conditional","permutation","test","to","obtain","a","p-value","representing","the","test","statistic","'s","extremity","under","the","null","hypothesis",".","Parameters","--","--","--","--","--","x","Batch","of","instances",".","c","Context","associated","with","batch","of","instances",".","Returns","--","--","--","-","p-value","obtained","from","the","conditional","permutation","test",",","the","conditional","MMD","test","statistic",",","the","test","statistic","threshold","above","which","drift","is","flagged",",","and","a","tuple","containing","the","coupling","matrices","(","W_","{","ref",",","ref","}",",","W_","{","test",",","test","}",",","W_","{","ref",",","test","}",")","."]
code: def score(
      self,  # type: ignore[override]
      x: Union[np.ndarray, list],
      c: np.ndarray,
  ) -> Tuple[float, float, float, Tuple]:
      """
          Compute the MMD based conditional test statistic, and perform a conditional permutation test to obtain a
          p-value representing the test statistic's extremity under the null hypothesis.
  
          Parameters
          ----------
          x
              Batch of instances.
          c
              Context associated with batch of instances.
  
          Returns
          -------
          p-value obtained from the conditional permutation test, the conditional MMD test statistic, the test \
          statistic threshold above which drift is flagged, and a tuple containing the coupling matrices \
          (W_{ref,ref}, W_{test,test}, W_{ref,test}).
          """
      x_ref, x = self.preprocess(x)
  
      # Hold out a portion of contexts for conditioning on
      n, n_held = len(c), int(len(c) * self.prop_c_held)
      inds_held = np.random.choice(n, n_held, replace=False)
      inds_test = np.setdiff1d(np.arange(n), inds_held)
      c_held = c[inds_held]
      c, x = c[inds_test], x[inds_test]
      n_ref, n_test = len(x_ref), len(x)
      bools = tf.concat([tf.zeros(n_ref), tf.ones(n_test)], axis=0)
  
      # Compute kernel matrices
      x_all = tf.concat([x_ref, x], axis=0)
      c_all = tf.concat([self.c_ref, c], axis=0)
      K = self.x_kernel(x_all, x_all)
      L = self.c_kernel(c_all, c_all)
      L_held = self.c_kernel(c_held, c_all)
  
      # Fit and calibrate the domain classifier
      c_all_np, bools_np = c_all.numpy(), bools.numpy()
      self.clf.fit(c_all_np, bools_np)
      self.clf.calibrate(c_all_np, bools_np)
  
      # Obtain n_permutations conditional reassignments
      prop_scores = self.clf.predict(c_all_np)
      self.redrawn_bools = [
          tfp.distributions.Bernoulli(probs=prop_scores).sample()
          for _ in range(self.n_permutations)
      ]
      iters = (
          tqdm(self.redrawn_bools, total=self.n_permutations)
          if self.verbose
          else self.redrawn_bools
      )
  
      # Compute test stat on original and reassigned data
      stat, coupling_xx, coupling_yy, coupling_xy = self._cmmd(
          K, L, bools, L_held=L_held
      )
      permuted_stats = tf.stack(
          [
              self._cmmd(K, L, perm_bools, L_held=L_held)[0]
              for perm_bools in iters
          ]
      )
  
      # Compute p-value
      p_val = tf.reduce_mean(tf.cast(stat <= permuted_stats, float))
      coupling = (
          coupling_xx.numpy(),
          coupling_yy.numpy(),
          coupling_xy.numpy(),
      )
  
      # compute distance threshold
      idx_threshold = int(self.p_val * len(permuted_stats))
      distance_threshold = np.sort(permuted_stats)[::-1][idx_threshold]
      return (
          p_val.numpy().item(),
          stat.numpy().item(),
          distance_threshold,
          coupling,
      )
  
file_path: alibi-detect/alibi_detect/cd/tensorflow/context_aware.py
imports: import logging
  import numpy
  import tensorflow
  import tensorflow_probability
  from typing import Callable, Dict, Optional, Tuple, Union, List
  from alibi_detect.cd.base import BaseContextMMDDrift
  from alibi_detect.utils.tensorflow.kernels import GaussianRBF
  from alibi_detect.utils.warnings import deprecated_alias
  from alibi_detect.utils.frameworks import Framework
  from alibi_detect.cd._domain_clf import _SVCDomainClf
  from tqdm import tqdm
label_desc: Use image node_id 2 for calling the ContextMMDDriftTF obj's underlying member method code with example usage: obj.score(x, c) and returns: p_val,  stat,  distance_threshold,  coupling