Skip to content

Commit eefffdd

Browse files
authored
Merge pull request #8 from clemensvonschwerin/enh/AP-7241-improved-python-integration
Support for new python2 extension points added
2 parents 92435ae + 82bb897 commit eefffdd

File tree

9 files changed

+402
-174
lines changed

9 files changed

+402
-174
lines changed

org.knime.knip.knimepython/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ Require-Bundle: org.knime.base;bundle-version="2.11.0",
2020
scijava-common;bundle-version="2.37.0",
2121
imagej-common;bundle-version="0.12.1",
2222
scifio-bf-compat;bundle-version="1.11.0",
23-
org.knime.python.nodes;bundle-version="3.0.0"
23+
org.knime.python.nodes;bundle-version="3.0.0",
24+
org.knime.python2;bundle-version="3.4.0"
2425
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
2526
Bundle-ClassPath: .
2627
Export-Package: org.knime.knip.knimepython

org.knime.knip.knimepython/plugin.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,21 @@
3030
path="templates/">
3131
</folder>
3232
</extension>
33+
<extension
34+
point="org.knime.python2.typeextension.knimetopython">
35+
<type
36+
id="org.knime.knip.knimepython.ImgPlus"
37+
java-serializer-factory="org.knime.knip.knimepython2.ImgPlusSerializerFactory"
38+
python-deserializer="py/KNIPImageDeserializer.py">
39+
</type>
40+
</extension>
41+
<extension
42+
point="org.knime.python2.typeextension.pythontoknime">
43+
<type
44+
id="org.knime.knip.knimepython.type2"
45+
java-deserializer-factory="org.knime.knip.knimepython2.ImgPlusDeserializerFactory"
46+
python-serializer="py/KNIPImageSerializer.py"
47+
python-type-identifier="KNIPImage.KNIPImage">
48+
</type>
49+
</extension>
3350
</plugin>

org.knime.knip.knimepython/py/KNIPImage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
class KNIPImage:
33
# data is ndarray
44
def __init__(self, array):
5-
self.array = array
5+
self.array = array
66

org.knime.knip.knimepython/src/org/knime/knip/knimepython/ImgPlusDeserializer.java

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.knime.knip.base.data.img.ImgPlusCell;
88
import org.knime.knip.base.data.img.ImgPlusCellFactory;
99
import org.knime.knip.io.ScifioGateway;
10+
import org.knime.knip.serialization.BytesToImgPlusConvertor;
1011
import org.knime.python.typeextension.Deserializer;
1112
import org.knime.python.typeextension.DeserializerFactory;
1213

@@ -21,78 +22,29 @@
2122
import net.imagej.ImgPlus;
2223

