Skip to content

Instantly share code, notes, and snippets.

@HedgehogCode
Last active December 12, 2018 14:53
Show Gist options
  • Select an option

  • Save HedgehogCode/44fba21697954944f17e28c378315eee to your computer and use it in GitHub Desktop.

Select an option

Save HedgehogCode/44fba21697954944f17e28c378315eee to your computer and use it in GitHub Desktop.
package org.knime.image.labkit.base.nodes;
import gnu.trove.map.hash.TLongIntHashMap;
import net.imglib2.AbstractWrappedInterval;
import net.imglib2.Interval;
import net.imglib2.Localizable;
import net.imglib2.Point;
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.Sampler;
import net.imglib2.img.basictypeaccess.IntAccess;
import net.imglib2.type.numeric.integer.IntType;
import net.imglib2.util.IntervalIndexer;
public class DifferenceRandomAccessibleIntType extends AbstractWrappedInterval<RandomAccessibleInterval<IntType>>
implements RandomAccessibleInterval<IntType> {
private final TLongIntHashMap values;
public DifferenceRandomAccessibleIntType(final RandomAccessibleInterval<IntType> source) {
super(source);
values = new TLongIntHashMap();
}
public DifferenceRandomAccessibleIntType(final RandomAccessibleInterval<IntType> source,
final TLongIntHashMap difference) {
super(source);
values = difference;
}
@Override
public RandomAccess<IntType> randomAccess() {
return new DifferenceRandomAccess();
}
@Override
public RandomAccess<IntType> randomAccess(final Interval interval) {
return new DifferenceRandomAccess(interval);
}
private class DifferenceRandomAccess extends Point implements RandomAccess<IntType> {
private final IntType value = new IntType(new IntAccess() {
@Override
public int getValue(final int ignored) {
final long index = IntervalIndexer.positionToIndex(DifferenceRandomAccess.this, sourceInterval);
if (values.containsKey(index)) {
return values.get(index);
} else {
sourceRA.setPosition(DifferenceRandomAccess.this);
return sourceRA.get().get();
}
}
@Override
public void setValue(final int ignored, final int value) {
final long index = IntervalIndexer.positionToIndex(DifferenceRandomAccess.this, sourceInterval);
sourceRA.setPosition(DifferenceRandomAccess.this);
if (sourceRA.get().get() == value) {
values.remove(index);
} else {
values.put(index, value);
}
}
});
private final RandomAccess<IntType> sourceRA;
private DifferenceRandomAccess() {
super(sourceInterval.numDimensions());
sourceRA = sourceInterval.randomAccess();
}
private DifferenceRandomAccess(final Interval interval) {
super(sourceInterval.numDimensions());
sourceRA = sourceInterval.randomAccess(interval);
}
private DifferenceRandomAccess(final Localizable localizable) {
super(localizable);
sourceRA = sourceInterval.randomAccess();
}
@Override
public RandomAccess<IntType> copyRandomAccess() {
return new DifferenceRandomAccess(this);
}
@Override
public IntType get() {
return value;
}
@Override
public Sampler<IntType> copy() {
throw new UnsupportedOperationException();
}
}
}
/*
* ------------------------------------------------------------------------
*
* Copyright by KNIME AG, Zurich, Switzerland
* Website: http://www.knime.com; Email: contact@knime.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 3, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses>.
*
* Additional permission under GNU GPL version 3 section 7:
*
* KNIME interoperates with ECLIPSE solely via ECLIPSE's plug-in APIs.
* Hence, KNIME and ECLIPSE are both independent programs and are not
* derived from each other. Should, however, the interpretation of the
* GNU GPL Version 3 ("License") under any applicable laws result in
* KNIME and ECLIPSE being a combined program, KNIME AG herewith grants
* you the additional permission to use and propagate KNIME together with
* ECLIPSE with only the license terms in place for ECLIPSE applying to
* ECLIPSE and the GNU GPL Version 3 applying for KNIME, provided the
* license terms of ECLIPSE themselves allow for the respective use and
* propagation of ECLIPSE together with KNIME.
*
* Additional permission relating to nodes for KNIME that extend the Node
* Extension (and in particular that are based on subclasses of NodeModel,
* NodeDialog, and NodeView) and that only interoperate with KNIME through
* standard APIs ("Nodes"):
* Nodes are deemed to be separate and independent programs and to not be
* covered works. Notwithstanding anything to the contrary in the
* License, the License does not apply to Nodes, you are not required to
* license Nodes under the License, and you are granted a license to
* prepare and propagate Nodes, in each case even if such Nodes are
* propagated with or for interoperation with KNIME. The owner of a Node
* may freely choose the license terms applicable to such Node, including
* when such Node is propagated with or for interoperation with KNIME.
* ---------------------------------------------------------------------
*
* History
* Dec 10, 2018 (bw): created
*/
package org.knime.image.labkit.base.nodes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.xmlbeans.impl.util.Base64;
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.NodeSettingsRO;
import org.knime.core.node.NodeSettingsWO;
import org.knime.core.node.NotConfigurableException;
import org.knime.core.node.defaultnodesettings.SettingsModel;
import org.knime.core.node.port.PortObjectSpec;
import gnu.trove.map.hash.TLongIntHashMap;
/**
*
* @author bw
*/
public class SettingsModelAwesomeLabeling extends SettingsModel {
private final String m_configName;
// TODO change object to the type we want to save in the settings
private Map<RowColKey, Overlay> m_labelings;
SettingsModelAwesomeLabeling(final String configName) {
m_configName = configName;
m_labelings = new HashMap<>();
}
@Override
protected <T extends SettingsModel> T createClone() {
final SettingsModelAwesomeLabeling clone = new SettingsModelAwesomeLabeling(m_configName);
clone.m_labelings.putAll(m_labelings);
return (T)clone;
}
@Override
protected String getModelTypeID() {
return "SMID_labeling";
}
@Override
protected String getConfigName() {
return m_configName;
}
@Override
protected void loadSettingsForDialog(final NodeSettingsRO settings, final PortObjectSpec[] specs)
throws NotConfigurableException {
try {
loadSettings(settings);
} catch (final InvalidSettingsException ex) {
m_labelings = new HashMap<>();
}
}
@Override
protected void saveSettingsForDialog(final NodeSettingsWO settings) throws InvalidSettingsException {
saveSettings(settings);
}
@Override
protected void validateSettingsForModel(final NodeSettingsRO settings) throws InvalidSettingsException {
// TODO Auto-generated method stub
}
@Override
protected void loadSettingsForModel(final NodeSettingsRO settings) throws InvalidSettingsException {
loadSettings(settings);
}
@Override
protected void saveSettingsForModel(final NodeSettingsWO settings) {
saveSettings(settings);
}
private void saveSettings(final NodeSettingsWO settings) {
try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
final ObjectOutputStream objOut = new ObjectOutputStream(byteOut);) {
objOut.writeObject(m_labelings);
settings.addString(m_configName, new String(Base64.encode(byteOut.toByteArray())));
} catch (final IOException e) {
// TODO better error message?
throw new IllegalStateException(e);
}
}
private void loadSettings(final NodeSettingsRO settings) throws InvalidSettingsException {
final byte[] data = Base64.decode(settings.getString(m_configName).getBytes());
try (final ByteArrayInputStream byteIn = new ByteArrayInputStream(data);
final ObjectInputStream objIn = new ObjectInputStream(byteIn)) {
m_labelings = (Map<RowColKey, Overlay>)objIn.readObject();
} catch (final IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
throw new InvalidSettingsException(e);
}
}
@Override
public String toString() {
// TODO Auto-generated method stub
return null;
}
public Overlay getLabeling(final String rowKey, final String colName) {
final RowColKey key = new RowColKey(rowKey, colName);
if (m_labelings.containsKey(key)) {
return m_labelings.get(key);
} else {
Overlay difference = new Overlay(new ArrayList<>(), new TLongIntHashMap());
m_labelings.put(key, difference);
return difference;
}
}
public void setLabeling(final String rowKey, final String colName, final Overlay labeling) {
m_labelings.put(new RowColKey(rowKey, colName), labeling);
}
static class Overlay implements Serializable {
private static final long serialVersionUID = 1L;
private final List<Set<String>> m_labels;
private final TLongIntHashMap m_difference;
Overlay(final List<Set<String>> labels, final TLongIntHashMap difference) {
m_labels = labels;
m_difference = difference;
}
List<Set<String>> getLabels() {
return m_labels;
}
TLongIntHashMap getDifference() {
return m_difference;
}
}
static class RowColKey implements Serializable {
private final String m_rowKey;
private final String m_colName;
RowColKey(final String rowKey, final String colName) {
m_rowKey = rowKey;
m_colName = colName;
}
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof RowColKey)) {
return false;
}
final RowColKey o = (RowColKey)obj;
return m_rowKey.equals(o.m_rowKey) && m_colName.equals(o.m_colName);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((m_rowKey == null) ? 0 : m_rowKey.hashCode());
result = prime * result + ((m_colName == null) ? 0 : m_colName.hashCode());
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment