Skip to content

Commit

Permalink
Merge pull request #199 from saalfeldlab/fix-fragment-segment-assignm…
Browse files Browse the repository at this point in the history
…ent-deserialization

Serialize initial lut supplier in paintera project
  • Loading branch information
hanslovsky authored Feb 7, 2019
2 parents 8396bfc + e0a0099 commit 2369b6d
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.function.LongSupplier;
import java.util.function.Supplier;

import com.google.gson.annotations.Expose;
import gnu.trove.impl.Constants;
import gnu.trove.iterator.TLongLongIterator;
import gnu.trove.map.TLongLongMap;
Expand All @@ -31,14 +32,39 @@ public interface Persister
public static class DoesNotPersist implements Persister
{

@Expose
private final String persistError;

public DoesNotPersist() {
this("Cannot persist at all!");
}

public DoesNotPersist(final String persistError) {
this.persistError = persistError;
}

@Override
public void persist(final long[] keys, final long[] values) throws UnableToPersist
{
throw new UnableToPersist("Cannot persist at all!");
throw new UnableToPersist(this.persistError);
}

}

public static class NoInitialLutAvailable implements Supplier<TLongLongMap> {

@Override
public TLongLongMap get() {
return new TLongLongHashMap();
}
}

public static Supplier<TLongLongMap> NO_INITIAL_LUT_AVAILABLE = new NoInitialLutAvailable();

public static Persister doesNotPersist(final String persistError) {
return new DoesNotPersist(persistError);
}

