Search in sources :

Example 1 with LoopStartNodeTerminator

use of org.knime.core.node.workflow.LoopStartNodeTerminator in project knime-core by knime.

the class LoopEndJoinNodeModel method execute.

/**
 * {@inheritDoc}
 */
@Override
protected BufferedDataTable[] execute(final BufferedDataTable[] inData, final ExecutionContext exec) throws Exception {
    boolean hasSameRowsInEachIteration = m_configuration.hasSameRowsInEachIteration();
    LoopStartNode startNode = getLoopStartNode();
    if (!(startNode instanceof LoopStartNodeTerminator)) {
        throw new IllegalStateException("Loop end is not connected" + " to matching/corresponding loop start node. You" + " are trying to create an infinite loop!");
    }
    boolean continueLoop = !((LoopStartNodeTerminator) startNode).terminateLoop();
    if (m_currentAppendTable == null) {
        m_currentAppendTable = copy(inData[0], false, exec);
    } else if (hasSameRowsInEachIteration) {
        boolean isCacheNew = m_iteration % 50 == 0;
        double amount = isCacheNew ? (1.0 / 3.0) : (1.0 / 2.0);
        ExecutionContext copyCtx = exec.createSubExecutionContext(amount);
        ExecutionContext joinCtx = exec.createSubExecutionContext(amount);
        exec.setProgress("Copying input");
        BufferedDataTable t = copy(inData[0], true, copyCtx);
        copyCtx.setProgress(1.0);
        exec.setProgress("Joining with previous input");
        m_currentAppendTable = exec.createJoinedTable(m_currentAppendTable, t, joinCtx);
        joinCtx.setProgress(1.0);
        if (isCacheNew) {
            exec.setProgress("Caching intermediate results (iteration " + m_iteration + ")");
            ExecutionContext ctx = exec.createSubExecutionContext(amount);
            // copy the whole table every 50 columns (avoids wrapping to much individual tables)
            // In this case the whole table is copied and column names DON'T need to be made unique (bugfix 6544)
            m_currentAppendTable = copy(m_currentAppendTable, m_appendIterSuffixForBackwardComp, ctx);
            ctx.setProgress(1.0);
        }
    } else {
        Joiner2Settings settings = new Joiner2Settings();
        settings.setCompositionMode(CompositionMode.MatchAll);
        settings.setDuplicateColumnSuffix(" (Iter #" + m_iteration + ")");
        settings.setDuplicateHandling(DuplicateHandling.AppendSuffix);
        settings.setEnableHiLite(false);
        // joining on RowIDs, this should not generate new row IDs but
        // only fill missing rows in either table
        settings.setJoinMode(JoinMode.FullOuterJoin);
        settings.setLeftIncludeAll(true);
        settings.setRightIncludeAll(true);
        // TODO to be replaced by Joiner2Settings.ROW_KEY_IDENTIFIER
        // once that is public
        settings.setLeftJoinColumns(new String[] { "$RowID$" });
        settings.setRightJoinColumns(new String[] { "$RowID$" });
        BufferedDataTable left = m_currentAppendTable;
        BufferedDataTable right = copy(inData[0], true, exec.createSubExecutionContext(0.1));
        Joiner joiner = new Joiner(left.getDataTableSpec(), right.getDataTableSpec(), settings);
        m_currentAppendTable = joiner.computeJoinTable(left, right, exec.createSubExecutionContext(0.9));
    }
    m_iteration += 1;
    if (continueLoop) {
        super.continueLoop();
        return null;
    } else {
        return new BufferedDataTable[] { m_currentAppendTable };
    }
}
Also used : ExecutionContext(org.knime.core.node.ExecutionContext) Joiner(org.knime.base.node.preproc.joiner.Joiner) BufferedDataTable(org.knime.core.node.BufferedDataTable) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator) LoopStartNode(org.knime.core.node.workflow.LoopStartNode) Joiner2Settings(org.knime.base.node.preproc.joiner.Joiner2Settings)

Example 2 with LoopStartNodeTerminator

