package org.knime.knip.io.nodes.imgreader2.readfrominput;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.InvalidPathException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.knime.core.data.DataCell;
import org.knime.core.data.DataRow;
import org.knime.core.data.RowKey;
import org.knime.core.data.StringValue;
import org.knime.core.data.def.DefaultRow;
import org.knime.core.node.ExecutionContext;
import org.knime.core.util.FileUtil;
import org.knime.core.util.Pair;
import org.knime.knip.base.node.nodesettings.SettingsModelSubsetSelection2;
import org.knime.knip.io.nodes.imgreader2.AbstractReadImgFunction;
import org.knime.knip.io.nodes.imgreader2.ColumnCreationMode;
import org.knime.knip.io.nodes.imgreader2.URLUtil;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
/**
* {@link Function} to read an {@link Img}, OME-XML Metadata or both from a file
* path.
*
* @author <a href="mailto:danielseebacher@t-online.de">Daniel Seebacher,
* University of Konstanz.</a>
*/
class ReadImgTableFunction<T extends RealType<T> & NativeType<T>> extends AbstractReadImgFunction<T, DataRow> {
private ColumnCreationMode m_columnCreationMode;
private int m_stringIndex;
public ReadImgTableFunction(ExecutionContext exec, int numberOfFiles, SettingsModelSubsetSelection2 sel,
boolean readImage, boolean readMetadata, boolean readAllMetaData, boolean checkFileFormat,
boolean isGroupFiles, int seriesSelectionFrom, int seriesSelectionTo, ImgFactory<T> imgFactory,
ColumnCreationMode columnCreationMode, int stringIndex, final String pixelType) {
super(exec, numberOfFiles, sel, readImage, readMetadata, readAllMetaData, checkFileFormat, false, isGroupFiles,
seriesSelectionFrom, seriesSelectionTo, imgFactory, pixelType);
m_columnCreationMode = columnCreationMode;
m_stringIndex = stringIndex;
}
@Override
public Stream<Pair<DataRow, Optional<Throwable>>> apply(DataRow input) {
List<Pair<DataRow, Optional<Throwable>>> tempResults = new ArrayList<>();
if (input.getCell(m_stringIndex).isMissing()) {
m_exec.setProgress(Double.valueOf(m_currentFile.incrementAndGet()) / m_numberOfFiles);
return Arrays.asList(createResultFromException("no path specified", input.getKey().getString(),
new IllegalArgumentException("Input was missing"))).stream();
}
String t = ((StringValue) input.getCell(m_stringIndex)).getStringValue();
String path;
int numSeries;
try {
URI uri = URLUtil.encode(t);
URL url = uri.toURL();
// check if its an internet address;
if (url.getProtocol().equalsIgnoreCase("HTTP") || url.getProtocol().equalsIgnoreCase("FTP")
|| url.getProtocol().equalsIgnoreCase("HTTPS")) {
path = url.toURI().toString();
} else {
path = FileUtil.resolveToPath(url).toString();
}
numSeries = m_imgSource.getSeriesCount(path);
} catch (InvalidPathException | IOException | URISyntaxException exc) {
m_exec.setProgress(Double.valueOf(m_currentFile.incrementAndGet()) / m_numberOfFiles);
return Arrays.asList(createResultFromException(t, input.getKey().getString(), exc)).stream();
} catch (Exception exc) {
m_exec.setProgress(Double.valueOf(m_currentFile.incrementAndGet()) / m_numberOfFiles);
return Arrays.asList(createResultFromException(t, input.getKey().getString(), exc)).stream();
}
int seriesStart = m_selectedSeriesFrom == -1 ? 0 : m_selectedSeriesFrom;
int seriesEnd = m_selectedSeriesTo == -1 ? numSeries : Math.min(m_selectedSeriesTo + 1, numSeries);
// load image and metadata for each series index
IntStream.range(seriesStart, seriesEnd).forEachOrdered(currentSeries -> {
RowKey rowKey = input.getKey();
if (currentSeries > 0) {
rowKey = new RowKey(rowKey.getString() + "_" + currentSeries);
}
tempResults.add(readImageAndMetadata(path, rowKey, currentSeries));
});
m_exec.setProgress(Double.valueOf(m_currentFile.incrementAndGet()) / m_numberOfFiles);
return createOutput(input, tempResults, m_columnCreationMode, m_stringIndex);
}
/**
* Takes the input {@link DataRow}, the read images and metadata and creates
* the output result row.
*
* @param inputRow
* the input {@link DataRow}
* @param readFiles
* the {@link List} of read {@link Img}s, with {@link Optional}
* {@link Exception}s.
* @param columnSelectionMode
* the column selection mode see
* {@link ImgReaderTableNodeModel#COL_CREATION_MODES}
* @param inputColumnIndex
* the column index of the path.
* @return a {@link Stream} with the output {@link DataRow}s.
*/
private Stream<Pair<DataRow, Optional<Throwable>>> createOutput(DataRow inputRow,
List<Pair<DataRow, Optional<Throwable>>> readFiles, ColumnCreationMode columnCreationMode,
int inputColumnIndex) {
List<Pair<DataRow, Optional<Throwable>>> outputResults = new ArrayList<>();
if (columnCreationMode == ColumnCreationMode.NEW_TABLE) {
return readFiles.stream();
} else if (columnCreationMode == ColumnCreationMode.APPEND) {
for (Pair<DataRow, Optional<Throwable>> result : readFiles) {
List<DataCell> cells = new ArrayList<>();
for (int i = 0; i < inputRow.getNumCells(); i++) {
cells.add(inputRow.getCell(i));
}
for (int i = 0; i < result.getFirst().getNumCells(); i++) {
cells.add(result.getFirst().getCell(i));
}
outputResults.add(new Pair<>(
new DefaultRow(result.getFirst().getKey(), cells.toArray(new DataCell[cells.size()])),
result.getSecond()));
}
} else if (columnCreationMode == ColumnCreationMode.REPLACE) {
for (Pair<DataRow, Optional<Throwable>> result : readFiles) {
List<DataCell> cells = new ArrayList<>();
for (int i = 0; i < inputRow.getNumCells(); i++) {
cells.add(inputRow.getCell(i));
}
cells.set(m_stringIndex, result.getFirst().getCell(0));
if (result.getFirst().getNumCells() > 1) {
cells.add(m_stringIndex + 1, result.getFirst().getCell(1));
}
outputResults.add(new Pair<>(
new DefaultRow(result.getFirst().getKey(), cells.toArray(new DataCell[cells.size()])),
result.getSecond()));
}
} else {
throw new IllegalStateException(
"Support for the columncreation mode" + columnCreationMode.toString() + " is not implemented!");
}
return outputResults.stream();
}
}