Source code for node_adaf2table

# This file is part of Sympathy for Data.
# Copyright (c) 2013, 2017, Combine Control Systems AB
#
# Sympathy for Data is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# Sympathy for Data 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Sympathy for Data.  If not, see <http://www.gnu.org/licenses/>.
from sympathy.api import qt2 as qt_compat
from sympathy.api import node as synode
from sympathy.api.nodeconfig import Port, Ports, Tag, Tags
from sympathy.api.exceptions import SyDataError
from sympathy.api.exceptions import SyConfigurationError
from sympathy.api.exceptions import sywarn
QtGui = qt_compat.import_module('QtGui')
QtWidgets = qt_compat.import_module('QtWidgets')


COMMON_DOCS = """
When converting a raster, its timebasis will be given the name of the raster.
Note that if the name of the raster also exists among the names of the
timeseries in that raster, the timebasis for that raster will not be included
in the output Table.

See also :ref:`working_with_adafs` for tips about how to use these conversion
nodes.
"""


RELATED = [
    'org.sysess.sympathy.data.adaf.adaf2table',
    'org.sysess.sympathy.data.adaf.adaf2tables',
    'org.sysess.sympathy.data.adaf.adafs2tables',
    'org.sysess.sympathy.data.table.table2adaf',
    'org.sysess.sympathy.data.table.updateadafwithtable',
]


def write_adaf_to_table(export_group, adaffile, tablefile, tb_name=None,
                        tb_col_name=''):
    """Write the selected export group to a table."""
    if export_group == 'Meta':
        tablefile.update(adaffile.meta.to_table())
    elif export_group == 'Result':
        tablefile.update(adaffile.res.to_table())
    elif export_group == 'Time series':
        system_name, raster_name = get_system_raster_names(tb_name)
        if system_name in adaffile.sys:
            system = adaffile.sys[system_name]
            if raster_name in system:
                raster = system[raster_name]
            else:
                raise SyDataError(
                    'The selected raster does not exist in incoming ADAF')
        else:
            raise SyDataError(
                'The selected system does not exist in incoming ADAF')

        if not tb_col_name:
            tb_col_name = raster_name
        # Check if tb_col_name already exists in Table
        if tb_col_name in raster.keys():
            message = ('A column with the entered time basis column name '
                       'do already exist. The column will be overwritten '
                       'to time basis in the outgoing Table.')
            sywarn(message)

        tablefile.update(raster.to_table(tb_col_name))

    source = adaffile.source_id()
    if source:
        tablefile.set_name(source)


def get_system_raster_names(tb_path):
    """Split time basis path, system_name/raster_name/ and the return the
    system_name and the raster_name.
    """
    return tuple(tb_path.split('/')[:2])


def get_raster_name(tb_path):
    """Return the raster name from given time basis path."""
    system_name, raster_name = get_system_raster_names(tb_path)
    return raster_name


def get_rasters_from_adaf(adafdata):
    """Return a list with the paths to all rasters in an adaf,
    system_name/raster_name/
    """
    if not adafdata:
        return []
    return ['{0}/{1}/'.format(system, raster)
            for system, rastergroup in adafdata.sys.items()
            for raster in rastergroup.keys()]


class ADAF2TableSuperNode(synode.Node):
    author = "Alexander Busck"
    icon = 'adaf2table.svg'
    tags = Tags(Tag.DataProcessing.Convert)


def _get_single_tb_editor():
    return synode.editors.combo_editor('', filter=True, edit=False)


def base_parameters(multiselect):
    parameters = simple_base_parameters()

    if multiselect:
        tb_editor = synode.editors.multilist_editor(mode=False)
    else:
        tb_editor = _get_single_tb_editor()
    parameters.set_list('tb',
                        label="Time basis raster",
                        description=(
                            'Specify the raster among the time resolved data '
                            'which will be exported'),
                        value=[],
                        editor=tb_editor)

    parameters.set_string('tb_col_name',
                          label='Time basis column name',
                          description=('Specify the name for the time basis '
                                       'column in the outgoing Table. The '
                                       'default name is the name of the '
                                       'selected raster.'),
                          value='')
    return parameters


def simple_base_parameters():
    parameters = synode.parameters()
    parameters.set_list(
        'export_group', ['Meta', 'Result', 'Time series'],
        label='Export group',
        description='Specify group in the ADAF which will be exported',
        value=[0],
        editor=synode.editors.combo_editor())
    return parameters


def base_controllers():
    controllers = (
        synode.controller(
            when=synode.field('export_group', 'value', value=['Time series']),
            action=(synode.field('tb', 'enabled'),
                    synode.field('tb_col_name', 'enabled'))),)
    return controllers


