code: def test_mackwolfe(
      data: Union[List, np.ndarray, DataFrame],
      val_col: str = None,
      group_col: str = None,
      p: int = None,
      n_perm: int = 100,
      sort: bool = False,
  ) -> Tuple[float, float]:
      """Mack-Wolfe Test for Umbrella Alternatives.
  
      In dose-finding studies one may assume an increasing treatment effect with
      increasing dose level. However, the test subject may actually succumb to
      toxic effects at high doses, which leads to decresing treatment
      effects [1]_, [2]_.
  
      The scope of the Mack-Wolfe Test is to test for umbrella alternatives for
      either a known or unknown point P (i.e. dose-level), where the peak
      (umbrella point) is present.
  
      Parameters
      ----------
      data : Union[List, numpy.ndarray, DataFrame]
          An array, any object exposing the array interface or a pandas
          DataFrame with data values.
  
      val_col : str = None
          Name of a DataFrame column that contains dependent variable values
          (test or response variable). Values should have a non-nominal scale.
          Must be specified if ``a`` is a pandas DataFrame object.
  
      group_col : str = None
          Name of a DataFrame column that contains independent variable values
          (grouping or predictor variable). Values should have a nominal scale
          (categorical). Must be specified if ``a`` is a pandas DataFrame object.
  
      p : int = None
          The a priori known peak as an ordinal number of the treatment group
          including the zero dose level, i.e. p = {0, ..., k-1}.
          Defaults to None.
  
      n_perm: int = 100
          Permutations number.
  
      sort : bool = False
          If ``True``, sort data by block and group columns.
  
      Returns
      -------
      Tuple[float, float]
          P value and statistic.
  
      References
      ----------
      .. [1] Chen, I.Y. (1991) Notes on the Mack-Wolfe and Chen-Wolfe Tests for
          Umbrella Alternatives. Biom. J., 33, 281-290.
      .. [2] Mack, G.A., Wolfe, D. A. (1981) K-sample rank tests for umbrella
          alternatives. J. Amer. Statist. Assoc., 76, 175-181.
  
      Examples
      --------
      >>> x = [[22, 23, 35], [60, 59, 54], [98, 78, 50], [60, 82, 59], [22, 44, 33], [23, 21, 25]]
      >>> sp.posthoc_mackwolfe(x)
      """
      x, _val_col, _group_col = __convert_to_df(
          data, val_col, group_col
      )
  
      if not sort:
          x[_group_col] = Categorical(
              x[_group_col],
              categories=x[_group_col].unique(),
              ordered=True,
          )
      x.sort_values(by=[_group_col], ascending=True, inplace=True)
  
      k = x[_group_col].unique().size
  
      if p and p > k:
          print(
              "Selected 'p' > number of groups:", str(p), " > ", str(k)
          )
          return False
      elif p is not None and p < 1:
          print("Selected 'p' < 1: ", str(p))
          return False
  
      Rij = x[_val_col].rank()
      n = x.groupby(_group_col)[_val_col].count()
  
      def _fn(Ri, Rj):
          return np.sum(Ri.apply(lambda x: Rj[Rj > x].size))
  
      def _ustat(Rij, g, k):
          levels = np.unique(g)
          U = np.identity(k)
  
          for i in range(k):
              for j in range(i):
                  U[i, j] = _fn(
                      Rij[x[_group_col] == levels[i]],
                      Rij[x[_group_col] == levels[j]],
                  )
                  U[j, i] = _fn(
                      Rij[x[_group_col] == levels[j]],
                      Rij[x[_group_col] == levels[i]],
                  )
  
          return U
  
      def _ap(p, U):
          tmp1 = 0.0
          if p > 0:
              for i in range(p):
                  for j in range(i + 1, p + 1):
                      tmp1 += U[i, j]
          tmp2 = 0.0
          if p < k:
              for i in range(p, k):
                  for j in range(i + 1, k):
                      tmp2 += U[j, i]
  
          return tmp1 + tmp2
  
      def _n1(p, n):
          return np.sum(n[: p + 1])
  
      def _n2(p, n):
          return np.sum(n[p:k])
  
      def _mean_at(p, n):
          N1 = _n1(p, n)
          N2 = _n2(p, n)
          return (
              N1**2.0
              + N2**2.0
              - np.sum(n**2.0)
              - n.iloc[p] ** 2.0
          ) / 4.0
  
      def _var_at(p, n):
          N1 = _n1(p, n)
          N2 = _n2(p, n)
          N = np.sum(n)
  
          var = (
              2.0 * (N1**3 + N2**3)
              + 3.0 * (N1**2 + N2**2)
              - np.sum(n**2 * (2 * n + 3.0))
              - n.iloc[p] ** 2.0 * (2.0 * n.iloc[p] + 3.0)
              + 12.0 * n.iloc[p] * N1 * N2
              - 12.0 * n.iloc[p] ** 2.0 * N
          ) / 72.0
          return var
  
      if p:
          # if (x.groupby(_val_col).count() > 1).any().any():
          #    print("Ties are present")
          U = _ustat(Rij, x[_group_col], k)
          est = _ap(p, U)
          mean = _mean_at(p, n)
          sd = np.sqrt(_var_at(p, n))
          stat = (est - mean) / sd
          p_value = ss.norm.sf(stat)
      else:
          U = _ustat(Rij, x[_group_col], k)
          Ap = np.array([_ap(i, U) for i in range(k)]).ravel()
          mean = np.array([_mean_at(i, n) for i in range(k)]).ravel()
          var = np.array([_var_at(i, n) for i in range(k)]).ravel()
          A = (Ap - mean) / np.sqrt(var)
          stat = np.max(A)
  
          mt = []
          for _ in range(n_perm):
              ix = Series(np.random.permutation(Rij))
              uix = _ustat(ix, x[_group_col], k)
              apix = np.array([_ap(i, uix) for i in range(k)])
              astarix = (apix - mean) / np.sqrt(var)
              mt.append(np.max(astarix))
  
          mt = np.array(mt)
          p_value = mt[mt > stat] / n_perm
  
      return p_value, stat
  
file_path: scikit-posthocs/scikit_posthocs/_omnibus.py
imports: from typing import Union, List, Tuple
  import itertools
  import numpy
  import scipy.stats
  from statsmodels.stats.libqsturng import psturng
  from pandas import DataFrame, Categorical, Series
  from scikit_posthocs._posthocs import __convert_to_df, __convert_to_block_df
label_desc: Use image node_id 1 for calling a global function with example usage: test_mackwolfe(data, val_col, group_col, p, n_perm, sort) and returns: p_value,  stat, False, np, U, unknown, np, np, unknown, var, False