Skip to content

Commit

Permalink
WIP Refactor responsibilities of backend and state
Browse files Browse the repository at this point in the history
The backend should not hold on to the source. Instead, it should create it on demand.

WIP because of weird compilation error.
  • Loading branch information
hanslovsky committed Nov 27, 2019
1 parent a6f5aa8 commit 7c5c5e9
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 398 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -734,15 +734,19 @@ private static <D extends NativeType<D> & IntegerType<D>, T extends Volatile<D>
final N5Backend<D, T> backend = N5Backend.createFrom(
container,
dataset,
projectDirectory,
viewer.getPropagationQueue());
return new ConnectomicsLabelState<D, T>(
backend,
viewer.viewer3D().meshesGroup(),
viewer.getMeshManagerExecutorService(),
viewer.getMeshWorkerExecutorService(),
viewer.getQueue(),
0, // TODO is this the right priority?
name,
projectDirectory,
viewer.getPropagationQueue(),
resolution,
offset,
null);
return new ConnectomicsLabelState<>(backend, viewer.viewer3D().meshesGroup(), viewer.getMeshManagerExecutorService(), viewer.getMeshWorkerExecutorService());
}

private static <D extends RealType<D> & NativeType<D>, T extends AbstractVolatileRealType<D, T> & NativeType<T>> SourceState<D, T> makeRawSourceState(
Expand All @@ -758,13 +762,14 @@ private static <D extends RealType<D> & NativeType<D>, T extends AbstractVolatil
try {
final N5BackendRaw<D, T> backend = new N5BackendRaw<>(
N5Meta.fromReader(container, group).getWriter(),
group,
resolution,
offset,
group);
final ConnectomicsRawState<D, T> state = new ConnectomicsRawState<>(
backend,
viewer.getQueue(),
0,
name);
final ConnectomicsRawState<D, T> state = new ConnectomicsRawState<>(backend);
name,
resolution,
offset);
state.converter().setMin(min);
state.converter().setMax(max);
return state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,19 @@ private static void createAndAddNewLabelDataset(
final N5Backend backend = N5Backend.createFrom(
meta.getWriter(),
meta.getDataset(),
pbv.getQueue(),
0,
metaAndName.get().getValue(),
projecDirectory,
pbv.getPropagationQueue(),
N5Helpers.getResolution(meta.getWriter(), String.format("%s/data", meta.getDataset())),
N5Helpers.getOffset(meta.getWriter(), String.format("%s/data", meta.getDataset())),
null);
pbv.getPropagationQueue());
pbv.addState(new ConnectomicsLabelState<>(
backend,
pbv.viewer3D().meshesGroup(),
pbv.getMeshManagerExecutorService(),
pbv.getMeshWorkerExecutorService()));
pbv.getMeshWorkerExecutorService(),
pbv.getQueue(),
0,
metaAndName.get().getValue(),
N5Helpers.getResolution(meta.getWriter(), String.format("%s/data", meta.getDataset())),
N5Helpers.getOffset(meta.getWriter(), String.format("%s/data", meta.getDataset())),
null));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -521,17 +521,14 @@ List<? extends SourceState<RealComposite<T>, VolatileWithSet<RealComposite<V>>>>
final long numChannels = datasetAttributes.get().getDimensions()[axisOrderProperty().get().channelIndex()];

LOG.debug("Got channel info: num channels={} channels selection={}", numChannels, channelSelection);
final N5BackendChannel<T, V> backend = new N5BackendChannel<>(
n5.get(),
dataset,
resolution,
offset,
channelSelection,
axisOrder.get().channelIndex(),
final N5BackendChannel<T, V> backend = new N5BackendChannel<>(n5.get(), dataset, channelSelection, axisOrder.get().channelIndex());
final ConnectomicsChannelState<T, V, RealComposite<T>, RealComposite<V>, VolatileWithSet<RealComposite<V>>> state = new ConnectomicsChannelState<>(
backend,
queue,
priority,
name + "-" + Arrays.toString(channelSelection));
final ConnectomicsChannelState<T, V, RealComposite<T>, RealComposite<V>, VolatileWithSet<RealComposite<V>>> state = new ConnectomicsChannelState<>(backend);
name + "-" + Arrays.toString(channelSelection),
resolution,
offset);
state.converter().setMins(i -> min().get());
state.converter().setMaxs(i -> max().get());
return Collections.singletonList(state);
Expand All @@ -548,8 +545,8 @@ SourceState<T, V> getRaw(
final String dataset = this.dataset.get();
final double[] resolution = asPrimitiveArray(resolution());
final double[] offset = asPrimitiveArray(offset());
final N5BackendRaw<T, V> backend = new N5BackendRaw<>(writer, dataset, resolution, offset, queue, priority, name);
final SourceState<T, V> state = new ConnectomicsRawState<>(backend);
final N5BackendRaw<T, V> backend = new N5BackendRaw<>(writer, dataset);
final SourceState<T, V> state = new ConnectomicsRawState<>(backend, queue, priority, name, resolution, offset);
LOG.debug("Returning raw source state {} {}", name, state);
return state;
}
Expand All @@ -572,15 +569,19 @@ SourceState<T, V> getRaw(
final N5Backend<D, T> backend = N5Backend.createFrom(
reader,
dataset,
projectDirectory,
propagationQueue);
return new ConnectomicsLabelState<>(
backend,
meshesGroup,
manager,
workers,
queue,
priority,
name,
projectDirectory,
propagationQueue,
resolution,
offset,
null);
return new ConnectomicsLabelState<>(backend, meshesGroup, manager, workers);
}