2324
/**
24-
* Deserializing ImgPlus instances from byte stream. Used format is .tif.
25+
* Deserializer using the extension points in org.knime.python.
2526
*
26-
* TODO: Use a Scijava Service in the background such that one could replace the
27-
* way images are serialized/deserialized
28-
*
29-
* @author Christian Dietz (University of Konstanz)
27+
* @author Clemens von Schwerin, KNIME.com, Konstanz, Germany
3028
*/
3129
public class ImgPlusDeserializer extends DeserializerFactory {
3230

33-
/**
34-
* ImgOpener to read ImgPlus from stream
35-
*/
36-
private ImgOpener m_imgOpener;
37-
private SCIFIOConfig m_scifioConfig;
31+
private BytesToImgPlusConvertor m_convertor;
3832

3933
public ImgPlusDeserializer() {
4034
super(ImgPlusCell.TYPE);
41-
m_imgOpener = new ImgOpener(ScifioGateway.getSCIFIO().context());
42-
m_scifioConfig = new SCIFIOConfig();
43-
m_scifioConfig.groupableSetGroupFiles(false);
44-
m_scifioConfig.imgOpenerSetComputeMinMax(false);
35+
m_convertor = new BytesToImgPlusConvertor();
4536
}
4637

4738
@Override
4839
public Deserializer createDeserializer() {
4940

5041
return new Deserializer() {
5142

52-
private final Format m_format;
53-
private final Parser m_parser;
54-
55-
{
56-
try {
57-
m_format = ScifioGateway.getSCIFIO().format().getFormat(".tif");
58-
m_parser = m_format.createParser();
59-
} catch (FormatException e) {
60-
throw new RuntimeException(e);
61-
}
62-
}
63-
64-
@SuppressWarnings({ "rawtypes", "unchecked" })
6543
@Override
6644
public DataCell deserialize(final byte[] bytes, final FileStoreFactory fileStoreFactory)
6745
throws IOException {
6846

69-
final ImgPlusCellFactory factory = new ImgPlusCellFactory(fileStoreFactory);
70-
71-
// TODO this hack should be removed in the future, as soon as
72-
// filename bug is resolved
73-
// We have to set the filename as a NPE would be thrown
74-
// otherwise
75-
final RandomAccessInputStream stream = new RandomAccessInputStream(
76-
ScifioGateway.getSCIFIO().getContext(), bytes) {
77-
@Override
78-
public String getFileName() {
79-
return "";
80-
}
81-
};
82-
83-
try {
84-
85-
final Metadata metadata = m_parser.parse(stream, m_scifioConfig);
86-
metadata.setSource(stream);
87-
88-
final Reader reader = m_format.createReader();
89-
reader.setMetadata(metadata);
90-
reader.setSource(stream, m_scifioConfig);
91-
92-
return factory.createCell((ImgPlus) m_imgOpener.openImgs(reader, m_scifioConfig).get(0));
93-
} catch (final Exception e) {
94-
throw new RuntimeException(e);
95-
}
47+
return m_convertor.deserialize(bytes, fileStoreFactory);
9648
}
9749
};
9850
}

org.knime.knip.knimepython/src/org/knime/knip/knimepython/ImgPlusSerializer.java

Lines changed: 6 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import org.knime.knip.base.data.img.ImgPlusValue;
99
import org.knime.knip.io.ScifioGateway;
10+
import org.knime.knip.serialization.ImgPlusToBytesConvertor;
1011
import org.knime.python.typeextension.Serializer;
1112
import org.knime.python.typeextension.SerializerFactory;
1213

@@ -28,144 +29,31 @@
2829
import net.imagej.axis.CalibratedAxis;
2930

3031
/**
31-
* Serializing ImgPlus instances to byte stream. Used format is .tif.
32-
*
33-
* TODO: Use a Scijava Service in the background such that one could replace the
34-
* way images are serialized/deserialized
32+
* Serializer using the extension points in org.knime.python.
3533
*
36-
* @author Christian Dietz (University of Konstanz)
37-
*
34+
* @author Clemens von Schwerin, KNIME.com, Konstanz, Germany
3835
*/
3936
@SuppressWarnings("rawtypes")
4037
public class ImgPlusSerializer extends SerializerFactory<ImgPlusValue> {
4138

42-
/**
43-
* ImgSaver to write ImgPlus to stream as tif
44-
*/
45-
private ImgSaver m_saver;
46-
47-
/**
48-
* SCIFIO config to read/write images
49-
*/
50-
private SCIFIOConfig m_scifioConfig;
51-
39+
private final ImgPlusToBytesConvertor m_convertor;
5240
/**
5341
* Constructor
5442
*/
5543
public ImgPlusSerializer() {
5644
super(ImgPlusValue.class);
57-
m_saver = new ImgSaver(ScifioGateway.getSCIFIO().getContext());
58-
m_scifioConfig = new SCIFIOConfig();
59-
m_scifioConfig.groupableSetGroupFiles(false);
60-
m_scifioConfig.imgOpenerSetComputeMinMax(false);
45+
m_convertor = new ImgPlusToBytesConvertor();
6146
}
6247

6348
@Override
6449
public Serializer<? extends ImgPlusValue<?>> createSerializer() {
6550

6651
return new Serializer<ImgPlusValue<?>>() {
6752

68-
private final Writer m_writer;
69-
70-
{
71-
try {
72-
m_writer = ScifioGateway.format().getWriterByExtension(".tif");
73-
} catch (FormatException e) {
74-
throw new RuntimeException(e);
75-
}
76-
}
77-
7853
@Override
7954
public byte[] serialize(final ImgPlusValue<?> value) throws IOException {
80-
final ImgPlus<?> imgPlus = TypeUtils.converted(value.getImgPlus());
81-
82-
try {
83-
final ByteArrayHandle handle = new ByteArrayHandle();
84-
populateMeta(m_writer, imgPlus, m_scifioConfig, 0);
85-
// HACK Corresponds to filename
86-
m_writer.getMetadata().setDatasetName("");
87-
m_writer.setDest(new RandomAccessOutputStream(handle), 0);
88-
89-
m_saver.saveImg(m_writer, imgPlus.getImg(), m_scifioConfig);
90-
91-
m_writer.close();
92-
93-
return handle.getBytes();
94-
} catch (Exception e) {
95-
e.printStackTrace();
96-
throw new RuntimeException(
97-
"Could not serialize image. Possible reasons: Unsupported image type, dimensionality of the image,...");
98-
}
55+
return m_convertor.serialize(value);
9956
}
10057
};
10158
}
102-
103-
/**
104-
* This method is copied from SCIFIO
105-
*
106-
* FIXME/TODO: Remove when method available in SCIFIO (see
107-
* https://github.com/scifio/scifio/issues/233)
108-
*
109-
* Uses the provided {@link SCIFIOImgPlus} to populate the minimum metadata
110-
* fields necessary for writing.
111-
*
112-
* @param imageIndex
113-
*/
114-
private void populateMeta(final Writer w, final ImgPlus<?> img, final SCIFIOConfig config, final int imageIndex)
115-
throws FormatException, IOException, ImgIOException {
116-
117-
final Metadata meta = w.getFormat().createMetadata();
118-
119-
// Get format-specific metadata
120-
Metadata imgMeta = ScifioGateway.getSCIFIO().imgUtil().makeSCIFIOImgPlus(img).getMetadata();
121-
122-
final List<ImageMetadata> imageMeta = new ArrayList<ImageMetadata>();
123-
124-
if (imgMeta == null) {
125-
imgMeta = new DefaultMetadata();
126-
imgMeta.createImageMetadata(1);
127-
imageMeta.add(imgMeta.get(0));
128-
} else {
129-
for (int i = 0; i < imgMeta.getImageCount(); i++) {
130-
imageMeta.add(new DefaultImageMetadata());
131-
}
132-
}
133-
134-
// Create Img-specific ImageMetadatas
135-
final int pixelType = ScifioGateway.getSCIFIO().imgUtil().makeType(img.firstElement());
136-
137-
// TODO is there some way to consolidate this with the isCompressible
138-
// method?
139-
final CalibratedAxis[] axes = new CalibratedAxis[img.numDimensions()];
140-
img.axes(axes);
141-
142-
final long[] axisLengths = new long[img.numDimensions()];
143-
img.dimensions(axisLengths);
144-
145-
for (int i = 0; i < imageMeta.size(); i++) {
146-
final ImageMetadata iMeta = imageMeta.get(i);
147-
iMeta.populate(img.getName(), Arrays.asList(axes), axisLengths, pixelType, true, false, false, false, true);
148-
149-
// Adjust for RGB information
150-
if (img.getCompositeChannelCount() > 1) {
151-
if (config.imgSaverGetWriteRGB()) {
152-
iMeta.setPlanarAxisCount(3);
153-
}
154-
iMeta.setAxisType(2, Axes.CHANNEL);
155-
// Split Axes.CHANNEL if necessary
156-
if (iMeta.getAxisLength(Axes.CHANNEL) > img.getCompositeChannelCount()) {
157-
iMeta.addAxis(Axes.get("Channel-planes", false),
158-
iMeta.getAxisLength(Axes.CHANNEL) / img.getCompositeChannelCount());
159-
iMeta.setAxisLength(Axes.CHANNEL, img.getCompositeChannelCount());
160-
}
161-
}
162-
}
163-
164-
// Translate to the output metadata
165-
final Translator t = ScifioGateway.getSCIFIO().translator().findTranslator(imgMeta, meta, false);
166-
167-
t.translate(imgMeta, imageMeta, meta);
168-
169-
w.setMetadata(meta);
170-
}
17159
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.knime.knip.knimepython2;
2+
3+
import java.io.IOException;
4+
5+
import org.knime.core.data.DataCell;
6+
import org.knime.core.data.filestore.FileStoreFactory;
7+
import org.knime.knip.base.data.img.ImgPlusCell;
8+
import org.knime.knip.base.data.img.ImgPlusCellFactory;
9+
import org.knime.knip.io.ScifioGateway;
10+
import org.knime.knip.serialization.BytesToImgPlusConvertor;
11+
import org.knime.python2.typeextension.Deserializer;
12+
import org.knime.python2.typeextension.DeserializerFactory;
13+
14+
import io.scif.Format;
15+
import io.scif.FormatException;
16+
import io.scif.Metadata;
17+
import io.scif.Parser;
18+
import io.scif.Reader;
19+
import io.scif.config.SCIFIOConfig;
20+
import io.scif.img.ImgOpener;
21+
import io.scif.io.RandomAccessInputStream;
22+
import net.imagej.ImgPlus;
23+
24+
/**
25+
* Deserializer using the extension points in org.knime.python2.
26+
*
27+
* @author Clemens von Schwerin, KNIME.com, Konstanz, Germany
28+
*/
29+
public class ImgPlusDeserializerFactory extends DeserializerFactory {
30+
31+
private BytesToImgPlusConvertor m_convertor;
32+
33+
public ImgPlusDeserializerFactory() {
34+
super(ImgPlusCell.TYPE);
35+
m_convertor = new BytesToImgPlusConvertor();
36+
}
37+
38+
@Override
39+
public Deserializer createDeserializer() {
40+
41+
return new Deserializer() {
42+
43+
@Override
44+
public DataCell deserialize(final byte[] bytes, final FileStoreFactory fileStoreFactory)
45+
throws IOException {
46+
47+
return m_convertor.deserialize(bytes, fileStoreFactory);
48+
}
49+
};
50+
}
51+
}
52+

0 commit comments

Comments
 (0)