use of org.knime.core.node.workflow.LoopStartNodeTerminator in project knime-core by knime.

the class LoopEnd2NodeModel method execute.

/**
 * {@inheritDoc}
 */
@Override
protected BufferedDataTable[] execute(final BufferedDataTable[] inData, final ExecutionContext exec) throws Exception {
    if (!(this.getLoopStartNode() instanceof LoopStartNodeTerminator)) {
        throw new IllegalStateException("Loop end is not connected" + " to matching/corresponding loop start node. You" + "are trying to create an infinite loop!");
    }
    if (m_tableFactories[0] == null) {
        // first iteration -> create table factories
        Optional<Function<RowKey, RowKey>> rowKeyFunc1;
        Optional<Function<RowKey, RowKey>> rowKeyFunc2;
        switch(m_settings.rowKeyPolicy()) {
            case APPEND_SUFFIX:
                rowKeyFunc1 = Optional.of(k -> {
                    return new RowKey(k.toString() + "#" + (m_iteration));
                });
                rowKeyFunc2 = Optional.of(k -> {
                    return new RowKey(k.toString() + "#" + (m_iteration));
                });
                break;
            case GENERATE_NEW:
                rowKeyFunc1 = Optional.of(k -> {
                    return new RowKey("Row" + (m_count1++));
                });
                rowKeyFunc2 = Optional.of(k -> {
                    return new RowKey("Row" + (m_count2++));
                });
                break;
            case UNMODIFIED:
            default:
                rowKeyFunc1 = Optional.empty();
                rowKeyFunc2 = Optional.empty();
        }
        m_tableFactories[0] = new ConcatenateTableFactory(m_settings.ignoreEmptyTables1(), m_settings.tolerateColumnTypes1(), m_settings.addIterationColumn(), m_settings.tolerateChangingTableSpecs1(), rowKeyFunc1);
        m_tableFactories[1] = new ConcatenateTableFactory(m_settings.ignoreEmptyTables2(), m_settings.tolerateColumnTypes2(), m_settings.addIterationColumn(), m_settings.tolerateChangingTableSpecs2(), rowKeyFunc2);
    }
    // add tables to factories
    m_tableFactories[0].addTable(inData[0], exec);
    m_tableFactories[1].addTable(inData[1], exec);
    final boolean terminateLoop = ((LoopStartNodeTerminator) this.getLoopStartNode()).terminateLoop();
    if (terminateLoop) {
        m_iteration = 0;
        m_count1 = 0;
        m_count2 = 0;
        BufferedDataTable[] outTables = new BufferedDataTable[2];
        outTables[0] = m_tableFactories[0].createTable(exec);
        outTables[1] = m_tableFactories[1].createTable(exec);
        return outTables;
    } else {
        continueLoop();
        m_iteration++;
        return new BufferedDataTable[2];
    }
}
Also used : ExecutionMonitor(org.knime.core.node.ExecutionMonitor) Arrays(java.util.Arrays) NodeSettingsRO(org.knime.core.node.NodeSettingsRO) RowKey(org.knime.core.data.RowKey) DataTableSpec(org.knime.core.data.DataTableSpec) InvalidSettingsException(org.knime.core.node.InvalidSettingsException) CanceledExecutionException(org.knime.core.node.CanceledExecutionException) LoopEndNode(org.knime.core.node.workflow.LoopEndNode) IOException(java.io.IOException) NodeModel(org.knime.core.node.NodeModel) Function(java.util.function.Function) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator) File(java.io.File) NodeSettingsWO(org.knime.core.node.NodeSettingsWO) ExecutionContext(org.knime.core.node.ExecutionContext) BufferedDataTable(org.knime.core.node.BufferedDataTable) Optional(java.util.Optional) Function(java.util.function.Function) RowKey(org.knime.core.data.RowKey) BufferedDataTable(org.knime.core.node.BufferedDataTable) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator)

Example 3 with LoopStartNodeTerminator

use of org.knime.core.node.workflow.LoopStartNodeTerminator in project knime-core by knime.

