# -*- coding: utf-8 -*-
##############################################################################
# Copyright (c), <NAME> and <NAME>'.                      #
# All rights reserved.                                                       #
#                                                                            #
# This file is part of the Quantas code.                                     #
#                                                                            #
# For further information on the license, see the LICENSE file               #
##############################################################################

"""
This module contains a class used to export data generated by Quantas from the
HDF5 format to text file.

Formatting constants, functions and classes are employed to export data in
different file formats.
"""

import os
from quantas.IO.hdf5_reader import QuantasHDF5Reader


class QuantasHDF5Export(object):

    def __init__(self):
        return

    def run(self):
        """
        This method begins the export of the data contained in the HDF5 file
        generated by Quantas.
        """
        stop = False
        while not stop:
            print()
            print('Select quantity to export')
            print("[type 'help' to see available results, or 'quit' to exit]")
            var = input('Selection: ')
            if var.lower() == 'help':
                self.report_input_data()
                continue
            elif var.lower() == 'quit':
                stop = True
                continue
            elif not self._reader.has_data(var):
                print('Error: {}'.format(self._reader.has_data(var)))
                continue
            else:
                outfile = self._outbase + '_{}'.format(var) + '.dat'
                self.export_data(var, outfile)
                print()
                msg = 'Would you like to export other results? [y/N] '
                choice = 'go'
                while (choice.lower() != 'n' or choice.lower() != 'y'
                       or choice != ''):
                    choice = input(msg)
                    if choice == '' or choice.lower() == 'n':
                        stop = True
                        break
                    elif choice.lower() == 'y':
                        break
        return True

    def read_input(self, hdf5file):
        error = None
        self._hdf5file = hdf5file
        self._outbase = os.path.splitext(self._hdf5file)[0]
        #
        self._reader = QuantasHDF5Reader(self._hdf5file)
        self._reader.read()
        if 'This file was created with Quantas.' not in self._reader.info:
            error = 'The selected file does not appear as a Quantas output'
            return error
        self.get_file_data()
        return error

    def report_input_data(self):
        print(self._reader.info)
        return

    def get_file_data(self):
        if '(HA)' in self._reader.info:
            self._type = 'ha'
            self._x1 = 'T'
            self._x2 = 'V'
        if '(QHA)' in self._reader.info:
            self._type = 'qha'
            self._x1 = 'T'
            self._x2 = 'P'
        return

    def export_data(self, varname, outfile):
        tmpfile = input(
            'Select output file for the selected data: ({})'.format(outfile)
            )
        if tmpfile != '':
            outfile = tmpfile
        if self._type == 'qha' or self._type == 'ha':
            data = QHATableFile(
                outfile,
                self._reader.get_data(self._x1),
                self._reader.get_attribute(self._x1, 'desc'),
                self._reader.get_attribute(self._x1, 'unit'),
                self._reader.get_data(self._x2),
                self._reader.get_attribute(self._x2, 'desc'),
                self._reader.get_attribute(self._x2, 'unit'),
                self._reader.get_data(varname),
                self._reader.get_attribute(varname, 'desc'),
                self._reader.get_attribute(varname, 'unit'),
                self._reader.get_attribute(varname, 'desc')
                )
            data.write()
        print('Results exported correctly!')
        return


# -----------------------------------------------------------------------------#
# Formatting constants
# -----------------------------------------------------------------------------#
sep = '{s:{c}<{w}}{s}'                          # Row separator format
head = '{s}{v1:{c}^{w1}}{s}{v2:{c}^{w2}}{s}'    # Header format
subhd = '{s}{v:{c}<{w}}{s}'                     # Sub-Header format
t_space = 10                                    # Space for T values
t_line = '{s}{t:{c}^{w}}'                       # T format
d_space = 20                                    # Space for data values
d_line = '{s}{d:{c}^{w}}'                       # Data format
endrow = '{s:{c}>{w}}'                          # End of row format
ttype = '%.2f'                                  # T numeric format
etype = '%.12E'                                 # Energy numeric format
vtype = '%.8f'                                  # Volume numeric format
ptype = '%.8f'                                  # Pressure numeric format
stype = '%.s'                                   # Text format
nl = '\n'                                       # New line
fileHeader = '*- This file was created using Quantas -*\n'


# -----------------------------------------------------------------------------#
# Writing functions
# -----------------------------------------------------------------------------#
def calc_space(n):
    totw = (n * d_space) + t_space + (n + 1)
    dataw = (n * d_space) + (n - 1)
    return totw, dataw


def separator(totw, sym, char):
    return sep.format(s=sym, w=totw, c=char)


