package de.mpicbg.knime.scripting.r.generic; import de.mpicbg.knime.knutils.AbstractNodeModel; import de.mpicbg.knime.scripting.core.AbstractScriptingNodeModel; import de.mpicbg.knime.scripting.core.exceptions.KnimeScriptingException; import de.mpicbg.knime.scripting.r.AbstractRScriptingNodeModel; import de.mpicbg.knime.scripting.r.RUtils; import de.mpicbg.knime.scripting.r.node.snippet.RSnippetNodeModel; import org.knime.core.node.BufferedDataTable; import org.knime.core.node.ExecutionContext; import org.knime.core.node.InvalidSettingsException; import org.knime.core.node.port.PortObject; import org.knime.core.node.port.PortObjectSpec; import org.rosuda.REngine.REXP; import org.rosuda.REngine.Rserve.RConnection; import java.io.File; import java.util.Collections; /** * A generic R node which converts generic R objects (which are assumed to be data-frames) back into knime * BufferedDatatables. * * @author Holger Brandl * {@deprecated} */ public class ConvertToTable extends AbstractRScriptingNodeModel { private File rWorkspaceFile; public ConvertToTable() { // the input port is optional just to allow generative R nodes super(createPorts(1, RPortObject.TYPE, RPortObject.class), createPorts(1, BufferedDataTable.TYPE, BufferedDataTable.class)); } @Override protected PortObject[] execute(PortObject[] inObjects, ExecutionContext exec) throws Exception { m_con = RUtils.createConnection(); BufferedDataTable dataTable = null; try { // 1) restore the workspace in a different server session RUtils.loadGenericInputs(Collections.singletonMap(RSnippetNodeModel.R_INVAR_BASE_NAME, ((RPortObject)inObjects[0]).getFile()), m_con); // 2) Make sure that the R-object in the persistied workspace is of type data-frame boolean isDataFrame = Boolean.parseBoolean(m_con.eval("is.data.frame(" + RSnippetNodeModel.R_INVAR_BASE_NAME + ")").asString()); if (!isDataFrame) { logger.warn("The R object in the input is not a data-frame. Only data frames can be converted into Knime tables. Trying casting to data.frame..."); REXP xp = m_con.parseAndEval("try(" + RSnippetNodeModel.R_INVAR_BASE_NAME + " <- as.data.frame(" + RSnippetNodeModel.R_INVAR_BASE_NAME + " ))"); if (xp.inherits("try-error")) { throw new RuntimeException("Casting to data-frame failed. You need to change your script to return a data-structure that is a data-frame or can be coerced into one. "); } } //3) convert the data frame back into a knime table REXP rexp = m_con.eval(RSnippetNodeModel.R_INVAR_BASE_NAME); String[] rowNames = m_con.eval("rownames(" + RSnippetNodeModel.R_INVAR_BASE_NAME + ")").asStrings(); dataTable = RUtils.convert2DataTable(exec, rexp, null); m_con.voidEval("rm(list = ls(all = TRUE));"); } catch(Exception e) { closeRConnection(); throw e; } closeRConnection(); return new BufferedDataTable[]{dataTable}; } @Override // note: This is not the usual configure but a more generic one with PortObjectSpec instead of DataTableSpec protected PortObjectSpec[] configure(final PortObjectSpec[] inSpecs) throws InvalidSettingsException { return new PortObjectSpec[1]; } @Override protected BufferedDataTable[] execute(BufferedDataTable[] inData, ExecutionContext exec) throws Exception { throw new RuntimeException("fake implementation: This method should be never called"); } @Override protected PortObject[] executeImpl(PortObject[] inData, ExecutionContext exec) throws Exception { // TODO Auto-generated method stub return null; } @Override protected void openIn(PortObject[] inData, ExecutionContext exec) throws KnimeScriptingException { // TODO Auto-generated method stub } }