#!/usr/bin/env python

##############################################################################
##
# This file is part of Sardana
##
# http://www.tango-controls.org/static/sardana/latest/doc/html/index.html
##
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
# Sardana is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
##
# Sardana is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
##
# You should have received a copy of the GNU Lesser General Public License
# along with Sardana.  If not, see <http://www.gnu.org/licenses/>.
##
##############################################################################

'''
Script for extracting "scan tables" from Sardana NeXus files into an tab-separated ASCII tables.
When data from multiple entries are extracted from a file, each table is stored in a different file.
The output files for a given input file are stored in a directory whose name matches the input file name (minus extension)

Usage:
python h52ascii.py <nexusfilename> [<entryname1> [<entryname2>] ...]

If no entry names are provided, all entries from the given nexus file name will be extracted.

Note: only scalar values are extracted
'''

import nxs
import sys
import os
import numpy


def measurement2ascii(fd, entryname, ofname):
    # check if there is a measurement datagroup
    tmp = "/%s/measurement" % entryname
    try:
        fd.openpath(tmp)
    except:
        print 'Cannot open hdf5 path "%s". Skipping.' % tmp
        return False

    # read the point number data
    # possible ways of storing the point number (along different versions)
    ptnb_names = ('Pt_No', 'point_nb', '#Pt No')
    for i, ptnb_name in enumerate(ptnb_names):
        try:
            fd.opendata(ptnb_name)
            break
        except:
            print 'cannot open %s' % ptnb_name
            if i == len(ptnb_names) - 1:  # if this was not the last choice
                print 'I give up!'
                return False
    ptnb = fd.getdata()
    fd.closedata()
    # prepare a list with column names and a table made of data "columns"
    namelist = [ptnb_name]
    table = [ptnb.copy().flatten()]
    for name, nxclass in fd.entries():
        if name == ptnb_name:
            continue
        if nxclass != 'SDS':
            continue  # not a dataset
        dshape, dtype = fd.getinfo()
        if tuple(dshape) != ptnb.shape:
            continue  # not a scalar (incompatible shape)
        table.append(fd.getdata().flatten())
        namelist.append(name)
    # write the table to a file
    try:
        datfile = open(ofname, 'w')
    except:
        print 'Cannot create file "%s". Skipping.' % ofname
        return False
    datfile.write("\t".join(namelist))  # write a header of column names
    datfile.write("\n")
    numpy.savetxt(datfile, numpy.vstack(table).transpose(),
                  delimiter='\t')  # write the data table
    datfile.close()
    return True


def main():
    if len(sys.argv) > 1:
        fname = sys.argv[1]
    else:
        print "Usage:\nh5toascii <nexusfilename> [<entryname1> [<entryname2>] ...] "
        sys.exit(1)

    entrynames = sys.argv[2:]

    fd = nxs.open(fname, 'r')

    if len(entrynames) == 0:
        entrynames = [n for n, c in fd.entries() if c == 'NXentry']

    dirname, ext = os.path.splitext(fname)
    try:
        os.makedirs(dirname)
    except:
        print 'Cannot create dir "%s". Skipping.' % dirname

    for ename in entrynames:
        ofname = os.path.join(dirname, "%s.dat" % ename)
        print "Extracting %s:%s to %s" % (fname, ename, ofname)
        measurement2ascii(fd, ename, ofname)

    fd.close()


if __name__ == "__main__":
    main()