def header(dataw, tag1, tag2):
    return head.format(s=' ', v1=tag1, w1=t_space, v2=tag2, w2=dataw, c=' ')


def subhead(totw, tag):
    return subhd.format(s=' ', v=tag, w=totw-1, c='')


def put_data(x, dtype):
    if x == '':
        value = t_line.format(s=' ', t='', w=t_space, c=' ')
    elif dtype == ttype:
        value = t_line.format(s=' ', t=str(dtype % x), w=t_space, c=' ')
    elif dtype == stype:
        value = d_line.format(s=' ', d=(x), w=d_space, c=' ')
    else:
        value = d_line.format(s=' ', d=str(dtype % x), w=d_space, c=' ')
    return value


def newrow():
    return endrow.format(s=' \n', w=0, c=' ')


# -----------------------------------------------------------------------------#
# Writing classes
# -----------------------------------------------------------------------------#
class QHATableFile():
    """
    File export class for (Q)HA results. It exports data in a table format
    in selected file.

    Parameters
    ----------

    outfile = str
        name of the file where data will be saved

    var1 = ndarray
        First independent variable data

    var1Name = str
        Name of the variable of var1

    var1Unit = str
        Measurement unit of var1

    var2 = ndarray
        Second independent variable data

    var2Name = str
        Name of the variable of var2

    var2Unit = str
        Measurement unit of var1

    res = ndarray
        Results in a 2D-array format (1D or 2D)

    resName = str
        Name of the result data

    resUnit = str
        Measurement unit of result data

    desc = str, optional
        Description to be included in the file header

    """
    def __init__(self, outfile,
                 x, xname, xunit,
                 y, yname, yunit,
                 z, zname, zunit,
                 description=None):
        self.outfile = outfile
        #
        # Set x data and style
        self.x = x
        self.xname = xname
        self.xstyle, self.xlabel = self._set_style(xname, xunit)
        #
        # Set variable 2 data and style
        self.y = y
        self.yname = yname
        self.ystyle, self.ylabel = self._set_style(yname, yunit)
        #
        # Set results data and style
        self.z = z
        self.zname = zname
        self.zunit = zunit
        self.zstyle, self.zlabel = self._set_style(zname, zunit)
        #
        # Set description in the file, if any
        if description != ('' or None):
            self.description = description
        else:
            self.description = None
        return

    def _set_style(self, name, unit):
        if name == 'Temperature':
            style = ttype
            label = 'T (' + unit + ')'
        elif 'volume' in name.lower():
            style = vtype
            label = 'Volume (' + unit + ')'
        elif 'bulk modulus' in name.lower() or name == 'Pressure':
            style = ptype
            label = 'Pressure (' + unit + ')'
        else:
            style = etype
            label = name + ' (' + unit + ')'
        return style, label

    def write(self):
        f = open(self.outfile, 'wt', encoding='utf8')
        totw, dataw = calc_space(len(self.y))
        # Write the header
        f.write(fileHeader)
        f.write(nl)
        if not isinstance(self.description, type(None)):
            f.write(self.description)
        f.write(nl)
        f.write('Data in ' + self.zunit + ' units')
        f.write(nl)
        f.write(nl)
        # Start constructing the table
        f.write(separator(totw, '+', '-'))
        f.write(nl)
        f.write(header(dataw, self.xlabel, self.ylabel))
        f.write(nl)
        f.write(put_data('', ttype))
        for i in range(len(self.y)):
            f.write(put_data(self.y[i], self.ystyle))
        f.write(newrow())
        f.write(separator(totw, '+', '='))
        f.write(nl)
        for i in range(len(self.x)):
            f.write(put_data(self.x[i], self.xstyle))
            for j in range(len(self.y)):
                f.write(put_data(self.z[i][j], self.zstyle))
            f.write(newrow())
        f.write(separator(totw, '+', '='))
        f.close()
        return

# -*- coding: utf-8 -*-
##############################################################################
# Copyright (c), <NAME> and <NAME>'.                      #
# All rights reserved.                                                       #
#                                                                            #
# This file is part of the Quantas code.                                     #
#                                                                            #
# For further information on the license, see the LICENSE file               #
##############################################################################

"""
This module contains a class used to export data generated by Quantas from the
HDF5 format to text file.

Formatting constants, functions and classes are employed to export data in
different file formats.
"""

import os
from quantas.IO.hdf5_reader import QuantasHDF5Reader