public boolean isLabelMultisetType() throws Exception
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package org.janelia.saalfeldlab.paintera.state

import bdv.util.volatiles.SharedQueue
import javafx.scene.Node
import org.janelia.saalfeldlab.paintera.data.DataSource

interface SourceStateBackend<D, T> {

val source: DataSource<D, T>
fun createSource(
queue: SharedQueue,
priority: Int,
name: String,
resolution: DoubleArray = doubleArrayOf(1.0, 1.0, 1.0),
offset: DoubleArray = doubleArrayOf(1.0, 1.0, 1.0)): DataSource<D, T>

fun createMetaDataNode(): Node

val defaultSourceName: String

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import org.janelia.saalfeldlab.n5.N5Writer
interface SourceStateBackendN5<D, T> : SourceStateBackend<D, T> {
val container: N5Writer
val dataset: String
override val defaultSourceName: String
get() = dataset.split("/").last()
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
package org.janelia.saalfeldlab.paintera.state.channel

import bdv.util.volatiles.SharedQueue
import org.janelia.saalfeldlab.paintera.data.ChannelDataSource
import org.janelia.saalfeldlab.paintera.state.SourceStateBackend

interface ConnectomicsChannelBackend<D, T> : SourceStateBackend<D, T> {
override val source: ChannelDataSource<D, T>

val channelSelection: IntArray
val channelIndex: Int
val numChannels: Int
get() = channelSelection.size

override fun createSource(
queue: SharedQueue,
priority: Int,
name: String,
resolution: DoubleArray,
offset: DoubleArray): ChannelDataSource<D, T>

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.janelia.saalfeldlab.paintera.state.channel

import bdv.util.volatiles.SharedQueue
import bdv.viewer.Interpolation
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
Expand All @@ -25,33 +26,43 @@ import org.janelia.saalfeldlab.paintera.data.axisorder.AxisOrder
import org.janelia.saalfeldlab.paintera.serialization.GsonExtensions
import org.janelia.saalfeldlab.paintera.serialization.PainteraSerialization
import org.janelia.saalfeldlab.paintera.serialization.SerializationHelpers
import org.janelia.saalfeldlab.paintera.serialization.StatefulSerializer
import org.janelia.saalfeldlab.paintera.state.ARGBComposite
import org.janelia.saalfeldlab.paintera.state.ChannelSourceStateConverterNode
import org.janelia.saalfeldlab.paintera.state.SourceState
import org.janelia.saalfeldlab.paintera.state.SourceStateWithBackend
import org.scijava.plugin.Plugin
import java.lang.reflect.Type
import java.util.function.IntFunction
import java.util.function.Supplier

typealias ARGBComoposite = org.janelia.saalfeldlab.paintera.composition.Composite<ARGBType, ARGBType>

class ConnectomicsChannelState<D, T, CD, CT, V>
@JvmOverloads constructor(
override val backend: ConnectomicsChannelBackend<CD, V>,
private val converter: ARGBCompositeColorConverter<T, CT, V> = ARGBCompositeColorConverter.InvertingImp0<T, CT, V>(backend.source.numChannels().toInt())) : SourceStateWithBackend<CD, V>
override val backend: ConnectomicsChannelBackend<CD, V>,
queue: SharedQueue,
priority: Int,
name: String,
private val resolution: DoubleArray = DoubleArray(3) { 1.0 },
private val offset: DoubleArray = DoubleArray(3) { 0.0 },
private val converter: ARGBCompositeColorConverter<T, CT, V> = ARGBCompositeColorConverter.InvertingImp0<T, CT, V>(backend.numChannels)) : SourceStateWithBackend<CD, V>
where D: RealType<D>, T: AbstractVolatileRealType<D, T>, CD: RealComposite<D>, CT: RealComposite<T>, V: Volatile<CT> {

override fun getDataSource(): DataSource<CD, V> = backend.source
private val source = backend.createSource(queue, priority, name, resolution, offset)

override fun getDataSource(): DataSource<CD, V> = source

override fun converter(): ARGBCompositeColorConverter<T, CT, V> = converter

val numChannels = backend.source.numChannels()
val numChannels = source.numChannels()

private val _composite: ObjectProperty<ARGBComoposite> = SimpleObjectProperty(ARGBCompositeAlphaAdd())
var composite: ARGBComposite
get() = _composite.value
set(composite) = _composite.set(composite)

private val _name = SimpleStringProperty(backend.source.name)
private val _name = SimpleStringProperty(name)
var name: String
get() = _name.value
set(name) = _name.set(name)
Expand Down Expand Up @@ -109,6 +120,8 @@ class ConnectomicsChannelState<D, T, CD, CT, V>
const val CONVERTER = "converter"
const val INTERPOLATION = "interpolation"
const val IS_VISIBLE = "isVisible"
const val RESOLUTION = "resolution"
const val OFFSET = "offset"
}

@Plugin(type = PainteraSerialization.PainteraSerializer::class)
Expand All @@ -123,22 +136,45 @@ class ConnectomicsChannelState<D, T, CD, CT, V>
map.add(CONVERTER, SerializationHelpers.serializeWithClassInfo(state.converter, context))
map.add(INTERPOLATION, context.serialize(state.interpolation))
map.addProperty(IS_VISIBLE, state.isVisible)
state.resolution.takeIf { r -> r.any { it != 1.0 } }?.let { map.add(RESOLUTION, context.serialize(it)) }
state.offset.takeIf { o -> o.any { it != 0.0 } }?.let { map.add(OFFSET, context.serialize(it)) }
}
return map
}