the class LoopEndConditionNodeModel method execute.

/**
 * {@inheritDoc}
 */
@Override
protected BufferedDataTable[] execute(final BufferedDataTable[] inData, final ExecutionContext exec) throws Exception {
    int count = peekFlowVariableInt("currentIteration");
    exec.setMessage("Iteration " + count);
    DataTableSpec spec1 = createSpec1(inData[0].getDataTableSpec());
    if (m_collectContainer == null) {
        assert m_variableContainer == null;
        m_startTime = System.currentTimeMillis();
        // first time we are getting to this: open container
        m_collectContainer = exec.createDataContainer(spec1);
        m_variableContainer = exec.createDataContainer(createSpec2());
    } else if (!spec1.equalStructure(m_collectContainer.getTableSpec())) {
        DataTableSpec predSpec = m_collectContainer.getTableSpec();
        StringBuilder error = new StringBuilder("Input table's structure differs from reference " + "(first iteration) table: ");
        if (spec1.getNumColumns() != predSpec.getNumColumns()) {
            error.append("different column counts ");
            error.append(spec1.getNumColumns());
            error.append(" vs. ").append(predSpec.getNumColumns());
        } else {
            for (int i = 0; i < spec1.getNumColumns(); i++) {
                DataColumnSpec inCol = spec1.getColumnSpec(i);
                DataColumnSpec predCol = predSpec.getColumnSpec(i);
                if (!inCol.equalStructure(predCol)) {
                    error.append("Column ").append(i).append(" [");
                    error.append(inCol).append("] vs. [");
                    error.append(predCol).append("]");
                }
            }
        }
        throw new IllegalArgumentException(error.toString());
    }
    RowKey rk = new RowKey("Iteration " + count);
    if (m_settings.variableType() == Type.DOUBLE) {
        m_variableContainer.addRowToTable(new DefaultRow(rk, new DoubleCell(peekFlowVariableDouble(m_settings.variableName()))));
    } else if (m_settings.variableType() == Type.INTEGER) {
        m_variableContainer.addRowToTable(new DefaultRow(rk, new IntCell(peekFlowVariableInt(m_settings.variableName()))));
    } else {
        m_variableContainer.addRowToTable(new DefaultRow(rk, new StringCell(peekFlowVariableString(m_settings.variableName()))));
    }
    LoopStartNode lsn = getLoopStartNode();
    boolean stop = checkCondition() || ((lsn instanceof LoopStartNodeTerminator) && ((LoopStartNodeTerminator) lsn).terminateLoop());
    if ((m_settings.addLastRows() && !m_settings.addLastRowsOnly()) || ((stop == m_settings.addLastRows()) && (stop == m_settings.addLastRowsOnly()))) {
        exec.setMessage("Collecting rows from current iteration");
        int k = 0;
        final double max = inData[0].size();
        IntCell currIterCell = new IntCell(count);
        for (DataRow row : inData[0]) {
            exec.checkCanceled();
            if (k++ % 10 == 0) {
                exec.setProgress(k / max);
            }
            DataRow newRow = new DefaultRow(new RowKey(row.getKey() + "#" + count), row);
            if (m_settings.addIterationColumn()) {
                newRow = new AppendedColumnRow(newRow, currIterCell);
            }
            m_collectContainer.addRowToTable(newRow);
        }
    }
    if (stop) {
        m_collectContainer.close();
        m_variableContainer.close();
        BufferedDataTable out1 = m_collectContainer.getTable();
        BufferedDataTable out2 = m_variableContainer.getTable();
        LOGGER.debug("Total loop execution time: " + (System.currentTimeMillis() - m_startTime) + "ms");
        m_startTime = 0;
        return new BufferedDataTable[] { out1, out2 };
    } else {
        continueLoop();
        return new BufferedDataTable[2];
    }
}
Also used : DataTableSpec(org.knime.core.data.DataTableSpec) RowKey(org.knime.core.data.RowKey) DoubleCell(org.knime.core.data.def.DoubleCell) DataRow(org.knime.core.data.DataRow) IntCell(org.knime.core.data.def.IntCell) DataColumnSpec(org.knime.core.data.DataColumnSpec) StringCell(org.knime.core.data.def.StringCell) BufferedDataTable(org.knime.core.node.BufferedDataTable) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator) DefaultRow(org.knime.core.data.def.DefaultRow) LoopStartNode(org.knime.core.node.workflow.LoopStartNode) AppendedColumnRow(org.knime.base.data.append.column.AppendedColumnRow)

