(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
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.
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 .
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
    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] = np.matmul(B1[:, :, j], C1[:, j])

    # Second Order
    if maxorder > 1:
        for j in range(n1, n1+n2):
            Y_em[:, j] = np.matmul(B2[:, :, j-n1], C2[:, j-n1])

    # Third Order
    if maxorder == 3:
        for j in range(n1+n2, n1+n2+n3):
            Y_em[:, j] = np.matmul(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

    emulated = np.sum(Y_em, axis=1)+Y_mean
    self['emulated'] = emulated
def emulate ( self , X , Y = None ) : # 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 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 ] = np . matmul ( B1 [ : , : , j ] , C1 [ : , j ] ) # Second Order if maxorder > 1 : for j in range ( n1 , n1 + n2 ) : Y_em [ : , j ] = np . matmul ( B2 [ : , : , j - n1 ] , C2 [ : , j - n1 ] ) # Third Order if maxorder == 3 : for j in range ( n1 + n2 , n1 + n2 + n3 ) : Y_em [ : , j ] = np . matmul ( 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 emulated = np . sum ( Y_em , axis = 1 ) + Y_mean self [ 'emulated' ] = emulated