override fun getTargetClass(): Class<ConnectomicsChannelState<D, T, CD, CT, V>> = ConnectomicsChannelState::class.java as Class<ConnectomicsChannelState<D, T, CD, CT, V>>
}

@Plugin(type = PainteraSerialization.PainteraDeserializer::class)
class Deserializer<D, T, CD, CT, V> : PainteraSerialization.PainteraDeserializer<ConnectomicsChannelState<D, T, CD, CT, V>>
class Deserializer<D, T, CD, CT, V>(
private val queue: SharedQueue,
private val priority: Int) : PainteraSerialization.PainteraDeserializer<ConnectomicsChannelState<D, T, CD, CT, V>>
where D: RealType<D>, T: AbstractVolatileRealType<D, T>, CD: RealComposite<D>, CT: RealComposite<T>, V: Volatile<CT> {

@Plugin(type = StatefulSerializer.DeserializerFactory::class)
class Factory<D, T, CD, CT, V> : StatefulSerializer.DeserializerFactory<ConnectomicsChannelState<D, T, CD, CT, V>, Deserializer<D, T, CD, CT, V>>
where D: RealType<D>, T: AbstractVolatileRealType<D, T>, CD: RealComposite<D>, CT: RealComposite<T>, V: Volatile<CT> {
override fun createDeserializer(
arguments: StatefulSerializer.Arguments,
projectDirectory: Supplier<String>,
dependencyFromIndex: IntFunction<SourceState<*, *>>
): Deserializer<D, T, CD, CT, V> = Deserializer(
arguments.viewer.queue,
0)

override fun getTargetClass() = ConnectomicsChannelState::class.java as Class<ConnectomicsChannelState<D, T, CD, CT, V>>
}

override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ConnectomicsChannelState<D, T, CD, CT, V> {
return with (SerializationKeys) {
with (GsonExtensions) {
val backend = SerializationHelpers.deserializeFromClassInfo<ConnectomicsChannelBackend<CD, V>>(json.getJsonObject(BACKEND)!!, context)
ConnectomicsChannelState<D, T, CD, CT, V>(
SerializationHelpers.deserializeFromClassInfo(json.getJsonObject(BACKEND)!!, context),
backend,
queue,
priority,
json.getStringProperty(NAME) ?: backend.defaultSourceName,
json.getProperty(RESOLUTION)?.let { context.deserialize<DoubleArray>(it, DoubleArray::class.java) } ?: DoubleArray(3) { 1.0 },
json.getProperty(OFFSET)?.let { context.deserialize<DoubleArray>(it, DoubleArray::class.java) } ?: DoubleArray(3) { 0.0 },
SerializationHelpers.deserializeFromClassInfo(json.getJsonObject(CONVERTER)!!, context))
.also { state -> json.getStringProperty(NAME)?.let { state.name = it } }
.also { state -> json.getJsonObject(COMPOSITE)?.let { state.composite = SerializationHelpers.deserializeFromClassInfo(it, context) } }
Expand Down
Loading

1 comment on commit 7c5c5e9

@hanslovsky
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The weird Kotlin compilation error is probably caused by any subset of

  • ConnectomicsLabelState
  • ConnectomicsChannelState
  • ConnectomcisRawState

Please sign in to comment.