Example 4 with LoopStartNodeTerminator

use of org.knime.core.node.workflow.LoopStartNodeTerminator in project knime-core by knime.

the class LoopEndNodeModel method execute.

/**
 * {@inheritDoc}
 */
@Override
protected BufferedDataTable[] execute(final BufferedDataTable[] inData, final ExecutionContext exec) throws Exception {
    if (!(this.getLoopStartNode() instanceof LoopStartNodeTerminator)) {
        throw new IllegalStateException("Loop End is not connected" + " to matching/corresponding Loop Start node. You" + " are trying to create an infinite loop!");
    }
    if (m_tableFactory == null) {
        // first time we get here: create table factory
        Optional<Function<RowKey, RowKey>> rowKeyFunc;
        switch(m_settings.rowKeyPolicy()) {
            case APPEND_SUFFIX:
                rowKeyFunc = Optional.of(k -> {
                    return new RowKey(k.toString() + "#" + (m_iteration));
                });
                break;
            case GENERATE_NEW:
                rowKeyFunc = Optional.of(k -> {
                    return new RowKey("Row" + (m_count++));
                });
                break;
            case UNMODIFIED:
            default:
                rowKeyFunc = Optional.empty();
        }
        m_tableFactory = new ConcatenateTableFactory(m_settings.ignoreEmptyTables(), m_settings.tolerateColumnTypes(), m_settings.addIterationColumn(), m_settings.tolerateChangingTableSpecs(), rowKeyFunc);
        m_startTime = System.currentTimeMillis();
    }
    m_tableFactory.addTable(inData[0], exec);
    boolean terminateLoop = ((LoopStartNodeTerminator) this.getLoopStartNode()).terminateLoop();
    if (terminateLoop) {
        LOGGER.debug("Total loop execution time: " + (System.currentTimeMillis() - m_startTime) + "ms");
        m_startTime = 0;
        m_iteration = 0;
        m_count = 0;
        return new BufferedDataTable[] { m_tableFactory.createTable(exec) };
    } else {
        m_iteration++;
        continueLoop();
        return new BufferedDataTable[1];
    }
}
Also used : ExecutionMonitor(org.knime.core.node.ExecutionMonitor) NodeSettingsRO(org.knime.core.node.NodeSettingsRO) RowKey(org.knime.core.data.RowKey) DataTableSpec(org.knime.core.data.DataTableSpec) InvalidSettingsException(org.knime.core.node.InvalidSettingsException) CanceledExecutionException(org.knime.core.node.CanceledExecutionException) LoopEndNode(org.knime.core.node.workflow.LoopEndNode) IOException(java.io.IOException) NodeModel(org.knime.core.node.NodeModel) Function(java.util.function.Function) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator) File(java.io.File) NodeSettingsWO(org.knime.core.node.NodeSettingsWO) ExecutionContext(org.knime.core.node.ExecutionContext) BufferedDataTable(org.knime.core.node.BufferedDataTable) NodeLogger(org.knime.core.node.NodeLogger) Optional(java.util.Optional) Function(java.util.function.Function) RowKey(org.knime.core.data.RowKey) BufferedDataTable(org.knime.core.node.BufferedDataTable) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator)

Example 5 with LoopStartNodeTerminator

use of org.knime.core.node.workflow.LoopStartNodeTerminator in project knime-core by knime.

the class VariableLoopEndNodeModel method execute.

/**
 * {@inheritDoc}
 */
