Source code for node_split_table_table
# This file is part of Sympathy for Data.
# Copyright (c) 2018, Combine Control Systems AB
#
# SYMPATHY FOR DATA COMMERCIAL LICENSE
# You should have received a link to the License with Sympathy for Data.
import numpy as np
from sympathy.api import node
from sympathy.api.exceptions import SyDataError
from sympathy.api.nodeconfig import Port, Ports, Tag, Tags, adjust
from sympathy.api import table
[docs]
class VSplitTableWithTable(node.Node):
name = 'VSplit Table with Table'
author = 'Mathias Broxvall'
icon = 'vsplit_table_table.svg'
description = (
'Uses a list of indices or boolean values to split a table.\n'
'\nIf given a table of integers, then all intervals '
'between each successive set of integers will be kept as '
'one table.\n'
'\nIf given a table of booleans, then a table '
'is created for each consecutive sequence of true values. '
)
nodeid = 'com.sympathyfordata.timeseriesanalysis.vsplit_table_with_table'
tags = Tags(Tag.DataProcessing.TransformStructure)
inputs = Ports([
Port.Table('Value table', name='value'),
Port.Table('Index table, must contain integer values for the rows to '
'split at or a boolean value mask for the areas to keep',
name='index')
])
outputs = Ports([
Port.Custom('[table]', 'Result tables', name='out')
])
parameters = node.parameters()
parameters.set_list(
'index column',
label='Select indexing column',
description='Select column used for indexing.',
value=[],
editor=node.editors.combo_editor())
parameters.set_integer(
'offset',
label='Offset',
value=0,
description='Offset subtracted from indices before splitting. Use '
'offset=1 to have indexes where the first row starts at '
'one. For boolean values, toggles between keeping only '
'positive intervals (offset=0), negative (offset=1) or '
'all (offset>1)')
def execute(self, node_context):
index_tbl = node_context.input['index']
value_tbl = node_context.input['value']
out_tbls = node_context.output['out']
offset = node_context.parameters['offset'].value
index_name = node_context.parameters['index column'].selected
try:
indices = index_tbl.col(index_name).data
except Exception as exc:
raise SyDataError("Invalid column selection for index") from exc
if np.issubdtype(indices.dtype, np.integer):
indices = np.minimum(value_tbl.number_of_rows()-1,
np.maximum(0, indices - offset))
# sywarn("There's a bug in node_split_table_table... i doesn't "
# "include the END ")
indices = np.hstack([indices, [value_tbl.number_of_rows()]])
if indices[0] == 0:
indices = indices[1:]
prev = 0
for idx in indices:
tbl = table.File()
for col in value_tbl.cols():
tbl.set_column_from_array(col.name, col.data[prev:idx])
out_tbls.append(tbl)
prev = idx
elif np.issubdtype(indices.dtype, np.dtype(bool).type):
prev = 0
changes = (((indices[1:]*1) & (1-indices[:-1])) +
((1-indices[1:]) & (indices[:-1]*1))).nonzero()[0]
if changes[-1] != value_tbl.number_of_rows()-1:
changes = np.r_[changes, value_tbl.number_of_rows()-1]
for idx in changes:
if indices[idx]-offset:
tbl = table.File()
for col in value_tbl.cols():
tbl.set_column_from_array(
col.name, col.data[prev:idx+1])
out_tbls.append(tbl)
prev = idx+1
else:
raise SyDataError('Invalid datatype {} in index column'
.format(indices.dtype))
def adjust_parameters(self, node_context):
adjust(node_context.parameters['index column'],
node_context.input['index'])