from __future__ import print_function, division
import os
import numpy as np
import h5py


def dict_2_h5(fname, dic, append=False):
    '''Writes a dictionary to a hdf5 file with given filename
        It will use lzf compression for all numpy arrays

    Args:
        fname (str): filename to write to
        dic (dict): dictionary to write
        append (bool): if true, will append to file instead of overwriting, default=False
    '''
    if append:
        method = 'r+'
    else:
        method = 'w'
    with h5py.File(fname, method) as h5:
        recursive_save_dict_to_h5(h5, '/', dic)


def h5_2_dict(fname):
    '''Reads a dictionary from a hdf5 file with given filename

    Args:
        fname (str): hdf5 filename to read

    Returns:
        dict: dictionary of hdf5 keys
    '''
    with h5py.File(fname, 'r') as h5:
        return recursive_load_dict_from_h5(h5, '/')


def prep_folder(path):
    '''Checks if folder exists and recursively creates folders
        to ensure the path is valid

    Args:
        path (str): path to folder
    '''
    if os.path.isdir(path):
        return
    else:
        os.makedirs(path)


def recursive_save_dict_to_h5(h5, path, dic):
    ''' function used in save_dict_to_h5 in order to get recursion
    '''
    for key, item in dic.items():
        if path + key in h5:  ### overwrites pre-existing keys with same name
            del h5[path + key]
        if type(item) in [np.ndarray, np.generic]:
            h5.create_dataset(path + key, data=item, compression='lzf')
        elif type(item) != dict:
            try:
                h5.create_dataset(path + key, data=item)
            except TypeError:
                raise ValueError('Cannot save %s type' % type(item))
        else:
            recursive_save_dict_to_h5(h5, path + key + '/', item)


def recursive_load_dict_from_h5(h5, path):
    ''' function used in load_h5_to_dict in order to get recursion
    '''
    out_dict = {}
    for key, item in h5[path].items():
        # if type(item) == h5py._hl.dataset.Dataset:
        if isinstance(item, h5py.Dataset):
            out_dict[key] = item.value
        # elif type(item) == h5py._hl.group.Group:
        elif isinstance(item, h5py.Group):
            out_dict[key] = recursive_load_dict_from_h5(h5, path + key + '/')
    return out_dict


def read_Ld_results(Ld_directory):
    '''Reads L and d histogram data from multinest run

    Args:
        Ld_directory (str): path to multinest save directory

    Returns:
        Tuple (np.ndarray, np.ndarray) L histogram values (in pixels), d histogram values (in mm)
    '''
    try:
        fname = os.path.join(Ld_directory, "Ld_post_equal_weights.dat")
        post = np.loadtxt(fname, ndmin=2)
    except IOError:
        fname = os.path.join(Ld_directory, "Ld_solver_post_equal_weights.dat")
        post = np.loadtxt(fname, ndmin=2)

    L = post[:, 0]
    d = post[:, 1]
    return L, d


def read_match_finesse_results(finesse_directory, errtemp=False):
    fname = os.path.join(finesse_directory, "F_post_equal_weights.dat")
    post = np.loadtxt(fname, ndmin=2)
    F = post[:, 0]
    V = post[:, 1]
    T = post[:, 2]
    if errtemp:
        E = post[:, 3]
        return F, V, T, E
    else:
        return F, V, T


def read_finesse_results(finesse_directory):
    fname = os.path.join(finesse_directory, "finesse_post_equal_weights.dat")
    post = np.loadtxt(fname, ndmin=2)
    F = post[:, 0]
    A = post[:, 1]
    Arel = post[:, 2]
    Ti = post[:, 3]

    return F, A, Arel, Ti


def read_lyon_temp_results(temp_directory):
    fname = os.path.join(temp_directory, 'temp_post_equal_weights.dat')
    post = np.loadtxt(fname, ndmin=2)
    T = post[:, 0]
    V = post[:, 1]
    # A = post[:,2]
    # O = post[:,3]
    return T, V  # ,A#,O

[((1075, 1094), 'os.path.isdir', 'os.path.isdir', (['path'], {}), '(path)\n', (1088, 1094), False, 'import os\n'), ((3009, 3068), 'os.path.join', 'os.path.join', (['finesse_directory', '"""F_post_equal_weights.dat"""'], {}), "(finesse_directory, 'F_post_equal_weights.dat')\n", (3021, 3068), False, 'import os\n'), ((3080, 3106), 'numpy.loadtxt', 'np.loadtxt', (['fname'], {'ndmin': '(2)'}), '(fname, ndmin=2)\n', (3090, 3106), True, 'import numpy as np\n'), ((3321, 3386), 'os.path.join', 'os.path.join', (['finesse_directory', '"""finesse_post_equal_weights.dat"""'], {}), "(finesse_directory, 'finesse_post_equal_weights.dat')\n", (3333, 3386), False, 'import os\n'), ((3398, 3424), 'numpy.loadtxt', 'np.loadtxt', (['fname'], {'ndmin': '(2)'}), '(fname, ndmin=2)\n', (3408, 3424), True, 'import numpy as np\n'), ((3590, 3649), 'os.path.join', 'os.path.join', (['temp_directory', '"""temp_post_equal_weights.dat"""'], {}), "(temp_directory, 'temp_post_equal_weights.dat')\n", (3602, 3649), False, 'import os\n'), ((3661, 3687), 'numpy.loadtxt', 'np.loadtxt', (['fname'], {'ndmin': '(2)'}), '(fname, ndmin=2)\n', (3671, 3687), True, 'import numpy as np\n'), ((519, 543), 'h5py.File', 'h5py.File', (['fname', 'method'], {}), '(fname, method)\n', (528, 543), False, 'import h5py\n'), ((809, 830), 'h5py.File', 'h5py.File', (['fname', '"""r"""'], {}), "(fname, 'r')\n", (818, 830), False, 'import h5py\n'), ((1129, 1146), 'os.makedirs', 'os.makedirs', (['path'], {}), '(path)\n', (1140, 1146), False, 'import os\n'), ((2635, 2690), 'os.path.join', 'os.path.join', (['Ld_directory', '"""Ld_post_equal_weights.dat"""'], {}), "(Ld_directory, 'Ld_post_equal_weights.dat')\n", (2647, 2690), False, 'import os\n'), ((2706, 2732), 'numpy.loadtxt', 'np.loadtxt', (['fname'], {'ndmin': '(2)'}), '(fname, ndmin=2)\n', (2716, 2732), True, 'import numpy as np\n'), ((2769, 2831), 'os.path.join', 'os.path.join', (['Ld_directory', '"""Ld_solver_post_equal_weights.dat"""'], {}), "(Ld_directory, 'Ld_solver_post_equal_weights.dat')\n", (2781, 2831), False, 'import os\n'), ((2847, 2873), 'numpy.loadtxt', 'np.loadtxt', (['fname'], {'ndmin': '(2)'}), '(fname, ndmin=2)\n', (2857, 2873), True, 'import numpy as np\n')]