code: def emulate(self, X, Y=None):
      """Emulates model output with new input data.
  
      Generates B-Splines with new input matrix, X, and multiplies it with
      coefficient matrix, C.
  
      Compares emulated results with observed vector, Y.
  
      Returns
      ========
      Si : ResultDict, Updated
  
      """
      # Dimensionality
      N, d = X.shape
  
      # Expand C
      Em = self["Em"]
      C1, C2, C3 = Em["C1"], Em["C2"], Em["C3"]
  
      # Take average coefficient
      C1 = np.mean(C1, axis=2)
      C2 = np.mean(C2, axis=2)
      C3 = np.mean(C3, axis=2)
  
      # Get maxorder and other information from C matrix
      m = C1.shape[0] - 3
      m1 = m + 3
      n1, n2, n3 = d, 0, 0
      maxorder = 1
  
      if C2.shape[0] != 1:
          maxorder = 2
          m2 = C2.shape[0]
          c2 = np.asarray(
              list(itertools.combinations(np.arange(0, d), 2))
          )
          n2 = c2.shape[0]
      if C3.shape[0] != 1:
          maxorder = 3
          m3 = C3.shape[0]
          c3 = np.asarray(
              list(itertools.combinations(np.arange(0, d), 3))
          )
          n3 = c3.shape[0]
  
      # Initialize emulated Y's
      Y_em = np.zeros((N, n1 + n2 + n3))
  
      # Compute normalized X-values
      X_n = (X - np.tile(X.min(0), (N, 1))) / np.tile(
          (X.max(0)) - X.min(0), (N, 1)
      )
  
      # Now compute B values
      B1 = B_spline(X_n, m, d)
      if maxorder > 1:
          B2 = np.zeros((N, m2, n2))
          beta = np.array(list(itertools.product(range(m1), repeat=2)))
          for k, j in itertools.product(range(n2), range(m2)):
              B2[:, j, k] = np.multiply(
                  B1[:, beta[j, 0], c2[k, 0]],
                  B1[:, beta[j, 1], c2[k, 1]],
              )
      if maxorder == 3:
          B3 = np.zeros((N, m3, n3))
          beta = np.array(list(itertools.product(range(m1), repeat=3)))
          for k, j in itertools.product(range(n3), range(m3)):
              Emc3_k = c3[k]
              beta_j = beta[j]
              B3[:, j, k] = np.multiply(
                  np.multiply(
                      B1[:, beta_j[0], Emc3_k[0]],
                      B1[:, beta_j[1], Emc3_k[1]],
                  ),
                  B1[:, beta_j[2], Emc3_k[2]],
              )
  
      # Calculate emulated output: First Order
      for j in range(0, n1):
          Y_em[:, j] = B1[:, :, j] @ C1[:, j]
  
      # Second Order
      if maxorder > 1:
          for j in range(n1, n1 + n2):
              Y_em[:, j] = B2[:, :, j - n1] @ C2[:, j - n1]
  
      # Third Order
      if maxorder == 3:
          for j in range(n1 + n2, n1 + n2 + n3):
              Y_em[:, j] = B3[:, :, j - n1 - n2] @ C3[:, j - n1 - n2]
  
      Y_mean = 0
      if Y is not None:
          Y_mean = np.mean(Y)
          self["Y_test"] = Y
  
      self["emulated"] = np.sum(Y_em, axis=1) + Y_mean
  
imports: from typing import Dict
  from types import MethodType
  import itertools
  import time
  import warnings
  import numpy
  from numpy.linalg import solve
  from numpy.linalg import svd
  from numpy import identity
  import pandas
  from scipy import stats, special, interpolate
  from .None import common_args
  from ..util import read_param_file, ResultDict
  from SALib.plotting.hdmr import plot
  from SALib.util.problem import ProblemSpec
label_desc: Use image node_id 12 for calling a global function with example usage: emulate(X, Y) without return types