code: def _fanova(b_m, hdmr, Si, Y, bootstrap, max_iter, l2_penalty, alpha):
      """The functional ANOVA decomposition offers two main approaches:
      the extended base approach and the non-extended base approach. These
      approaches follow the guidelines presented in [1] and [2]. The
      extended base approach provides additional information to ensure
      hierarchical orthogonality.
  
      Parameters
      ----------
      b_m : numpy.array
          Basis matrix
      hdmr : namedtuple
          Core parameters of hdmr expansion
      Si : ResultDict
          Sensitivity Indices
      Y : numpy.array
          Model output
      bootstrap : int
          Number of iteration to be used in bootstrap
      max_iter : int
          Maximum number of iteration used in backfitting algorithm
      l2_penalty : float
          Penalty term for ridge regression
      alpha : float
          Significant level
  
      Returns
      -------
      Si : ResultDict
          Sensitivity Indices
      hdmr : namedtuple
          Core parameters of hdmr expansion
  
      Notes
      -----
      .. [1] Li, G., Rabitz, H., Yelvington, P., Oluwole, O., Bacon, F., Kolb, C.,
          and Schoendorf, J. 2010. Global Sensitivity Analysis for Systems with
          Independent and/or Correlated Inputs. The Journal of Physical Chemistry A,
          114(19), p.6022-6032.
      .. [2] Li, G., Rabitz, H. General formulation of HDMR component functions with
          independent and correlated variables. J Math Chem 50, 99–130 (2012).
          https://doi.org/10.1007/s10910-011-9898-0
      """
      for t in range(bootstrap):
          # Extract model output for a corresponding bootstrap iteration
          Y_idx = Y[hdmr.idx[:, t], 0]
          # Subtract mean from it
          Y_idx -= np.mean(Y_idx)
  
          if hdmr.ext_base:
              cost = _cost_matrix(b_m[hdmr.idx[:, t], :], hdmr)
              hdmr.x[:, t] = _d_morph(
                  b_m[hdmr.idx[:, t], :], cost, Y_idx, bootstrap, hdmr
              )
          else:
              Y_res = _first_order(
                  b_m[hdmr.idx[:, t], : hdmr.tnt1],
                  Y_idx,
                  max_iter,
                  l2_penalty,
                  hdmr,
                  t,
              )
              if hdmr.max_order > 1:
                  Y_res = _second_order(
                      b_m[
                          hdmr.idx[:, t],
                          hdmr.tnt1 : hdmr.tnt1 + hdmr.tnt2,
                      ],
                      Y_res,
                      max_iter,
                      l2_penalty,
                      hdmr,
                      t,
                  )
              if hdmr.max_order == 3:
                  _third_order(
                      b_m[hdmr.idx[:, t], hdmr.tnt1 + hdmr.tnt2 :],
                      Y_res,
                      l2_penalty,
                      hdmr,
                  )
  
          # Calculate component functions
          Y_e = _comp_func(b_m[hdmr.idx[:, t], :], hdmr, t)
          # Test significancy
          Si["Signf"][:, t] = _f_test(Y_idx, Y_e, alpha, hdmr)
          # Sensitivity Analysis
          Si["S"][:, t], Si["Sa"][:, t], Si["Sb"][:, t] = _ancova(
              Y_idx, Y_e, hdmr
          )
  
      return Si, hdmr
  
imports: import math
  import warnings
  from typing import Dict, Tuple
  from types import MethodType
  from itertools import combinations, product
  from collections import defaultdict, namedtuple
  import numpy
  from pandas import DataFrame
  from numpy.linalg import det, pinv, matrix_rank
  from scipy.linalg import svd, LinAlgError, solve
  from scipy import stats, special
  from .None import common_args
  from ..util import read_param_file, ResultDict
label_desc: Use image node_id 7 for calling a global function with example usage: _fanova(b_m, hdmr, Si, Y, bootstrap, max_iter, l2_penalty, alpha) and returns: Si,  hdmr