class QuantasHDF5Export(object):

    def __init__(self):
        return

    def run(self):
        """
        This method begins the export of the data contained in the HDF5 file
        generated by Quantas.
        """
        stop = False
        while not stop:
            print()
            print('Select quantity to export')
            print("[type 'help' to see available results, or 'quit' to exit]")
            var = input('Selection: ')
            if var.lower() == 'help':
                self.report_input_data()
                continue
            elif var.lower() == 'quit':
                stop = True
                continue
            elif not self._reader.has_data(var):
                print('Error: {}'.format(self._reader.has_data(var)))
                continue
            else:
                outfile = self._outbase + '_{}'.format(var) + '.dat'
                self.export_data(var, outfile)
                print()
                msg = 'Would you like to export other results? [y/N] '
                choice = 'go'
                while (choice.lower() != 'n' or choice.lower() != 'y'
                       or choice != ''):
                    choice = input(msg)
                    if choice == '' or choice.lower() == 'n':
                        stop = True
                        break
                    elif choice.lower() == 'y':
                        break
        return True

    def read_input(self, hdf5file):
        error = None
        self._hdf5file = hdf5file
        self._outbase = os.path.splitext(self._hdf5file)[0]
        #
        self._reader = QuantasHDF5Reader(self._hdf5file)
        self._reader.read()
        if 'This file was created with Quantas.' not in self._reader.info:
            error = 'The selected file does not appear as a Quantas output'
            return error
        self.get_file_data()
        return error

    def report_input_data(self):
        print(self._reader.info)
        return

    def get_file_data(self):
        if '(HA)' in self._reader.info:
            self._type = 'ha'
            self._x1 = 'T'
            self._x2 = 'V'
        if '(QHA)' in self._reader.info:
            self._type = 'qha'
            self._x1 = 'T'
            self._x2 = 'P'
        return

    def export_data(self, varname, outfile):
        tmpfile = input(
            'Select output file for the selected data: ({})'.format(outfile)
            )
        if tmpfile != '':
            outfile = tmpfile
        if self._type == 'qha' or self._type == 'ha':
            data = QHATableFile(
                outfile,
                self._reader.get_data(self._x1),
                self._reader.get_attribute(self._x1, 'desc'),
                self._reader.get_attribute(self._x1, 'unit'),
                self._reader.get_data(self._x2),
                self._reader.get_attribute(self._x2, 'desc'),
                self._reader.get_attribute(self._x2, 'unit'),
                self._reader.get_data(varname),
                self._reader.get_attribute(varname, 'desc'),
                self._reader.get_attribute(varname, 'unit'),
                self._reader.get_attribute(varname, 'desc')
                )
            data.write()
        print('Results exported correctly!')
        return


# -----------------------------------------------------------------------------#
# Formatting constants
# -----------------------------------------------------------------------------#
sep = '{s:{c}<{w}}{s}'                          # Row separator format
head = '{s}{v1:{c}^{w1}}{s}{v2:{c}^{w2}}{s}'    # Header format
subhd = '{s}{v:{c}<{w}}{s}'                     # Sub-Header format
t_space = 10                                    # Space for T values
t_line = '{s}{t:{c}^{w}}'                       # T format
d_space = 20                                    # Space for data values
d_line = '{s}{d:{c}^{w}}'                       # Data format
endrow = '{s:{c}>{w}}'                          # End of row format
ttype = '%.2f'                                  # T numeric format
etype = '%.12E'                                 # Energy numeric format
vtype = '%.8f'                                  # Volume numeric format
ptype = '%.8f'                                  # Pressure numeric format
stype = '%.s'                                   # Text format
nl = '\n'                                       # New line
fileHeader = '*- This file was created using Quantas -*\n'


# -----------------------------------------------------------------------------#
# Writing functions
# -----------------------------------------------------------------------------#
def calc_space(n):
    totw = (n * d_space) + t_space + (n + 1)
    dataw = (n * d_space) + (n - 1)
    return totw, dataw


def separator(totw, sym, char):
    return sep.format(s=sym, w=totw, c=char)


def header(dataw, tag1, tag2):
    return head.format(s=' ', v1=tag1, w1=t_space, v2=tag2, w2=dataw, c=' ')


def subhead(totw, tag):
    return subhd.format(s=' ', v=tag, w=totw-1, c='')


def put_data(x, dtype):
    if x == '':
        value = t_line.format(s=' ', t='', w=t_space, c=' ')
    elif dtype == ttype:
        value = t_line.format(s=' ', t=str(dtype % x), w=t_space, c=' ')
    elif dtype == stype:
        value = d_line.format(s=' ', d=(x), w=d_space, c=' ')
    else:
        value = d_line.format(s=' ', d=str(dtype % x), w=d_space, c=' ')
    return value


def newrow():
    return endrow.format(s=' \n', w=0, c=' ')