private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private final TLongLongHashMap fragmentToSegmentMap = new TLongLongHashMap(
Expand All @@ -60,7 +86,7 @@ public void persist(final long[] keys, final long[] values) throws UnableToPersi

public FragmentSegmentAssignmentOnlyLocal(final Persister persister)
{
this(() -> new TLongLongHashMap(), persister);
this(NO_INITIAL_LUT_AVAILABLE, persister);
}

public FragmentSegmentAssignmentOnlyLocal(
Expand All @@ -81,6 +107,10 @@ public Persister getPersister() {
return this.persister;
}

public Supplier<TLongLongMap> getInitialLutSupplier() {
return this.initialLut;
}

@Override
public synchronized void persist() throws UnableToPersist
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
package org.janelia.saalfeldlab.paintera.serialization.assignments;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import gnu.trove.map.TLongLongMap;
import javafx.util.Pair;
import org.janelia.saalfeldlab.paintera.control.assignment.FragmentSegmentAssignmentOnlyLocal;
import org.janelia.saalfeldlab.paintera.control.assignment.FragmentSegmentAssignmentState;
import org.janelia.saalfeldlab.paintera.control.assignment.action.AssignmentAction;
import org.janelia.saalfeldlab.paintera.serialization.PainteraSerialization;
import org.janelia.saalfeldlab.paintera.serialization.SerializationHelpers;
import org.janelia.saalfeldlab.util.n5.N5Helpers;
import org.scijava.plugin.Plugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Plugin(type = PainteraSerialization.PainteraAdapter.class)
public class FragmentSegmentAssignmentOnlyLocalSerializer implements PainteraSerialization.PainteraAdapter<FragmentSegmentAssignmentOnlyLocal>
{
Expand All @@ -38,6 +37,8 @@ public class FragmentSegmentAssignmentOnlyLocalSerializer implements PainteraSer

public static final String PERSISTER_KEY = "persister";

public static final String INITIAL_LUT_KEY = "initialLut";

@Override
public JsonElement serialize(
final FragmentSegmentAssignmentOnlyLocal src,
Expand All @@ -58,6 +59,7 @@ public JsonElement serialize(
final JsonObject map = new JsonObject();
map.add(ACTIONS_KEY, context.serialize(serializedActions));
map.add(PERSISTER_KEY, SerializationHelpers.serializeWithClassInfo(src.getPersister(), context));
map.add(INITIAL_LUT_KEY, SerializationHelpers.serializeWithClassInfo(src.getInitialLutSupplier(), context));
return map;
}

Expand All @@ -67,12 +69,18 @@ public FragmentSegmentAssignmentOnlyLocal deserialize(JsonElement jsonElement, T
LOG.debug("Deserializing from {}", jsonElement);
try {

if (!(jsonElement instanceof JsonObject) || !jsonElement.getAsJsonObject().has(PERSISTER_KEY))
throw new NoPersisterFound(jsonElement);

if (!(jsonElement instanceof JsonObject))
throw new JsonParseException(String.format("Expected instanceof %s but got %s", JsonObject.class, jsonElement));
final JsonObject map = jsonElement.getAsJsonObject();

if (!map.has(PERSISTER_KEY))
throw new NoPersisterFound(map);

if (!map.has(INITIAL_LUT_KEY))
throw new NoInitialLutFound(map);

final FragmentSegmentAssignmentOnlyLocal.Persister persister = SerializationHelpers.deserializeFromClassInfo(map.get(PERSISTER_KEY).getAsJsonObject(), context);
final FragmentSegmentAssignmentOnlyLocal assignment = new FragmentSegmentAssignmentOnlyLocal(persister);
final FragmentSegmentAssignmentOnlyLocal assignment = new FragmentSegmentAssignmentOnlyLocal(tryDeserializeInitialLutSupplier(map.getAsJsonObject(INITIAL_LUT_KEY), context), persister);

if (map.has(ACTIONS_KEY)) {
final JsonArray serializedActions = map.get(FragmentSegmentAssignmentOnlyLocalSerializer.ACTIONS_KEY).getAsJsonArray();
Expand All @@ -99,10 +107,10 @@ public Class<FragmentSegmentAssignmentOnlyLocal> getTargetClass() {

public static class NoPersisterFound extends JsonParseException {

private final JsonElement el;
private final JsonObject el;

public NoPersisterFound(final JsonElement el) {
super("No Persister found in JsonElement " + (el == null ? null : el.getAsString()));
public NoPersisterFound(final JsonObject el) {
super(String.format("No Persister found for key %s in JsonObject %s", PERSISTER_KEY, el));
this.el = el;
}

Expand All @@ -111,4 +119,30 @@ public JsonElement getJsonElement() {
}

}

public static class NoInitialLutFound extends JsonParseException {

private final JsonObject el;

public NoInitialLutFound(final JsonObject el) {
super(String.format("No initial lut found for key %s in JsonObject %s", INITIAL_LUT_KEY, el));
this.el = el;
}

public JsonElement getJsonElement() {
return el == null ? null : el.deepCopy();
}

}

private static Supplier<TLongLongMap> tryDeserializeInitialLutSupplier(
final JsonObject map,
final JsonDeserializationContext context) {
try {
return SerializationHelpers.deserializeFromClassInfo(map, context);
} catch (ClassNotFoundException e)
{
throw new JsonParseException("Unable to deserialize initial lut supplier", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.janelia.saalfeldlab.paintera.serialization.assignments;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import org.janelia.saalfeldlab.paintera.data.n5.N5Meta;
import org.janelia.saalfeldlab.paintera.data.n5.ReflectionException;
import org.janelia.saalfeldlab.paintera.serialization.PainteraSerialization;
import org.janelia.saalfeldlab.paintera.serialization.SerializationHelpers;
import org.janelia.saalfeldlab.util.n5.N5FragmentSegmentAssignmentInitialLut;
import org.janelia.saalfeldlab.util.n5.N5FragmentSegmentAssignmentPersister;
import org.scijava.plugin.Plugin;

import java.io.IOException;
import java.lang.reflect.Type;


@Plugin(type = PainteraSerialization.PainteraAdapter.class)
public class N5FragmentSegmentAssignmentInitialLutSerializer implements
PainteraSerialization.PainteraAdapter<N5FragmentSegmentAssignmentInitialLut>
{


private static final String N5_META_KEY = "N5";

@Override
public N5FragmentSegmentAssignmentInitialLut deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
try {
final N5Meta meta = SerializationHelpers.deserializeFromClassInfo(jsonElement.getAsJsonObject().get(N5_META_KEY).getAsJsonObject(), context);
return new N5FragmentSegmentAssignmentInitialLut(meta);
} catch (ClassNotFoundException e) {
throw new JsonParseException(e);
}
}

@Override
public JsonElement serialize(N5FragmentSegmentAssignmentInitialLut src, Type type, JsonSerializationContext context) {
final JsonObject map = new JsonObject();
map.add(N5_META_KEY, SerializationHelpers.serializeWithClassInfo(src.getMeta(), context));
return map;
}

@Override
public Class<N5FragmentSegmentAssignmentInitialLut> getTargetClass() {
return N5FragmentSegmentAssignmentInitialLut.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,9 @@ private static FragmentSegmentAssignmentState tryDeserializeOrFallBackToN5(
try {
LOG.debug("Deserializing {} from {}", FragmentSegmentAssignmentState.class.getName(), assignmentMap);
return SerializationHelpers.deserializeFromClassInfo(assignmentMap, context);
} catch (final FragmentSegmentAssignmentOnlyLocalSerializer.NoPersisterFound | NullPointerException e) {
} catch (final FragmentSegmentAssignmentOnlyLocalSerializer.NoPersisterFound
| FragmentSegmentAssignmentOnlyLocalSerializer.NoInitialLutFound
| NullPointerException e) {
LOG.debug("Caught exception when trying to deserialize assignment", e);
LOG.warn("Trying to load fragment-segment-assignment with legacy loader, assuming the underlying persister is N5. " +
"If successfully loaded, this will not be necessary anymore after you save the project.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,8 @@ LabelSourceState<D, T> simpleSourceFromSingleRAI(
);

final SelectedIds selectedIds = new SelectedIds();
final FragmentSegmentAssignmentOnlyLocal assignment = new FragmentSegmentAssignmentOnlyLocal(new
FragmentSegmentAssignmentOnlyLocal.DoesNotPersist());
final LockedSegmentsOnlyLocal lockedSegments = new LockedSegmentsOnlyLocal(seg -> {
});
final FragmentSegmentAssignmentOnlyLocal assignment = new FragmentSegmentAssignmentOnlyLocal(new FragmentSegmentAssignmentOnlyLocal.DoesNotPersist());
final LockedSegmentsOnlyLocal lockedSegments = new LockedSegmentsOnlyLocal(seg -> {});
final ModalGoldenAngleSaturatedHighlightingARGBStream stream = new
ModalGoldenAngleSaturatedHighlightingARGBStream(
selectedIds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,8 @@ public ModalGoldenAngleSaturatedHighlightingARGBStream()
{
this(
new SelectedIds(),
new FragmentSegmentAssignmentOnlyLocal((k, v) -> {
}),
new LockedSegmentsOnlyLocal(locked -> {
})
);
new FragmentSegmentAssignmentOnlyLocal((k, v) -> {}),
new LockedSegmentsOnlyLocal(locked -> {}));
}

public ModalGoldenAngleSaturatedHighlightingARGBStream(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.janelia.saalfeldlab.util.n5;

import com.google.gson.annotations.Expose;
import gnu.trove.map.TLongLongMap;
import gnu.trove.map.hash.TLongLongHashMap;
import net.imglib2.Cursor;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.converter.Converters;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.IntegerType;
import net.imglib2.type.numeric.integer.UnsignedLongType;
import net.imglib2.view.Views;
import org.janelia.saalfeldlab.n5.DataType;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.imglib2.N5Utils;
import org.janelia.saalfeldlab.paintera.data.n5.N5Meta;
import org.janelia.saalfeldlab.paintera.data.n5.ReflectionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.function.Supplier;

public class N5FragmentSegmentAssignmentInitialLut implements Supplier<TLongLongMap> {

private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

@Expose
private final N5Meta meta;

public N5FragmentSegmentAssignmentInitialLut(final N5Reader container, final String dataset) throws ReflectionException {
this(N5Meta.fromReader(container, dataset));
}

public N5FragmentSegmentAssignmentInitialLut(final N5Meta meta) {
this.meta = meta;
}

public N5Meta getMeta() {
return this.meta;
}

@Override
public TLongLongMap get() {
try {
RandomAccessibleInterval<UnsignedLongType> data = openDatasetSafe(meta.reader(), meta.dataset());
final long[] keys = new long[(int) data.dimension(0)];
final long[] values = new long[keys.length];
LOG.debug("Found {} assignments", keys.length);
final Cursor<UnsignedLongType> keyCursor = Views.flatIterable(Views.hyperSlice(data, 1, 0L)).cursor();
final Cursor<UnsignedLongType> valueCursor = Views.flatIterable(Views.hyperSlice(data, 1, 1L)).cursor();
for (int i = 0; i < keys.length; ++i) {
keys[i] = keyCursor.next().getIntegerLong();
values[i] = valueCursor.next().getIntegerLong();
}
return new TLongLongHashMap(keys, values);
} catch (IOException e) {
LOG.debug("Exception while trying to return initial lut from N5", e);
LOG.error("Unable to read initial lut from {} -- returning empty map", meta, e);
return new TLongLongHashMap();
}
}

private static RandomAccessibleInterval<UnsignedLongType> openDatasetSafe(
final N5Reader reader,
final String dataset
) throws IOException {
return DataType.UINT64.equals(reader.getDatasetAttributes(dataset).getDataType())
? N5Utils.open(reader, dataset)
: openAnyIntegerTypeAsUnsignedLongType(reader, dataset);
}

private static <T extends IntegerType<T> & NativeType<T>> RandomAccessibleInterval<UnsignedLongType> openAnyIntegerTypeAsUnsignedLongType(
final N5Reader reader,
final String dataset
) throws IOException {
return Converters.convert(N5Utils.<T>open(reader, dataset), (s, t) -> t.setInteger(s.getIntegerLong()), new UnsignedLongType());
}
}
Loading

0 comments on commit 2369b6d

Please sign in to comment.