Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/1.2.2 #535

Merged
merged 7 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,14 @@ public ViewerPanelFX(
startRenderAnimator();
setWidth(options.getWidth());
setHeight(options.getHeight());
this.widthProperty().addListener((obs, oldv, newv) -> this.renderUnit.setDimensions((long) getWidth(), (long) getHeight()));
this.heightProperty().addListener((obs, oldv, newv) -> this.renderUnit.setDimensions((long) getWidth(), (long) getHeight()));
widthProperty().subscribe(width -> renderUnit.setDimensions(width.longValue(), (long)getHeight()));
heightProperty().subscribe(height -> renderUnit.setDimensions((long)getWidth(), height.longValue()));

visibleProperty().subscribe(visible -> {
if (!visible)
renderUnit.stopRendering();
});


transformListeners.add(tf -> Paintera.whenPaintable(getDisplay()::drawOverlays));

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
package org.janelia.saalfeldlab.bdv.fx.viewer.project;

import bdv.viewer.render.VolatileProjector;
import io.github.oshai.kotlinlogging.KLogger;
import io.github.oshai.kotlinlogging.KotlinLogging;
import net.imglib2.FinalInterval;
import net.imglib2.IterableInterval;
import net.imglib2.RandomAccessible;
Expand All @@ -51,6 +53,7 @@
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

Expand All @@ -64,6 +67,8 @@
*/
public class VolatileHierarchyProjector<A extends Volatile<?>, B extends SetZero> implements VolatileProjector {

private static KLogger LOG = KotlinLogging.INSTANCE.logger(() -> null);

/**
* A converter from the source pixel type to the target pixel type.
*/
Expand Down Expand Up @@ -211,10 +216,12 @@ public void clearMask() {

try {
LoopBuilder.setImages(mask).multiThreaded(taskExecutor).forEachPixel(val -> val.set(Byte.MAX_VALUE));
} catch (RejectedExecutionException e) {
LOG.trace(e, () -> "Clear Mask Rejected");
} catch (RuntimeException e) {
if (!e.getMessage().contains("Interrupted")) {
throw e;
}
if (e.getMessage() != null && e.getMessage().contains("Interrupted"))
LOG.trace(e, () -> "Clear Mask Interrupted");
else throw e;
}
numInvalidLevels = sources.size();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ public int paint(
clearQueue = newFrameRequest;
if (clearQueue)
cacheControl.prepareNextFrame();
createProjector = newFrameRequest || resized || requestedScreenScaleIndex != currentScreenScaleIndex || !sameAsLastRenderedInterval;
createProjector = projector == null || newFrameRequest || resized || requestedScreenScaleIndex != currentScreenScaleIndex || !sameAsLastRenderedInterval;
newFrameRequest = false;

final List<SourceAndConverter<?>> sacs = List.copyOf(sources);
Expand Down Expand Up @@ -624,8 +624,10 @@ public void requestRepaint(final Interval interval, final int screenScaleIndex)
if (Intervals.isEmpty(interval))
return;

if (renderingMayBeCancelled && projector != null)
if (renderingMayBeCancelled && projector != null) {
projector.cancel();
projector = null;
}

int newRequestedScaleIdx;
if (screenScaleIndex > maxScreenScaleIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ private Interval clampRepaintInterval(final Interval interval) {
protected synchronized void update() {

LOG.debug("Updating render unit");
if (renderer != null)
renderer.animation.stop();

renderTarget = new TransformAwareBufferedImageOverlayRendererFX();
renderTarget.setCanvasSize((int)dimensions[0], (int)dimensions[1]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public Interval getMaskInterval() {
} else {
mask = viewerMask;
}
final var maskPos = mask.displayPointToInitialMaskPoint(viewerSeedX, viewerSeedY);
final var maskPos = mask.displayPointToMask(viewerSeedX, viewerSeedY, true);
final var filter = getBackgorundLabelMaskForAssignment(maskPos, mask, assignment, fill);
if (filter == null)
return null;
Expand Down Expand Up @@ -179,7 +179,7 @@ public UtilityTask<?> fillViewerAt(final double viewerSeedX, final double viewer
} else {
mask = viewerMask;
}
final var maskPos = mask.displayPointToInitialMaskPoint(viewerSeedX, viewerSeedY);
final var maskPos = mask.displayPointToMask(viewerSeedX, viewerSeedY, true);
final UtilityTask<?> floodFillTask = fillMaskAt(maskPos, mask, fill, filter);
if (this.viewerMask == null) {
floodFillTask.onCancelled(true, (state, task) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package org.janelia.saalfeldlab.paintera.control
import org.janelia.saalfeldlab.bdv.fx.viewer.ViewerPanelFX
import bdv.viewer.TransformListener
import io.github.oshai.kotlinlogging.KotlinLogging
import javafx.application.Platform
import javafx.beans.InvalidationListener
import javafx.beans.Observable
import javafx.beans.property.ObjectProperty
import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleDoubleProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.value.ChangeListener
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.concurrent.Task
import javafx.concurrent.Worker
import javafx.scene.paint.Color
Expand Down Expand Up @@ -40,6 +41,7 @@ import net.imglib2.util.*
import net.imglib2.view.ExtendedRealRandomAccessibleRealInterval
import net.imglib2.view.IntervalView
import net.imglib2.view.Views
import org.checkerframework.common.reflection.qual.Invoke
import org.janelia.saalfeldlab.fx.Tasks
import org.janelia.saalfeldlab.fx.extensions.*
import org.janelia.saalfeldlab.fx.util.InvokeOnJavaFXApplicationThread
Expand All @@ -62,6 +64,7 @@ import org.janelia.saalfeldlab.util.*
import org.janelia.saalfeldlab.net.imglib2.view.BundleView
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.Collections
import java.util.concurrent.ExecutionException
import java.util.concurrent.atomic.AtomicBoolean
import java.util.function.Supplier
Expand All @@ -88,9 +91,6 @@ class ShapeInterpolationController<D : IntegerType<D>>(

private val slicesAndInterpolants = SlicesAndInterpolants()

val sliceDepthProperty = SimpleDoubleProperty(0.0)
private var sliceDepth: Double by sliceDepthProperty.nonnull()

val isBusyProperty = SimpleBooleanProperty(false, "Shape Interpolation Controller is Busy")
private var isBusy: Boolean by isBusyProperty.nonnull()

Expand All @@ -99,8 +99,11 @@ class ShapeInterpolationController<D : IntegerType<D>>(
val isControllerActive: Boolean
get() = controllerState != ControllerState.Off

private val sliceAtCurrentDepthBinding = sliceDepthProperty.createNonNullValueBinding(slicesAndInterpolants) { slicesAndInterpolants.getSliceAtDepth(it.toDouble()) }
private val sliceAtCurrentDepth by sliceAtCurrentDepthBinding.nullableVal()
internal val currentDepthProperty = SimpleDoubleProperty()
internal val currentDepth: Double by currentDepthProperty.nonnullVal()

internal val sliceAtCurrentDepthProperty = slicesAndInterpolants.createObservableBinding(currentDepthProperty) { it.getSliceAtDepth(currentDepth) }
private val sliceAtCurrentDepth by sliceAtCurrentDepthProperty.nullableVal()

val currentSliceMaskInterval get() = sliceAtCurrentDepth?.maskBoundingBox

Expand Down Expand Up @@ -133,9 +136,6 @@ class ShapeInterpolationController<D : IntegerType<D>>(
return viewerState.getBestMipMapLevel(screenScaleTransform, source)
}


internal val currentDepth: Double by LazyForeignValue(this::globalToViewerTransform) { depthAt(it) }

private var selector: Task<Unit>? = null
private var interpolator: Task<Unit>? = null
private val onTaskFinished = {
Expand All @@ -152,10 +152,7 @@ class ShapeInterpolationController<D : IntegerType<D>>(
private var globalCompositeFillAndInterpolationImgs: Pair<RealRandomAccessible<UnsignedLongType>, RealRandomAccessible<VolatileUnsignedLongType>>? = null

private val viewerTransformDepthUpdater = TransformListener<AffineTransform3D> {
updateDepth()
sliceAtCurrentDepth?.mask.let {
currentViewerMask = it
}
currentDepthProperty.set(depthAt(it))
}

internal fun depthAt(globalTransform: AffineTransform3D): Double {
Expand Down Expand Up @@ -240,19 +237,17 @@ class ShapeInterpolationController<D : IntegerType<D>>(
selectNewInterpolationId()
initialGlobalToViewerTransform = globalToViewerTransform
activeViewer!!.addTransformListener(viewerTransformDepthUpdater)
updateDepth()
controllerState = ControllerState.Select

sliceAtCurrentDepthBinding.addListener { _, old, new ->
sliceAtCurrentDepthProperty.addListener { _, old, new ->
old?.mask?.setMaskOnUpdate = false
new?.mask?.setMaskOnUpdate = false
new?.mask?.also {
currentViewerMask = it
it.setMaskOnUpdate = false
}
}
}

private fun updateDepth() {
sliceDepth = currentDepth
}

fun exitShapeInterpolation(completed: Boolean) {
if (!isControllerActive) {
LOG.debug { "Not in shape interpolation" }
Expand All @@ -274,7 +269,6 @@ class ShapeInterpolationController<D : IntegerType<D>>(
selectedIds.activateAlso(lastSelectedId)
controllerState = ControllerState.Off
slicesAndInterpolants.clear()
sliceDepth = 0.0
currentViewerMask = null
interpolator = null
globalCompositeFillAndInterpolationImgs = null
Expand Down Expand Up @@ -381,7 +375,6 @@ class ShapeInterpolationController<D : IntegerType<D>>(
paintera().manager().apply {
setTransform(globalTransform, Duration(300.0)) {
transform = globalTransform
updateDepth()
controllerState = ControllerState.Select
}
}
Expand Down Expand Up @@ -989,7 +982,7 @@ class ShapeInterpolationController<D : IntegerType<D>>(
}
}

private class SlicesAndInterpolants : ObservableList<SliceOrInterpolant> by FXCollections.synchronizedObservableList(FXCollections.observableArrayList()) {
private class SlicesAndInterpolants : MutableList<SliceOrInterpolant> by Collections.synchronizedList(mutableListOf()), Observable {
fun removeSlice(slice: SliceInfo): Boolean {
synchronized(this) {
for (idx in indices) {
Expand All @@ -998,6 +991,9 @@ class ShapeInterpolationController<D : IntegerType<D>>(
LOG.trace { "Removing Slice: $idx" }
removeAt(idx).getSlice()
removeIfInterpolant(idx - 1)

notifyListeners()

return true
}
}
Expand All @@ -1017,7 +1013,11 @@ class ShapeInterpolationController<D : IntegerType<D>>(
synchronized(this) {
return if (idx >= 0 && idx <= size - 1 && get(idx).isInterpolant) {
LOG.trace { "Removing Interpolant: $idx" }
removeAt(idx).getInterpolant()
val interp = removeAt(idx).getInterpolant()

notifyListeners()

interp
} else null
}

Expand All @@ -1043,6 +1043,10 @@ class ShapeInterpolationController<D : IntegerType<D>>(
}
LOG.trace { "Adding Slice: ${this.size}" }
add(sliceOrInterpolant)

InvokeOnJavaFXApplicationThread {
listeners.forEach { it.invalidated(this) }
}
}
}

Expand Down Expand Up @@ -1145,6 +1149,20 @@ class ShapeInterpolationController<D : IntegerType<D>>(
return false
}
}

private val listeners = mutableListOf<InvalidationListener>()

override fun addListener(p0: InvalidationListener) {
listeners += p0
}

override fun removeListener(p0: InvalidationListener) {
listeners -= p0
}

private fun notifyListeners() = Platform.runLater {
listeners.forEach { it.invalidated(this) }
}
}

var initialGlobalToViewerTransform: AffineTransform3D? = null
Expand Down
Loading
Loading