# -----------------------------------------------------------------------------#
# Writing classes
# -----------------------------------------------------------------------------#
class QHATableFile():
    """
    File export class for (Q)HA results. It exports data in a table format
    in selected file.

    Parameters
    ----------

    outfile = str
        name of the file where data will be saved

    var1 = ndarray
        First independent variable data

    var1Name = str
        Name of the variable of var1

    var1Unit = str
        Measurement unit of var1

    var2 = ndarray
        Second independent variable data

    var2Name = str
        Name of the variable of var2

    var2Unit = str
        Measurement unit of var1

    res = ndarray
        Results in a 2D-array format (1D or 2D)

    resName = str
        Name of the result data

    resUnit = str
        Measurement unit of result data

    desc = str, optional
        Description to be included in the file header

    """
    def __init__(self, outfile,
                 x, xname, xunit,
                 y, yname, yunit,
                 z, zname, zunit,
                 description=None):
        self.outfile = outfile
        #
        # Set x data and style
        self.x = x
        self.xname = xname
        self.xstyle, self.xlabel = self._set_style(xname, xunit)
        #
        # Set variable 2 data and style
        self.y = y
        self.yname = yname
        self.ystyle, self.ylabel = self._set_style(yname, yunit)
        #
        # Set results data and style
        self.z = z
        self.zname = zname
        self.zunit = zunit
        self.zstyle, self.zlabel = self._set_style(zname, zunit)
        #
        # Set description in the file, if any
        if description != ('' or None):
            self.description = description
        else:
            self.description = None
        return

    def _set_style(self, name, unit):
        if name == 'Temperature':
            style = ttype
            label = 'T (' + unit + ')'
        elif 'volume' in name.lower():
            style = vtype
            label = 'Volume (' + unit + ')'
        elif 'bulk modulus' in name.lower() or name == 'Pressure':
            style = ptype
            label = 'Pressure (' + unit + ')'
        else:
            style = etype
            label = name + ' (' + unit + ')'
        return style, label

    def write(self):
        f = open(self.outfile, 'wt', encoding='utf8')
        totw, dataw = calc_space(len(self.y))
        # Write the header
        f.write(fileHeader)
        f.write(nl)
        if not isinstance(self.description, type(None)):
            f.write(self.description)
        f.write(nl)
        f.write('Data in ' + self.zunit + ' units')
        f.write(nl)
        f.write(nl)
        # Start constructing the table
        f.write(separator(totw, '+', '-'))
        f.write(nl)
        f.write(header(dataw, self.xlabel, self.ylabel))
        f.write(nl)
        f.write(put_data('', ttype))
        for i in range(len(self.y)):
            f.write(put_data(self.y[i], self.ystyle))
        f.write(newrow())
        f.write(separator(totw, '+', '='))
        f.write(nl)
        for i in range(len(self.x)):
            f.write(put_data(self.x[i], self.xstyle))
            for j in range(len(self.y)):
                f.write(put_data(self.z[i][j], self.zstyle))
            f.write(newrow())
        f.write(separator(totw, '+', '='))
        f.close()
        return

# -*- coding: utf-8 -*- ############################################################################## # Copyright (c), <NAME> and <NAME>'.                      # # All rights reserved.                                                       # #                                                                            # # This file is part of the Quantas code.                                     # #                                                                            # # For further information on the license, see the LICENSE file               # ############################################################################## This module contains a class used to export data generated by Quantas from the HDF5 format to text file.  Formatting constants, functions and classes are employed to export data in different file formats. This method begins the export of the data contained in the HDF5 file         generated by Quantas. # # -----------------------------------------------------------------------------# # Formatting constants # -----------------------------------------------------------------------------# # Row separator format # Header format # Sub-Header format # Space for T values # T format # Space for data values # Data format # End of row format # T numeric format # Energy numeric format # Volume numeric format # Pressure numeric format # Text format # New line # -----------------------------------------------------------------------------# # Writing functions # -----------------------------------------------------------------------------# # -----------------------------------------------------------------------------# # Writing classes # -----------------------------------------------------------------------------# File export class for (Q)HA results. It exports data in a table format     in selected file.      Parameters     ----------      outfile = str         name of the file where data will be saved      var1 = ndarray         First independent variable data      var1Name = str         Name of the variable of var1      var1Unit = str         Measurement unit of var1      var2 = ndarray         Second independent variable data      var2Name = str         Name of the variable of var2      var2Unit = str         Measurement unit of var1      res = ndarray         Results in a 2D-array format (1D or 2D)      resName = str         Name of the result data      resUnit = str         Measurement unit of result data      desc = str, optional         Description to be included in the file header # # Set x data and style # # Set variable 2 data and style # # Set results data and style # # Set description in the file, if any # Write the header # Start constructing the table