# Path: experiments/exp_setup.py
# SDCIT_DATA_DIR = os.path.expanduser('~/kcipt_data')
# 
# Path: sdcit/utils.py
# def rbf_kernel_median(data: np.ndarray, *args, without_two=False):
#     """A list of RBF kernel matrices for data sets in arguments based on median heuristic"""
#     if args is None:
#         args = []
# 
#     outs = []
#     for x in [data, *args]:
#         D_squared = euclidean_distances(x, squared=True)
#         # masking upper triangle and the diagonal.
#         mask = np.triu(np.ones(D_squared.shape), 0)
#         median_squared_distance = ma.median(ma.array(D_squared, mask=mask))
#         if without_two:
#             kx = exp(-D_squared / median_squared_distance)
#         else:
#             kx = exp(-0.5 * D_squared / median_squared_distance)
#         outs.append(kx)
# 
#     if len(outs) == 1:
#         return outs[0]
#     else:
#         return outs
# 
# def K2D(K: Union[None, np.ndarray]) -> np.ndarray:
#     """An RKHS distance matrix given a kernel matrix
# 
#     A distance matrix D of the same size of the given kernel matrix K
#      :math:`d^2(i,j)=k(i,i)+k(j,j)-2k(i,j)`.
#     """
#     if K is None:
#         return None
# 
#     Kd = repmat(diag(K).reshape((len(K), 1)), 1, len(K))
#     temp = Kd + Kd.transpose() - 2 * K
#     min_val = np.min(temp)
#     if min_val < 0.0:
#         if min_val < -1e-15:
#             warnings.warn('K2D: negative values will be treated as zero. Observed: {}'.format(min_val))
#         temp *= (temp > 0)
#     return np.sqrt(temp)
# 
# def cythonize(*matrices):
#     return tuple(np.ascontiguousarray(matrix, dtype=np.float64) for matrix in matrices)


import itertools
import os
import numpy as np
import scipy
import scipy.io
from experiments.exp_setup import SDCIT_DATA_DIR
from sdcit.utils import rbf_kernel_median, K2D, cythonize




def chaotic_configs():
    return list(itertools.product([0, 1], [200, 400], ['0.0', '0.1', '0.2', '0.3', '0.4', '0.5']))


def postnonlinear_noise_configs():
    return list(itertools.product(range(5), [0, 1], [200, 400])) + \
           list(itertools.product([9, 19, 49], [0, 1], [400]))  # high-dimensional


def read_chaotic(independent, gamma, trial, N, dir_at=SDCIT_DATA_DIR + '/'):
    X, Y, Z = read_chaotic_data(independent, gamma, trial, N, dir_at)
    kx, ky, kz = rbf_kernel_median(X, Y, Z)
    Dz = K2D(kz)
    return kx, ky, kz, Dz


def read_postnonlinear_noise(independent, noise, trial, N, dir_at=SDCIT_DATA_DIR + '/'):
    X, Y, Z = read_postnonlinear_noise_data(independent, noise, trial, N, dir_at)

# Path: experiments/exp_setup.py
# SDCIT_DATA_DIR = os.path.expanduser('~/kcipt_data')
# 
# Path: sdcit/utils.py
# def rbf_kernel_median(data: np.ndarray, *args, without_two=False):
#     """A list of RBF kernel matrices for data sets in arguments based on median heuristic"""
#     if args is None:
#         args = []
# 
#     outs = []
#     for x in [data, *args]:
#         D_squared = euclidean_distances(x, squared=True)
#         # masking upper triangle and the diagonal.
#         mask = np.triu(np.ones(D_squared.shape), 0)
#         median_squared_distance = ma.median(ma.array(D_squared, mask=mask))
#         if without_two:
#             kx = exp(-D_squared / median_squared_distance)
#         else:
#             kx = exp(-0.5 * D_squared / median_squared_distance)
#         outs.append(kx)
# 
#     if len(outs) == 1:
#         return outs[0]
#     else:
#         return outs
# 
# def K2D(K: Union[None, np.ndarray]) -> np.ndarray:
#     """An RKHS distance matrix given a kernel matrix
# 
#     A distance matrix D of the same size of the given kernel matrix K
#      :math:`d^2(i,j)=k(i,i)+k(j,j)-2k(i,j)`.
#     """
#     if K is None:
#         return None
# 
#     Kd = repmat(diag(K).reshape((len(K), 1)), 1, len(K))
#     temp = Kd + Kd.transpose() - 2 * K
#     min_val = np.min(temp)
#     if min_val < 0.0:
#         if min_val < -1e-15:
#             warnings.warn('K2D: negative values will be treated as zero. Observed: {}'.format(min_val))
#         temp *= (temp > 0)
#     return np.sqrt(temp)
# 
# def cythonize(*matrices):
#     return tuple(np.ascontiguousarray(matrix, dtype=np.float64) for matrix in matrices)


# Path: experiments/exp_utils.py
import itertools
import os
import numpy as np
import scipy
import scipy.io
from experiments.exp_setup import SDCIT_DATA_DIR
from sdcit.utils import rbf_kernel_median, K2D, cythonize





def chaotic_configs():
    return list(itertools.product([0, 1], [200, 400], ['0.0', '0.1', '0.2', '0.3', '0.4', '0.5']))


def postnonlinear_noise_configs():
    return list(itertools.product(range(5), [0, 1], [200, 400])) + \
           list(itertools.product([9, 19, 49], [0, 1], [400]))  # high-dimensional


def read_chaotic(independent, gamma, trial, N, dir_at=SDCIT_DATA_DIR + '/'):
    X, Y, Z = read_chaotic_data(independent, gamma, trial, N, dir_at)
    kx, ky, kz = rbf_kernel_median(X, Y, Z)
    Dz = K2D(kz)
    return kx, ky, kz, Dz


def read_postnonlinear_noise(independent, noise, trial, N, dir_at=SDCIT_DATA_DIR + '/'):
    X, Y, Z = read_postnonlinear_noise_data(independent, noise, trial, N, dir_at)

    kx, ky, kz = rbf_kernel_median(X, Y, Z)