From 4a89956e54b602fc81e7a85551fb7f8f99c59360 Mon Sep 17 00:00:00 2001 From: tpietzsch Date: Wed, 22 May 2024 18:00:32 +0200 Subject: [PATCH] Move all classes from bigdataviewer-vistools to bigdataviewer-core --- pom.xml | 11 + src/main/java/bdv/util/AbstractSource.java | 145 ++++ src/main/java/bdv/util/AxisOrder.java | 273 ++++++ src/main/java/bdv/util/Bdv.java | 55 ++ src/main/java/bdv/util/BdvFunctions.java | 795 ++++++++++++++++++ src/main/java/bdv/util/BdvHandle.java | 304 +++++++ src/main/java/bdv/util/BdvHandleFrame.java | 152 ++++ src/main/java/bdv/util/BdvHandlePanel.java | 231 +++++ src/main/java/bdv/util/BdvOptions.java | 407 +++++++++ src/main/java/bdv/util/BdvOverlay.java | 125 +++ src/main/java/bdv/util/BdvOverlaySource.java | 129 +++ src/main/java/bdv/util/BdvPointsSource.java | 67 ++ src/main/java/bdv/util/BdvSource.java | 79 ++ src/main/java/bdv/util/BdvStackSource.java | 138 +++ .../bdv/util/BdvVirtualChannelSource.java | 128 +++ src/main/java/bdv/util/ChannelSources.java | 67 ++ .../java/bdv/util/DefaultInterpolators.java | 67 ++ .../java/bdv/util/PlaceHolderOverlayInfo.java | 214 +++++ src/main/java/bdv/util/PlaceHolderSource.java | 109 +++ src/main/java/bdv/util/PointsOverlay.java | 92 ++ .../RandomAccessibleIntervalMipmapSource.java | 147 ++++ ...andomAccessibleIntervalMipmapSource4D.java | 226 +++++ .../util/RandomAccessibleIntervalSource.java | 98 +++ .../RandomAccessibleIntervalSource4D.java | 118 +++ .../java/bdv/util/RandomAccessibleSource.java | 104 +++ .../bdv/util/RandomAccessibleSource4D.java | 142 ++++ .../RealRandomAccessibleIntervalSource.java | 86 ++ src/main/java/bdv/util/VirtualChannels.java | 190 +++++ ...eRandomAccessibleIntervalMipmapSource.java | 58 ++ src/main/java/bdv/util/VolatileSource.java | 91 ++ .../java/bdv/util/volatiles/SharedQueue.java | 48 ++ .../VolatileRandomAccessibleIntervalView.java | 73 ++ .../VolatileRandomAccessibleView.java | 77 ++ .../util/volatiles/VolatileTypeMatcher.java | 84 ++ .../java/bdv/util/volatiles/VolatileView.java | 46 + .../bdv/util/volatiles/VolatileViewData.java | 117 +++ .../bdv/util/volatiles/VolatileViews.java | 249 ++++++ .../java/bdv/util/ActionBlockingExample.java | 77 ++ src/test/java/bdv/util/ActionExample.java | 64 ++ .../BdvHandlePanelGarbageCollectionTest.java | 118 +++ .../bdv/util/BehaviourBlockingExample.java | 84 ++ src/test/java/bdv/util/BehaviourExample.java | 69 ++ .../java/bdv/util/BoxSelectionExample.java | 79 ++ .../java/bdv/util/DisplayRangeExample.java | 83 ++ src/test/java/bdv/util/Example2D.java | 54 ++ src/test/java/bdv/util/Example3D.java | 56 ++ src/test/java/bdv/util/Example4D.java | 51 ++ .../java/bdv/util/ExampleMipmapSource4D.java | 99 +++ src/test/java/bdv/util/ExampleOpenEmpty.java | 39 + .../java/bdv/util/ExampleSharedKeymaps.java | 55 ++ src/test/java/bdv/util/ExampleSource4D.java | 56 ++ .../bdv/util/ExampleSourceAndConverter4D.java | 70 ++ src/test/java/bdv/util/ExampleSpimData.java | 44 + .../java/bdv/util/InputConfigExample.java | 61 ++ .../java/bdv/util/InputConfigExample2.java | 65 ++ .../bdv/util/IntervalPaintingExample.java | 206 +++++ .../java/bdv/util/ManySourcesExample.java | 114 +++ src/test/java/bdv/util/OverlayExample2D.java | 89 ++ src/test/java/bdv/util/OverlayExample3D.java | 104 +++ src/test/java/bdv/util/PanelExample.java | 63 ++ .../bdv/util/RealBoxSelectionExample.java | 88 ++ src/test/java/bdv/util/SplitPanelExample.java | 107 +++ .../Rendering25SourcesBenchmark.java | 127 +++ .../bdv/util/benchmark/RenderingSetup.java | 171 ++++ .../RenderingSingleSourceBenchmark.java | 117 +++ .../RenderingWithEmptyBenchmark.java | 123 +++ src/test/resources/bdvkeyconfig.yaml | 82 ++ 67 files changed, 8157 insertions(+) create mode 100644 src/main/java/bdv/util/AbstractSource.java create mode 100644 src/main/java/bdv/util/AxisOrder.java create mode 100644 src/main/java/bdv/util/Bdv.java create mode 100644 src/main/java/bdv/util/BdvFunctions.java create mode 100644 src/main/java/bdv/util/BdvHandle.java create mode 100644 src/main/java/bdv/util/BdvHandleFrame.java create mode 100644 src/main/java/bdv/util/BdvHandlePanel.java create mode 100644 src/main/java/bdv/util/BdvOptions.java create mode 100644 src/main/java/bdv/util/BdvOverlay.java create mode 100644 src/main/java/bdv/util/BdvOverlaySource.java create mode 100644 src/main/java/bdv/util/BdvPointsSource.java create mode 100644 src/main/java/bdv/util/BdvSource.java create mode 100644 src/main/java/bdv/util/BdvStackSource.java create mode 100644 src/main/java/bdv/util/BdvVirtualChannelSource.java create mode 100644 src/main/java/bdv/util/ChannelSources.java create mode 100644 src/main/java/bdv/util/DefaultInterpolators.java create mode 100644 src/main/java/bdv/util/PlaceHolderOverlayInfo.java create mode 100644 src/main/java/bdv/util/PlaceHolderSource.java create mode 100644 src/main/java/bdv/util/PointsOverlay.java create mode 100644 src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource.java create mode 100644 src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource4D.java create mode 100644 src/main/java/bdv/util/RandomAccessibleIntervalSource.java create mode 100644 src/main/java/bdv/util/RandomAccessibleIntervalSource4D.java create mode 100644 src/main/java/bdv/util/RandomAccessibleSource.java create mode 100644 src/main/java/bdv/util/RandomAccessibleSource4D.java create mode 100644 src/main/java/bdv/util/RealRandomAccessibleIntervalSource.java create mode 100644 src/main/java/bdv/util/VirtualChannels.java create mode 100644 src/main/java/bdv/util/VolatileRandomAccessibleIntervalMipmapSource.java create mode 100644 src/main/java/bdv/util/VolatileSource.java create mode 100644 src/main/java/bdv/util/volatiles/SharedQueue.java create mode 100644 src/main/java/bdv/util/volatiles/VolatileRandomAccessibleIntervalView.java create mode 100644 src/main/java/bdv/util/volatiles/VolatileRandomAccessibleView.java create mode 100644 src/main/java/bdv/util/volatiles/VolatileTypeMatcher.java create mode 100644 src/main/java/bdv/util/volatiles/VolatileView.java create mode 100644 src/main/java/bdv/util/volatiles/VolatileViewData.java create mode 100644 src/main/java/bdv/util/volatiles/VolatileViews.java create mode 100644 src/test/java/bdv/util/ActionBlockingExample.java create mode 100644 src/test/java/bdv/util/ActionExample.java create mode 100644 src/test/java/bdv/util/BdvHandlePanelGarbageCollectionTest.java create mode 100644 src/test/java/bdv/util/BehaviourBlockingExample.java create mode 100644 src/test/java/bdv/util/BehaviourExample.java create mode 100644 src/test/java/bdv/util/BoxSelectionExample.java create mode 100644 src/test/java/bdv/util/DisplayRangeExample.java create mode 100644 src/test/java/bdv/util/Example2D.java create mode 100644 src/test/java/bdv/util/Example3D.java create mode 100644 src/test/java/bdv/util/Example4D.java create mode 100644 src/test/java/bdv/util/ExampleMipmapSource4D.java create mode 100644 src/test/java/bdv/util/ExampleOpenEmpty.java create mode 100644 src/test/java/bdv/util/ExampleSharedKeymaps.java create mode 100644 src/test/java/bdv/util/ExampleSource4D.java create mode 100644 src/test/java/bdv/util/ExampleSourceAndConverter4D.java create mode 100644 src/test/java/bdv/util/ExampleSpimData.java create mode 100644 src/test/java/bdv/util/InputConfigExample.java create mode 100644 src/test/java/bdv/util/InputConfigExample2.java create mode 100644 src/test/java/bdv/util/IntervalPaintingExample.java create mode 100644 src/test/java/bdv/util/ManySourcesExample.java create mode 100644 src/test/java/bdv/util/OverlayExample2D.java create mode 100644 src/test/java/bdv/util/OverlayExample3D.java create mode 100644 src/test/java/bdv/util/PanelExample.java create mode 100644 src/test/java/bdv/util/RealBoxSelectionExample.java create mode 100644 src/test/java/bdv/util/SplitPanelExample.java create mode 100644 src/test/java/bdv/util/benchmark/Rendering25SourcesBenchmark.java create mode 100644 src/test/java/bdv/util/benchmark/RenderingSetup.java create mode 100644 src/test/java/bdv/util/benchmark/RenderingSingleSourceBenchmark.java create mode 100644 src/test/java/bdv/util/benchmark/RenderingWithEmptyBenchmark.java create mode 100644 src/test/resources/bdvkeyconfig.yaml diff --git a/pom.xml b/pom.xml index 50a28d6f..7fa0a2be 100644 --- a/pom.xml +++ b/pom.xml @@ -241,5 +241,16 @@ junit test + + + org.openjdk.jmh + jmh-core + test + + + org.openjdk.jmh + jmh-generator-annprocess + test + diff --git a/src/main/java/bdv/util/AbstractSource.java b/src/main/java/bdv/util/AbstractSource.java new file mode 100644 index 00000000..c856de5a --- /dev/null +++ b/src/main/java/bdv/util/AbstractSource.java @@ -0,0 +1,145 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.function.Supplier; + +import bdv.viewer.Interpolation; +import bdv.viewer.Source; +import mpicbg.spim.data.sequence.DefaultVoxelDimensions; +import mpicbg.spim.data.sequence.FinalVoxelDimensions; +import mpicbg.spim.data.sequence.VoxelDimensions; +import net.imglib2.RealRandomAccessible; +import net.imglib2.type.Type; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.view.Views; + +public abstract class AbstractSource< T extends NumericType< T > > implements Source< T > +{ + protected final T type; + + protected final String name; + + protected final VoxelDimensions voxelDimensions; + + protected final DefaultInterpolators< T > interpolators; + + private final boolean doBoundingBoxCulling; + + public AbstractSource( final T type, final String name, final VoxelDimensions voxelDimensions, final boolean doBoundingBoxCulling ) + { + this.type = tryCreateVariable( type ); + this.name = name; + this.voxelDimensions = voxelDimensions; + interpolators = new DefaultInterpolators<>(); + this.doBoundingBoxCulling = doBoundingBoxCulling; + } + + public AbstractSource( final T type, final String name, final VoxelDimensions voxelDimensions ) + { + /* + * Do bounding box culling by default + */ + this( type, name, voxelDimensions, true ); + } + + public AbstractSource( final T type, final String name ) + { + /* + * We don't know the dimensionality of the source here, but the + * DefaultVoxelDimensionsimplementation will return the same result + * for spacing and units regardless of the number of dimensions passed. + */ + this( type, name, new DefaultVoxelDimensions( -1 ), true ); + } + + public AbstractSource( final T type, final String name, final boolean doBoundingBoxCulling ) + { + this( type, name, new DefaultVoxelDimensions( -1 ), doBoundingBoxCulling ); + } + + public AbstractSource( final Supplier< T > typeSupplier, final String name ) + { + this( typeSupplier.get(), name ); + } + + @Override + public boolean isPresent( final int t ) + { + return true; + } + + @Override + public T getType() + { + return type; + } + + @Override + public RealRandomAccessible< T > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + return Views.interpolate( Views.extendZero( getSource( t, level ) ), interpolators.get( method ) ); + } + + @Override + public String getName() + { + return name; + } + + @Override + public VoxelDimensions getVoxelDimensions() + { + return voxelDimensions; + } + + @Override + public int getNumMipmapLevels() + { + return 1; + } + + @Override + public boolean doBoundingBoxCulling() + { + return doBoundingBoxCulling; + } + + static < T > T tryCreateVariable( final T t ) + { + if ( t instanceof Type< ? > ) + { + final Type< ? > type = ( Type< ? > ) t; + @SuppressWarnings( "unchecked" ) + final T copy = ( T ) type.createVariable(); + return copy; + } + return t; + } +} diff --git a/src/main/java/bdv/util/AxisOrder.java b/src/main/java/bdv/util/AxisOrder.java new file mode 100644 index 00000000..39fb6474 --- /dev/null +++ b/src/main/java/bdv/util/AxisOrder.java @@ -0,0 +1,273 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.LongStream; + +import net.imglib2.Dimensions; +import net.imglib2.EuclideanSpace; +import net.imglib2.FinalInterval; +import net.imglib2.Interval; +import net.imglib2.RandomAccessible; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.util.Intervals; +import net.imglib2.util.Pair; +import net.imglib2.util.ValuePair; +import net.imglib2.view.Views; + +public enum AxisOrder implements EuclideanSpace +{ + XYZ ( 3, 2, -1, -1 ), // --> XYZ + XYZC ( 4, 2, 3, -1 ), // --> XYZ + XYZT ( 4, 2, -1, 3 ), // --> XYZT + XYZCT ( 5, 2, 3, 4 ), // --> XYZT + XYZTC ( 5, 2, 4, 3 ), // --> XYZT + XYCZT ( 5, 3, 2, 4 ), // --> XYZT + XY ( 2, -1, -1, -1 ), // --> XY --> XYZ + XYC ( 3, -1, 2, -1 ), // --> XY --> XYZ + XYT ( 3, -1, -1, 2 ), // --> XYT --> XYTZ --> XYZT + XYCT ( 4, -1, 2, 3 ), // --> XYT --> XYTZ --> XYZT + XYTC ( 4, -1, 3, 2 ), // --> XYT --> XYTZ --> XYZT + XYCZ ( 4, 3, 2, -1 ), // --> XYZ + DEFAULT( 0, 0, 0, 0 ); + + final int numDimensions; + + final int zDimension; + + final int channelDimension; + + final int timeDimension; + + AxisOrder( + final int numDimensions, + final int zDimension, + final int channelDimension, + final int timeDimension ) + { + this.numDimensions = numDimensions; + this.zDimension = zDimension; + this.channelDimension = channelDimension; + this.timeDimension = timeDimension; + } + + public static AxisOrder getAxisOrder( final AxisOrder axisOrder, final EuclideanSpace space, final boolean viewerIs2D ) + { + if ( axisOrder == DEFAULT ) + { + if ( viewerIs2D ) + { + switch ( space.numDimensions() ) + { + case 2: + return XY; + case 3: + return XYT; + case 4: + return XYTC; + case 5: + return XYZTC; + } + } + else + { + switch ( space.numDimensions() ) + { + case 2: + return XY; + case 3: + return XYZ; + case 4: + return XYZT; + case 5: + return XYZTC; + } + } + throw new IllegalArgumentException( "image dimensionality " + space.numDimensions() + " is not supported" ); + } + return axisOrder; + } + + public static < T > ArrayList< RandomAccessibleInterval< T > > splitInputStackIntoSourceStacks( + final RandomAccessibleInterval< T > img, + final AxisOrder axisOrder ) + { + if ( img.numDimensions() != axisOrder.numDimensions ) + throw new IllegalArgumentException( "provided AxisOrder doesn't match dimensionality of image" ); + + final ArrayList< RandomAccessibleInterval< T > > sourceStacks = new ArrayList< >(); + + /* + * If there a channels dimension, slice img along that dimension. + */ + final int c = axisOrder.channelDimension; + if ( c != -1 ) + { + final int numSlices = ( int ) img.dimension( c ); + for ( int s = 0; s < numSlices; ++s ) + sourceStacks.add( Views.hyperSlice( img, c, s + img.min( c ) ) ); + } + else + sourceStacks.add( img ); + + /* + * If AxisOrder is a 2D variant (has no Z dimension), augment the + * sourceStacks by a Z dimension. + */ + final boolean addZ = !axisOrder.hasZ(); + if ( addZ ) + for ( int i = 0; i < sourceStacks.size(); ++i ) + sourceStacks.set( i, Views.addDimension( sourceStacks.get( i ), 0, 0 ) ); + + /* + * If at this point the dim order is XYTZ, permute to XYZT + */ + final boolean flipZ = !axisOrder.hasZ() && axisOrder.hasTimepoints(); + if ( flipZ ) + for ( int i = 0; i < sourceStacks.size(); ++i ) + sourceStacks.set( i, Views.permute( sourceStacks.get( i ), 2, 3 ) ); + + return sourceStacks; + } + + public static < T > Pair< ArrayList< RandomAccessible< T > >, Interval > splitInputStackIntoSourceStacks( + final RandomAccessible< T > img, + Interval interval, + final AxisOrder axisOrder ) + { + if ( img.numDimensions() != axisOrder.numDimensions ) + throw new IllegalArgumentException( "provided AxisOrder doesn't match dimensionality of image" ); + + final ArrayList< RandomAccessible< T > > sourceStacks = new ArrayList<>(); + + /* + * If there a channels dimension, slice img along that dimension. + */ + final int c = axisOrder.channelDimension; + if ( c != -1 ) + { + final long[] min = new long[ interval.numDimensions() -1 ]; + final long[] max = new long[ interval.numDimensions() -1 ]; + for ( int dim = 0; dim < min.length; ++dim ) { + final int otherIndex = dim >= axisOrder.channelDimension ? dim + 1 : dim; + min[ dim ] = interval.min( otherIndex ); + max[ dim ] = interval.max( otherIndex ); + } + interval = new FinalInterval( min, max ); + final int numSlices = ( int ) interval.dimension( c ); + for ( int s = 0; s < numSlices; ++s ) + sourceStacks.add( Views.hyperSlice( img, c, s + interval.min( c ) ) ); + } + else + sourceStacks.add( img ); + + /* + * If AxisOrder is a 2D variant (has no Z dimension), augment the + * sourceStacks by a Z dimension. + */ + final boolean addZ = !axisOrder.hasZ(); + if ( addZ ) + { + final long[] min = LongStream.concat( Arrays.stream( Intervals.minAsLongArray( interval ) ), LongStream.of( 0 ) ).toArray(); + final long[] max = LongStream.concat( Arrays.stream( Intervals.maxAsLongArray( interval ) ), LongStream.of( 0 ) ).toArray(); + interval = new FinalInterval( min, max ); + for ( int i = 0; i < sourceStacks.size(); ++i ) + sourceStacks.set( i, Views.addDimension( sourceStacks.get( i ) ) ); + } + + /* + * If at this point the dim order is XYTZ, permute to XYZT + */ + final boolean flipZ = !axisOrder.hasZ() && axisOrder.hasTimepoints(); + if ( flipZ ) + { + final long[] min = Intervals.minAsLongArray( interval ); + final long[] max = Intervals.maxAsLongArray( interval ); + final long minTmp = min[ 3 ]; + final long maxTmp = max[ 3 ]; + min[ 3 ] = min[ 2 ]; + max[ 3 ] = max[ 2 ]; + min[ 2 ] = minTmp; + max[ 2 ] = maxTmp; + interval = new FinalInterval( min, max ); + for ( int i = 0; i < sourceStacks.size(); ++i ) + sourceStacks.set( i, Views.permute( sourceStacks.get( i ), 2, 3 ) ); + } + + return new ValuePair<>( sourceStacks, interval ); + } + + public int zDimension() + { + return zDimension; + } + + public boolean hasZ() + { + return zDimension >= 0; + } + + public int channelDimension() + { + return channelDimension; + } + + public boolean hasChannels() + { + return channelDimension >= 0; + } + + public long numChannels( Dimensions dimensions ) + { + return hasChannels() ? dimensions.dimension( channelDimension ) : 1; + } + + public int timeDimension() + { + return timeDimension; + } + + public boolean hasTimepoints() + { + return timeDimension >= 0; + } + + public long numTimepoints( Dimensions dimensions ) + { + return hasTimepoints() ? dimensions.dimension( timeDimension ) : 1; + } + + @Override + public int numDimensions() + { + return numDimensions; + } +} diff --git a/src/main/java/bdv/util/Bdv.java b/src/main/java/bdv/util/Bdv.java new file mode 100644 index 00000000..b344d69a --- /dev/null +++ b/src/main/java/bdv/util/Bdv.java @@ -0,0 +1,55 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +/** + * Something that has a {@link BdvHandle}. This includes {@link BdvSource}s, as + * well as {@link BdvHandle}s (which return themselves with + * {@link #getBdvHandle()}). + *

+ * Having a {@link Bdv} is useful for adding more stuff to a BigDataViewer + * window or panel. This is done using + * {@code BdvFunctions.show(..., Bdv.options().addTo(myBdv))}. + * + * @author Tobias Pietzsch <tobias.pietzsch@gmail.com> + */ +public interface Bdv +{ + BdvHandle getBdvHandle(); + + default void close() + { + getBdvHandle().close(); + } + + static BdvOptions options() + { + return BdvOptions.options(); + } +} diff --git a/src/main/java/bdv/util/BdvFunctions.java b/src/main/java/bdv/util/BdvFunctions.java new file mode 100644 index 00000000..beeab23a --- /dev/null +++ b/src/main/java/bdv/util/BdvFunctions.java @@ -0,0 +1,795 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.imglib2.FinalInterval; +import net.imglib2.Interval; +import net.imglib2.RandomAccessible; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealInterval; +import net.imglib2.RealLocalizable; +import net.imglib2.RealRandomAccessible; +import net.imglib2.converter.Converter; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.realtransform.RealViews; +import net.imglib2.type.Type; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.type.numeric.RealType; +import net.imglib2.type.volatiles.VolatileARGBType; +import net.imglib2.util.Pair; +import net.imglib2.util.Util; +import net.imglib2.view.Views; + +import org.scijava.ui.behaviour.io.InputTriggerConfig; + +import bdv.BigDataViewer; +import bdv.ViewerImgLoader; +import bdv.cache.CacheControl; +import bdv.img.cache.VolatileGlobalCellCache; +import bdv.spimdata.WrapBasicImgLoader; +import bdv.tools.boundingbox.BoxSelectionOptions; +import bdv.tools.boundingbox.TransformedBoxSelectionDialog; +import bdv.tools.boundingbox.TransformedRealBoxSelectionDialog; +import bdv.tools.brightness.ConverterSetup; +import bdv.tools.brightness.SetupAssignments; +import bdv.tools.transformation.TransformedSource; +import bdv.util.VirtualChannels.VirtualChannel; +import bdv.util.volatiles.VolatileView; +import bdv.util.volatiles.VolatileViewData; +import bdv.viewer.Source; +import bdv.viewer.SourceAndConverter; +import mpicbg.spim.data.generic.AbstractSpimData; +import mpicbg.spim.data.generic.sequence.AbstractSequenceDescription; + +/** + * all show methods return a {@link Bdv} which can be used to add more stuff to the same window + * + * + * @author Tobias Pietzsch + * @author Philipp Hanslovsky + * @author Igor Pisarev + * @author Stephan Saalfeld + */ +public class BdvFunctions +{ + public static BdvHandle show() + { + return show( Bdv.options() ); + } + + public static BdvHandle show( + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + if ( handle instanceof BdvHandleFrame && ( ( BdvHandleFrame ) handle ).getBigDataViewer() == null ) + handle.createViewer( Collections.emptyList(), Collections.emptyList(), 1 ); + return handle; + } + + public static < T > BdvStackSource< T > show( + final RandomAccessibleInterval< T > img, + final String name ) + { + return show( img, name, Bdv.options() ); + } + + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public static < T > BdvStackSource< T > show( + final RandomAccessibleInterval< T > img, + final String name, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + final AxisOrder axisOrder = AxisOrder.getAxisOrder( options.values.axisOrder(), img, handle.is2D() ); + final AffineTransform3D sourceTransform = options.values.getSourceTransform(); + final T type; + if ( img instanceof VolatileView ) + { + final VolatileViewData< ?, ? > viewData = ( ( VolatileView< ?, ? > ) img ).getVolatileViewData(); + type = ( T ) viewData.getVolatileType(); + handle.getCacheControls().addCacheControl( viewData.getCacheControl() ); + } + else + type = Util.getTypeFromInterval( img ); + + return addRandomAccessibleInterval( handle, ( RandomAccessibleInterval ) img, ( NumericType ) type, name, axisOrder, sourceTransform ); + } + + public static < T extends NumericType< T > > BdvStackSource< T > show( + final RandomAccessible< T > img, + final Interval interval, + final String name ) + { + return show( img, interval, name, Bdv.options() ); + } + + // TODO version with numTimepoints argument + @SuppressWarnings( "unchecked" ) + public static < T extends NumericType< T > > BdvStackSource< T > show( + final RandomAccessible< T > img, + final Interval interval, + final String name, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + final int numTimepoints = 1; + final AxisOrder axisOrder = AxisOrder.getAxisOrder( options.values.axisOrder(), img, handle.is2D() ); + final AffineTransform3D sourceTransform = options.values.getSourceTransform(); + final T type; + if ( img instanceof VolatileView ) + { + final VolatileViewData< ?, ? > viewData = ( ( VolatileView< ?, ? > ) img ).getVolatileViewData(); + type = ( T ) viewData.getVolatileType(); + handle.getCacheControls().addCacheControl( viewData.getCacheControl() ); + } + else + type = Util.getTypeFromInterval( Views.interval( img, interval ) ); + + return addRandomAccessible( handle, img, interval, numTimepoints, type, name, axisOrder, sourceTransform ); + } + + public static < T extends Type< T > > BdvStackSource< T > show( + final RealRandomAccessible< T > img, + final Interval interval, + final String name ) + { + return show( img, interval, name, Bdv.options() ); + } + + public static < T extends Type< T > > BdvStackSource< T > show( + final RealRandomAccessible< T > img, + final Interval interval, + final String name, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + final AxisOrder axisOrder = AxisOrder.getAxisOrder( options.values.axisOrder(), img, handle.is2D() ); + final AffineTransform3D sourceTransform = options.values.getSourceTransform(); + final T type = img.realRandomAccess().get(); + return addRealRandomAccessible( handle, img, interval, type, name, axisOrder, sourceTransform ); + } + + public static List< BdvVirtualChannelSource > show( + final RandomAccessibleInterval< ARGBType > img, + final List< ? extends VirtualChannel > virtualChannels, + final String name ) + { + return show( img, virtualChannels, name, Bdv.options() ); + } + + public static List< BdvVirtualChannelSource > show( + final RandomAccessibleInterval< ARGBType > img, + final List< ? extends VirtualChannel > virtualChannels, + final String name, + final BdvOptions options ) + { + return VirtualChannels.show( img, virtualChannels, name, options ); + } + + public static < T > BdvStackSource< T > show( + final Source< T > source ) + { + return show( source, Bdv.options() ); + } + + public static < T > BdvStackSource< T > show( + final Source< T > source, + final BdvOptions options ) + { + return show( source, 1, options ); + } + + public static < T > BdvStackSource< T > show( + final Source< T > source, + final int numTimePoints ) + { + return show( source, numTimePoints, Bdv.options() ); + } + + public static < T > BdvStackSource< T > show( + final Source< T > source, + final int numTimePoints, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + @SuppressWarnings( { "unchecked", "rawtypes" } ) + final BdvStackSource< T > stackSource = addSource( handle, ( Source ) source, numTimePoints ); + return stackSource; + } + + public static < T > BdvStackSource< T > show( + final SourceAndConverter< T > source ) + { + return show( source, Bdv.options() ); + } + + public static < T > BdvStackSource< T > show( + final SourceAndConverter< T > source, + final BdvOptions options ) + { + return show( source, 1, options ); + } + + public static < T > BdvStackSource< T > show( + final SourceAndConverter< T > source, + final int numTimePoints ) + { + return show( source, numTimePoints, Bdv.options() ); + } + + public static < T > BdvStackSource< T > show( + final SourceAndConverter< T > soc, + final int numTimepoints, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + final T type = soc.getSpimSource().getType(); + final int setupId = handle.getUnusedSetupId(); + final List< ConverterSetup > converterSetups = Collections.singletonList( BigDataViewer.createConverterSetup( soc, setupId ) ); + final List< SourceAndConverter< T > > sources = Collections.singletonList( soc ); + handle.add( converterSetups, sources, numTimepoints ); + final BdvStackSource< T > bdvSource = new BdvStackSource<>( handle, numTimepoints, type, converterSetups, sources ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + public static < T > BdvStackSource< T > show( + final List< SourceAndConverter< T > > sources, + final int numTimepoints, + final BdvOptions options ) + { + if ( sources.isEmpty() ) + throw new IllegalArgumentException(); + final BdvHandle handle = getHandle( options ); + final T type = sources.get( 0 ).getSpimSource().getType(); + final List< ConverterSetup > converterSetups = new ArrayList<>( sources.size() ); + for ( final SourceAndConverter< T > source : sources ) + { + final int setupId = handle.getUnusedSetupId(); + ConverterSetup converterSetup = BigDataViewer.createConverterSetup( source, setupId ); + handle.add( Collections.singletonList( converterSetup ), Collections.singletonList( source ), numTimepoints ); + converterSetups.add( converterSetup ); + } + final BdvStackSource< T > bdvSource = new BdvStackSource<>( handle, numTimepoints, type, converterSetups, sources ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + public static < T > BdvStackSource< T > show( final ChannelSources< T > channels ) + { + return show( channels, Bdv.options() ); + } + + public static < T > BdvStackSource< T > show( + final ChannelSources< T > channels, + final BdvOptions options ) + { + final List< SourceAndConverter< T > > sources = channels.getSources(); + if ( sources.isEmpty() ) + throw new IllegalArgumentException(); + final int numTimepoints = channels.numTimepoints(); + + final BdvHandle handle = getHandle( options ); + final List< ConverterSetup > converterSetups = new ArrayList<>( sources.size() ); + for ( final SourceAndConverter< T > source : sources ) + { + final int setupId = handle.getUnusedSetupId(); + ConverterSetup converterSetup = BigDataViewer.createConverterSetup( source, setupId ); + handle.add( Collections.singletonList( converterSetup ), Collections.singletonList( source ), numTimepoints ); + converterSetups.add( converterSetup ); + } + final T type = channels.getType(); + final BdvStackSource< T > bdvSource = new BdvStackSource( handle, numTimepoints, type, converterSetups, sources ); + handle.addBdvSource( bdvSource ); + + final CacheControl cacheControl = channels.getCacheControl(); + if ( cacheControl != null ) + handle.getCacheControls().addCacheControl( cacheControl ); + + return bdvSource; + } + + public static List< BdvStackSource< ? > > show( + final AbstractSpimData< ? > spimData ) + { + return show( spimData, Bdv.options() ); + } + + public static List< BdvStackSource< ? > > show( + final AbstractSpimData< ? > spimData, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + WrapBasicImgLoader.wrapImgLoaderIfNecessary( spimData ); + + final AbstractSequenceDescription< ?, ?, ? > seq = spimData.getSequenceDescription(); + final int numTimepoints = seq.getTimePoints().size(); + final CacheControl cache = ( ( ViewerImgLoader ) seq.getImgLoader() ).getCacheControl(); + handle.getBdvHandle().getCacheControls().addCacheControl( cache ); + if ( cache instanceof VolatileGlobalCellCache ) + ( ( VolatileGlobalCellCache ) cache ).clearCache(); + + final ArrayList< SourceAndConverter< ? > > sources = new ArrayList<>(); + BigDataViewer.initSetups( spimData, new ArrayList<>(), sources ); + + final List< BdvStackSource< ? > > bdvSources = new ArrayList<>(); + for ( final SourceAndConverter< ? > source : sources ) + bdvSources.add( addSpimDataSource( handle, source, numTimepoints ) ); + + WrapBasicImgLoader.removeWrapperIfPresent( spimData ); + return bdvSources; + } + + public static BdvPointsSource showPoints( + final List< ? extends RealLocalizable > points, + final String name ) + { + return showPoints( points, name, Bdv.options() ); + } + + public static BdvPointsSource showPoints( + final List< ? extends RealLocalizable > points, + final String name, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + final AffineTransform3D sourceTransform = options.values.getSourceTransform(); + + final int setupId = handle.getUnusedSetupId(); + final ARGBType defaultColor = new ARGBType( 0xff00ff00 ); + final PlaceHolderConverterSetup setup = new PlaceHolderConverterSetup( setupId, 0, 255, defaultColor ); + final PlaceHolderSource source = new PlaceHolderSource( name ); + final SourceAndConverter< Void > soc = new SourceAndConverter<>( source, null ); + + final List< ConverterSetup > converterSetups = new ArrayList<>( Collections.singletonList( setup ) ); + final List< SourceAndConverter< Void > > sources = new ArrayList<>( Collections.singletonList( soc ) ); + + final int numTimepoints = 1; + handle.add( converterSetups, sources, numTimepoints ); + + final PlaceHolderOverlayInfo info = new PlaceHolderOverlayInfo( handle.getViewerPanel(), soc, setup ); + final PointsOverlay overlay = new PointsOverlay(); + overlay.setOverlayInfo( info ); + overlay.setPoints( points ); + overlay.setSourceTransform( sourceTransform ); + handle.getViewerPanel().getDisplay().overlays().add( overlay ); + + final BdvPointsSource bdvSource = new BdvPointsSource( handle, numTimepoints, setup, soc, info, overlay ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + public static < O extends BdvOverlay > BdvOverlaySource< O > showOverlay( + final O overlay, + final String name ) + { + return showOverlay( overlay, name, Bdv.options() ); + } + + public static < O extends BdvOverlay > BdvOverlaySource< O > showOverlay( + final O overlay, + final String name, + final BdvOptions options ) + { + final BdvHandle handle = getHandle( options ); + final AffineTransform3D sourceTransform = options.values.getSourceTransform(); + + final int setupId = handle.getUnusedSetupId(); + final ARGBType defaultColor = new ARGBType( 0xff00ff00 ); + final PlaceHolderConverterSetup setup = new PlaceHolderConverterSetup( setupId, 0, 255, defaultColor ); + final PlaceHolderSource source = new PlaceHolderSource( name ); + final SourceAndConverter< Void > soc = new SourceAndConverter<>( source, null ); + + final List< ConverterSetup > converterSetups = new ArrayList<>( Collections.singletonList( setup ) ); + final List< SourceAndConverter< Void > > sources = new ArrayList<>( Collections.singletonList( soc ) ); + + final int numTimepoints = 1; + handle.add( converterSetups, sources, numTimepoints ); + + final PlaceHolderOverlayInfo info = new PlaceHolderOverlayInfo( handle.getViewerPanel(), soc, setup ); + overlay.setOverlayInfo( info ); + overlay.setSourceTransform( sourceTransform ); + handle.getViewerPanel().getDisplay().overlays().add( overlay ); + + final BdvOverlaySource< O > bdvSource = new BdvOverlaySource<>( handle, numTimepoints, setup, soc, info, overlay ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + // TODO: move to BdvFunctionUtils + + /** + * @deprecated Ok to use for now, but shouldn't be required in the future. + */ + public static int getUnusedSetupId( final BigDataViewer bdv ) + { + return getUnusedSetupId( bdv.getSetupAssignments() ); + } + + // TODO: move to BdvFunctionUtils + /** + * @deprecated Ok to use for now, but shouldn't be required in the future. + */ + public static synchronized int getUnusedSetupId( final SetupAssignments setupAssignments ) + { + return SetupAssignments.getUnusedSetupId( setupAssignments ); + } + + public static TransformedRealBoxSelectionDialog.Result selectRealBox( + final Bdv bdv, + final AffineTransform3D boxTransform, + final RealInterval initialInterval, + final RealInterval rangeInterval ) + { + return selectRealBox( bdv, boxTransform, initialInterval, rangeInterval, BoxSelectionOptions.options() ); + } + + public static TransformedRealBoxSelectionDialog.Result selectRealBox( + final Bdv bdv, + final AffineTransform3D boxTransform, + final RealInterval initialInterval, + final RealInterval rangeInterval, + final BoxSelectionOptions options ) + { + final BdvHandle handle = bdv.getBdvHandle(); + + InputTriggerConfig keyConfig = options.values.getInputTriggerConfig(); + if ( keyConfig == null ) + keyConfig = new InputTriggerConfig(); + + return new TransformedRealBoxSelectionDialog( + handle.getViewerPanel(), + handle.getConverterSetups(), + handle.getUnusedSetupId(), + keyConfig, + handle.getTriggerbindings(), + boxTransform, + initialInterval, + rangeInterval, + options + ).getResult(); + } + + public static TransformedBoxSelectionDialog.Result selectBox( + final Bdv bdv, + final AffineTransform3D boxTransform, + final Interval initialInterval, + final Interval rangeInterval ) + { + return selectBox( bdv, boxTransform, initialInterval, rangeInterval, BoxSelectionOptions.options() ); + } + + public static TransformedBoxSelectionDialog.Result selectBox( + final Bdv bdv, + final AffineTransform3D boxTransform, + final Interval initialInterval, + final Interval rangeInterval, + final BoxSelectionOptions options ) + { + final BdvHandle handle = bdv.getBdvHandle(); + + InputTriggerConfig keyConfig = options.values.getInputTriggerConfig(); + if ( keyConfig == null ) + keyConfig = new InputTriggerConfig(); + + return new TransformedBoxSelectionDialog( + handle.getViewerPanel(), + handle.getConverterSetups(), + handle.getUnusedSetupId(), + keyConfig, + handle.getTriggerbindings(), + boxTransform, + initialInterval, + rangeInterval, + options + ).getResult(); + } + + /** + * Get existing {@code BdvHandle} from {@code options} or create a new + * {@code BdvHandleFrame}. + */ + private static BdvHandle getHandle( final BdvOptions options ) + { + final Bdv bdv = options.values.addTo(); + return ( bdv == null ) + ? new BdvHandleFrame( options ) + : bdv.getBdvHandle(); + } + + /** + * Add the given {@link RandomAccessibleInterval} {@code img} to the given + * {@link BdvHandle} as a new {@link BdvStackSource}. The {@code img} is + * expected to be 2D, 3D, 4D, or 5D with the given {@link AxisOrder}. + * + * @param handle + * handle to add the {@code img} to. + * @param img + * {@link RandomAccessibleInterval} to add. + * @param type + * instance of the {@code img} type. + * @param name + * name to give to the new source + * @param axisOrder + * {@link AxisOrder} of the source, is used to appropriately split {@code img} into channels and timepoints. + * @param sourceTransform + * transforms from source coordinates to global coordinates. + * @return a new {@link BdvStackSource} handle for the newly added source(s). + */ + private static < T extends NumericType< T > > BdvStackSource< T > addRandomAccessibleInterval( + final BdvHandle handle, + final RandomAccessibleInterval< T > img, + final T type, + final String name, + final AxisOrder axisOrder, + final AffineTransform3D sourceTransform ) + { + final List< ConverterSetup > converterSetups = new ArrayList<>(); + final List< SourceAndConverter< T > > sources = new ArrayList<>(); + final ArrayList< RandomAccessibleInterval< T > > stacks = AxisOrder.splitInputStackIntoSourceStacks( img, axisOrder ); + int numTimepoints = 1; + for ( final RandomAccessibleInterval< T > stack : stacks ) + { + final Source< T > s; + if ( stack.numDimensions() > 3 ) + { + numTimepoints = ( int ) stack.max( 3 ) + 1; + s = new RandomAccessibleIntervalSource4D<>( stack, type, sourceTransform, name ); + } + else + { + s = new RandomAccessibleIntervalSource<>( stack, type, sourceTransform, name ); + } + addSourceToListsGenericType( s, handle.getUnusedSetupId(), converterSetups, sources ); + } + handle.add( converterSetups, sources, numTimepoints ); + final BdvStackSource< T > bdvSource = new BdvStackSource<>( handle, numTimepoints, type, converterSetups, sources ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + /** + * Add the given {@link RandomAccessible} {@code img} to the given + * {@link BdvHandle} as a new {@link BdvStackSource}. The {@code img} is + * expected to be 2D, 3D, 4D, or 5D with the given {@link AxisOrder}. + * + * @param handle + * handle to add the {@code img} to. + * @param img + * {@link RandomAccessible} to add. + * @param interval + * interval of the source (this is only used in the navigation + * box overlay in BDV). + * @param numTimepoints + * the number of timepoints of the source. + * @param type + * instance of the {@code img} type. + * @param name + * name to give to the new source + * @param axisOrder + * {@link AxisOrder} of the source, is used to appropriately split {@code img} into channels and timepoints. + * @param sourceTransform + * transforms from source coordinates to global coordinates. + * @return a new {@link BdvStackSource} handle for the newly added source(s). + */ + private static < T extends NumericType< T > > BdvStackSource< T > addRandomAccessible( + final BdvHandle handle, + final RandomAccessible< T > img, + final Interval interval, + final int numTimepoints, + final T type, + final String name, + final AxisOrder axisOrder, + final AffineTransform3D sourceTransform ) + { + + final List< ConverterSetup > converterSetups = new ArrayList<>(); + final List< SourceAndConverter< T > > sources = new ArrayList<>(); + final Pair< ArrayList< RandomAccessible< T > >, Interval > stacksAndInterval = AxisOrder.splitInputStackIntoSourceStacks( + img, + interval, + axisOrder ); + final ArrayList< RandomAccessible< T > > stacks = stacksAndInterval.getA(); + final Interval stackInterval = stacksAndInterval.getB(); + for ( final RandomAccessible< T > stack : stacks ) + { + final Source< T > s; + if ( stack.numDimensions() > 3 ) + s = new RandomAccessibleSource4D<>( stack, stackInterval, type, sourceTransform, name ); + else + s = new RandomAccessibleSource<>( stack, stackInterval, type, sourceTransform, name ); + addSourceToListsGenericType( s, handle.getUnusedSetupId(), converterSetups, sources ); + } + + handle.add( converterSetups, sources, numTimepoints ); + final BdvStackSource< T > bdvSource = new BdvStackSource<>( handle, numTimepoints, type, converterSetups, sources ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + /** + * Add the given {@link RealRandomAccessible} {@code img} to the given + * {@link BdvHandle} as a new {@link BdvStackSource}. The {@code img} is + * expected to be 2D or 3D, and the new source will have one timepoint. + * + * @param handle + * handle to add the {@code img} to. + * @param img + * {@link RealRandomAccessible} to add. + * @param interval + * interval of the source (this is only used in the navigation + * box overlay in BDV). + * @param type + * instance of the {@code img} type. + * @param name + * name to give to the new source + * @param axisOrder + * {@link AxisOrder} of the source, must be {@link AxisOrder#XY} + * or {@link AxisOrder#XYZ}. + * @param sourceTransform + * transforms from source coordinates to global coordinates. + * @return a new {@link BdvStackSource} handle for the newly added source. + */ + private static < T extends Type< T > > BdvStackSource< T > addRealRandomAccessible( + final BdvHandle handle, + RealRandomAccessible< T > img, + Interval interval, + final T type, + final String name, + final AxisOrder axisOrder, + final AffineTransform3D sourceTransform ) + { + /* + * If AxisOrder is a 2D variant (has no Z dimension), augment the + * sourceStacks by a Z dimension. + */ + if ( !axisOrder.hasZ() ) + { + img = RealViews.addDimension( img ); + interval = new FinalInterval( + new long[]{ interval.min( 0 ), interval.min( 1 ), 0 }, + new long[]{ interval.max( 0 ), interval.max( 1 ), 0 } ); + } + + final Source< T > s = new RealRandomAccessibleIntervalSource<>( img, interval, type, sourceTransform, name ); + return addSource( handle, s, 1 ); + } + + /** + * Add the given {@link Source} to the given {@link BdvHandle} as a new + * {@link BdvStackSource}. + * + * @param handle + * handle to add the {@code source} to. + * @param source + * source to add. + * @param numTimepoints + * the number of timepoints of the source. + * @return a new {@link BdvStackSource} handle for the newly added + * {@code source}. + */ + @SuppressWarnings( "rawtypes" ) + private static < T > BdvStackSource< T > addSource( + final BdvHandle handle, + final Source< T > source, + final int numTimepoints ) + { + final T type = source.getType(); + final List< ConverterSetup > converterSetups = new ArrayList<>(); + final List< SourceAndConverter< T > > sources = new ArrayList<>(); + addSourceToListsGenericType( source, handle.getUnusedSetupId(), converterSetups, sources ); + handle.add( converterSetups, sources, numTimepoints ); + final BdvStackSource< T > bdvSource = new BdvStackSource<>( handle, numTimepoints, type, converterSetups, sources ); + handle.addBdvSource( bdvSource ); + return bdvSource; + } + + /** + * Add the given {@code source} to the lists of {@code converterSetups} + * (using specified {@code setupId}) and {@code sources}. For this, the + * {@code source} is wrapped with an appropriate {@link Converter} to + * {@link ARGBType} and into a {@link TransformedSource}. + * + * @param source + * source to add. + * @param setupId + * id of the new source for use in {@link SetupAssignments}. + * @param converterSetups + * list of {@link ConverterSetup}s to which the source should be + * added. + * @param sources + * list of {@link SourceAndConverter}s to which the source should + * be added. + */ + @SuppressWarnings( { "rawtypes", "unchecked" } ) + private static < T > void addSourceToListsGenericType( + final Source< T > source, + final int setupId, + final List< ConverterSetup > converterSetups, + final List< SourceAndConverter< T > > sources ) + { + final T type = source.getType(); + if ( type instanceof RealType || type instanceof ARGBType || type instanceof VolatileARGBType ) + addSourceToListsNumericType( ( Source ) source, setupId, converterSetups, ( List ) sources ); + else + throw new IllegalArgumentException( "Unknown source type. Expected RealType, ARGBType, or VolatileARGBType" ); + } + + /** + * Add the given {@code source} to the lists of {@code converterSetups} + * (using specified {@code setupId}) and {@code sources}. For this, the + * {@code source} is wrapped with an appropriate {@link Converter} to + * {@link ARGBType} and into a {@link TransformedSource}. + * + * @param source + * source to add. + * @param setupId + * id of the new source for use in {@link SetupAssignments}. + * @param converterSetups + * list of {@link ConverterSetup}s to which the source should be + * added. + * @param sources + * list of {@link SourceAndConverter}s to which the source should + * be added. + */ + private static < T extends NumericType< T > > void addSourceToListsNumericType( + final Source< T > source, + final int setupId, + final List< ConverterSetup > converterSetups, + final List< SourceAndConverter< T > > sources ) + { + final T type = source.getType(); + final SourceAndConverter< T > soc = BigDataViewer.wrapWithTransformedSource( + new SourceAndConverter<>( source, BigDataViewer.createConverterToARGB( type ) ) ); + converterSetups.add( BigDataViewer.createConverterSetup( soc, setupId ) ); + sources.add( soc ); + } + + private static < T > BdvStackSource< T > addSpimDataSource( + final BdvHandle handle, + final SourceAndConverter< T > source, + final int numTimepoints ) + { + final ConverterSetup setup = BigDataViewer.createConverterSetup( source, handle.getUnusedSetupId() ); + final List< ConverterSetup > setups = Collections.singletonList( setup ); + final List< SourceAndConverter< T > > sources = Collections.singletonList( source ); + handle.add( setups, sources, numTimepoints ); + + final T type = source.getSpimSource().getType(); + final BdvStackSource< T > bdvSource = new BdvStackSource<>( handle, numTimepoints, type, setups, sources ); + handle.addBdvSource( bdvSource ); + + return bdvSource; + } +} diff --git a/src/main/java/bdv/util/BdvHandle.java b/src/main/java/bdv/util/BdvHandle.java new file mode 100644 index 00000000..f40ef2e5 --- /dev/null +++ b/src/main/java/bdv/util/BdvHandle.java @@ -0,0 +1,304 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.ui.CardPanel; +import bdv.ui.appearance.AppearanceManager; +import bdv.ui.keymap.KeymapManager; +import bdv.ui.splitpanel.SplitPanel; +import bdv.viewer.ConverterSetups; +import bdv.viewer.ViewerStateChangeListener; +import java.util.ArrayList; +import java.util.List; + +import org.scijava.ui.behaviour.util.InputActionBindings; +import org.scijava.ui.behaviour.util.TriggerBehaviourBindings; + +import bdv.cache.CacheControl.CacheControls; +import bdv.tools.InitializeViewerState; +import bdv.tools.brightness.ConverterSetup; +import bdv.tools.brightness.SetupAssignments; +import bdv.tools.transformation.ManualTransformationEditor; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.TimePointListener; +import bdv.viewer.ViewerPanel; +import net.imglib2.realtransform.AffineTransform3D; +import bdv.viewer.OverlayRenderer; +import bdv.viewer.TransformListener; + +/** + * Represents a BigDataViewer frame or panel and can be used to get to the bdv + * internals. + * + * @author Tobias Pietzsch + */ +public abstract class BdvHandle implements Bdv +{ + protected ViewerPanel viewer; + + protected CardPanel cards; + + protected SplitPanel splitPanel; + + protected ConverterSetups setups; + + // TODO: Remove + protected SetupAssignments setupAssignments; + + protected final ArrayList< BdvSource > bdvSources; + + protected final BdvOptions bdvOptions; + + protected boolean hasPlaceHolderSources; + + protected final int origNumTimepoints; + + protected CacheControls cacheControls; + + public BdvHandle( final BdvOptions options ) + { + bdvOptions = options; + bdvSources = new ArrayList<>(); + origNumTimepoints = 1; + } + + @Override + public BdvHandle getBdvHandle() + { + return this; + } + + public ViewerPanel getViewerPanel() + { + return viewer; + } + + public CardPanel getCardPanel() + { + return cards; + } + + public SplitPanel getSplitPanel() + { + return splitPanel; + } + + public ConverterSetups getConverterSetups() + { + return setups; + } + + // TODO: REMOVE + @Deprecated + public SetupAssignments getSetupAssignments() + { + return setupAssignments; + } + + public CacheControls getCacheControls() + { + return cacheControls; + } + + public abstract KeymapManager getKeymapManager(); + + public abstract AppearanceManager getAppearanceManager(); + + @Deprecated + int getUnusedSetupId() + { + return BdvFunctions.getUnusedSetupId( setupAssignments ); + } + + @Override + public void close() + { + if ( viewer != null ) + { + viewer.stop(); + bdvSources.clear(); + cacheControls.clear(); + + viewer = null; + cards = null; + splitPanel = null; + setups = null; + setupAssignments = null; + cacheControls = null; + } + } + + public abstract ManualTransformationEditor getManualTransformEditor(); + + public abstract InputActionBindings getKeybindings(); + + public abstract TriggerBehaviourBindings getTriggerbindings(); + + abstract boolean createViewer( + final List< ? extends ConverterSetup > converterSetups, + final List< ? extends SourceAndConverter< ? > > sources, + final int numTimepoints ); + + void add( + final List< ? extends ConverterSetup > converterSetups, + final List< ? extends SourceAndConverter< ? > > sources, + final int numTimepoints ) + { + final boolean initTransform; + if ( viewer == null ) + { + initTransform = createViewer( converterSetups, sources, numTimepoints ); + } + else + { + initTransform = viewer.state().getSources().isEmpty() && sources != null && !sources.isEmpty(); + + if ( converterSetups != null && sources != null && converterSetups.size() != sources.size() ) + System.err.println( "WARNING! Adding sources to BdvHandle with converterSetups.size() != sources.size()." ); + + if ( converterSetups != null ) + { + final int numSetups = Math.min( converterSetups.size(), sources.size() ); + for ( int i = 0; i < numSetups; ++i ) + { + final SourceAndConverter< ? > source = sources.get( i ); + final ConverterSetup setup = converterSetups.get( i ); + if ( setup != null ) + setups.put( source, setup ); + } + + // TODO: REMOVE + converterSetups.forEach( setupAssignments::addSetup ); + } + + if ( sources != null ) + for ( final SourceAndConverter< ? > soc : sources ) + { + viewer.state().addSource( soc ); + viewer.state().setSourceActive( soc, true ); + } + } + + if ( initTransform ) + { + synchronized ( this ) + { + initTransformPending = true; + tryInitTransform(); + } + } + } + + private boolean initTransformPending; + + protected synchronized void tryInitTransform() + { + if ( viewer.getDisplay().getWidth() <= 0 || viewer.getDisplay().getHeight() <= 0 ) + return; + + if ( initTransformPending ) + { + initTransformPending = false; + InitializeViewerState.initTransform( viewer ); + } + } + + void remove( + final List< ? extends ConverterSetup > converterSetups, + final List< ? extends SourceAndConverter< ? > > sources, + final List< TransformListener< AffineTransform3D > > transformListeners, + final List< TimePointListener > timepointListeners, + final List< ViewerStateChangeListener > viewerStateChangeListeners, + final List< OverlayRenderer > overlays ) + { + if ( viewer == null ) + return; + + // TODO: REMOVE + if ( converterSetups != null ) + converterSetups.forEach( setupAssignments::removeSetup ); + + if ( transformListeners != null ) + for ( final TransformListener< AffineTransform3D > l : transformListeners ) + viewer.removeTransformListener( l ); + + if ( timepointListeners != null ) + for ( final TimePointListener l : timepointListeners ) + viewer.removeTimePointListener( l ); + + if ( viewerStateChangeListeners != null ) + viewer.state().changeListeners().removeAll( viewerStateChangeListeners ); + + if ( overlays != null ) + for ( final OverlayRenderer o : overlays ) + viewer.getDisplay().overlays().remove( o ); + + if ( sources != null ) + viewer.state().removeSources( sources ); + } + + void addBdvSource( final BdvSource bdvSource ) + { + bdvSources.add( bdvSource ); + updateHasPlaceHolderSources(); + updateNumTimepoints(); + } + + void removeBdvSource( final BdvSource bdvSource ) + { + bdvSources.remove( bdvSource ); + updateHasPlaceHolderSources(); + updateNumTimepoints(); + } + + void updateHasPlaceHolderSources() + { + for ( final BdvSource s : bdvSources ) + if ( s.isPlaceHolderSource() ) + { + hasPlaceHolderSources = true; + return; + } + hasPlaceHolderSources = false; + } + + void updateNumTimepoints() + { + int numTimepoints = origNumTimepoints; + for ( final BdvSource s : bdvSources ) + numTimepoints = Math.max( numTimepoints, s.getNumTimepoints() ); + if ( viewer != null ) + viewer.setNumTimepoints( numTimepoints ); + } + + boolean is2D() + { + return bdvOptions.values.is2D(); + } +} diff --git a/src/main/java/bdv/util/BdvHandleFrame.java b/src/main/java/bdv/util/BdvHandleFrame.java new file mode 100644 index 00000000..a82c7a7d --- /dev/null +++ b/src/main/java/bdv/util/BdvHandleFrame.java @@ -0,0 +1,152 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.ui.UIUtils; +import bdv.ui.appearance.AppearanceManager; +import bdv.ui.keymap.KeymapManager; +import bdv.viewer.ViewerStateChange; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.List; + +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.util.InputActionBindings; +import org.scijava.ui.behaviour.util.TriggerBehaviourBindings; + +import bdv.BigDataViewer; +import bdv.cache.CacheControl.CacheControls; +import bdv.export.ProgressWriter; +import bdv.export.ProgressWriterConsole; +import bdv.tools.brightness.ConverterSetup; +import bdv.tools.transformation.ManualTransformationEditor; +import bdv.viewer.DisplayMode; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerFrame; +import bdv.viewer.ViewerOptions; + +public class BdvHandleFrame extends BdvHandle +{ + private BigDataViewer bdv; + + private final String frameTitle; + + BdvHandleFrame( final BdvOptions options ) + { + super( options ); + frameTitle = options.values.getFrameTitle(); + bdv = null; + cacheControls = new CacheControls(); + UIUtils.installFlatLafInfos(); + } + + public BigDataViewer getBigDataViewer() + { + return bdv; + } + + @Override + public void close() + { + if ( bdv != null ) + { + final ViewerFrame frame = bdv.getViewerFrame(); + frame.dispatchEvent( new WindowEvent( frame, WindowEvent.WINDOW_CLOSING ) ); + bdv = null; + } + super.close(); + } + + @Override + public ManualTransformationEditor getManualTransformEditor() + { + return bdv.getManualTransformEditor(); + } + + @Override + public KeymapManager getKeymapManager() + { + return bdv.getKeymapManager(); + } + + @Override + public AppearanceManager getAppearanceManager() + { + return bdv.getAppearanceManager(); + } + + @Override + public InputActionBindings getKeybindings() + { + return bdv.getViewerFrame().getKeybindings(); + } + + @Override + public TriggerBehaviourBindings getTriggerbindings() + { + return bdv.getViewerFrame().getTriggerbindings(); + } + + @Override + boolean createViewer( + final List< ? extends ConverterSetup > converterSetups, + final List< ? extends SourceAndConverter< ? > > sources, + final int numTimepoints ) + { + final ProgressWriter progressWriter = new ProgressWriterConsole(); + final ViewerOptions viewerOptions = bdvOptions.values.getViewerOptions(); + final InputTriggerConfig inputTriggerConfig = BigDataViewer.getInputTriggerConfig( viewerOptions ); + bdv = new BigDataViewer( + new ArrayList<>( converterSetups ), + new ArrayList<>( sources ), + null, + numTimepoints, + cacheControls, + frameTitle, + progressWriter, + viewerOptions.inputTriggerConfig( inputTriggerConfig ) ); + viewer = bdv.getViewer(); + cards = bdv.getViewerFrame().getCardPanel(); + splitPanel = bdv.getViewerFrame().getSplitPanel(); + setupAssignments = bdv.getSetupAssignments(); + setups = bdv.getConverterSetups(); + + // this triggers repaint when PlaceHolderSources are toggled + viewer.state().changeListeners().add( change -> { + if ( change == ViewerStateChange.VISIBILITY_CHANGED ) + viewer.getDisplay().repaint(); + } ); + + viewer.setDisplayMode( DisplayMode.FUSED ); + bdv.getViewerFrame().setVisible( true ); + + final boolean initTransform = !sources.isEmpty(); + return initTransform; + } +} diff --git a/src/main/java/bdv/util/BdvHandlePanel.java b/src/main/java/bdv/util/BdvHandlePanel.java new file mode 100644 index 00000000..9914b5f2 --- /dev/null +++ b/src/main/java/bdv/util/BdvHandlePanel.java @@ -0,0 +1,231 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.ui.BdvDefaultCards; +import bdv.ui.CardPanel; +import bdv.ui.UIUtils; +import bdv.ui.appearance.AppearanceManager; +import bdv.ui.keymap.KeymapManager; +import bdv.ui.splitpanel.SplitPanel; +import bdv.viewer.ConverterSetups; +import java.awt.Frame; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + +import org.scijava.ui.behaviour.MouseAndKeyHandler; +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.util.Actions; +import org.scijava.ui.behaviour.util.Behaviours; +import org.scijava.ui.behaviour.util.InputActionBindings; +import org.scijava.ui.behaviour.util.TriggerBehaviourBindings; + +import bdv.BigDataViewer; +import bdv.BigDataViewerActions; +import bdv.cache.CacheControl.CacheControls; +import bdv.tools.VisibilityAndGroupingDialog; +import bdv.tools.bookmarks.Bookmarks; +import bdv.tools.bookmarks.BookmarksEditor; +import bdv.tools.brightness.BrightnessDialog; +import bdv.tools.brightness.ConverterSetup; +import bdv.tools.brightness.SetupAssignments; +import bdv.tools.transformation.ManualTransformationEditor; +import bdv.viewer.DisplayMode; +import bdv.viewer.NavigationActions; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerPanel; +import bdv.TransformEventHandler; + +import static bdv.BigDataViewerActions.COLLAPSE_CARDS; +import static bdv.BigDataViewerActions.COLLAPSE_CARDS_KEYS; +import static bdv.BigDataViewerActions.EXPAND_CARDS; +import static bdv.BigDataViewerActions.EXPAND_CARDS_KEYS; + +public class BdvHandlePanel extends BdvHandle +{ + private final BrightnessDialog brightnessDialog; + + private final VisibilityAndGroupingDialog activeSourcesDialog; + + private final ManualTransformationEditor manualTransformationEditor; + + private final Bookmarks bookmarks; + + private final BookmarksEditor bookmarksEditor; + + private final InputActionBindings keybindings; + + private final TriggerBehaviourBindings triggerbindings; + + private final KeymapManager keymapManager; + + private final AppearanceManager appearanceManager; + + public BdvHandlePanel( final Frame dialogOwner, final BdvOptions options ) + { + super( options ); + UIUtils.installFlatLafInfos(); + + final KeymapManager optionsKeymapManager = options.values.getKeymapManager(); + final AppearanceManager optionsAppearanceManager = options.values.getAppearanceManager(); + keymapManager = optionsKeymapManager != null ? optionsKeymapManager : new KeymapManager( BigDataViewer.configDir ); + appearanceManager = optionsAppearanceManager != null ? optionsAppearanceManager : new AppearanceManager( BigDataViewer.configDir ); + + cacheControls = new CacheControls(); + + viewer = new ViewerPanel( new ArrayList<>(), 1, cacheControls, options.values.getViewerOptions() ); + if ( !options.values.hasPreferredSize() ) + viewer.getDisplay().setPreferredSize( null ); + viewer.getDisplay().addComponentListener( new ComponentAdapter() + { + @Override + public void componentResized( final ComponentEvent e ) + { + tryInitTransform(); + } + } ); + + setupAssignments = new SetupAssignments( new ArrayList<>(), 0, 65535 ); + setups = new ConverterSetups( viewer.state() ); + setups.listeners().add( s -> viewer.requestRepaint() ); + + cards = new CardPanel(); + BdvDefaultCards.setup( cards, viewer, setups ); + splitPanel = new SplitPanel( viewer, cards ); + + keybindings = new InputActionBindings(); + SwingUtilities.replaceUIActionMap( viewer, keybindings.getConcatenatedActionMap() ); + SwingUtilities.replaceUIInputMap( viewer, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keybindings.getConcatenatedInputMap() ); + + triggerbindings = new TriggerBehaviourBindings(); + final MouseAndKeyHandler mouseAndKeyHandler = new MouseAndKeyHandler(); + mouseAndKeyHandler.setInputMap( triggerbindings.getConcatenatedInputTriggerMap() ); + mouseAndKeyHandler.setBehaviourMap( triggerbindings.getConcatenatedBehaviourMap() ); + viewer.getDisplay().addHandler( mouseAndKeyHandler ); + + final InputTriggerConfig inputTriggerConfig = viewer.getInputTriggerConfig(); + + // TODO: should be a field? + final Behaviours transformBehaviours = new Behaviours( inputTriggerConfig, "bdv" ); + transformBehaviours.install( triggerbindings, "transform" ); + + final TransformEventHandler tfHandler = viewer.getTransformEventHandler(); + tfHandler.install( transformBehaviours ); + + manualTransformationEditor = new ManualTransformationEditor( viewer, keybindings ); + + bookmarks = new Bookmarks(); + bookmarksEditor = new BookmarksEditor( viewer, keybindings, bookmarks ); + + brightnessDialog = new BrightnessDialog( dialogOwner, setupAssignments ); + activeSourcesDialog = new VisibilityAndGroupingDialog( dialogOwner, viewer.state() ); + + appearanceManager.appearance().updateListeners().add( () -> SwingUtilities.getWindowAncestor( viewer ).repaint() ); + SwingUtilities.invokeLater(() -> appearanceManager.updateLookAndFeel()); + + final Actions navigationActions = new Actions( inputTriggerConfig, "bdv", "navigation" ); + navigationActions.install( keybindings, "navigation" ); + NavigationActions.install( navigationActions, viewer, options.values.is2D() ); + + final Actions bdvActions = new Actions( inputTriggerConfig, "bdv" ); + bdvActions.install( keybindings, "bdv" ); + BigDataViewerActions.dialog( bdvActions, brightnessDialog ); + BigDataViewerActions.dialog( bdvActions, activeSourcesDialog ); + BigDataViewerActions.bookmarks( bdvActions, bookmarksEditor ); + BigDataViewerActions.manualTransform( bdvActions, manualTransformationEditor ); + bdvActions.runnableAction( this::expandAndFocusCardPanel, EXPAND_CARDS, EXPAND_CARDS_KEYS ); + bdvActions.runnableAction( this::collapseCardPanel, COLLAPSE_CARDS, COLLAPSE_CARDS_KEYS ); + + viewer.setDisplayMode( DisplayMode.FUSED ); + } + + @Override + public ManualTransformationEditor getManualTransformEditor() + { + return manualTransformationEditor; + } + + @Override + public KeymapManager getKeymapManager() + { + return keymapManager; + } + + @Override + public AppearanceManager getAppearanceManager() + { + return appearanceManager; + } + + @Override + public InputActionBindings getKeybindings() + { + return keybindings; + } + + @Override + public TriggerBehaviourBindings getTriggerbindings() + { + return triggerbindings; + } + + @Override + boolean createViewer( + final List< ? extends ConverterSetup > converterSetups, + final List< ? extends SourceAndConverter< ? > > sources, + final int numTimepoints ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void close() + { + brightnessDialog.dispose(); + activeSourcesDialog.dispose(); + super.close(); + } + + public void expandAndFocusCardPanel() + { + splitPanel.setCollapsed( false ); + splitPanel.getRightComponent().requestFocusInWindow(); + } + + public void collapseCardPanel() + { + splitPanel.setCollapsed( true ); + viewer.requestFocusInWindow(); + } +} diff --git a/src/main/java/bdv/util/BdvOptions.java b/src/main/java/bdv/util/BdvOptions.java new file mode 100644 index 00000000..b959920b --- /dev/null +++ b/src/main/java/bdv/util/BdvOptions.java @@ -0,0 +1,407 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.TransformEventHandler2D; +import bdv.TransformEventHandler3D; +import bdv.TransformEventHandlerFactory; +import bdv.ui.appearance.AppearanceManager; +import bdv.ui.keymap.KeymapManager; +import bdv.viewer.render.AccumulateProjectorARGB; +import org.scijava.ui.behaviour.io.InputTriggerConfig; + +import bdv.viewer.ViewerOptions; +import bdv.viewer.ViewerPanel; +import bdv.viewer.render.AccumulateProjector; +import bdv.viewer.render.AccumulateProjectorFactory; +import bdv.viewer.render.MultiResolutionRenderer; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; + +/** + * Optional parameters for {@link BdvFunctions}. + * + * @author Tobias Pietzsch <tobias.pietzsch@gmail.com> + */ +public class BdvOptions +{ + public final Values values = new Values(); + + /** + * Create default {@link BdvOptions}. + * @return default {@link BdvOptions}. + */ + public static BdvOptions options() + { + return new BdvOptions(); + } + + /** + * Set preferred size of {@link ViewerPanel} canvas. (This does not include + * the time slider). + */ + public BdvOptions preferredSize( final int w, final int h ) + { + values.width = w; + values.height = h; + return this; + } + + /** + * Set the number and scale factors for scaled screen images. + * + * @param s + * Scale factors from the viewer canvas to screen images of + * different resolutions. A scale factor of 1 means 1 pixel in + * the screen image is displayed as 1 pixel on the canvas, a + * scale factor of 0.5 means 1 pixel in the screen image is + * displayed as 2 pixel on the canvas, etc. + * @see MultiResolutionRenderer + */ + public BdvOptions screenScales( final double[] s ) + { + values.screenScales = s; + return this; + } + + /** + * Set target rendering time in nanoseconds. + * + * @param t + * Target rendering time in nanoseconds. The rendering time for + * the coarsest rendered scale should be below this threshold. + * @see MultiResolutionRenderer + */ + public BdvOptions targetRenderNanos( final long t ) + { + values.targetRenderNanos = t; + return this; + } + + /** + * Set how many threads to use for rendering. + * + * @param n + * How many threads to use for rendering. + * @see MultiResolutionRenderer + */ + public BdvOptions numRenderingThreads( final int n ) + { + values.numRenderingThreads = n; + return this; + } + + /** + * Set how many source groups there are initially. + * + * @param n + * How many source groups to create initially. + */ + public BdvOptions numSourceGroups( final int n ) + { + values.numSourceGroups = n; + return this; + } + + public BdvOptions transformEventHandlerFactory( final TransformEventHandlerFactory f ) + { + values.transformEventHandlerFactory = f; + return this; + } + + /** + * Set the factory for creating {@link AccumulateProjector}. This can be + * used to customize how sources are combined. + * + * @param f + * factory for creating {@link AccumulateProjector}. + * @see MultiResolutionRenderer + */ + public BdvOptions accumulateProjectorFactory( final AccumulateProjectorFactory< ARGBType > f ) + { + values.accumulateProjectorFactory = f; + return this; + } + + /** + * Set the {@link InputTriggerConfig} from which keyboard and mouse action mapping is loaded. + *

+ * Note that this will override the managed {@code InputTriggerConfig}, that is, + * modifying the keymap through the preferences dialog will have no effect. + * + * @param c the {@link InputTriggerConfig} from which keyboard and mouse action mapping is loaded + */ + public BdvOptions inputTriggerConfig( final InputTriggerConfig c ) + { + values.inputTriggerConfig = c; + return this; + } + + /** + * Set the {@link KeymapManager} to share keymap settings with other + * BigDataViewer windows. + *

+ * This can be used to link multiple BigDataViewer windows such that they + * use (and modify) the same {@code Keymap}, shortcuts and mouse gestures. + *

+ */ + public BdvOptions keymapManager( final KeymapManager keymapManager ) + { + values.keymapManager = keymapManager; + return this; + } + + /** + * Set the {@link AppearanceManager} to share appearance settings with other + * BigDataViewer windows. + *

+ * This can be used to link multiple BigDataViewer windows such that they + * use (and modify) the same {@code Appearance} settings, e.g., LookAndFeel, + * scalebar overlay settings, etc. + *

+ */ + public BdvOptions appearanceManager( final AppearanceManager appearanceManager ) + { + values.appearanceManager = appearanceManager; + return this; + } + + /** + * Set the transform of the {@link BdvSource} to be created. + * + * @param t + * the source transform. + */ + public BdvOptions sourceTransform( final AffineTransform3D t ) + { + values.sourceTransform.set( t ); + return this; + } + + /** + * Set the title of the BigDataViewer window. + * + * @param title + * the window title. + */ + public BdvOptions frameTitle( final String title ) + { + values.frameTitle = title; + return this; + } + + /** + * Set the transform of the {@link BdvSource} to be created to account for + * the given calibration (scaling of the source axes). + * + * @param calibration + * the source calibration (scaling of the source axes). + */ + public BdvOptions sourceTransform( final double ... calibration ) + { + final double sx = calibration.length >= 1 ? calibration[ 0 ] : 1; + final double sy = calibration.length >= 2 ? calibration[ 1 ] : 1; + final double sz = calibration.length >= 3 ? calibration[ 2 ] : 1; + values.sourceTransform.set( + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0 ); + return this; + } + + /** + * Set up the BigDataViewer for 2D navigation. + * + * TODO: add more detailed explanation + * + * @return + */ + public BdvOptions is2D() + { + values.is2D = true; + transformEventHandlerFactory( TransformEventHandler2D::new ); + return this; + } + + /** + * Specified when adding a stack. Describes how the axes of the stack are + * ordered. + * + * @param axisOrder + * the axis order of a stack to add. + */ + public BdvOptions axisOrder( final AxisOrder axisOrder ) + { + values.axisOrder = axisOrder; + return this; + } + + /** + * When showing content using one of the {@link BdvFunctions} methods, this + * option can be given to specify that the content should be added to an + * existing window. (All {@link BdvFunctions} methods return an instance of + * {@link Bdv} that can be used that way). + * + * @param bdv + * to which viewer should the content be added. + */ + public BdvOptions addTo( final Bdv bdv ) + { + values.addTo = bdv; + return this; + } + + /** + * Read-only {@link BdvOptions} values. + */ + public static class Values + { + private int width = -1; + + private int height = -1; + + private double[] screenScales = new double[] { 1, 0.75, 0.5, 0.25, 0.125 }; + + private long targetRenderNanos = 30 * 1000000l; + + private int numRenderingThreads = 3; + + private int numSourceGroups = 10; + + private TransformEventHandlerFactory transformEventHandlerFactory = TransformEventHandler3D::new; + + private AccumulateProjectorFactory< ARGBType > accumulateProjectorFactory = AccumulateProjectorARGB.factory; + + private InputTriggerConfig inputTriggerConfig = null; + + private KeymapManager keymapManager = null; + + private AppearanceManager appearanceManager = null; + + private final AffineTransform3D sourceTransform = new AffineTransform3D(); + + private String frameTitle = "BigDataViewer"; + + private boolean is2D = false; + + private AxisOrder axisOrder = AxisOrder.DEFAULT; + + private Bdv addTo = null; + + Values() + { + sourceTransform.identity(); + } + + public BdvOptions optionsFromValues() + { + final BdvOptions o = new BdvOptions() + .preferredSize( width, height ) + .screenScales( screenScales ) + .targetRenderNanos( targetRenderNanos ) + .numRenderingThreads( numRenderingThreads ) + .numSourceGroups( numSourceGroups ) + .transformEventHandlerFactory( transformEventHandlerFactory ) + .accumulateProjectorFactory( accumulateProjectorFactory ) + .inputTriggerConfig( inputTriggerConfig ) + .keymapManager( keymapManager ) + .appearanceManager( appearanceManager ) + .sourceTransform( sourceTransform ) + .frameTitle( frameTitle ) + .axisOrder( axisOrder ) + .addTo( addTo ); + if ( is2D() ) + o.is2D(); + return o; + } + + public ViewerOptions getViewerOptions() + { + final ViewerOptions o = ViewerOptions.options() + .screenScales( screenScales ) + .targetRenderNanos( targetRenderNanos ) + .numRenderingThreads( numRenderingThreads ) + .numSourceGroups( numSourceGroups ) + .is2D( is2D ) + .transformEventHandlerFactory( transformEventHandlerFactory ) + .accumulateProjectorFactory( accumulateProjectorFactory ) + .inputTriggerConfig( inputTriggerConfig ) + .keymapManager( keymapManager ) + .appearanceManager( appearanceManager ); + if ( hasPreferredSize() ) + o.width( width ).height( height ); + return o; + } + + public AffineTransform3D getSourceTransform() + { + return sourceTransform; + } + + public String getFrameTitle() + { + return frameTitle; + } + + public boolean is2D() + { + return is2D; + } + + public boolean hasPreferredSize() + { + return width > 0 && height > 0; + } + + public AxisOrder axisOrder() + { + return axisOrder; + } + + public InputTriggerConfig getInputTriggerConfig() + { + return inputTriggerConfig; + } + + public KeymapManager getKeymapManager() + { + return keymapManager; + } + + public AppearanceManager getAppearanceManager() + { + return appearanceManager; + } + + public Bdv addTo() + { + return addTo; + } + } +} diff --git a/src/main/java/bdv/util/BdvOverlay.java b/src/main/java/bdv/util/BdvOverlay.java new file mode 100644 index 00000000..0beee7fc --- /dev/null +++ b/src/main/java/bdv/util/BdvOverlay.java @@ -0,0 +1,125 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.Graphics; +import java.awt.Graphics2D; + +import bdv.BigDataViewer; +import bdv.tools.brightness.ConverterSetup; +import bdv.viewer.Source; +import net.imglib2.realtransform.AffineTransform2D; +import net.imglib2.realtransform.AffineTransform3D; +import bdv.viewer.OverlayRenderer; + +/** + * An overlay that can be shown with + * {@link BdvFunctions#showOverlay(BdvOverlay, String, BdvOptions)}: This method + * will add a dummy {@link Source} and {@link ConverterSetup} to the + * {@link BigDataViewer} such that the visibility, display range, and color for + * the overlay can be adjusted by the user, like for a normal {@link Source}. + *

+ * Derived classes need to implement {@link #draw(Graphics2D)}. They can access + * the current viewer transform using + * {@link #getCurrentTransform2D(AffineTransform2D)}, + * {@link #getCurrentTransform3D(AffineTransform3D)}. They can access the + * user-set display range and color via {@link #info}. + * + * @author Tobias Pietzsch + */ +public abstract class BdvOverlay implements OverlayRenderer +{ + protected final AffineTransform3D sourceTransform; + + private final AffineTransform3D tmp; + + protected PlaceHolderOverlayInfo info; + + public BdvOverlay() + { + this.sourceTransform = new AffineTransform3D(); + this.tmp = new AffineTransform3D(); + this.info = null; + } + + public void setOverlayInfo( final PlaceHolderOverlayInfo info ) + { + this.info = info; + } + + public void setSourceTransform( final AffineTransform3D t ) + { + sourceTransform.set( t ); + } + + @Override + public void drawOverlays( final Graphics g ) + { + if ( info == null || !info.isVisible() ) + return; + + draw( ( Graphics2D ) g ); + } + + /** + * Can be used by derived classes in the {@link #draw(Graphics2D)} method to + * get the current transform from 2D source coordinates to screen + * coordinates. + * + * @param transform + */ + protected void getCurrentTransform2D( final AffineTransform2D transform ) + { + info.getViewerTransform( tmp ); + tmp.concatenate( sourceTransform ); + transform.set( + tmp.get( 0, 0 ), tmp.get( 0, 1 ), tmp.get( 0, 3 ), + tmp.get( 1, 0 ), tmp.get( 1, 1 ), tmp.get( 1, 3 ) ); + } + + /** + * Can be used by derived classes in the {@link #draw(Graphics2D)} method to + * get the current transform from 3D source coordinates to 3D screen + * coordinates (where Z coordinate is distance from the slice shown on the + * screen). + * + * @param transform + */ + protected void getCurrentTransform3D( final AffineTransform3D transform ) + { + info.getViewerTransform( transform ); + transform.concatenate( sourceTransform ); + } + + protected abstract void draw( final Graphics2D g ); + + @Override + public void setCanvasSize( final int width, final int height ) + {} +} diff --git a/src/main/java/bdv/util/BdvOverlaySource.java b/src/main/java/bdv/util/BdvOverlaySource.java new file mode 100644 index 00000000..3d0dee26 --- /dev/null +++ b/src/main/java/bdv/util/BdvOverlaySource.java @@ -0,0 +1,129 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Collections; + +import net.imglib2.type.numeric.ARGBType; +import bdv.viewer.OverlayRenderer; + +import bdv.tools.brightness.MinMaxGroup; +import bdv.tools.brightness.SetupAssignments; +import bdv.viewer.SourceAndConverter; + +public class BdvOverlaySource< O extends OverlayRenderer > extends BdvSource +{ + protected final PlaceHolderConverterSetup setup; + + private final SourceAndConverter< Void > source; + + private final PlaceHolderOverlayInfo info; + + protected final O overlay; + + public O getOverlay() + { + return overlay; + } + + protected BdvOverlaySource( + final BdvHandle bdv, + final int numTimepoints, + final PlaceHolderConverterSetup setup, + final SourceAndConverter< Void > source, + final PlaceHolderOverlayInfo info, + final O overlay ) + { + super( bdv, numTimepoints ); + this.setup = setup; + this.source = source; + this.info = info; + this.overlay = overlay; + } + + @Override + public void removeFromBdv() + { + getBdvHandle().remove( + Collections.singletonList( setup ), + Collections.singletonList( source ), + Collections.singletonList( info ), + Collections.singletonList( info ), + Collections.singletonList( info ), + Collections.singletonList( overlay ) ); + getBdvHandle().removeBdvSource( this ); + } + + @Override + protected boolean isPlaceHolderSource() + { + return true; + } + + @Override + public void setDisplayRange( final double min, final double max ) + { + setup.setDisplayRange( min, max ); + } + + @Override + public void setDisplayRangeBounds( final double min, final double max ) + { + getBdvHandle().getConverterSetups().getBounds().setBounds( setup, new Bounds( min, max ) ); + + // TODO: REMOVE + final SetupAssignments sa = getBdvHandle().getSetupAssignments(); + final MinMaxGroup group = sa.getMinMaxGroup( setup ); + group.setRange( min, max ); + } + + @Override + public void setColor( final ARGBType color ) + { + setup.setColor( color ); + } + + @Override + public void setCurrent() + { + getBdvHandle().getViewerPanel().state().setCurrentSource( source ); + } + + @Override + public boolean isCurrent() + { + return getBdvHandle().getViewerPanel().state().isCurrentSource( source ); + } + + @Override + public void setActive( final boolean isActive ) + { + getBdvHandle().getViewerPanel().state().setSourceActive( source, isActive ); + } +} diff --git a/src/main/java/bdv/util/BdvPointsSource.java b/src/main/java/bdv/util/BdvPointsSource.java new file mode 100644 index 00000000..0a5fcbd1 --- /dev/null +++ b/src/main/java/bdv/util/BdvPointsSource.java @@ -0,0 +1,67 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.List; + +import net.imglib2.RealLocalizable; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; + +import bdv.viewer.SourceAndConverter; + +public class BdvPointsSource extends BdvOverlaySource< PointsOverlay > +{ + protected BdvPointsSource( + final BdvHandle bdv, + final int numTimepoints, + final PlaceHolderConverterSetup setup, + final SourceAndConverter< Void > source, + final PlaceHolderOverlayInfo info, + final PointsOverlay overlay ) + { + super( bdv, numTimepoints, setup, source, info, overlay ); + } + + public < T extends RealLocalizable > void setPoints( final List< T > points ) + { + overlay.setPoints( points ); + } + + public void setSourceTransform( final AffineTransform3D t ) + { + overlay.setSourceTransform( t ); + } + + @Override + public void setColor( final ARGBType color ) + { + setup.setColor( color ); + } +} diff --git a/src/main/java/bdv/util/BdvSource.java b/src/main/java/bdv/util/BdvSource.java new file mode 100644 index 00000000..efba4d12 --- /dev/null +++ b/src/main/java/bdv/util/BdvSource.java @@ -0,0 +1,79 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import net.imglib2.type.numeric.ARGBType; + +public abstract class BdvSource implements Bdv +{ + private BdvHandle bdv; + + // so that we can fix the bdv numTimepoints when removing sources. + private final int numTimepoints; + + protected BdvSource( final BdvHandle bdv, final int numTimepoints ) + { + this.bdv = bdv; + this.numTimepoints = numTimepoints; + } + + // invalidates this BdvSource completely + // closes bdv if it was the last source + public abstract void removeFromBdv(); + + public abstract void setDisplayRange( final double min, final double max ); + + public abstract void setDisplayRangeBounds( final double min, final double max ); + + public abstract void setColor( final ARGBType color ); + + public abstract void setCurrent(); + + public abstract boolean isCurrent(); + + public abstract void setActive( final boolean isActive ); + + @Override + public BdvHandle getBdvHandle() + { + return bdv; + } + + protected void setBdvHandle( final BdvHandle bdv ) + { + this.bdv = bdv; + } + + protected abstract boolean isPlaceHolderSource(); + + protected int getNumTimepoints() + { + return numTimepoints; + } +} diff --git a/src/main/java/bdv/util/BdvStackSource.java b/src/main/java/bdv/util/BdvStackSource.java new file mode 100644 index 00000000..e7cb9d09 --- /dev/null +++ b/src/main/java/bdv/util/BdvStackSource.java @@ -0,0 +1,138 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.tools.brightness.ConverterSetup; +import bdv.tools.brightness.MinMaxGroup; +import bdv.tools.brightness.SetupAssignments; +import bdv.viewer.ConverterSetupBounds; +import bdv.viewer.SourceAndConverter; +import java.util.HashSet; +import java.util.List; +import net.imglib2.type.numeric.ARGBType; + +import static bdv.util.AbstractSource.tryCreateVariable; + +public class BdvStackSource< T > extends BdvSource +{ + private final T type; + + private final List< ConverterSetup > converterSetups; + + private final List< SourceAndConverter< T > > sources; + + protected BdvStackSource( + final BdvHandle bdv, + final int numTimepoints, + final T type, + final List< ConverterSetup > converterSetups, + final List< SourceAndConverter< T > > sources ) + { + super( bdv, numTimepoints ); + this.type = tryCreateVariable( type ); + this.converterSetups = converterSetups; + this.sources = sources; + } + + @Override + public void removeFromBdv() + { + getBdvHandle().remove( converterSetups, sources, null, null, null, null ); + getBdvHandle().removeBdvSource( this ); + } + + @Override + protected boolean isPlaceHolderSource() + { + return false; + } + + @Override + public void setColor( final ARGBType color ) + { + for ( final ConverterSetup setup : converterSetups ) + setup.setColor( color ); + } + + @Override + public void setDisplayRange( final double min, final double max ) + { + for ( final ConverterSetup setup : converterSetups ) + setup.setDisplayRange( min, max ); + } + + @Override + public void setDisplayRangeBounds( final double min, final double max ) + { + final ConverterSetupBounds bounds = getBdvHandle().getConverterSetups().getBounds(); + for ( final ConverterSetup setup : converterSetups ) + bounds.setBounds( setup, new Bounds( min, max ) ); + + // TODO: REMOVE + final HashSet< MinMaxGroup > groups = new HashSet<>(); + final SetupAssignments sa = getBdvHandle().getSetupAssignments(); + for ( final ConverterSetup setup : converterSetups ) + groups.add( sa.getMinMaxGroup( setup ) ); + for ( final MinMaxGroup group : groups ) + group.setRange( min, max ); + } + + @Override + public void setCurrent() + { + getBdvHandle().getViewerPanel().state().setCurrentSource( sources.get( 0 ) ); + } + + @Override + public boolean isCurrent() + { + return sources.contains( getBdvHandle().getViewerPanel().state().getCurrentSource() ); + } + + @Override + public void setActive( final boolean isActive ) + { + getBdvHandle().getViewerPanel().state().setSourcesActive( sources, isActive ); + } + +// public T getType() +// { +// return type; +// } + + public List< ConverterSetup > getConverterSetups() + { + return converterSetups; + } + + public List< SourceAndConverter< T > > getSources() + { + return sources; + } +} diff --git a/src/main/java/bdv/util/BdvVirtualChannelSource.java b/src/main/java/bdv/util/BdvVirtualChannelSource.java new file mode 100644 index 00000000..41c81630 --- /dev/null +++ b/src/main/java/bdv/util/BdvVirtualChannelSource.java @@ -0,0 +1,128 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.tools.brightness.MinMaxGroup; +import bdv.tools.brightness.SetupAssignments; +import bdv.util.VirtualChannels.ChannelSourceCoordinator; +import bdv.viewer.SourceAndConverter; +import java.util.Collections; +import net.imglib2.type.numeric.ARGBType; + +public class BdvVirtualChannelSource extends BdvSource +{ + protected final PlaceHolderConverterSetup setup; + + private final SourceAndConverter< ARGBType > source; + + private final PlaceHolderOverlayInfo info; + + private final ChannelSourceCoordinator coordinator; + + protected BdvVirtualChannelSource( + final BdvHandle bdv, + final int numTimepoints, + final PlaceHolderConverterSetup setup, + final SourceAndConverter< ARGBType > source, + final PlaceHolderOverlayInfo info, + final ChannelSourceCoordinator coordinator ) + { + super( bdv, numTimepoints ); + this.setup = setup; + this.source = source; + this.info = info; + this.coordinator = coordinator; + } + + public PlaceHolderOverlayInfo getPlaceHolderOverlayInfo() + { + return info; + } + + @Override + public void removeFromBdv() + { + coordinator.sharedInfos.remove( info ); + getBdvHandle().remove( + Collections.singletonList( setup ), + Collections.singletonList( source ), + Collections.singletonList( info ), + Collections.singletonList( info ), + Collections.singletonList( info ), + null ); + getBdvHandle().removeBdvSource( this ); + } + + @Override + protected boolean isPlaceHolderSource() + { + return false; + } + + @Override + public void setDisplayRange( final double min, final double max ) + { + setup.setDisplayRange( min, max ); + } + + @Override + public void setDisplayRangeBounds( final double min, final double max ) + { + getBdvHandle().getConverterSetups().getBounds().setBounds( setup, new Bounds( min, max ) ); + + // TODO: REMOVE + final SetupAssignments sa = getBdvHandle().getSetupAssignments(); + final MinMaxGroup group = sa.getMinMaxGroup( setup ); + group.setRange( min, max ); + } + + @Override + public void setColor( final ARGBType color ) + { + setup.setColor( color ); + } + + @Override + public void setCurrent() + { + getBdvHandle().getViewerPanel().state().setCurrentSource( source ); + } + + @Override + public boolean isCurrent() + { + return getBdvHandle().getViewerPanel().state().isCurrentSource( source ); + } + + @Override + public void setActive( final boolean isActive ) + { + getBdvHandle().getViewerPanel().state().setSourceActive( source, isActive ); + } +} diff --git a/src/main/java/bdv/util/ChannelSources.java b/src/main/java/bdv/util/ChannelSources.java new file mode 100644 index 00000000..799a8215 --- /dev/null +++ b/src/main/java/bdv/util/ChannelSources.java @@ -0,0 +1,67 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.cache.CacheControl; +import bdv.viewer.SourceAndConverter; +import java.util.List; + +/** + * Channels of an image as a collection of {@link SourceAndConverter + * sources}. The channels should all have the same pixel type, number of + * timepoints, and dimensions. + */ +public interface ChannelSources< T > +{ + /** + * Get the list of sources, one for each channel. + */ + List< SourceAndConverter< T > > getSources(); + + /** + * Get the number timepoints. + */ + int numTimepoints(); + + /** + * Get (an instance of) the pixel type. + */ + default T getType() + { + return getSources().get( 0 ).getSpimSource().getType(); + } + + /** + * Get handle for controlling cache behaviour. + */ + default CacheControl getCacheControl() + { + return null; + } +} diff --git a/src/main/java/bdv/util/DefaultInterpolators.java b/src/main/java/bdv/util/DefaultInterpolators.java new file mode 100644 index 00000000..986a0ba3 --- /dev/null +++ b/src/main/java/bdv/util/DefaultInterpolators.java @@ -0,0 +1,67 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.function.Function; + +import bdv.viewer.Interpolation; +import net.imglib2.RandomAccessible; +import net.imglib2.interpolation.InterpolatorFactory; +import net.imglib2.interpolation.randomaccess.ClampingNLinearInterpolatorFactory; +import net.imglib2.interpolation.randomaccess.NearestNeighborInterpolatorFactory; +import net.imglib2.type.numeric.NumericType; + +public class DefaultInterpolators< T extends NumericType< T > > implements Function< Interpolation, InterpolatorFactory< T, RandomAccessible< T > > > +{ + private final InterpolatorFactory< T, RandomAccessible< T > >[] factories; + + @SuppressWarnings( "unchecked" ) + public DefaultInterpolators() + { + factories = new InterpolatorFactory[ Interpolation.values().length ]; + factories[ Interpolation.NEARESTNEIGHBOR.ordinal() ] = new NearestNeighborInterpolatorFactory<>(); + factories[ Interpolation.NLINEAR.ordinal() ] = new ClampingNLinearInterpolatorFactory<>(); + } + + public InterpolatorFactory< T, RandomAccessible< T > > get( final Interpolation method ) + { + return factories[ method.ordinal() ]; + } + + public int size() + { + return factories.length; + } + + @Override + public InterpolatorFactory< T, RandomAccessible< T > > apply( final Interpolation t ) + { + return get( t ); + } +} diff --git a/src/main/java/bdv/util/PlaceHolderOverlayInfo.java b/src/main/java/bdv/util/PlaceHolderOverlayInfo.java new file mode 100644 index 00000000..4599f58c --- /dev/null +++ b/src/main/java/bdv/util/PlaceHolderOverlayInfo.java @@ -0,0 +1,214 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerStateChange; +import bdv.viewer.ViewerStateChangeListener; + +import bdv.tools.brightness.ConverterSetup; +import bdv.viewer.TimePointListener; +import bdv.viewer.ViewerPanel; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; +import bdv.viewer.TransformListener; +import org.scijava.listeners.Listeners; + +public final class PlaceHolderOverlayInfo implements TransformListener< AffineTransform3D >, TimePointListener, ViewerStateChangeListener +{ + private final ViewerPanel viewer; + + private final SourceAndConverter< ? > source; + + private final ConverterSetup converterSetup; + + private final AffineTransform3D viewerTransform; + + private int timePointIndex; + + private boolean wasVisible; + + private final Listeners.List< VisibilityChangeListener > listeners; + + public interface VisibilityChangeListener + { + void visibilityChanged(); + } + + /** + * + * @param viewer + * @param source + * used for determining visibility. + * @param converterSetup + */ + public PlaceHolderOverlayInfo( + final ViewerPanel viewer, + final SourceAndConverter< ? > source, + final ConverterSetup converterSetup ) + { + this.viewer = viewer; + this.source = source; + this.converterSetup = converterSetup; + this.viewerTransform = new AffineTransform3D(); + this.listeners = new Listeners.SynchronizedList<>(); + + viewer.addRenderTransformListener( this ); + viewer.addTimePointListener( this ); + viewer.state().changeListeners().add( this ); + } + + SourceAndConverter< ? > getSource() + { + return source; + } + + @Override + public void transformChanged( final AffineTransform3D t ) + { + synchronized( viewerTransform ) + { + viewerTransform.set( t ); + } + } + + public boolean isVisible() + { + return viewer.state().isSourceVisible( source ); + } + + public void getViewerTransform( final AffineTransform3D t ) + { + synchronized( viewerTransform ) + { + t.set( viewerTransform ); + } + } + + public int getTimePointIndex() + { + return timePointIndex; + } + + /** + * Get the (largest) source value that is mapped to the minimum of the + * target range. + * + * @return source value that is mapped to the minimum of the target range. + */ + public double getDisplayRangeMin() + { + return converterSetup.getDisplayRangeMin(); + } + + /** + * Get the (smallest) source value that is mapped to the maximum of the + * target range. + * + * @return source value that is mapped to the maximum of the target range. + */ + public double getDisplayRangeMax() + { + return converterSetup.getDisplayRangeMax(); + } + + /** + * Get the color for this converter. + * + * @return the color for this converter. + */ + public ARGBType getColor() + { + return converterSetup.getColor(); + } + + @Override + public void timePointChanged( final int timePointIndex ) + { + this.timePointIndex = timePointIndex; + } + + @Override + public void viewerStateChanged( final ViewerStateChange change ) + { + if ( change == ViewerStateChange.VISIBILITY_CHANGED ) + { + final boolean isVisible = isVisible(); + if ( wasVisible != isVisible ) + { + wasVisible = isVisible; + listeners.list.forEach( VisibilityChangeListener::visibilityChanged ); + } + } + } + + /** + * Register {@code VisibilityChangeListener}s, that will be notified when the + * visibility of the source represented by this PlaceHolderOverlayInfo + * changes. + */ + public Listeners< VisibilityChangeListener > visibilityChangeListeners() + { + return listeners; + } + + /** + * Registers a VisibilityChangeListener, that will be notified when the + * visibility of the source represented by this PlaceHolderOverlayInfo + * changes. + * + * @deprecated Use {@code visibilityChangeListeners().add(listener)} instead. + * + * @param listener + * the listener to register. + * @return {@code true} if the listener was successfully registered. + * {@code false} if it was already registered. + */ + @Deprecated + public boolean addVisibilityChangeListener( final VisibilityChangeListener listener ) + { + return listeners.add( listener ); + } + + /** + * Removes the specified listener. + * + * @deprecated Use {@code visibilityChangeListeners().remove(listener)} instead. + * + * @param listener + * the listener to remove. + * @return {@code true} if the listener was present in the listeners of + * this model and was successfully removed. + */ + @Deprecated + public boolean removeVisibilityChangeListener( final VisibilityChangeListener listener ) + { + return listeners.remove( listener ); + } +} diff --git a/src/main/java/bdv/util/PlaceHolderSource.java b/src/main/java/bdv/util/PlaceHolderSource.java new file mode 100644 index 00000000..09e3cf7c --- /dev/null +++ b/src/main/java/bdv/util/PlaceHolderSource.java @@ -0,0 +1,109 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; + +import bdv.viewer.Interpolation; +import bdv.viewer.Source; +import mpicbg.spim.data.sequence.VoxelDimensions; + +/** + * A dummy {@link Source} that represents a {@link BdvOverlay}. + *

+ * When a {@code BdvOverlay} is shown (with + * {@link BdvFunctions#showOverlay(BdvOverlay, String, BdvOptions)}), a dummy + * {@code Source} and {@code ConverterSetup} are added to the + * {@code BigDataViewer} such that the visibility, display range, and color for + * the overlay can be adjusted by the user, like for a normal {@link Source}. + *

+ * {@code PlaceHolderSource} is not {@link PlaceHolderSource#isPresent(int) + * present} at any time point, so it is never actually visible. + * + * @author Tobias Pietzsch + */ +public final class PlaceHolderSource implements Source< Void > +{ + private final String name; + + public PlaceHolderSource( final String name ) + { + this.name = name; + } + + @Override + public Void getType() + { + return null; + } + + @Override + public String getName() + { + return name; + } + + @Override + public VoxelDimensions getVoxelDimensions() + { + return null; + } + + @Override + public int getNumMipmapLevels() + { + return 1; + } + + @Override + public boolean isPresent( final int t ) + { + return false; + } + + @Override + public RandomAccessibleInterval< Void > getSource( final int t, final int level ) + { + return null; + } + + @Override + public RealRandomAccessible< Void > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + return null; + } + + @Override + public void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.identity(); + } +} diff --git a/src/main/java/bdv/util/PointsOverlay.java b/src/main/java/bdv/util/PointsOverlay.java new file mode 100644 index 00000000..bac0ba80 --- /dev/null +++ b/src/main/java/bdv/util/PointsOverlay.java @@ -0,0 +1,92 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.List; + +import net.imglib2.RealLocalizable; +import net.imglib2.realtransform.AffineTransform3D; + +public class PointsOverlay extends BdvOverlay +{ + private List< ? extends RealLocalizable > points; + + private Color col; + + public < T extends RealLocalizable > void setPoints( final List< T > points ) + { + this.points = points; + } + + @Override + protected void draw( final Graphics2D graphics ) + { + if ( points == null ) + return; + + col = new Color( info.getColor().get() ); + + final AffineTransform3D transform = new AffineTransform3D(); + getCurrentTransform3D( transform ); + final double[] lPos = new double[ 3 ]; + final double[] gPos = new double[ 3 ]; + for ( final RealLocalizable p : points ) + { + p.localize( lPos ); + transform.apply( lPos, gPos ); + final double size = getPointSize( gPos ); + final int x = ( int ) ( gPos[ 0 ] - 0.5 * size ); + final int y = ( int ) ( gPos[ 1 ] - 0.5 * size ); + final int w = ( int ) size; + graphics.setColor( getColor( gPos ) ); + graphics.fillOval( x, y, w, w ); + } + } + + /** screen pixels [x,y,z] **/ + private Color getColor( final double[] gPos ) + { + int alpha = 255 - ( int ) Math.round( Math.abs( gPos[ 2 ] ) ); + + if ( alpha < 64 ) + alpha = 64; + + return new Color( col.getRed(), col.getGreen(), col.getBlue(), alpha ); + } + + private double getPointSize( final double[] gPos ) + { + if ( Math.abs( gPos[ 2 ] ) < 3 ) + return 5.0; + else + return 3.0; + } +} diff --git a/src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource.java b/src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource.java new file mode 100644 index 00000000..56b28c57 --- /dev/null +++ b/src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource.java @@ -0,0 +1,147 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.function.Supplier; + +import bdv.cache.SharedQueue; +import bdv.util.volatiles.VolatileTypeMatcher; +import mpicbg.spim.data.sequence.VoxelDimensions; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.Volatile; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.NumericType; + +public class RandomAccessibleIntervalMipmapSource< T extends NumericType< T > > extends AbstractSource< T > +{ + protected final RandomAccessibleInterval< T >[] mipmapSources; + + protected final AffineTransform3D[] mipmapTransforms; + + public RandomAccessibleIntervalMipmapSource( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final AffineTransform3D[] mipmapTransforms, + final VoxelDimensions voxelDimensions, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, voxelDimensions, doBoundingBoxCulling ); + assert imgs.length == mipmapTransforms.length : "Number of mipmaps and scale factors do not match."; + + this.mipmapSources = imgs; + this.mipmapTransforms = mipmapTransforms; + } + + public RandomAccessibleIntervalMipmapSource( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final double[][] mipmapScales, + final VoxelDimensions voxelDimensions, + final AffineTransform3D sourceTransform, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, voxelDimensions, doBoundingBoxCulling ); + assert imgs.length == mipmapScales.length : "Number of mipmaps and scale factors do not match."; + + this.mipmapSources = imgs; + this.mipmapTransforms = new AffineTransform3D[ mipmapScales.length ]; + for ( int s = 0; s < mipmapScales.length; ++s ) + { + final AffineTransform3D mipmapTransform = new AffineTransform3D(); + mipmapTransform.set( + mipmapScales[ s ][ 0 ], 0, 0, 0.5 * ( mipmapScales[ s ][ 0 ] - 1 ), + 0, mipmapScales[ s ][ 1 ], 0, 0.5 * ( mipmapScales[ s ][ 1 ] - 1 ), + 0, 0, mipmapScales[ s ][ 2 ], 0.5 * ( mipmapScales[ s ][ 2 ] - 1 ) ); + mipmapTransform.preConcatenate(sourceTransform); + mipmapTransforms[ s ] = mipmapTransform; + } + } + + public RandomAccessibleIntervalMipmapSource( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final double[][] mipmapScales, + final VoxelDimensions voxelDimensions, + final AffineTransform3D sourceTransform, + final String name ) + { + this( imgs, type, mipmapScales, voxelDimensions, sourceTransform, name, true ); + } + + public RandomAccessibleIntervalMipmapSource( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final double[][] mipmapScales, + final VoxelDimensions voxelDimensions, + final String name ) + { + this(imgs, type, mipmapScales, voxelDimensions, new AffineTransform3D(), name); + } + + @Override + public RandomAccessibleInterval< T > getSource( final int t, final int level ) + { + return mipmapSources[ level ]; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( mipmapTransforms[ level ] ); + } + + @Override + public int getNumMipmapLevels() + { + return mipmapSources.length; + } + + public < V extends Volatile< T > & NumericType< V > > VolatileRandomAccessibleIntervalMipmapSource< T, V > asVolatile( final V vType, final SharedQueue queue ) + { + return new VolatileRandomAccessibleIntervalMipmapSource<>( this, vType, queue ); + } + + public < V extends Volatile< T > & NumericType< V > > VolatileRandomAccessibleIntervalMipmapSource< T, V > asVolatile( final Supplier< V > vTypeSupplier, final SharedQueue queue ) + { + return new VolatileRandomAccessibleIntervalMipmapSource<>( this, vTypeSupplier, queue ); + } + + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public < V extends Volatile< T > & NumericType< V > > VolatileRandomAccessibleIntervalMipmapSource< T, V > asVolatile( final SharedQueue queue ) + { + final T t = getType(); + if ( t instanceof NativeType ) + return new VolatileRandomAccessibleIntervalMipmapSource<>( this, ( V )VolatileTypeMatcher.getVolatileTypeForType( ( NativeType )getType() ), queue ); + else + throw new UnsupportedOperationException( "This method only works for sources of NativeType." ); + } +} diff --git a/src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource4D.java b/src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource4D.java new file mode 100644 index 00000000..87d4e08e --- /dev/null +++ b/src/main/java/bdv/util/RandomAccessibleIntervalMipmapSource4D.java @@ -0,0 +1,226 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Arrays; +import java.util.function.Supplier; + +import bdv.cache.SharedQueue; +import bdv.util.volatiles.VolatileTypeMatcher; +import bdv.viewer.Interpolation; +import mpicbg.spim.data.sequence.VoxelDimensions; +import net.imglib2.Interval; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.Volatile; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.view.Views; + +public class RandomAccessibleIntervalMipmapSource4D< T extends NumericType< T > > extends AbstractSource< T > +{ + protected final RandomAccessibleInterval< T >[] mipmapSources; + + protected final long minT, maxT; + + protected int currentTimePointIndex; + + private final RandomAccessibleInterval< T >[] currentMipmaps; + + private final RealRandomAccessible< T >[][] currentInterpolatedSources; + + protected final AffineTransform3D[] mipmapTransforms; + + private static boolean assertAllTDimensionsEqual(final Interval[] intervals) { + + final long min = intervals[0].min(3); + final long max = intervals[0].min(3); + + for (int i = 1; i < intervals.length; ++i) + if (!(intervals[i].min(3) == min && intervals[i].max(3) == max)) + return false; + + return true; + } + + public RandomAccessibleIntervalMipmapSource4D( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final AffineTransform3D[] mipmapTransforms, + final VoxelDimensions voxelDimensions, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, voxelDimensions, doBoundingBoxCulling ); + assert imgs.length == mipmapTransforms.length : "Number of mipmaps and scale factors do not match."; + assert assertAllTDimensionsEqual(imgs) : "Mipmaps have different numbers of timepoints."; + + this.mipmapSources = imgs; + currentMipmaps = new RandomAccessibleInterval[ imgs.length ]; + this.mipmapTransforms = mipmapTransforms; + + minT = mipmapSources[0].min(3); + maxT = mipmapSources[0].max(3); + + currentInterpolatedSources = new RealRandomAccessible[ Interpolation.values().length ][ imgs.length ]; + loadTimepoint( 0 ); + } + + public RandomAccessibleIntervalMipmapSource4D( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final double[][] mipmapScales, + final VoxelDimensions voxelDimensions, + final AffineTransform3D sourceTransform, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, voxelDimensions, doBoundingBoxCulling ); + assert imgs.length == mipmapScales.length : "Number of mipmaps and scale factors do not match."; + assert assertAllTDimensionsEqual(imgs) : "Mipmaps have different numbers of timepoints."; + + this.mipmapSources = imgs; + currentMipmaps = new RandomAccessibleInterval[ imgs.length ]; + this.mipmapTransforms = new AffineTransform3D[ mipmapScales.length ]; + for ( int s = 0; s < mipmapScales.length; ++s ) + { + final AffineTransform3D mipmapTransform = new AffineTransform3D(); + mipmapTransform.set( + mipmapScales[ s ][ 0 ], 0, 0, 0.5 * ( mipmapScales[ s ][ 0 ] - 1 ), + 0, mipmapScales[ s ][ 1 ], 0, 0.5 * ( mipmapScales[ s ][ 1 ] - 1 ), + 0, 0, mipmapScales[ s ][ 2 ], 0.5 * ( mipmapScales[ s ][ 2 ] - 1 ) ); + mipmapTransform.preConcatenate(sourceTransform); + mipmapTransforms[ s ] = mipmapTransform; + } + + minT = mipmapSources[0].min(3); + maxT = mipmapSources[0].max(3); + + currentInterpolatedSources = new RealRandomAccessible[ Interpolation.values().length ][ imgs.length ]; + loadTimepoint( 0 ); + } + + public RandomAccessibleIntervalMipmapSource4D( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final double[][] mipmapScales, + final VoxelDimensions voxelDimensions, + final AffineTransform3D sourceTransform, + final String name ) + { + this( imgs, type, mipmapScales, voxelDimensions, sourceTransform, name, true ); + } + + public RandomAccessibleIntervalMipmapSource4D( + final RandomAccessibleInterval< T >[] imgs, + final T type, + final double[][] mipmapScales, + final VoxelDimensions voxelDimensions, + final String name ) + { + this(imgs, type, mipmapScales, voxelDimensions, new AffineTransform3D(), name); + } + + private void loadTimepoint( final int timepointIndex ) + { + currentTimePointIndex = timepointIndex; + if ( isPresent( timepointIndex ) ) + { + final T zero = getType().createVariable(); + zero.setZero(); + for ( int level = 0; level < currentMipmaps.length; ++level ) + { + currentMipmaps[level] = Views.hyperSlice(mipmapSources[level], 3, timepointIndex ); + for ( final Interpolation method : Interpolation.values() ) + currentInterpolatedSources[ method.ordinal() ][ level ] = + Views.interpolate( Views.extendValue( currentMipmaps[level], zero ), interpolators.get( method ) ); + } + } + else + { + Arrays.fill( currentMipmaps, null ); + Arrays.fill( currentInterpolatedSources, null ); + } + } + + @Override + public boolean isPresent( final int t ) + { + return minT <= t && t <= maxT; + } + + @Override + public RandomAccessibleInterval< T > getSource( final int t, final int level ) + { + if ( t != currentTimePointIndex ) + loadTimepoint( t ); + return currentMipmaps[ level ]; + } + + @Override + public RealRandomAccessible< T > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + if ( t != currentTimePointIndex ) + loadTimepoint( t ); + return currentInterpolatedSources[ method.ordinal() ][ level ]; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( mipmapTransforms[ level ] ); + } + + @Override + public int getNumMipmapLevels() + { + return mipmapSources.length; + } + + public < V extends Volatile< T > & NumericType< V > > VolatileSource< T, V > asVolatile( final V vType, final SharedQueue queue ) + { + return new VolatileSource<>( this, vType, queue ); + } + + public < V extends Volatile< T > & NumericType< V > > VolatileSource< T, V > asVolatile( final Supplier< V > vTypeSupplier, final SharedQueue queue ) + { + return new VolatileSource<>( this, vTypeSupplier, queue ); + } + + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public < V extends Volatile< T > & NumericType< V > > VolatileSource< T, V > asVolatile( final SharedQueue queue ) + { + final T t = getType(); + if ( t instanceof NativeType ) + return new VolatileSource<>( this, ( V )VolatileTypeMatcher.getVolatileTypeForType( ( NativeType )getType() ), queue ); + else + throw new UnsupportedOperationException( "This method only works for sources of NativeType." ); + } +} diff --git a/src/main/java/bdv/util/RandomAccessibleIntervalSource.java b/src/main/java/bdv/util/RandomAccessibleIntervalSource.java new file mode 100644 index 00000000..8697ca91 --- /dev/null +++ b/src/main/java/bdv/util/RandomAccessibleIntervalSource.java @@ -0,0 +1,98 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.viewer.Interpolation; +import mpicbg.spim.data.sequence.DefaultVoxelDimensions; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.view.Views; + +public class RandomAccessibleIntervalSource< T extends NumericType< T > > extends AbstractSource< T > +{ + private final RandomAccessibleInterval< T > source; + + private final RealRandomAccessible< T >[] interpolatedSources; + + private final AffineTransform3D sourceTransform; + + public RandomAccessibleIntervalSource( + final RandomAccessibleInterval< T > img, + final T type, + final String name ) + { + this( img, type, new AffineTransform3D(), name, true ); + } + + public RandomAccessibleIntervalSource( + final RandomAccessibleInterval< T > img, + final T type, + final AffineTransform3D sourceTransform, + final String name ) + { + this( img, type, sourceTransform, name, true ); + } + + public RandomAccessibleIntervalSource( + final RandomAccessibleInterval< T > img, + final T type, + final AffineTransform3D sourceTransform, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, new DefaultVoxelDimensions( img.numDimensions() ), doBoundingBoxCulling ); + this.source = img; + this.sourceTransform = sourceTransform; + interpolatedSources = new RealRandomAccessible[ Interpolation.values().length ]; + final T zero = getType().createVariable(); + zero.setZero(); + for ( final Interpolation method : Interpolation.values() ) + interpolatedSources[ method.ordinal() ] = Views.interpolate( Views.extendValue( source, zero ), interpolators.get( method ) ); + } + + @Override + public RandomAccessibleInterval< T > getSource( final int t, final int level ) + { + return source; + } + + @Override + public RealRandomAccessible< T > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + return interpolatedSources[ method.ordinal() ]; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( sourceTransform ); + } +} diff --git a/src/main/java/bdv/util/RandomAccessibleIntervalSource4D.java b/src/main/java/bdv/util/RandomAccessibleIntervalSource4D.java new file mode 100644 index 00000000..6a68f9c6 --- /dev/null +++ b/src/main/java/bdv/util/RandomAccessibleIntervalSource4D.java @@ -0,0 +1,118 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Arrays; + +import bdv.viewer.Interpolation; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.view.Views; + +public class RandomAccessibleIntervalSource4D< T extends NumericType< T > > extends AbstractSource< T > +{ + private final RandomAccessibleInterval< T > source; + + protected int currentTimePointIndex; + + private RandomAccessibleInterval< T > currentSource; + + private final RealRandomAccessible< T >[] currentInterpolatedSources; + + private final AffineTransform3D sourceTransform; + + public RandomAccessibleIntervalSource4D( + final RandomAccessibleInterval< T > img, + final T type, + final String name ) + { + this( img, type, new AffineTransform3D(), name ); + } + + public RandomAccessibleIntervalSource4D( + final RandomAccessibleInterval< T > img, + final T type, + final AffineTransform3D sourceTransform, + final String name ) + { + super( type, name ); + this.source = img; + this.sourceTransform = sourceTransform; + currentInterpolatedSources = new RealRandomAccessible[ Interpolation.values().length ]; + loadTimepoint( 0 ); + } + + private void loadTimepoint( final int timepointIndex ) + { + currentTimePointIndex = timepointIndex; + if ( isPresent( timepointIndex ) ) + { + final T zero = getType().createVariable(); + zero.setZero(); + currentSource = Views.hyperSlice( source, 3, timepointIndex ); + for ( final Interpolation method : Interpolation.values() ) + currentInterpolatedSources[ method.ordinal() ] = Views.interpolate( Views.extendValue( currentSource, zero ), interpolators.get( method ) ); + } + else + { + currentSource = null; + Arrays.fill( currentInterpolatedSources, null ); + } + } + + @Override + public boolean isPresent( final int t ) + { + return source.min( 3 ) <= t && t <= source.max( 3 ); + } + + @Override + public RandomAccessibleInterval< T > getSource( final int t, final int level ) + { + if ( t != currentTimePointIndex ) + loadTimepoint( t ); + return currentSource; + } + + @Override + public RealRandomAccessible< T > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + if ( t != currentTimePointIndex ) + loadTimepoint( t ); + return currentInterpolatedSources[ method.ordinal() ]; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( sourceTransform ); + } +} diff --git a/src/main/java/bdv/util/RandomAccessibleSource.java b/src/main/java/bdv/util/RandomAccessibleSource.java new file mode 100644 index 00000000..fc79a907 --- /dev/null +++ b/src/main/java/bdv/util/RandomAccessibleSource.java @@ -0,0 +1,104 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.viewer.Interpolation; +import net.imglib2.Interval; +import net.imglib2.RandomAccessible; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.view.Views; + +public class RandomAccessibleSource< T extends NumericType< T > > extends AbstractSource< T > +{ + private final RandomAccessible< T > source; + + private final Interval interval; + + private final RealRandomAccessible< T >[] interpolatedSources; + + private final AffineTransform3D sourceTransform; + + public RandomAccessibleSource( + final RandomAccessible< T > img, + final Interval interval, + final T type, + final String name ) + { + this( img, interval, type, new AffineTransform3D(), name, false ); + } + + public RandomAccessibleSource( + final RandomAccessible< T > img, + final Interval interval, + final T type, + final AffineTransform3D sourceTransform, + final String name ) + { + this( img, interval, type, sourceTransform, name, false ); + } + + public RandomAccessibleSource( + final RandomAccessible< T > img, + final Interval interval, + final T type, + final AffineTransform3D sourceTransform, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, doBoundingBoxCulling ); + this.source = img; + this.interval = interval; + this.sourceTransform = sourceTransform; + interpolatedSources = new RealRandomAccessible[ Interpolation.values().length ]; + for ( final Interpolation method : Interpolation.values() ) + interpolatedSources[ method.ordinal() ] = Views.interpolate( source, interpolators.get( method ) ); + + } + + @Override + public RandomAccessibleInterval< T > getSource( final int t, final int level ) + { + return Views.interval( source, interval ); + } + + @Override + public RealRandomAccessible< T > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + return interpolatedSources[ method.ordinal() ]; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( sourceTransform ); + } +} diff --git a/src/main/java/bdv/util/RandomAccessibleSource4D.java b/src/main/java/bdv/util/RandomAccessibleSource4D.java new file mode 100644 index 00000000..617052b8 --- /dev/null +++ b/src/main/java/bdv/util/RandomAccessibleSource4D.java @@ -0,0 +1,142 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Arrays; + +import bdv.viewer.Interpolation; +import net.imglib2.Interval; +import net.imglib2.RandomAccessible; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.util.Intervals; +import net.imglib2.view.Views; + +public class RandomAccessibleSource4D< T extends NumericType< T > > extends AbstractSource< T > +{ + private final RandomAccessible< T > source; + + private final Interval interval; + + private final Interval timeSliceInterval; + + protected int currentTimePointIndex; + + private RandomAccessibleInterval< T > currentSource; + + private final RealRandomAccessible< T >[] currentInterpolatedSources; + + private final AffineTransform3D sourceTransform; + + public RandomAccessibleSource4D( + final RandomAccessible< T > img, + final Interval interval, + final T type, + final String name ) + { + this( img, interval, type, new AffineTransform3D(), name, false ); + } + public RandomAccessibleSource4D( + final RandomAccessible< T > img, + final Interval interval, + final T type, + final AffineTransform3D sourceTransform, + final String name ) + { + this( img, interval, type, sourceTransform, name, false ); + } + + public RandomAccessibleSource4D( + final RandomAccessible< T > img, + final Interval interval, + final T type, + final AffineTransform3D sourceTransform, + final String name, + final boolean doBoundingBoxCulling ) + { + super( type, name, doBoundingBoxCulling ); + this.source = img; + this.interval = interval; + this.timeSliceInterval = Intervals.createMinMax( + interval.min( 0 ), interval.min( 1 ), interval.min( 2 ), + interval.max( 0 ), interval.max( 1 ), interval.max( 2 ) ); + this.sourceTransform = sourceTransform; + currentInterpolatedSources = new RealRandomAccessible[ Interpolation.values().length ]; + loadTimepoint( 0 ); + } + + private void loadTimepoint( final int timepointIndex ) + { + currentTimePointIndex = timepointIndex; + if ( isPresent( timepointIndex ) ) + { + final T zero = getType().createVariable(); + zero.setZero(); + final RandomAccessible< T > slice = Views.hyperSlice( source, 3, timepointIndex ); + currentSource = Views.interval( slice, timeSliceInterval ); + for ( final Interpolation method : Interpolation.values() ) + currentInterpolatedSources[ method.ordinal() ] = Views.interpolate( slice, interpolators.get( method ) ); + } + else + { + currentSource = null; + Arrays.fill( currentInterpolatedSources, null ); + } + } + + @Override + public boolean isPresent( final int t ) + { + return interval.min( 3 ) <= t && t <= interval.max( 3 ); + } + + @Override + public RandomAccessibleInterval< T > getSource( final int t, final int level ) + { + if ( t != currentTimePointIndex ) + loadTimepoint( t ); + return currentSource; + } + + @Override + public RealRandomAccessible< T > getInterpolatedSource( final int t, final int level, final Interpolation method ) + { + if ( t != currentTimePointIndex ) + loadTimepoint( t ); + return currentInterpolatedSources[ method.ordinal() ]; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( sourceTransform ); + } +} diff --git a/src/main/java/bdv/util/RealRandomAccessibleIntervalSource.java b/src/main/java/bdv/util/RealRandomAccessibleIntervalSource.java new file mode 100644 index 00000000..d7d5825b --- /dev/null +++ b/src/main/java/bdv/util/RealRandomAccessibleIntervalSource.java @@ -0,0 +1,86 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import mpicbg.spim.data.sequence.DefaultVoxelDimensions; +import net.imglib2.Interval; +import net.imglib2.RealRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.Type; + +public class RealRandomAccessibleIntervalSource< T extends Type< T > > extends RealRandomAccessibleSource< T > +{ + private final Interval interval; + + private final AffineTransform3D sourceTransform; + + public RealRandomAccessibleIntervalSource( + final RealRandomAccessible< T > accessible, + final Interval interval, + final T type, + final String name ) + { + this( accessible, interval, type, new AffineTransform3D(), name, false ); + } + + public RealRandomAccessibleIntervalSource( + final RealRandomAccessible< T > accessible, + final Interval interval, + final T type, + final AffineTransform3D sourceTransform, + final String name ) + { + this( accessible, interval, type, sourceTransform, name, false ); + } + + public RealRandomAccessibleIntervalSource( + final RealRandomAccessible< T > accessible, + final Interval interval, + final T type, + final AffineTransform3D sourceTransform, + final String name, + final boolean doBoundingBoxIntersectionCheck ) + { + super( accessible, type, name, new DefaultVoxelDimensions( -1 ), doBoundingBoxIntersectionCheck ); + this.interval = interval; + this.sourceTransform = sourceTransform; + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + transform.set( sourceTransform ); + } + + @Override + public Interval getInterval( final int t, final int level ) + { + return interval; + } +} diff --git a/src/main/java/bdv/util/VirtualChannels.java b/src/main/java/bdv/util/VirtualChannels.java new file mode 100644 index 00000000..af892fd9 --- /dev/null +++ b/src/main/java/bdv/util/VirtualChannels.java @@ -0,0 +1,190 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import bdv.viewer.SourceAndConverter; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.converter.TypeIdentity; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; + + +/** + * The current application for VirtualChannel sources is the following scenario: + * + * We have a labeling and want to display it using lookup tables to convert + * labels to ARGBType. From the same labeling we want to make multiple channels, + * e.g., selected ROIs, ROIs having property A, property B, etc. These could be + * added to BDV as individually converted images. So we could use N lookup + * tables to display N converted images. Instead, it is more efficient to merge + * the N lookup tables and then display only one converted image. We still want + * to be able to control display range and color settings for the N + * "virtual channels" individually. So {@link VirtualChannels} adds N fake + * sources to the BDV. Each fake source is used to control visibility and + * settings for one lookup table. Only one of the fake source will then actually + * render the converted img. + * + * @author Tobias Pietzsch <tobias.pietzsch@gmail.com> + */ +public class VirtualChannels +{ + public interface VirtualChannel + { + void updateVisibility(); + + void updateSetupParameters(); + } + + static List< BdvVirtualChannelSource > show( + final RandomAccessibleInterval< ARGBType > img, + final List< ? extends VirtualChannel > virtualChannels, + final String name, + final BdvOptions options ) + { + final Bdv bdv = options.values.addTo(); + final BdvHandle handle = ( bdv == null ) + ? new BdvHandleFrame( options ) + : bdv.getBdvHandle(); + final AffineTransform3D sourceTransform = options.values.getSourceTransform(); + AxisOrder axisOrder = options.values.axisOrder(); + axisOrder = AxisOrder.getAxisOrder( axisOrder, img, handle.is2D() ); + + final ArrayList< RandomAccessibleInterval< ARGBType > > stacks = AxisOrder.splitInputStackIntoSourceStacks( img, axisOrder ); + if ( stacks.size() != 1 ) + throw new IllegalArgumentException( "The RandomAccessibleInterval of a VirtualChannelSource must have exactly one channel!" ); + final RandomAccessibleInterval< ARGBType > stack = stacks.get( 0 ); + + final List< BdvVirtualChannelSource > bdvSources = new ArrayList<>(); + + final int numTimepoints = ( stack.numDimensions() > 3 ) ? ( int ) stack.max( 3 ) + 1 : 1; + final ChannelSourceCoordinator coordinator = new ChannelSourceCoordinator(); + for ( final VirtualChannel vc : virtualChannels ) + { + final ChannelSource source = ( stack.numDimensions() > 3 ) + ? new ChannelSource4D( stack, coordinator, sourceTransform, name ) + : new DefaultChannelSource( stack, coordinator, sourceTransform, name ); + final int setupId = handle.getUnusedSetupId(); + final PlaceHolderConverterSetup setup = new PlaceHolderConverterSetup( setupId, 0, 255, new ARGBType( 0xffffffff ) ); + final SourceAndConverter< ARGBType > soc = source.getSourceAndConverter(); + handle.add( Collections.singletonList( setup ), Collections.singletonList( soc ), numTimepoints ); + + final PlaceHolderOverlayInfo info = new PlaceHolderOverlayInfo( handle.getViewerPanel(), soc, setup ); + coordinator.sharedInfos.add( info ); + setup.setupChangeListeners().add( s -> vc.updateSetupParameters() ); + info.visibilityChangeListeners().add( vc::updateVisibility ); + final BdvVirtualChannelSource bdvSource = new BdvVirtualChannelSource( handle, numTimepoints, setup, soc, info, coordinator ); + handle.addBdvSource( bdvSource ); + bdvSources.add( bdvSource ); + } + + return bdvSources; + } + + static class ChannelSourceCoordinator + { + List< PlaceHolderOverlayInfo > sharedInfos = new ArrayList<>(); + + boolean shouldBePresent( final ChannelSource source ) + { + for ( final PlaceHolderOverlayInfo info : sharedInfos ) + if ( info.isVisible() ) + return info.getSource().equals( source.getSourceAndConverter() ); + return false; + } + } + + interface ChannelSource + { + SourceAndConverter< ARGBType > getSourceAndConverter(); + } + + static class DefaultChannelSource extends RandomAccessibleIntervalSource< ARGBType > implements ChannelSource + { + private final ChannelSourceCoordinator coordinator; + + private final SourceAndConverter< ARGBType > soc; + + public DefaultChannelSource( + final RandomAccessibleInterval< ARGBType > img, + final ChannelSourceCoordinator coordinator, + final AffineTransform3D sourceTransform, + final String name ) + { + super( img, new ARGBType(), sourceTransform, name ); + this.coordinator = coordinator; + this.soc = new SourceAndConverter<>( this, new TypeIdentity< >() ); + } + + @Override + public boolean isPresent( final int t ) + { + return super.isPresent( t ) && coordinator.shouldBePresent( this ); + } + + @Override + public SourceAndConverter< ARGBType > getSourceAndConverter() + { + return soc; + } + } + + static class ChannelSource4D extends RandomAccessibleIntervalSource4D< ARGBType > implements ChannelSource + { + private final ChannelSourceCoordinator coordinator; + + private final SourceAndConverter< ARGBType > soc; + + public ChannelSource4D( + final RandomAccessibleInterval< ARGBType > img, + final ChannelSourceCoordinator coordinator, + final AffineTransform3D sourceTransform, + final String name ) + { + super( img, new ARGBType(), sourceTransform, name ); + this.coordinator = coordinator; + this.soc = new SourceAndConverter<>( this, new TypeIdentity< >() ); + } + + @Override + public boolean isPresent( final int t ) + { + return super.isPresent( t ) && coordinator.shouldBePresent( this ); + } + + @Override + public SourceAndConverter< ARGBType > getSourceAndConverter() + { + return soc; + } + } +} diff --git a/src/main/java/bdv/util/VolatileRandomAccessibleIntervalMipmapSource.java b/src/main/java/bdv/util/VolatileRandomAccessibleIntervalMipmapSource.java new file mode 100644 index 00000000..30a36da0 --- /dev/null +++ b/src/main/java/bdv/util/VolatileRandomAccessibleIntervalMipmapSource.java @@ -0,0 +1,58 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.function.Supplier; + +import bdv.cache.SharedQueue; +import net.imglib2.Volatile; +import net.imglib2.type.numeric.NumericType; + +/** + * @deprecated use {@code VolatileSource} + */ +@Deprecated +public class VolatileRandomAccessibleIntervalMipmapSource< T extends NumericType< T >, V extends Volatile< T > & NumericType< V > > extends VolatileSource< T, V > +{ + public VolatileRandomAccessibleIntervalMipmapSource( + final RandomAccessibleIntervalMipmapSource< T > source, + final V type, + final SharedQueue queue ) + { + super( source, type, queue ); + } + + public VolatileRandomAccessibleIntervalMipmapSource( + final RandomAccessibleIntervalMipmapSource< T > source, + final Supplier< V > typeSupplier, + final SharedQueue queue ) + { + super( source, typeSupplier, queue ); + } +} diff --git a/src/main/java/bdv/util/VolatileSource.java b/src/main/java/bdv/util/VolatileSource.java new file mode 100644 index 00000000..4f9de3f1 --- /dev/null +++ b/src/main/java/bdv/util/VolatileSource.java @@ -0,0 +1,91 @@ +/* + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.function.Supplier; + +import bdv.cache.SharedQueue; +import bdv.util.volatiles.VolatileViews; +import bdv.viewer.Source; +import mpicbg.spim.data.sequence.VoxelDimensions; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.Volatile; +import net.imglib2.cache.volatiles.CacheHints; +import net.imglib2.cache.volatiles.LoadingStrategy; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.NumericType; + +public class VolatileSource< T extends NumericType< T >, V extends Volatile< T > & NumericType< V > > extends AbstractSource< V > +{ + private final Source< T > source; + + private SharedQueue queue; + + public VolatileSource( + final Source< T > source, + final V type, + final SharedQueue queue ) + { + super( type, source.getName() ); + this.source = source; + this.queue = queue; + } + + public VolatileSource( + final Source< T > source, + final Supplier< V > typeSupplier, + final SharedQueue queue ) + { + this( source, typeSupplier.get(), queue ); + } + + @Override + public RandomAccessibleInterval< V > getSource( final int t, final int level ) + { + return VolatileViews.wrapAsVolatile( source.getSource( t, level ), queue, new CacheHints( LoadingStrategy.VOLATILE, level, true ) ); + } + + @Override + public synchronized void getSourceTransform( final int t, final int level, final AffineTransform3D transform ) + { + source.getSourceTransform( t, level, transform ); + } + + @Override + public VoxelDimensions getVoxelDimensions() + { + return source.getVoxelDimensions(); + } + + @Override + public int getNumMipmapLevels() + { + return source.getNumMipmapLevels(); + } +} diff --git a/src/main/java/bdv/util/volatiles/SharedQueue.java b/src/main/java/bdv/util/volatiles/SharedQueue.java new file mode 100644 index 00000000..0829be55 --- /dev/null +++ b/src/main/java/bdv/util/volatiles/SharedQueue.java @@ -0,0 +1,48 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +/** + * @deprecated This class lives now in bigdataviewer-core. Use {@code bdv.cache.SharedQueue} instead. + */ +@Deprecated +public class SharedQueue extends bdv.cache.SharedQueue +{ + @Deprecated + public SharedQueue( final int numFetcherThreads, final int numPriorities ) + { + super( numFetcherThreads, numPriorities ); + } + + @Deprecated + public SharedQueue( final int numFetcherThreads ) + { + super( numFetcherThreads, 1 ); + } +} diff --git a/src/main/java/bdv/util/volatiles/VolatileRandomAccessibleIntervalView.java b/src/main/java/bdv/util/volatiles/VolatileRandomAccessibleIntervalView.java new file mode 100644 index 00000000..bd833bdb --- /dev/null +++ b/src/main/java/bdv/util/volatiles/VolatileRandomAccessibleIntervalView.java @@ -0,0 +1,73 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +import net.imglib2.AbstractWrappedInterval; +import net.imglib2.Interval; +import net.imglib2.RandomAccess; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.Volatile; + +public class VolatileRandomAccessibleIntervalView< T, V extends Volatile< T > > + extends AbstractWrappedInterval< RandomAccessibleInterval< V > > + implements VolatileView< T, V >, RandomAccessibleInterval< V > +{ + private final VolatileViewData< T, V > viewData; + + public VolatileRandomAccessibleIntervalView( + final VolatileViewData< T, V > viewData ) + { + super( ( RandomAccessibleInterval< V > ) viewData.getImg() ); + this.viewData = viewData; + } + + @Override + public VolatileViewData< T, V > getVolatileViewData() + { + return viewData; + } + + @Override + public RandomAccess< V > randomAccess() + { + return sourceInterval.randomAccess(); + } + + @Override + public RandomAccess< V > randomAccess( final Interval interval ) + { + return sourceInterval.randomAccess( interval ); + } + + @Override + public V getType() + { + return viewData.getVolatileType(); + } +} diff --git a/src/main/java/bdv/util/volatiles/VolatileRandomAccessibleView.java b/src/main/java/bdv/util/volatiles/VolatileRandomAccessibleView.java new file mode 100644 index 00000000..05f9909a --- /dev/null +++ b/src/main/java/bdv/util/volatiles/VolatileRandomAccessibleView.java @@ -0,0 +1,77 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +import net.imglib2.Interval; +import net.imglib2.RandomAccess; +import net.imglib2.RandomAccessible; +import net.imglib2.Volatile; + +public class VolatileRandomAccessibleView< T, V extends Volatile< T > > + implements VolatileView< T, V >, RandomAccessible< V > +{ + private final VolatileViewData< T, V > viewData; + + public VolatileRandomAccessibleView( + final VolatileViewData< T, V > viewData ) + { + this.viewData = viewData; + } + + @Override + public VolatileViewData< T, V > getVolatileViewData() + { + return viewData; + } + + @Override + public RandomAccess< V > randomAccess() + { + return viewData.getImg().randomAccess(); + } + + @Override + public RandomAccess< V > randomAccess( final Interval interval ) + { + return viewData.getImg().randomAccess( interval ); + } + + @Override + public int numDimensions() + { + return viewData.getImg().numDimensions(); + + } + + @Override + public V getType() + { + return viewData.getVolatileType(); + } +} diff --git a/src/main/java/bdv/util/volatiles/VolatileTypeMatcher.java b/src/main/java/bdv/util/volatiles/VolatileTypeMatcher.java new file mode 100644 index 00000000..5a97a057 --- /dev/null +++ b/src/main/java/bdv/util/volatiles/VolatileTypeMatcher.java @@ -0,0 +1,84 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.integer.ByteType; +import net.imglib2.type.numeric.integer.IntType; +import net.imglib2.type.numeric.integer.LongType; +import net.imglib2.type.numeric.integer.ShortType; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.type.numeric.integer.UnsignedIntType; +import net.imglib2.type.numeric.integer.UnsignedLongType; +import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.type.numeric.real.FloatType; +import net.imglib2.type.volatiles.VolatileARGBType; +import net.imglib2.type.volatiles.VolatileByteType; +import net.imglib2.type.volatiles.VolatileDoubleType; +import net.imglib2.type.volatiles.VolatileFloatType; +import net.imglib2.type.volatiles.VolatileIntType; +import net.imglib2.type.volatiles.VolatileLongType; +import net.imglib2.type.volatiles.VolatileShortType; +import net.imglib2.type.volatiles.VolatileUnsignedByteType; +import net.imglib2.type.volatiles.VolatileUnsignedIntType; +import net.imglib2.type.volatiles.VolatileUnsignedLongType; +import net.imglib2.type.volatiles.VolatileUnsignedShortType; + +public class VolatileTypeMatcher +{ + public static < T extends NativeType< T > > NativeType< ? > getVolatileTypeForType( final T type ) + { + if ( type instanceof ARGBType ) + return new VolatileARGBType(); + else if ( type instanceof FloatType ) + return new VolatileFloatType(); + else if ( type instanceof DoubleType ) + return new VolatileDoubleType(); + else if ( type instanceof ByteType ) + return new VolatileByteType(); + else if ( type instanceof ShortType ) + return new VolatileShortType(); + else if ( type instanceof IntType ) + return new VolatileIntType(); + else if ( type instanceof LongType ) + return new VolatileLongType(); + else if ( type instanceof UnsignedByteType ) + return new VolatileUnsignedByteType(); + else if ( type instanceof UnsignedShortType ) + return new VolatileUnsignedShortType(); + else if ( type instanceof UnsignedIntType ) + return new VolatileUnsignedIntType(); + else if ( type instanceof UnsignedLongType ) + return new VolatileUnsignedLongType(); + else + return null; + } +} diff --git a/src/main/java/bdv/util/volatiles/VolatileView.java b/src/main/java/bdv/util/volatiles/VolatileView.java new file mode 100644 index 00000000..8c6456b1 --- /dev/null +++ b/src/main/java/bdv/util/volatiles/VolatileView.java @@ -0,0 +1,46 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +import net.imglib2.Volatile; + +/** + * Something that provides {@link VolatileViewData}. + * + * @param + * original image pixel type + * @param + * corresponding volatile pixel type + * + * @author Tobias Pietzsch + */ +public interface VolatileView< T, V extends Volatile< T > > +{ + public VolatileViewData< T, V > getVolatileViewData(); +} diff --git a/src/main/java/bdv/util/volatiles/VolatileViewData.java b/src/main/java/bdv/util/volatiles/VolatileViewData.java new file mode 100644 index 00000000..89c7b023 --- /dev/null +++ b/src/main/java/bdv/util/volatiles/VolatileViewData.java @@ -0,0 +1,117 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +import bdv.cache.CacheControl; +import net.imglib2.RandomAccessible; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.Volatile; +import net.imglib2.cache.img.CachedCellImg; + +/** + * Metadata associated with a {@link VolatileView}. It comprises the types + * of the original and volatile image, a {@link CacheControl} for the + * volatile cache, and the wrapped {@link RandomAccessible}. + *

+ * {@link VolatileViewData} is used while wrapping deeper layers of a view + * cascade (ending at a {@link CachedCellImg}) and only on the top layer + * wrapped as a {@link RandomAccessible} / {@link RandomAccessibleInterval}. + *

+ * + * @param + * original image pixel type + * @param + * corresponding volatile pixel type + * + * @author Tobias Pietzsch + */ +public class VolatileViewData< T, V extends Volatile< T > > +{ + private final RandomAccessible< V > img; + + private final CacheControl cacheControl; + + private final T type; + + private final V volatileType; + + public VolatileViewData( + final RandomAccessible< V > img, + final CacheControl cacheControl, + final T type, + final V volatileType ) + { + this.img = img; + this.cacheControl = cacheControl; + this.type = type; + this.volatileType = volatileType; + } + + /** + * Get the wrapped {@link RandomAccessible}. + * + * @return the wrapped {@link RandomAccessible} + */ + public RandomAccessible< V > getImg() + { + return img; + } + + /** + * Get the {@link CacheControl} for the {@link CachedCellImg}(s) at the + * bottom of the view cascade. + * + * @return the {@link CacheControl} for the {@link CachedCellImg}(s) at the + * bottom of the view cascade + */ + public CacheControl getCacheControl() + { + return cacheControl; + } + + /** + * Get the pixel type of the original image. + * + * @return the pixel type of the original image + */ + public T getType() + { + return type; + } + + /** + * Get the pixel type of the wrapped {@link RandomAccessible}. + * + * @return the pixel type of the wrapped {@link RandomAccessible} + */ + public V getVolatileType() + { + return volatileType; + } +} diff --git a/src/main/java/bdv/util/volatiles/VolatileViews.java b/src/main/java/bdv/util/volatiles/VolatileViews.java new file mode 100644 index 00000000..f004f359 --- /dev/null +++ b/src/main/java/bdv/util/volatiles/VolatileViews.java @@ -0,0 +1,249 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.volatiles; + +import static net.imglib2.img.basictypeaccess.AccessFlags.DIRTY; +import static net.imglib2.img.basictypeaccess.AccessFlags.VOLATILE; + +import java.util.Set; + +import net.imglib2.RandomAccessible; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.Volatile; +import net.imglib2.cache.Cache; +import net.imglib2.cache.img.CachedCellImg; +import net.imglib2.cache.ref.WeakRefVolatileCache; +import net.imglib2.cache.volatiles.CacheHints; +import net.imglib2.cache.volatiles.CreateInvalid; +import net.imglib2.cache.volatiles.LoadingStrategy; +import net.imglib2.cache.volatiles.VolatileCache; +import net.imglib2.img.WrappedImg; +import net.imglib2.img.basictypeaccess.AccessFlags; +import net.imglib2.img.basictypeaccess.DataAccess; +import net.imglib2.img.basictypeaccess.volatiles.VolatileArrayDataAccess; +import net.imglib2.img.cell.Cell; +import net.imglib2.img.cell.CellGrid; +import net.imglib2.type.NativeType; +import net.imglib2.view.IntervalView; +import net.imglib2.view.MixedTransformView; + +import bdv.cache.SharedQueue; +import bdv.img.cache.CreateInvalidVolatileCell; +import bdv.img.cache.VolatileCachedCellImg; + +/** + * Wrap view cascades ending in {@link CachedCellImg} as volatile views. + * {@link RandomAccessible}s wrapped in this way can be displayed in + * BigDataViewer while loading asynchronously. + * + * @author Tobias Pietzsch + */ +public class VolatileViews +{ + public static < T, V extends Volatile< T > > RandomAccessibleInterval< V > wrapAsVolatile( + final RandomAccessibleInterval< T > rai ) + { + return wrapAsVolatile( rai, null, null ); + } + + public static < T, V extends Volatile< T > > RandomAccessibleInterval< V > wrapAsVolatile( + final RandomAccessibleInterval< T > rai, + final SharedQueue queue ) + { + return wrapAsVolatile( rai, queue, null ); + } + + public static < T, V extends Volatile< T > > RandomAccessibleInterval< V > wrapAsVolatile( + final RandomAccessibleInterval< T > rai, + final SharedQueue queue, + final CacheHints hints ) + { + @SuppressWarnings( "unchecked" ) + final VolatileViewData< T, V > viewData = ( VolatileViewData< T, V > ) wrapAsVolatileViewData( rai, queue, hints ); + return new VolatileRandomAccessibleIntervalView<>( viewData ); + } + + public static < T, V extends Volatile< T > > RandomAccessible< V > wrapAsVolatile( + final RandomAccessible< T > rai ) + { + return wrapAsVolatile( rai, null, null ); + } + + public static < T, V extends Volatile< T > > RandomAccessible< V > wrapAsVolatile( + final RandomAccessible< T > rai, + final SharedQueue queue ) + { + return wrapAsVolatile( rai, queue, null ); + } + + public static < T, V extends Volatile< T > > RandomAccessible< V > wrapAsVolatile( + final RandomAccessible< T > rai, + final SharedQueue queue, + final CacheHints hints ) + { + @SuppressWarnings( "unchecked" ) + final VolatileViewData< T, V > viewData = ( VolatileViewData< T, V > ) wrapAsVolatileViewData( rai, queue, hints ); + return new VolatileRandomAccessibleView<>( viewData ); + } + + // ============================================================== + + @SuppressWarnings( "unchecked" ) + private static < T, V extends Volatile< T > > VolatileViewData< T, V > wrapAsVolatileViewData( + final RandomAccessible< T > rai, + final SharedQueue queue, + final CacheHints hints ) + { + if ( rai instanceof CachedCellImg ) + { + @SuppressWarnings( "rawtypes" ) + final Object o = wrapCachedCellImg( ( CachedCellImg ) rai, queue, hints ); + /* + * Need to assign to a Object first to satisfy Eclipse... Otherwise + * the following "unnecessary cast" will be removed, followed by + * compile error. Proposed solution: Add cast. Doh... + */ + final VolatileViewData< T, V > viewData = ( VolatileViewData< T, V > ) o; + return viewData; + } + else if ( rai instanceof IntervalView ) + { + final IntervalView< T > view = ( IntervalView< T > ) rai; + final VolatileViewData< T, V > sourceData = wrapAsVolatileViewData( view.getSource(), queue, hints ); + return new VolatileViewData<>( + new IntervalView<>( sourceData.getImg(), view ), + sourceData.getCacheControl(), + sourceData.getType(), + sourceData.getVolatileType() ); + } + else if ( rai instanceof MixedTransformView ) + { + final MixedTransformView< T > view = ( MixedTransformView< T > ) rai; + final VolatileViewData< T, V > sourceData = wrapAsVolatileViewData( view.getSource(), queue, hints ); + return new VolatileViewData<>( + new MixedTransformView<>( sourceData.getImg(), view.getTransformToSource() ), + sourceData.getCacheControl(), + sourceData.getType(), + sourceData.getVolatileType() ); + } + else if ( rai instanceof WrappedImg ) + { + return wrapAsVolatileViewData( ( ( WrappedImg< T > ) rai ).getImg(), queue, hints ); + } + + throw new IllegalArgumentException(); + } + + @SuppressWarnings( "unchecked" ) + private static < T extends NativeType< T >, V extends Volatile< T > & NativeType< V >, A extends DataAccess > VolatileViewData< T, V > wrapCachedCellImg( + final CachedCellImg< T, A > cachedCellImg, + SharedQueue queue, + CacheHints hints ) + { + final T type = cachedCellImg.createLinkedType(); + final CellGrid grid = cachedCellImg.getCellGrid(); + final Cache< Long, Cell< A > > cache = cachedCellImg.getCache(); + + final Set< AccessFlags > flags = AccessFlags.ofAccess( cachedCellImg.getAccessType() ); + if ( !flags.contains( VOLATILE ) ) + throw new IllegalArgumentException( "underlying " + CachedCellImg.class.getSimpleName() + " must have volatile access type" ); + final boolean dirty = flags.contains( DIRTY ); + + final V vtype = ( V ) VolatileTypeMatcher.getVolatileTypeForType( type ); + if ( queue == null ) + queue = new SharedQueue( 1, 1 ); + if ( hints == null ) + hints = new CacheHints( LoadingStrategy.VOLATILE, 0, false ); + @SuppressWarnings( "rawtypes" ) + final VolatileCachedCellImg< V, ? > img = createVolatileCachedCellImg( grid, vtype, dirty, ( Cache ) cache, queue, hints ); + + return new VolatileViewData<>( img, queue, type, vtype ); + } + + private static < T extends NativeType< T >, A extends VolatileArrayDataAccess< A > > VolatileCachedCellImg< T, A > createVolatileCachedCellImg( + final CellGrid grid, + final T type, + final boolean dirty, + final Cache< Long, Cell< A > > cache, + final SharedQueue queue, + final CacheHints hints ) + { + final CreateInvalid< Long, Cell< A > > createInvalid = CreateInvalidVolatileCell.get( grid, type, dirty ); + final VolatileCache< Long, Cell< A > > volatileCache = new WeakRefVolatileCache<>( cache, queue, createInvalid ); + final VolatileCachedCellImg< T, A > volatileImg = new VolatileCachedCellImg<>( grid, type, hints, volatileCache ); + return volatileImg; + } + + + // == DEPRECATED API == + + /** + * @deprecated Use {@code bdv.cache.SharedQueue} instead of {@code bdv.util.volatiles.SharedQueue} + */ + @Deprecated + public static < T, V extends Volatile< T > > RandomAccessibleInterval< V > wrapAsVolatile( + final RandomAccessibleInterval< T > rai, + final bdv.util.volatiles.SharedQueue queue ) + { + return wrapAsVolatile( rai, ( SharedQueue ) queue ); + } + + /** + * @deprecated Use {@code bdv.cache.SharedQueue} instead of {@code bdv.util.volatiles.SharedQueue} + */ + @Deprecated + public static < T, V extends Volatile< T > > RandomAccessibleInterval< V > wrapAsVolatile( + final RandomAccessibleInterval< T > rai, + final bdv.util.volatiles.SharedQueue queue, + final CacheHints hints ) + { + return wrapAsVolatile( rai, ( SharedQueue ) queue, hints ); + } + + /** + * @deprecated Use {@code bdv.cache.SharedQueue} instead of {@code bdv.util.volatiles.SharedQueue} + */ + @Deprecated + public static < T, V extends Volatile< T > > RandomAccessible< V > wrapAsVolatile( + final RandomAccessible< T > rai, + final bdv.util.volatiles.SharedQueue queue ) + { + return wrapAsVolatile( rai, ( SharedQueue ) queue ); + } + + /** + * @deprecated Use {@code bdv.cache.SharedQueue} instead of {@code bdv.util.volatiles.SharedQueue} + */ + @Deprecated + public static < T, V extends Volatile< T > > RandomAccessible< V > wrapAsVolatile( final RandomAccessible< T > rai, final bdv.util.volatiles.SharedQueue queue, final CacheHints hints ) + { + return wrapAsVolatile( rai, ( SharedQueue ) queue, hints ); + } +} + diff --git a/src/test/java/bdv/util/ActionBlockingExample.java b/src/test/java/bdv/util/ActionBlockingExample.java new file mode 100644 index 00000000..8894b531 --- /dev/null +++ b/src/test/java/bdv/util/ActionBlockingExample.java @@ -0,0 +1,77 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.BigDataViewerActions; +import java.util.Random; +import javax.swing.Action; +import javax.swing.ActionMap; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.util.Actions; +import org.scijava.ui.behaviour.util.InputActionBindings; +import org.scijava.ui.behaviour.util.RunnableAction; + +public class ActionBlockingExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + Bdv bdv = BdvFunctions.show( img, "greens", Bdv.options() ); + + // Add an ActionMap that maps the "manual transform" action name to an Action that does nothing. + // This effectively blocks the action from being triggered. + final ActionMap blockMap = new ActionMap(); + final Action doNothing = new RunnableAction( "do nothing", () -> {} ); + blockMap.put( BigDataViewerActions.MANUAL_TRANSFORM, doNothing ); + + final String BLOCKING_MAP = "transform-blocking"; + final InputActionBindings keybindings = bdv.getBdvHandle().getKeybindings(); + keybindings.addActionMap( BLOCKING_MAP, blockMap ); + + // The following restores the rotation behaviours (by removing the blocking map): +// keybindings.removeActionMap( BLOCKING_MAP ); + + // We can attach this to an action (triggered by pressing "R") + Actions actions = new Actions( new InputTriggerConfig() ); + actions.install( bdv.getBdvHandle().getKeybindings(), "my-new-actions" ); + actions.runnableAction( () -> { + keybindings.removeActionMap( BLOCKING_MAP ); + bdv.getBdvHandle().getViewerPanel().showMessage( "Manual transform action restored" ); + }, "restore manual transform", "R" ); + } +} diff --git a/src/test/java/bdv/util/ActionExample.java b/src/test/java/bdv/util/ActionExample.java new file mode 100644 index 00000000..144c8303 --- /dev/null +++ b/src/test/java/bdv/util/ActionExample.java @@ -0,0 +1,64 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Random; +import net.imglib2.RealPoint; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.util.Util; +import org.scijava.ui.behaviour.ClickBehaviour; +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.util.Actions; +import org.scijava.ui.behaviour.util.Behaviours; + +public class ActionExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + Bdv bdv = BdvFunctions.show( img, "greens", Bdv.options().is2D() ); + + Actions actions = new Actions( new InputTriggerConfig() ); + actions.install( bdv.getBdvHandle().getKeybindings(), "my-new-actions" ); + + actions.runnableAction( () -> { + final RealPoint pos = new RealPoint( 3 ); + bdv.getBdvHandle().getViewerPanel().getGlobalMouseCoordinates( pos ); + System.out.println( "global coordinates: " + Util.printCoordinates(pos) ); + }, "print global pos", "G" ); + } +} diff --git a/src/test/java/bdv/util/BdvHandlePanelGarbageCollectionTest.java b/src/test/java/bdv/util/BdvHandlePanelGarbageCollectionTest.java new file mode 100644 index 00000000..c34e4db9 --- /dev/null +++ b/src/test/java/bdv/util/BdvHandlePanelGarbageCollectionTest.java @@ -0,0 +1,118 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.GraphicsEnvironment; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.function.Consumer; +import javax.swing.JFrame; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.type.numeric.integer.ByteType; +import org.junit.Test; + +import static org.junit.Assume.assumeFalse; + +public class BdvHandlePanelGarbageCollectionTest +{ + @Test + public void testBdv() throws InterruptedException + { + assumeFalse( GraphicsEnvironment.isHeadless() ); + + for ( int i = 0; i < 8; i++ ) + showAndCloseJFrame( this::addBdvHandlePanel ); + } + + @Test( expected = OutOfMemoryError.class ) + public void testMemoryExhaustion() + { + assumeFalse( GraphicsEnvironment.isHeadless() ); + + for ( int i = 0; i < 8; i++ ) + showJFrame( this::addBdvHandlePanel ); + } + + private void showAndCloseJFrame( final Consumer< JFrame > componentAdder ) + { + final JFrame frame = ( showJFrame( componentAdder ) ); + try + { + Thread.sleep( 100 ); + } + catch ( final InterruptedException ignored ) + { + } + closeJFrame( frame ); + System.gc(); + } + + private JFrame showJFrame( final Consumer< JFrame > componentAdder ) + { + final JFrame frame = new JFrame(); + frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); + frame.setSize( 500, 500 ); + componentAdder.accept( frame ); + frame.setVisible( true ); + return frame; + } + + private void closeJFrame( final JFrame frame ) + { + frame.dispatchEvent( new WindowEvent( frame, WindowEvent.WINDOW_CLOSING ) ); + } + + private void addBdvHandlePanel( final JFrame frame ) + { + final BdvHandle handle = new BdvHandlePanel( null, Bdv.options() ); + BdvFunctions.show( dummyLargeImage(), "Image", BdvOptions.options().addTo( handle ) ); + frame.add( handle.getSplitPanel() ); + frame.addWindowListener( new WindowAdapter() + { + @Override + public void windowClosed( final WindowEvent e ) + { + handle.close(); + } + } ); + } + + private RandomAccessibleInterval< ByteType > dummyLargeImage() + { + // NB: The image is intended to use on tenth of the maximal memory. + final byte[] array = new byte[ boundedConvertToInt( Runtime.getRuntime().maxMemory() / 5 ) ]; + return ArrayImgs.bytes( array, 10, 10 ); + } + + private int boundedConvertToInt( final long dataSize ) + { + return ( int ) Math.max( Integer.MIN_VALUE, Math.min( Integer.MAX_VALUE, dataSize ) ); + } +} diff --git a/src/test/java/bdv/util/BehaviourBlockingExample.java b/src/test/java/bdv/util/BehaviourBlockingExample.java new file mode 100644 index 00000000..fcda0194 --- /dev/null +++ b/src/test/java/bdv/util/BehaviourBlockingExample.java @@ -0,0 +1,84 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.TransformEventHandler3D; +import java.util.Random; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import org.scijava.ui.behaviour.Behaviour; +import org.scijava.ui.behaviour.BehaviourMap; +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.util.Actions; +import org.scijava.ui.behaviour.util.TriggerBehaviourBindings; + +public class BehaviourBlockingExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + Bdv bdv = BdvFunctions.show( img, "greens", Bdv.options() ); + + // Add a BehaviourMap that maps all rotation behaviour names to a behaviour that does nothing. + // This effectively blocks these rotation behaviours from being triggered. + final BehaviourMap blockMap = new BehaviourMap(); + final Behaviour doNothing = new Behaviour() {}; + blockMap.put(TransformEventHandler3D.DRAG_ROTATE, doNothing ); + blockMap.put(TransformEventHandler3D.ROTATE_LEFT, doNothing ); + blockMap.put(TransformEventHandler3D.ROTATE_RIGHT, doNothing ); + blockMap.put(TransformEventHandler3D.DRAG_ROTATE_FAST, doNothing ); + blockMap.put(TransformEventHandler3D.ROTATE_LEFT_FAST, doNothing ); + blockMap.put(TransformEventHandler3D.ROTATE_RIGHT_FAST, doNothing ); + blockMap.put(TransformEventHandler3D.DRAG_ROTATE_SLOW, doNothing ); + blockMap.put(TransformEventHandler3D.ROTATE_LEFT_SLOW, doNothing ); + blockMap.put(TransformEventHandler3D.ROTATE_RIGHT_SLOW, doNothing ); + + final String BLOCKING_MAP = "transform-blocking"; + final TriggerBehaviourBindings triggerbindings = bdv.getBdvHandle().getTriggerbindings(); + triggerbindings.addBehaviourMap( BLOCKING_MAP, blockMap ); + + // The following restores the rotation behaviours (by removing the blocking map): + // triggerbindings.removeBehaviourMap( BLOCKING_MAP ); + + // We can attach this to an action (triggered by pressing "R") + Actions actions = new Actions( new InputTriggerConfig() ); + actions.install( bdv.getBdvHandle().getKeybindings(), "my-new-actions" ); + actions.runnableAction( () -> { + triggerbindings.removeBehaviourMap( BLOCKING_MAP ); + bdv.getBdvHandle().getViewerPanel().showMessage( "Rotation behaviours restored" ); + }, "restore rotations", "R" ); + } +} diff --git a/src/test/java/bdv/util/BehaviourExample.java b/src/test/java/bdv/util/BehaviourExample.java new file mode 100644 index 00000000..5f15af90 --- /dev/null +++ b/src/test/java/bdv/util/BehaviourExample.java @@ -0,0 +1,69 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Arrays; +import java.util.Random; +import net.imglib2.Point; +import net.imglib2.RealPoint; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.util.Util; +import org.scijava.ui.behaviour.ClickBehaviour; +import org.scijava.ui.behaviour.DragBehaviour; +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.io.InputTriggerDescription; +import org.scijava.ui.behaviour.util.Behaviours; + +public class BehaviourExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + Bdv bdv = BdvFunctions.show( img, "greens", Bdv.options().is2D() ); + + Behaviours behaviours = new Behaviours( new InputTriggerConfig() ); + behaviours.install( bdv.getBdvHandle().getTriggerbindings(), "my-new-behaviours" ); + + behaviours.behaviour( ( ClickBehaviour ) ( x, y ) -> { + final RealPoint pos = new RealPoint( 3 ); + bdv.getBdvHandle().getViewerPanel().displayToGlobalCoordinates( x, y, pos ); + System.out.println( "global coordinates: " + Util.printCoordinates(pos) ); + }, "print global pos", "G" ); + + // Note that you can also add DragBehaviours, ScrollBehaviours ... + } +} diff --git a/src/test/java/bdv/util/BoxSelectionExample.java b/src/test/java/bdv/util/BoxSelectionExample.java new file mode 100644 index 00000000..46b8fbac --- /dev/null +++ b/src/test/java/bdv/util/BoxSelectionExample.java @@ -0,0 +1,79 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Random; + +import net.imglib2.Interval; +import net.imglib2.img.Img; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.util.Intervals; +import net.imglib2.view.Views; + +import bdv.tools.boundingbox.BoxSelectionOptions; +import bdv.tools.boundingbox.TransformedBoxSelectionDialog; + +public class BoxSelectionExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 100, 100, 50, 10 ); + img.forEach( t -> t.set( random.nextInt( 128 ) ) ); + + final AffineTransform3D imageTransform = new AffineTransform3D(); + imageTransform.set( 2, 2, 2 ); + final Bdv bdv = BdvFunctions.show( img, "image", BdvOptions.options().sourceTransform( imageTransform ) ); + + final Interval initialInterval = Intervals.createMinMax( 30, 30, 15, 80, 80, 40 ); + final Interval rangeInterval = Intervals.createMinMax( 0, 0, 0, 100, 100, 50 ); + final TransformedBoxSelectionDialog.Result result = BdvFunctions.selectBox( + bdv, + imageTransform, + initialInterval, + rangeInterval, + BoxSelectionOptions.options() + .title( "Select box to fill" ) + .selectTimepointRange() + .initialTimepointRange( 0, 5 ) ); + + if ( result.isValid() ) + { + for ( int tp = result.getMinTimepoint(); tp <= result.getMaxTimepoint(); ++tp ) + Views.interval( Views.extendZero( Views.hyperSlice( img, 3, tp ) ), result.getInterval() ).forEach( t -> t.set( 255 ) ); + bdv.getBdvHandle().getViewerPanel().requestRepaint(); + } + } + +} diff --git a/src/test/java/bdv/util/DisplayRangeExample.java b/src/test/java/bdv/util/DisplayRangeExample.java new file mode 100644 index 00000000..e4a99c61 --- /dev/null +++ b/src/test/java/bdv/util/DisplayRangeExample.java @@ -0,0 +1,83 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.Random; + +import javax.swing.JFrame; +import javax.swing.WindowConstants; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class DisplayRangeExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + final Random random = new Random(); + img.forEach( t -> t.set( random.nextInt() ) ); + + final JFrame frame = new JFrame( "my test frame" ); + final BdvHandlePanel handle = new BdvHandlePanel( frame, Bdv.options() ); + frame.add( handle.getSplitPanel(), BorderLayout.CENTER ); + frame.setPreferredSize( new Dimension( 800, 600 ) ); + frame.pack(); + frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE ); + frame.setVisible( true ); + + final BdvSource source = BdvFunctions.show( img, "img", Bdv.options().addTo( handle ) ); + source.setDisplayRangeBounds( 0, 1255 ); + + synchronized ( DisplayRangeExample.class ) + { + try + { + for ( int i = 1; i <= 100; ++i ) + { + DisplayRangeExample.class.wait( 50 ); + source.setDisplayRange( 0, 255 + 10 * i ); + /* + * Press "S" to show brightness dialog and see the values change... + */ + } + } + catch ( final InterruptedException e ) + { + e.printStackTrace(); + } + } + } +} diff --git a/src/test/java/bdv/util/Example2D.java b/src/test/java/bdv/util/Example2D.java new file mode 100644 index 00000000..bac0227d --- /dev/null +++ b/src/test/java/bdv/util/Example2D.java @@ -0,0 +1,54 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Random; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class Example2D +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + final Bdv bdv2D = BdvFunctions.show( img, "greens", Bdv.options().is2D() ); + + final ArrayImg< ARGBType, IntArray > img2 = ArrayImgs.argbs( 100, 100, 100 ); + img2.forEach( t -> t.set( random.nextInt() & 0xFFFF0000 ) ); + BdvFunctions.show( img2, "reds", Bdv.options().addTo( bdv2D ) ); + } +} diff --git a/src/test/java/bdv/util/Example3D.java b/src/test/java/bdv/util/Example3D.java new file mode 100644 index 00000000..572a2596 --- /dev/null +++ b/src/test/java/bdv/util/Example3D.java @@ -0,0 +1,56 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Random; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class Example3D +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + final Bdv bdv3D = BdvFunctions.show( img, "greens" ); + + final ArrayImg< ARGBType, IntArray > img2 = ArrayImgs.argbs( 100, 100, 100 ); + img2.forEach( t -> t.set( random.nextInt() & 0xFFFF0000 ) ); + BdvFunctions.show( img2, "reds", Bdv.options().addTo( bdv3D ) ); + + // TODO: add BdvOptions.closeAfterRemovingLastSource() + } +} diff --git a/src/test/java/bdv/util/Example4D.java b/src/test/java/bdv/util/Example4D.java new file mode 100644 index 00000000..5679ceb2 --- /dev/null +++ b/src/test/java/bdv/util/Example4D.java @@ -0,0 +1,51 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.util.Util; + +import java.util.Random; + +public class Example4D +{ + public static void main( String[] args ) + { + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100, 5 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + + BdvFunctions.show( img, "4d rai" ); + + } +} diff --git a/src/test/java/bdv/util/ExampleMipmapSource4D.java b/src/test/java/bdv/util/ExampleMipmapSource4D.java new file mode 100644 index 00000000..cbdde1db --- /dev/null +++ b/src/test/java/bdv/util/ExampleMipmapSource4D.java @@ -0,0 +1,99 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import net.imglib2.FinalInterval; +import net.imglib2.Localizable; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.position.FunctionRandomAccessible; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.util.Intervals; +import net.imglib2.util.Util; +import net.imglib2.view.IntervalView; +import net.imglib2.view.Views; + +import java.util.function.BiConsumer; +import java.util.stream.DoubleStream; + +import mpicbg.spim.data.sequence.FinalVoxelDimensions; + +public class ExampleMipmapSource4D +{ + public static void main( String[] args ) + { + final BiConsumer< Localizable, DoubleType > f = ( p, v ) -> { + + final double xc = p.getDoublePosition( 0 ) - 100; + final double yc = p.getDoublePosition( 1 ) - 100; + final double zc = p.getDoublePosition( 2 ) - 100; + final double t = p.getDoublePosition( 3 ); + final double s = 20 + ( 20 * t ); + v.set( Math.sqrt( xc * xc / 2 + yc * yc / 16 + zc * zc / 64 ) / s ); + }; + + final IntervalView< DoubleType > img = Views.interval( + new FunctionRandomAccessible<>( 4, f, DoubleType::new ), + new FinalInterval( 200, 200, 200, 20 ) ); + + + // set to true to make the scale transforms not match the downsampling factors + // its can be useful to confirm that bdv really sees the multiple scales + final boolean scalesTooBig = false; + + final int N = 3; + @SuppressWarnings( "unchecked" ) + final RandomAccessibleInterval< DoubleType >[] imgs = new RandomAccessibleInterval[ N ]; + final AffineTransform3D[] transforms = new AffineTransform3D[ N ]; + for ( int i = 0; i < N; i++ ) + { + transforms[ i ] = new AffineTransform3D(); + if ( scalesTooBig ) + transforms[ i ].scale( Math.pow( 4, i ) ); + else + transforms[ i ].scale( Math.pow( 2, i ) ); + + if ( i == 0 ) + imgs[ i ] = img; + else + imgs[ i ] = Views.subsample( img, 2 * i, 2 * i, 2 * i, 1 ); + } + + final RandomAccessibleIntervalMipmapSource4D< DoubleType > raiSource4D = new RandomAccessibleIntervalMipmapSource4D<>( + imgs, + Util.getTypeFromInterval( img ), + transforms, + new FinalVoxelDimensions( "um", 1, 1, 1 ), + "4d rai source", true ); + + final BdvStackSource< DoubleType > bdv = BdvFunctions.show( raiSource4D, 5 ); + bdv.setDisplayRange( 0, 3 ); + } +} diff --git a/src/test/java/bdv/util/ExampleOpenEmpty.java b/src/test/java/bdv/util/ExampleOpenEmpty.java new file mode 100644 index 00000000..1ef1c9c1 --- /dev/null +++ b/src/test/java/bdv/util/ExampleOpenEmpty.java @@ -0,0 +1,39 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +public class ExampleOpenEmpty +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); +// Bdv bdv = BdvFunctions.show(); + Bdv bdv = BdvFunctions.show( Bdv.options().frameTitle( "empty bdv window" ).is2D() ); + } +} diff --git a/src/test/java/bdv/util/ExampleSharedKeymaps.java b/src/test/java/bdv/util/ExampleSharedKeymaps.java new file mode 100644 index 00000000..7e102ad2 --- /dev/null +++ b/src/test/java/bdv/util/ExampleSharedKeymaps.java @@ -0,0 +1,55 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Random; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class ExampleSharedKeymaps +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + final BdvHandle bdv = BdvFunctions.show( img, "greens" ).getBdvHandle(); + + final ArrayImg< ARGBType, IntArray > img2 = ArrayImgs.argbs( 100, 100, 100 ); + img2.forEach( t -> t.set( random.nextInt() & 0xFFFF0000 ) ); + BdvFunctions.show( img2, "reds", Bdv.options() + .keymapManager( bdv.getKeymapManager() ) + .appearanceManager( bdv.getAppearanceManager() ) ); + } +} diff --git a/src/test/java/bdv/util/ExampleSource4D.java b/src/test/java/bdv/util/ExampleSource4D.java new file mode 100644 index 00000000..600e3dda --- /dev/null +++ b/src/test/java/bdv/util/ExampleSource4D.java @@ -0,0 +1,56 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.util.Util; + +import java.util.Random; + +public class ExampleSource4D +{ + public static void main( String[] args ) + { + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100, 5 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + + final RandomAccessibleIntervalSource4D raiSource4D + = new RandomAccessibleIntervalSource4D( + img, + Util.getTypeFromInterval( img ), + "4d rai source" ); + + BdvFunctions.show( raiSource4D, 5 ); + } +} diff --git a/src/test/java/bdv/util/ExampleSourceAndConverter4D.java b/src/test/java/bdv/util/ExampleSourceAndConverter4D.java new file mode 100644 index 00000000..512a8d67 --- /dev/null +++ b/src/test/java/bdv/util/ExampleSourceAndConverter4D.java @@ -0,0 +1,70 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.viewer.SourceAndConverter; +import net.imglib2.converter.Converter; +import net.imglib2.display.ColorConverter; +import net.imglib2.display.RealARGBColorConverter; +import net.imglib2.display.ScaledARGBConverter; +import net.imglib2.img.Img; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.NumericType; +import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.integer.IntType; +import net.imglib2.util.Util; + +import java.util.Random; + +public class ExampleSourceAndConverter4D +{ + public static void main( String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final int numTimePoints = 5; + final Img< IntType > ints = ArrayImgs.ints( 100, 100, 100, numTimePoints ); + ints.forEach( t -> t.set( random.nextInt( 65535 ) ) ); + + final IntType type = new IntType(); + final RandomAccessibleIntervalSource4D< IntType > raiSource4D = + new RandomAccessibleIntervalSource4D<>( ints, type, "4d rai source" ); + final RealARGBColorConverter< IntType > colorConverter = + RealARGBColorConverter.create( type, 0, 65535 ); + final SourceAndConverter< IntType > sourceAndConverter = + new SourceAndConverter<>( raiSource4D, colorConverter ); + + BdvFunctions.show( sourceAndConverter, numTimePoints ); + } +} diff --git a/src/test/java/bdv/util/ExampleSpimData.java b/src/test/java/bdv/util/ExampleSpimData.java new file mode 100644 index 00000000..e52770ce --- /dev/null +++ b/src/test/java/bdv/util/ExampleSpimData.java @@ -0,0 +1,44 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.spimdata.SpimDataMinimal; +import bdv.spimdata.XmlIoSpimDataMinimal; +import mpicbg.spim.data.SpimDataException; + +public class ExampleSpimData +{ + public static void main( final String[] args ) throws SpimDataException + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + final String xmlFilename = "/Users/pietzsch/workspace/data/111010_weber_full.xml"; + final SpimDataMinimal spimData = new XmlIoSpimDataMinimal().load( xmlFilename ); + BdvFunctions.show( spimData ); + } +} diff --git a/src/test/java/bdv/util/InputConfigExample.java b/src/test/java/bdv/util/InputConfigExample.java new file mode 100644 index 00000000..6ff361dd --- /dev/null +++ b/src/test/java/bdv/util/InputConfigExample.java @@ -0,0 +1,61 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Arrays; +import java.util.Random; + +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.io.InputTriggerDescription; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class InputConfigExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + final InputTriggerConfig conf = new InputTriggerConfig( + Arrays.asList( + /* translate by pressing "A" and moving the mouse */ + new InputTriggerDescription( new String[] {"A"}, "2d drag translate", "bdv" ), + /* translate by pressing "alt" and scrolling horizontally/vertically */ + new InputTriggerDescription( new String[] {"alt scroll"}, "2d scroll translate", "bdv" ) ) + ); + BdvFunctions.show( img, "greens", Bdv.options().is2D().inputTriggerConfig( conf ) ); + } +} diff --git a/src/test/java/bdv/util/InputConfigExample2.java b/src/test/java/bdv/util/InputConfigExample2.java new file mode 100644 index 00000000..baf2fc4c --- /dev/null +++ b/src/test/java/bdv/util/InputConfigExample2.java @@ -0,0 +1,65 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.io.IOException; +import java.util.Random; + +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.io.yaml.YamlConfigIO; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class InputConfigExample2 +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF00FF00 ) ); + InputTriggerConfig conf = null; + try + { + /* load input config from file */ + final String config = InputConfigExample2.class.getResource( "/bdvkeyconfig.yaml" ).getFile(); + conf = new InputTriggerConfig( YamlConfigIO.read( config ) ); + } + catch ( IllegalArgumentException | IOException e ) + { + e.printStackTrace(); + } + BdvFunctions.show( img, "greens", Bdv.options().is2D().inputTriggerConfig( conf ) ); + } +} diff --git a/src/test/java/bdv/util/IntervalPaintingExample.java b/src/test/java/bdv/util/IntervalPaintingExample.java new file mode 100644 index 00000000..90a09acc --- /dev/null +++ b/src/test/java/bdv/util/IntervalPaintingExample.java @@ -0,0 +1,206 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.viewer.OverlayRenderer; +import bdv.viewer.ViewerPanel; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import net.imglib2.Interval; +import net.imglib2.RandomAccess; +import net.imglib2.RealPositionable; +import net.imglib2.algorithm.neighborhood.HyperSphereShape; +import net.imglib2.algorithm.neighborhood.Neighborhood; +import net.imglib2.cache.img.CellLoader; +import net.imglib2.cache.img.DiskCachedCellImgFactory; +import net.imglib2.cache.img.DiskCachedCellImgOptions; +import net.imglib2.cache.img.SingleCellArrayImg; +import net.imglib2.img.Img; +import net.imglib2.img.cell.CellGrid; +import net.imglib2.position.transform.Round; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.util.Intervals; +import net.imglib2.view.Views; +import org.scijava.ui.behaviour.DragBehaviour; +import org.scijava.ui.behaviour.io.InputTriggerConfig; +import org.scijava.ui.behaviour.util.Behaviours; + +import static net.imglib2.cache.img.DiskCachedCellImgOptions.options; +import static net.imglib2.cache.img.optional.CacheOptions.CacheType.BOUNDED; + +/** + * Shows a disk-cached checkerboard image. + * A drag gesture with {@code SPACE} or {@code D} shortcut can be used to interactively draw 3D spheres into the image. + * The new {@code ViewerPanel.requestRepaint(Interval)} method is used to selectively update the BDV for the modified regions. + */ +public class IntervalPaintingExample +{ + private static final int radius = 10; + + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final int[] cellDimensions = new int[] { 64, 64, 64 }; + final long[] dimensions = new long[] { 640, 640, 640 }; + + final DiskCachedCellImgOptions options = options() + .cellDimensions( cellDimensions ) + .cacheType( BOUNDED ) + .maxCacheSize( 1000 ); + + final CellLoader< ARGBType > loader = new CheckerboardLoader( new CellGrid( dimensions, cellDimensions ) ); + + final Img< ARGBType > img = new DiskCachedCellImgFactory<>( new ARGBType(), options ).create( + dimensions, + loader ); + + new IntervalPaintingExample( img ); + } + + private final ViewerPanel viewer; + + private final RandomAccess< Neighborhood< ARGBType > > sphere; + + private final RealPositionable roundpos; + + public IntervalPaintingExample( final Img< ARGBType > img ) + { + final Bdv bdv = BdvFunctions.show( img, "IntervalPaintingExample" ); + + viewer = bdv.getBdvHandle().getViewerPanel(); + sphere = new HyperSphereShape( radius ).neighborhoodsRandomAccessible( Views.extendZero( img ) ).randomAccess(); + roundpos = new Round<>( sphere ); + + /* + * Install behaviour for painting into img with shortcut "D" or "SPACE" + */ + + final Behaviours behaviours = new Behaviours( new InputTriggerConfig() ); + behaviours.install( bdv.getBdvHandle().getTriggerbindings(), "paint" ); + behaviours.behaviour( new PaintBehaviour(), "paint", "D", "SPACE" ); + + /* + * Install overly to highlight painted region + */ + + viewer.getDisplay().overlays().add( new Overlay() ); + } + + private Interval repaintInterval; + + private synchronized void drawOverlay( final Graphics2D g ) + { + if ( repaintInterval != null ) + { + g.setColor( Color.green ); + final int x = ( int ) repaintInterval.min( 0 ); + final int y = ( int ) repaintInterval.min( 1 ); + final int w = ( int ) repaintInterval.dimension( 0 ); + final int h = ( int ) repaintInterval.dimension( 1 ); + g.drawRect( x, y, w, h ); + } + } + + private synchronized void draw( final int x, final int y ) + { + if ( x < 0 || y < 0 ) + { + repaintInterval = null; + viewer.getDisplay().repaint(); + } + else + { + viewer.displayToGlobalCoordinates( x, y, roundpos ); + sphere.get().forEach( t -> t.set( 0xFFFF0000 ) ); + + final double scale = Affine3DHelpers.extractScale( viewer.state().getViewerTransform(), 0 ); + final int w = ( int ) Math.ceil( scale * radius ) + 3; + repaintInterval = Intervals.createMinMax( x - w, y - w, x + w, y + w ); + viewer.requestRepaint( repaintInterval ); + } + } + + private class PaintBehaviour implements DragBehaviour + { + @Override + public void init( final int x, final int y ) + { + draw( x, y ); + } + + @Override + public void drag( final int x, final int y ) + { + draw( x, y ); + } + + @Override + public void end( final int x, final int y ) + { + draw( -1, -1 ); + } + } + + private class Overlay implements OverlayRenderer + { + @Override + public void drawOverlays( final Graphics g ) + { + drawOverlay( ( Graphics2D ) g ); + } + + @Override + public void setCanvasSize( final int width, final int height ) + { + } + } + + static class CheckerboardLoader implements CellLoader< ARGBType > + { + private final CellGrid grid; + + public CheckerboardLoader( final CellGrid grid ) + { + this.grid = grid; + } + + @Override + public void load( final SingleCellArrayImg< ARGBType, ? > cell ) throws Exception + { + final int n = grid.numDimensions(); + long sum = 0; + for ( int d = 0; d < n; ++d ) + sum += cell.min( d ) / grid.cellDimension( d ); + final int color = ( sum % 2 == 0 ) ? 0xff000000 : 0xff008800; + cell.forEach( t -> t.set( color ) ); + } + } +} diff --git a/src/test/java/bdv/util/ManySourcesExample.java b/src/test/java/bdv/util/ManySourcesExample.java new file mode 100644 index 00000000..b4630df4 --- /dev/null +++ b/src/test/java/bdv/util/ManySourcesExample.java @@ -0,0 +1,114 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import net.imglib2.img.Img; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.integer.UnsignedByteType; + +public class ManySourcesExample +{ + private static Bdv addSource(final Bdv bdv, final Random random, final int i, final Img< UnsignedByteType > img, final int xOffset, final int yOffset) { + AffineTransform3D transform = new AffineTransform3D(); + transform.translate( xOffset, yOffset, 0 ); + final BdvSource source = BdvFunctions.show( img, "img " + i, + Bdv.options() + .addTo( bdv ) + .preferredSize( 900, 900 ) + .numRenderingThreads( Runtime.getRuntime().availableProcessors() ) + .sourceTransform( transform ) ); + final ARGBType color = new ARGBType( random.nextInt() & 0xFFFFFF ); + source.setColor( color ); + return bdv == null ? source : bdv; + } + + private static Img< UnsignedByteType > createImg( final Random random ) + { + final long[] dim = { 100, 100, 100 }; + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( dim ); + img.forEach( t -> t.set( 64 + random.nextInt( 128 ) ) ); + return img; + } + + public static void main( String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final int[] numSources = { 5, 5 }; + final Random random = new Random( 1L ); + + final List< Img< UnsignedByteType > > imgs = new ArrayList<>(); + for ( int i = 0; i < numSources[ 0 ] * numSources[ 1 ]; i++ ) + imgs.add( createImg( random ) ); + + int i = 0; + Bdv bdv = null; + for ( int y = 0; y < numSources[ 1 ]; ++y ) + { + for ( int x = 0; x < numSources[ 0 ]; ++x ) + { + final int xOffset = 90 * x; + final int yOffset = 90 * y; + bdv = addSource( bdv, random, i, imgs.get( i ), xOffset, yOffset ); + i++; + } + } + +// final ViewerPanel viewer = bdv.getBdvHandle().getViewerPanel(); +// final DebugTilingOverlay tilingOverlay = viewer.showDebugTileOverlay(); +// final Runnable toggleShowTiles = () -> { +// tilingOverlay.setShowTiles( !tilingOverlay.getShowTiles() ); +// viewer.getDisplay().repaint(); +// }; +// +// +// final InputTriggerConfig keyconf = viewer.getInputTriggerConfig(); +// Actions actions = new Actions( keyconf ); +// actions.install( bdv.getBdvHandle().getKeybindings(), "tile overlay" ); +// actions.runnableAction( toggleShowTiles, "toggle draw tiles", "T" ); + +// // print current transform +// viewer.state().changeListeners().add( change -> { +// if ( change == ViewerStateChange.VIEWER_TRANSFORM_CHANGED ) +// { +// final AffineTransform3D t = viewer.state().getViewerTransform(); +// System.out.println( "t = " + Arrays.toString( t.getRowPackedCopy() ) ); +// } +// } ); + + } + + + +} diff --git a/src/test/java/bdv/util/OverlayExample2D.java b/src/test/java/bdv/util/OverlayExample2D.java new file mode 100644 index 00000000..f884dcfe --- /dev/null +++ b/src/test/java/bdv/util/OverlayExample2D.java @@ -0,0 +1,89 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.Random; + +import net.imglib2.RealPoint; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.realtransform.AffineTransform2D; +import net.imglib2.type.numeric.ARGBType; + +public class OverlayExample2D +{ + + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF003F00 ) ); + final Bdv bdv2D = BdvFunctions.show( img, "greens", Bdv.options().is2D() ); + + final ArrayList< RealPoint > points = new ArrayList<>(); + for ( int i = 0; i < 1100; ++i ) + points.add( new RealPoint( random.nextInt( 100 ), random.nextInt( 100 ) ) ); + + final BdvOverlay overlay = new BdvOverlay() + { + @Override + protected void draw( final Graphics2D g ) + { + final AffineTransform2D t = new AffineTransform2D(); + getCurrentTransform2D( t ); + + g.setColor( Color.RED ); + + final double[] lPos = new double[ 2 ]; + final double[] gPos1 = new double[ 2 ]; + final double[] gPos2 = new double[ 2 ]; + final int start = info.getTimePointIndex() * 10; + final int end = info.getTimePointIndex() * 10 + 100; + for ( int i = start; i < end; i+=2 ) + { + points.get( i ).localize( lPos ); + t.apply( lPos, gPos1 ); + points.get( i + 1 ).localize( lPos ); + t.apply( lPos, gPos2 ); + g.drawLine( ( int ) gPos1[ 0 ], ( int ) gPos1[ 1 ], ( int ) gPos2[ 0 ], ( int ) gPos2[ 1 ] ); + } + } + }; + + BdvFunctions.showOverlay( overlay, "overlay", Bdv.options().addTo( bdv2D ) ); + // TODO: add BdvOptions.closeAfterRemovingLastSource() + } +} diff --git a/src/test/java/bdv/util/OverlayExample3D.java b/src/test/java/bdv/util/OverlayExample3D.java new file mode 100644 index 00000000..3d21eb6d --- /dev/null +++ b/src/test/java/bdv/util/OverlayExample3D.java @@ -0,0 +1,104 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.ArrayList; +import java.util.Random; + +import net.imglib2.RealPoint; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; + +public class OverlayExample3D +{ + + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF003F00 ) ); + final Bdv bdv3D = BdvFunctions.show( img, "greens" ); + + final ArrayList< RealPoint > points = new ArrayList<>(); + for ( int i = 0; i < 500; ++i ) + points.add( new RealPoint( random.nextInt( 100 ), random.nextInt( 100 ), random.nextInt( 100 ) ) ); + + final BdvOverlay overlay = new BdvOverlay() + { + @Override + protected void draw( final Graphics2D g ) + { + final AffineTransform3D t = new AffineTransform3D(); + getCurrentTransform3D( t ); + + final double[] lPos = new double[ 3 ]; + final double[] gPos = new double[ 3 ]; + for ( final RealPoint p : points ) + { + p.localize( lPos ); + t.apply( lPos, gPos ); + final int size = getSize( gPos[ 2 ] ); + final int x = ( int ) ( gPos[ 0 ] - 0.5 * size ); + final int y = ( int ) ( gPos[ 1 ] - 0.5 * size ); + g.setColor( getColor( gPos[ 2 ] ) ); + g.fillOval( x, y, size, size ); + } + } + + private Color getColor( final double depth ) + { + int alpha = 255 - ( int ) Math.round( Math.abs( depth ) ); + + if ( alpha < 64 ) + alpha = 64; + + final int r = ARGBType.red( info.getColor().get() ); + final int g = ARGBType.green( info.getColor().get() ); + final int b = ARGBType.blue( info.getColor().get() ); + return new Color( r , g, b, alpha ); + } + + private int getSize( final double depth ) + { + return ( int ) Math.max( 1, 10 - 0.1 * Math.round( Math.abs( depth ) ) ); + } + }; + + BdvFunctions.showOverlay( overlay, "overlay", Bdv.options().addTo( bdv3D ) ); + // TODO: add BdvOptions.closeAfterRemovingLastSource() + } +} diff --git a/src/test/java/bdv/util/PanelExample.java b/src/test/java/bdv/util/PanelExample.java new file mode 100644 index 00000000..feae8415 --- /dev/null +++ b/src/test/java/bdv/util/PanelExample.java @@ -0,0 +1,63 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.Random; + +import javax.swing.JFrame; +import javax.swing.WindowConstants; + +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +public class PanelExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + final Random random = new Random(); + img.forEach( t -> t.set( random.nextInt() ) ); + + final JFrame frame = new JFrame( "my test frame" ); + final BdvHandlePanel bdv = new BdvHandlePanel( frame, Bdv.options().is2D() ); + frame.add( bdv.getSplitPanel(), BorderLayout.CENTER ); + frame.setPreferredSize( new Dimension( 800, 600 ) ); + frame.pack(); + frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE ); + frame.setVisible( true ); + + BdvFunctions.show( img, "img", Bdv.options().addTo( bdv ) ); + } +} diff --git a/src/test/java/bdv/util/RealBoxSelectionExample.java b/src/test/java/bdv/util/RealBoxSelectionExample.java new file mode 100644 index 00000000..d433b30c --- /dev/null +++ b/src/test/java/bdv/util/RealBoxSelectionExample.java @@ -0,0 +1,88 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import java.util.Random; + +import net.imglib2.RealInterval; +import net.imglib2.RealRandomAccessibleRealInterval; +import net.imglib2.img.Img; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.roi.Masks; +import net.imglib2.roi.RealMaskRealInterval; +import net.imglib2.roi.Regions; +import net.imglib2.type.logic.BoolType; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.util.Intervals; +import net.imglib2.view.IntervalView; +import net.imglib2.view.Views; + +import bdv.tools.boundingbox.BoxSelectionOptions; +import bdv.tools.boundingbox.TransformedRealBoxSelectionDialog; + +public class RealBoxSelectionExample +{ + public static void main( final String[] args ) + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 100, 100, 50 ); + img.forEach( t -> t.set( random.nextInt( 128 ) ) ); + + final AffineTransform3D imageTransform = new AffineTransform3D(); + imageTransform.set( 2, 2, 2 ); + final Bdv bdv = BdvFunctions.show( img, "image", BdvOptions.options().sourceTransform( imageTransform ) ); + + final RealInterval initialInterval = Intervals.createMinMaxReal( 30, 30, 30, 80, 80, 80 ); + final RealInterval rangeInterval = Intervals.createMinMaxReal( 0, 0, 0, 100, 100, 100 ); + final AffineTransform3D boxTransform = new AffineTransform3D(); + boxTransform.rotate( 2, 0.5 ); + boxTransform.translate( 30, -20, 0 ); + + final TransformedRealBoxSelectionDialog.Result result = BdvFunctions.selectRealBox( + bdv, + boxTransform, + initialInterval, + rangeInterval, + BoxSelectionOptions.options() + .title( "Select box to fill" ) ); + + if ( result.isValid() ) + { + final RealMaskRealInterval imageMask = result.asMask().transform( imageTransform ); + final RealRandomAccessibleRealInterval< BoolType > rrai = Masks.toRealRandomAccessibleRealInterval( imageMask ); + final IntervalView< BoolType > rai = Views.interval( Views.raster( rrai ), Intervals.smallestContainingInterval( rrai ) ); + Regions.sample( Regions.iterable( rai ), Views.extendZero( img ) ).forEach( t -> t.set( 255 ) ); + bdv.getBdvHandle().getViewerPanel().requestRepaint(); + } + } +} diff --git a/src/test/java/bdv/util/SplitPanelExample.java b/src/test/java/bdv/util/SplitPanelExample.java new file mode 100644 index 00000000..9b932ee9 --- /dev/null +++ b/src/test/java/bdv/util/SplitPanelExample.java @@ -0,0 +1,107 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util; + +import bdv.ui.splitpanel.SplitPanel; +import net.imglib2.img.array.ArrayImg; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.img.basictypeaccess.array.IntArray; +import net.imglib2.type.numeric.ARGBType; + +import javax.swing.*; +import java.util.Random; +import java.util.function.Consumer; + +import static bdv.ui.BdvDefaultCards.DEFAULT_SOURCEGROUPS_CARD; + +public class SplitPanelExample +{ + + public static void main( final String[] args ) throws Exception + { + System.setProperty( "apple.laf.useScreenMenuBar", "true" ); + + final Random random = new Random(); + + final ArrayImg< ARGBType, IntArray > img = ArrayImgs.argbs( 100, 100, 100 ); + img.forEach( t -> t.set( random.nextInt() & 0xFF003F00 ) ); + final Bdv bdv2D = BdvFunctions.show( img, "greens", Bdv.options().is2D() ); + + int delayInMilliseconds = 2000; + + SplitPanel splitPanel = bdv2D.getBdvHandle().getSplitPanel(); + + Consumer logger = (str) -> { + System.out.println(str); + bdv2D.getBdvHandle().getViewerPanel().showMessage(str); + }; + + Thread.sleep(delayInMilliseconds); + + logger.accept("Split panel expansion."); + splitPanel.setCollapsed(false); // Expands the split Panel + + Thread.sleep(delayInMilliseconds); + + logger.accept("Split panel divider size change. NOT WORKING"); + splitPanel.setDividerSize(50); // TODO : fix divider size change not being triggered + + Thread.sleep(delayInMilliseconds); + + logger.accept("Forcing update through collapse / expansion."); + splitPanel.setCollapsed(true); // Expands the split Panel + splitPanel.setCollapsed(false); // Expands the split Panel + + Thread.sleep(delayInMilliseconds); + + logger.accept("Divider location change : 50/50"); + splitPanel.setDividerLocation(0.5); + + Thread.sleep(delayInMilliseconds); + + logger.accept("Collapsing 'Groups' card."); + bdv2D.getBdvHandle().getCardPanel().setCardExpanded(DEFAULT_SOURCEGROUPS_CARD, false); + + Thread.sleep(delayInMilliseconds); + + logger.accept("Expanding 'Groups' card"); + bdv2D.getBdvHandle().getCardPanel().setCardExpanded(DEFAULT_SOURCEGROUPS_CARD, true); + + Thread.sleep(delayInMilliseconds); + + logger.accept("Removing 'Groups' card"); + bdv2D.getBdvHandle().getCardPanel().removeCard(DEFAULT_SOURCEGROUPS_CARD); + + Thread.sleep(delayInMilliseconds); + + logger.accept("Adding 'Dummy' Card"); + bdv2D.getBdvHandle().getCardPanel().addCard("Dummy", "Dummy",new JPanel(), true); + + } +} diff --git a/src/test/java/bdv/util/benchmark/Rendering25SourcesBenchmark.java b/src/test/java/bdv/util/benchmark/Rendering25SourcesBenchmark.java new file mode 100644 index 00000000..106ed310 --- /dev/null +++ b/src/test/java/bdv/util/benchmark/Rendering25SourcesBenchmark.java @@ -0,0 +1,127 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.benchmark; + +import bdv.util.benchmark.RenderingSetup.Renderer; +import bdv.viewer.BasicViewerState; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerState; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; + +import static bdv.util.benchmark.RenderingSetup.createSourceAndConverter; +import static bdv.viewer.DisplayMode.FUSED; + +@State( Scope.Thread ) +@Fork( 1 ) +public class Rendering25SourcesBenchmark +{ + public ViewerState state; + public Renderer renderer; + + @Param({"1", "8"}) + public int numRenderingThreads; + + @Setup + public void setup() + { + final int[] numSources = { 5, 5 }; + final int[] targetSize = { 1680, 997 }; + final AffineTransform3D viewerTransform = new AffineTransform3D(); + viewerTransform.set( + 3.7078643166510905, -2.055302752278437, 0.0, 512.6446071237642, + 2.055302752278437, 3.7078643166510905, 0.0, -912.7996823819342, + 0.0, 0.0, 4.239401749565353, -208.1315727072766 ); + final Random random = new Random( 1L ); + + state = new BasicViewerState(); + + int i = 0; + for ( int y = 0; y < numSources[ 1 ]; ++y ) + { + for ( int x = 0; x < numSources[ 0 ]; ++x ) + { + final int xOffset = 90 * x; + final int yOffset = 90 * y; + final SourceAndConverter< UnsignedByteType > soc = createSourceAndConverter( random, i, xOffset, yOffset ); + state.addSource( soc ); + state.setSourceActive( soc, true ); + i++; + } + } + + state.setDisplayMode( FUSED ); + state.setViewerTransform( viewerTransform ); + + renderer = new Renderer( targetSize, numRenderingThreads ); + } + + @Benchmark + @BenchmarkMode( Mode.AverageTime ) + @OutputTimeUnit( TimeUnit.MILLISECONDS ) + public void bench() + { + renderer.render( state ); + } + + public static void main( final String... args ) throws RunnerException, IOException + { + final Options opt = new OptionsBuilder() + .include( Rendering25SourcesBenchmark.class.getSimpleName() ) + .warmupIterations( 4 ) + .measurementIterations( 8 ) + .warmupTime( TimeValue.milliseconds( 500 ) ) + .measurementTime( TimeValue.milliseconds( 500 ) ) + .build(); + new Runner( opt ).run(); + +// final Rendering25SourcesBenchmark b = new Rendering25SourcesBenchmark(); +// b.numRenderingThreads = 1; +// b.setup(); +// b.bench(); +// b.renderer.writeResult( "/Users/pietzsch/Desktop/Rendering25SourcesBenchmark.png" ); + } +} diff --git a/src/test/java/bdv/util/benchmark/RenderingSetup.java b/src/test/java/bdv/util/benchmark/RenderingSetup.java new file mode 100644 index 00000000..cd96de6a --- /dev/null +++ b/src/test/java/bdv/util/benchmark/RenderingSetup.java @@ -0,0 +1,171 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.benchmark; + +import bdv.BigDataViewer; +import bdv.cache.CacheControl; +import bdv.tools.brightness.ConverterSetup; +import bdv.util.RandomAccessibleIntervalSource; +import bdv.viewer.Source; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerState; +import bdv.viewer.render.AccumulateProjectorARGB; +import bdv.viewer.render.AccumulateProjectorFactory; +import bdv.viewer.render.MultiResolutionRenderer; +import bdv.viewer.render.RenderTarget; +import bdv.viewer.render.awt.BufferedImageRenderResult; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Random; +import javax.imageio.ImageIO; +import net.imglib2.img.Img; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.integer.UnsignedByteType; + +public class RenderingSetup +{ + private static Img< UnsignedByteType > createImg() + { + return createImg( new Random(), 100, 100, 100 ); + } + + private static Img< UnsignedByteType > createImg( final Random random, final long... dims ) + { + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( dims ); + img.forEach( t -> t.set( 64 + random.nextInt( 128 ) ) ); + return img; + } + + + private static Source< UnsignedByteType > createSource( + final Random random, + final int i, + final int xOffset, + final int yOffset ) + { + final AffineTransform3D sourceTransform = new AffineTransform3D(); + sourceTransform.translate( xOffset, yOffset, 0 ); + final String name = "img " + i; + final Img< UnsignedByteType > img = createImg( random, 100, 100, 100 ); + Source< UnsignedByteType > source = new RandomAccessibleIntervalSource( img, new UnsignedByteType(), sourceTransform, name ); + return source; + } + + public static SourceAndConverter< UnsignedByteType > createSourceAndConverter( + final Random random, + final int i, + final int xOffset, + final int yOffset ) + { + final Source< UnsignedByteType > source = createSource( random, i, xOffset, yOffset ); + final SourceAndConverter< UnsignedByteType > soc = BigDataViewer.wrapWithTransformedSource( + new SourceAndConverter<>( source, BigDataViewer.createConverterToARGB( source.getType() ) ) ); + final ConverterSetup converterSetup = BigDataViewer.createConverterSetup( soc, 0 ); + final ARGBType color = new ARGBType( random.nextInt() & 0xFFFFFF ); + converterSetup.setColor( color ); + return soc; + } + + public static class BenchmarkRenderTarget implements RenderTarget< BufferedImageRenderResult > + { + private final int width; + private final int height; + private final BufferedImageRenderResult renderResult = new BufferedImageRenderResult(); + + public BenchmarkRenderTarget( final int width, final int height ) + { + this.width = width; + this.height = height; + } + + @Override + public BufferedImageRenderResult getReusableRenderResult() + { + return renderResult; + } + + @Override + public BufferedImageRenderResult createRenderResult() + { + return new BufferedImageRenderResult(); + } + + @Override + public void setRenderResult( final BufferedImageRenderResult renderResult ) + {} + + @Override + public int getWidth() + { + return width; + } + + @Override + public int getHeight() + { + return height; + } + + public BufferedImageRenderResult getRenderResult() + { + return renderResult; + } + } + + public static class Renderer + { + private final BenchmarkRenderTarget target; + private final MultiResolutionRenderer renderer; + + public Renderer(final int[] targetSize, final int numRenderingThreads) + { + target = new BenchmarkRenderTarget( targetSize[ 0 ], targetSize[ 1 ] ); + final AccumulateProjectorFactory< ARGBType > accumulateProjectorFactory = AccumulateProjectorARGB.factory; + renderer = new MultiResolutionRenderer( + target, () -> {}, new double[] { 1 }, 0, + numRenderingThreads, null, false, + accumulateProjectorFactory, new CacheControl.Dummy() ); + } + + public void render( final ViewerState state ) + { + renderer.requestRepaint(); + renderer.paint( state ); + } + + public void writeResult( final String filename ) throws IOException + { + final BufferedImage bi = target.getRenderResult().getBufferedImage(); + ImageIO.write( bi, "png", new File( filename ) ); + } + } +} diff --git a/src/test/java/bdv/util/benchmark/RenderingSingleSourceBenchmark.java b/src/test/java/bdv/util/benchmark/RenderingSingleSourceBenchmark.java new file mode 100644 index 00000000..c626f49e --- /dev/null +++ b/src/test/java/bdv/util/benchmark/RenderingSingleSourceBenchmark.java @@ -0,0 +1,117 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.benchmark; + +import bdv.util.benchmark.RenderingSetup.Renderer; +import bdv.viewer.BasicViewerState; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerState; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; + +import static bdv.util.benchmark.RenderingSetup.createSourceAndConverter; + +@State( Scope.Thread ) +@Fork( 1 ) +public class RenderingSingleSourceBenchmark +{ + public ViewerState state; + public Renderer renderer; + + @Param({"1", "8"}) + public int numRenderingThreads; + + @Setup + public void setup() + { + final int[] targetSize = { 1680, 997 }; + final AffineTransform3D viewerTransform = new AffineTransform3D(); + viewerTransform.set( + 23.01374483164624, -2.19266950637996, -26.415703464229598, 1275.9089927440664, + 12.592003473417137, 31.68776756743586, 8.340052479934124, -1790.2640725526244, + 23.324635851386212, -14.943467712629362, 21.561163590406633, -1046.864337123486 ); + + + final Random random = new Random( 1L ); + + state = new BasicViewerState(); + final SourceAndConverter< UnsignedByteType > soc = createSourceAndConverter( random, 0, 0, 0 ); + state.addSource( soc ); + state.setSourceActive( soc, true ); + state.setViewerTransform( viewerTransform ); + +// final int numRenderingThreads = 1; +// final int numRenderingThreads = Runtime.getRuntime().availableProcessors(); +// System.out.println( "numRenderingThreads = " + numRenderingThreads ); + renderer = new Renderer( targetSize, numRenderingThreads ); + } + + @Benchmark + @BenchmarkMode( Mode.AverageTime ) + @OutputTimeUnit( TimeUnit.MILLISECONDS ) + public void bench() + { + renderer.render( state ); + } + + public static void main( final String... args ) throws RunnerException, IOException + { + final Options opt = new OptionsBuilder() + .include( RenderingSingleSourceBenchmark.class.getSimpleName() ) + .warmupIterations( 4 ) + .measurementIterations( 8 ) + .warmupTime( TimeValue.milliseconds( 500 ) ) + .measurementTime( TimeValue.milliseconds( 500 ) ) + .build(); + new Runner( opt ).run(); + +// final RenderingSingleSourceBenchmark b = new RenderingSingleSourceBenchmark(); +// b.numRenderingThreads = 1; +// b.setup(); +// b.bench(); +// b.renderer.writeResult( "/Users/pietzsch/Desktop/RenderingSingleSourceBenchmark.png" ); + } +} diff --git a/src/test/java/bdv/util/benchmark/RenderingWithEmptyBenchmark.java b/src/test/java/bdv/util/benchmark/RenderingWithEmptyBenchmark.java new file mode 100644 index 00000000..d1a1d7c2 --- /dev/null +++ b/src/test/java/bdv/util/benchmark/RenderingWithEmptyBenchmark.java @@ -0,0 +1,123 @@ +/*- + * #%L + * BigDataViewer core classes with minimal dependencies. + * %% + * Copyright (C) 2012 - 2024 BigDataViewer developers. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package bdv.util.benchmark; + +import bdv.util.benchmark.RenderingSetup.Renderer; +import bdv.viewer.BasicViewerState; +import bdv.viewer.DisplayMode; +import bdv.viewer.SourceAndConverter; +import bdv.viewer.ViewerState; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import net.imglib2.realtransform.AffineTransform3D; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; + +import static bdv.util.benchmark.RenderingSetup.createSourceAndConverter; +import static bdv.viewer.DisplayMode.FUSED; + +@State( Scope.Thread ) +@Fork( 1 ) +public class RenderingWithEmptyBenchmark +{ + public ViewerState state; + public Renderer renderer; + + @Param({"1", "8"}) + public int numRenderingThreads; + + @Setup + public void setup() + { + final int[] targetSize = { 1680, 997 }; + final AffineTransform3D viewerTransform = new AffineTransform3D(); + viewerTransform.set( + 6.085785957730029, -1.8606114880683469, 0.0, 706.509797402479, + 1.8606114880683469, 6.085785957730029, 0.0, 35.890787275681475, + 0.0, 0.0, 6.36385620774353, -318.02826989221813 ); + + final Random random = new Random( 1L ); + + state = new BasicViewerState(); + { + final SourceAndConverter< UnsignedByteType > soc = createSourceAndConverter( random, 0, 0, 0 ); + state.addSource( soc ); + state.setSourceActive( soc, true ); + } + { + final SourceAndConverter< UnsignedByteType > soc = createSourceAndConverter( random, 1, 90, 0 ); + state.addSource( soc ); + state.setSourceActive( soc, true ); + } + state.setDisplayMode( FUSED ); + state.setViewerTransform( viewerTransform ); + + renderer = new Renderer( targetSize, numRenderingThreads ); + } + + @Benchmark + @BenchmarkMode( Mode.AverageTime ) + @OutputTimeUnit( TimeUnit.MILLISECONDS ) + public void bench() + { + renderer.render( state ); + } + + public static void main( final String... args ) throws RunnerException, IOException + { + final Options opt = new OptionsBuilder() + .include( RenderingWithEmptyBenchmark.class.getSimpleName() ) + .warmupIterations( 4 ) + .measurementIterations( 8 ) + .warmupTime( TimeValue.milliseconds( 500 ) ) + .measurementTime( TimeValue.milliseconds( 500 ) ) + .build(); + new Runner( opt ).run(); + +// final RenderingWithEmptyBenchmark b = new RenderingWithEmptyBenchmark(); +// b.numRenderingThreads = 1; +// b.setup(); +// b.bench(); +// b.renderer.writeResult( "/Users/pietzsch/Desktop/RenderingWithEmptyBenchmark.png" ); + } +} diff --git a/src/test/resources/bdvkeyconfig.yaml b/src/test/resources/bdvkeyconfig.yaml new file mode 100644 index 00000000..d64f62ca --- /dev/null +++ b/src/test/resources/bdvkeyconfig.yaml @@ -0,0 +1,82 @@ +--- +#### KEYS +# rotate +- !mapping + action: 2d rotate left + contexts: [bdv] + triggers: [LEFT] +- !mapping + action: 2d rotate left fast + contexts: [bdv] + triggers: [shift LEFT] +- !mapping + action: 2d rotate left slow + contexts: [bdv] + triggers: [ctrl LEFT] +- !mapping + action: 2d rotate right + contexts: [bdv] + triggers: [RIGHT] +- !mapping + action: 2d rotate right fast + contexts: [bdv] + triggers: [shift RIGHT] +- !mapping + action: 2d rotate right slow + contexts: [bdv] + triggers: [ctrl RIGHT] +# zoom +- !mapping + action: 2d zoom in + contexts: [bdv] + triggers: [UP] +- !mapping + action: 2d zoom in fast + contexts: [bdv] + triggers: [shift UP] +- !mapping + action: 2d zoom in slow + contexts: [bdv] + triggers: [ctrl UP] +- !mapping + action: 2d zoom out + contexts: [bdv] + triggers: [DOWN] +- !mapping + action: 2d zoom out fast + contexts: [bdv] + triggers: [shift DOWN] +- !mapping + action: 2d zoom out slow + contexts: [bdv] + triggers: [ctrl DOWN] +############################## +#### MOUSE +- !mapping + action: 2d drag translate + contexts: [bdv] + triggers: [not mapped] +- !mapping + action: 2d drag rotate + contexts: [bdv] + triggers: [button3] +- !mapping + action: 2d scroll rotate + contexts: [bdv] + triggers: [not mapped] +- !mapping + action: 2d scroll rotate fast + contexts: [bdv] + triggers: [not mapped] +- !mapping + action: 2d scroll rotate slow + contexts: [bdv] + triggers: [not mapped] +- !mapping + action: 2d scroll zoom + contexts: [bdv] + triggers: [meta scroll, shift ctrl scroll] +- !mapping + action: 2d scroll translate + contexts: [bdv] + triggers: [scroll]