def get_params(node_context):
    group_name = node_context.parameters['export_group'].selected
    try:
        tb_names = node_context.parameters['tb'].value_names
    except Exception:
        tb_names = []
    try:
        tb_col_name = node_context.parameters['tb_col_name'].value
    except Exception:
        tb_col_name = ''
    return group_name, tb_names, tb_col_name


[docs]class ADAF2Table(ADAF2TableSuperNode): """ The selected part can either be the one raster from the timeseries container or the full content of either the metadata or the results containers. """ name = 'ADAF to Table' description = 'Convert selected part of an ADAF into a Table.' nodeid = 'org.sysess.sympathy.data.adaf.adaf2table' related = RELATED inputs = Ports([Port.ADAF('Input ADAF', name='port1')]) outputs = Ports([Port.Table( 'Table with the content of a specified group in the incoming ADAF', name='port1')]) parameters = base_parameters(False) controllers = base_controllers() def adjust_parameters(self, node_context): if node_context.input['port1'].is_valid(): adafdata = node_context.input['port1'] else: adafdata = None rasters = get_rasters_from_adaf(adafdata) node_context.parameters['tb'].adjust(rasters) def update_parameters(self, old_params): param = 'tb' if param in old_params: old_params[param].editor = _get_single_tb_editor() def execute(self, node_context): adaffile = node_context.input['port1'] tablefile = node_context.output['port1'] group_name, tb_names, tb_col_name = get_params(node_context) if group_name in ('Meta', 'Result'): write_adaf_to_table(group_name, adaffile, tablefile) for tb_name in tb_names: try: write_adaf_to_table( group_name, adaffile, tablefile, tb_name, tb_col_name) except AttributeError: raise SyConfigurationError('Configuration error')
[docs]class ADAFs2Tables(ADAF2TableSuperNode): """ The selected part can either be the one raster from the timeseries container or the full content of either the metadata or the results containers. """ name = 'ADAFs to Tables' description = 'Convert selected part of each input ADAF into a Table.' nodeid = 'org.sysess.sympathy.data.adaf.adafs2tables' related = RELATED inputs = Ports([Port.ADAFs('Input ADAF', name='port1')]) outputs = Ports([Port.Tables( 'Tables with the content of a specified group in the incoming ADAFs', name='port1')]) parameters = base_parameters(True) controllers = base_controllers() def adjust_parameters(self, node_context): port1 = node_context.input['port1'] if port1.is_valid() and len(port1): adafdata = port1[0] else: adafdata = None rasters = get_rasters_from_adaf(adafdata) node_context.parameters['tb'].adjust(rasters) def update_parameters(self, old_params): try: old_params['tb'].editor['mode'] = True except KeyError: pass def execute(self, node_context): input_list = node_context.input['port1'] output_list = node_context.output['port1'] group_name, tb_names, tb_col_name = get_params(node_context) for i, adaffile in enumerate(input_list): if group_name in ('Meta', 'Result'): tablefile = output_list.create() write_adaf_to_table(group_name, adaffile, tablefile) output_list.append(tablefile) else: tb_names = get_rasters_from_adaf(adaffile) for tb_name in node_context.parameters['tb'].selected_names( tb_names): tablefile = output_list.create() try: write_adaf_to_table( group_name, adaffile, tablefile, tb_name, tb_col_name) except AttributeError: raise SyConfigurationError('Configuration error') output_list.append(tablefile) self.set_progress(100.0 * i / len(input_list))
[docs]class ADAF2Tables(ADAF2TableSuperNode): """ Export of specified data from ADAF to Tables. The data can be the full content of either the metadata, the results or the timeseries containers. """ name = 'ADAF to Tables' description = 'Export of data from an ADAF to a list of Tables.' nodeid = 'org.sysess.sympathy.data.adaf.adaf2tables' icon = 'adaf2tables.svg' related = RELATED inputs = Ports([Port.ADAF('Input ADAF', name='port1')]) outputs = Ports([Port.Tables( 'All data from an ADAF group as a Tables list', name='port1')]) parameters = simple_base_parameters() def execute(self, node_context): group_name = node_context.parameters['export_group'].selected adaffile = node_context.input['port1'] output_list = node_context.output['port1'] if group_name == 'Time series': tb_names = get_rasters_from_adaf(adaffile) else: tb_names = [None] for tb_name in tb_names: tablefile = output_list.create() write_adaf_to_table( group_name, adaffile, tablefile, tb_name) output_list.append(tablefile)