@Override
protected PortObject[] execute(final PortObject[] inObjects, final ExecutionContext exec) throws Exception {
    // check for loop start node.
    if (!(this.getLoopStartNode() instanceof LoopStartNodeTerminator)) {
        throw new IllegalStateException("Loop End is not connected" + " to matching/corresponding Loop Start node. You" + " are trying to create an infinite loop!");
    }
    DataTableSpec amendedSpec = createDataTableSpec();
    if (m_resultContainer == null) {
        // first time we are getting to this: open container
        m_startTime = System.currentTimeMillis();
        m_resultContainer = exec.createDataContainer(amendedSpec);
    // if initially created data table spec and current spec differ, fail
    } else if (!amendedSpec.equalStructure(m_resultContainer.getTableSpec())) {
        DataTableSpec predSpec = m_resultContainer.getTableSpec();
        StringBuilder error = new StringBuilder("Output table's structure differs from reference " + "(first iteration) table: ");
        if (amendedSpec.getNumColumns() != predSpec.getNumColumns()) {
            error.append("different column counts ");
            error.append(amendedSpec.getNumColumns());
            error.append(" vs. ").append(predSpec.getNumColumns());
        } else {
            for (int i = 0; i < amendedSpec.getNumColumns(); i++) {
                DataColumnSpec inCol = amendedSpec.getColumnSpec(i);
                DataColumnSpec predCol = predSpec.getColumnSpec(i);
                if (!inCol.equalStructure(predCol)) {
                    error.append("Column ").append(i).append(" [");
                    error.append(inCol).append("] vs. [");
                    error.append(predCol).append("]");
                }
            }
        }
        error.append(". Have the input variables changed in number, name or type?");
        throw new IllegalArgumentException(error.toString());
    }
    // after all data table checks we are fine now and can add a single row
    // containing the values of the flow variables
    m_resultContainer.addRowToTable(createNewRow());
    boolean terminateLoop = ((LoopStartNodeTerminator) this.getLoopStartNode()).terminateLoop();
    if (terminateLoop) {
        // this was the last iteration - close container and continue
        m_resultContainer.close();
        BufferedDataTable outTable = m_resultContainer.getTable();
        m_resultContainer.close();
        m_resultContainer = null;
        m_count = 0;
        LOGGER.debug("Total loop execution time: " + (System.currentTimeMillis() - m_startTime) + "ms");
        m_startTime = 0;
        return new BufferedDataTable[] { outTable };
    } else {
        continueLoop();
        m_count++;
        return new BufferedDataTable[1];
    }
}
Also used : DataTableSpec(org.knime.core.data.DataTableSpec) DataColumnSpec(org.knime.core.data.DataColumnSpec) BufferedDataTable(org.knime.core.node.BufferedDataTable) LoopStartNodeTerminator(org.knime.core.node.workflow.LoopStartNodeTerminator)

Aggregations

BufferedDataTable (org.knime.core.node.BufferedDataTable)5 LoopStartNodeTerminator (org.knime.core.node.workflow.LoopStartNodeTerminator)5 DataTableSpec (org.knime.core.data.DataTableSpec)4 RowKey (org.knime.core.data.RowKey)3 ExecutionContext (org.knime.core.node.ExecutionContext)3 File (java.io.File)2 IOException (java.io.IOException)2 Optional (java.util.Optional)2 Function (java.util.function.Function)2 DataColumnSpec (org.knime.core.data.DataColumnSpec)2 CanceledExecutionException (org.knime.core.node.CanceledExecutionException)2 ExecutionMonitor (org.knime.core.node.ExecutionMonitor)2 InvalidSettingsException (org.knime.core.node.InvalidSettingsException)2 NodeModel (org.knime.core.node.NodeModel)2 NodeSettingsRO (org.knime.core.node.NodeSettingsRO)2 NodeSettingsWO (org.knime.core.node.NodeSettingsWO)2 LoopEndNode (org.knime.core.node.workflow.LoopEndNode)2 LoopStartNode (org.knime.core.node.workflow.LoopStartNode)2 Arrays (java.util.Arrays)1 AppendedColumnRow (org.knime.base.data.append.column.AppendedColumnRow)1