Skip to content

Commit

Permalink
Merge pull request bigdataviewer#33 from haesleinhuepf/samples
Browse files Browse the repository at this point in the history
add sample sources (mandelbrot / wave / voronoi) + command to display…
  • Loading branch information
Christian "Tischi" Tischer authored Dec 16, 2019
2 parents ea6fc0d + b4baa13 commit 63c42d6
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 3 deletions.
56 changes: 56 additions & 0 deletions src/main/java/sc/fiji/bdvpg/command/BdvAppendSampleCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package sc.fiji.bdvpg.command;

import bdv.util.BdvHandle;
import bdv.viewer.Source;
import org.scijava.ItemIO;
import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import sc.fiji.bdvpg.bdv.source.append.AddSourceToBdv;
import sc.fiji.bdvpg.bdv.source.displayopts.BrightnessAdjuster;
import sc.fiji.bdvpg.log.SystemLogger;
import sc.fiji.bdvpg.scijava.ScijavaBdvDefaults;
import sc.fiji.bdvpg.source.importer.samples.MandelbrotSourceGetter;
import sc.fiji.bdvpg.source.importer.samples.VoronoiSourceGetter;
import sc.fiji.bdvpg.source.importer.samples.Wave3DSourceGetter;

@Plugin(type = Command.class, menuPath = ScijavaBdvDefaults.RootMenu+"Tools>Append Sample Source to Bdv Window")
public class BdvAppendSampleCommand implements Command {

@Parameter(type = ItemIO.BOTH)
BdvHandle bdvh;

@Parameter(choices = {"Mandelbrot", "Wave3D", "Voronoi", "Big Voronoi"})
String sampleName;

@Override
public void run() {
Source src;
switch(sampleName) {

case "Mandelbrot":
src = (new MandelbrotSourceGetter()).get();
break;

case "Wave3D":
src = (new Wave3DSourceGetter()).get();
break;

case "Voronoi":
src = (new VoronoiSourceGetter(new long[]{512,512,1}, 256, true).get());
break;

case "Big Voronoi":
src = (new VoronoiSourceGetter(new long[]{2048,2048,2048}, 65536, false).get());
break;

default:
new SystemLogger().err("Invalid sample name");
return;
}
new AddSourceToBdv(bdvh, src).run();

// DO NOT WORK
//new BrightnessAdjuster(bdvh, src, 0.01, 0.99).run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

@Plugin(type = Command.class, menuPath = ScijavaBdvDefaults.RootMenu+"Create Empty BDV Frame",
label = "Creates an empty Bdv window")
public class BdvWindowCreate implements Command {
public class BdvWindowCreateCommand implements Command {

@Parameter(label = "Create a 2D Bdv window")
public boolean is2D = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.scijava.object.ObjectService;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import sc.fiji.bdvpg.command.BdvWindowCreate;
import sc.fiji.bdvpg.command.BdvWindowCreateCommand;
import sc.fiji.bdvpg.scijava.GuavaWeakCacheService;

import java.lang.ref.WeakReference;
Expand Down Expand Up @@ -54,7 +54,7 @@ public BdvHandle getValue() {
{

return (BdvHandle)
cs.run(BdvWindowCreate.class,
cs.run(BdvWindowCreateCommand.class,
true,
"is2D", false,
"windowTitle", "Bdv",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package sc.fiji.bdvpg.source.importer.samples;

import bdv.viewer.Source;
import net.imglib2.FinalInterval;

import java.util.function.Supplier;

public class MandelbrotSourceGetter implements Runnable, Supplier<Source> {

int maxIterations = 255;

public void run() {
// Useless
}

@Override
public Source get() {
return new Procedural3DImageShort(
p -> {
double re = p[0];
double im = p[1];
int i = 0;
for ( ; i < maxIterations; ++i )
{
final double squre = re * re;
final double squim = im * im;
if ( squre + squim > 4 )
break;
im = 2 * re * im + p[1];
re = squre - squim + p[0];
}
return i;
}
).getSource(new FinalInterval(new long[]{ -2, -1, -0}, new long[]{ 1, 1, 0 }), "Mandelbrot Set");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package sc.fiji.bdvpg.source.importer.samples;

import bdv.util.RealRandomAccessibleIntervalSource;
import bdv.viewer.Source;
import net.imglib2.*;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.type.numeric.integer.UnsignedShortType;

import java.util.function.ToIntFunction;

public class Procedural3DImageShort extends RealPoint implements RealRandomAccess<UnsignedShortType> {
final UnsignedShortType t;

ToIntFunction<double[]> evalFunction;

public Procedural3DImageShort(ToIntFunction<double[]> evalFunction)
{
super( 3 ); // number of dimensions is 3
t = new UnsignedShortType();
this.evalFunction=evalFunction;
}

public Procedural3DImageShort(UnsignedShortType t) {
this.t = t;
}

@Override
public RealRandomAccess<UnsignedShortType> copyRealRandomAccess() {
return copy();
}

@Override
public UnsignedShortType get() {
t.set(
evalFunction.applyAsInt(position)
);
return t;
}

@Override
public Procedural3DImageShort copy() {
Procedural3DImageShort a = new Procedural3DImageShort(evalFunction);
a.setPosition( this );
return a;
}

public RealRandomAccessible<UnsignedShortType> getRRA() {

RealRandomAccessible<UnsignedShortType> rra = new RealRandomAccessible<UnsignedShortType>() {
@Override
public RealRandomAccess<UnsignedShortType> realRandomAccess() {
return copy();
}

@Override
public RealRandomAccess<UnsignedShortType> realRandomAccess(RealInterval realInterval) {
return copy();
}

@Override
public int numDimensions() {
return 3;
}
};

return rra;
}

public Source<UnsignedShortType> getSource(final Interval interval, AffineTransform3D at3D, String name) {
return new RealRandomAccessibleIntervalSource<>( getRRA(), interval, new UnsignedShortType(),
new AffineTransform3D(), name );
}

public Source<UnsignedShortType> getSource(final Interval interval, String name) {
return new RealRandomAccessibleIntervalSource<>( getRRA(), interval, new UnsignedShortType(),
new AffineTransform3D(), name );
}

public Source<UnsignedShortType> getSource(String name) {
return new RealRandomAccessibleIntervalSource<>( getRRA(), new FinalInterval(new long[]{0,0,0}, new long[]{1,1,1}), new UnsignedShortType(),
new AffineTransform3D(), name );
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package sc.fiji.bdvpg.source.importer.samples;

import bdv.util.RandomAccessibleIntervalSource;
import bdv.viewer.Source;
import net.imglib2.*;
import net.imglib2.algorithm.util.Grids;
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.interpolation.neighborsearch.NearestNeighborSearchInterpolatorFactory;
import net.imglib2.neighborsearch.NearestNeighborSearch;
import net.imglib2.neighborsearch.NearestNeighborSearchOnKDTree;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.type.Type;
import net.imglib2.type.numeric.real.FloatType;
import net.imglib2.util.Util;
import net.imglib2.view.Views;

import java.util.Random;
import java.util.function.Supplier;

public class VoronoiSourceGetter implements Runnable, Supplier<Source> {

// Size of the image in pixels
final long[] imgSize;
// Number of random points that will define voronoi cells
final int numPts;
// Flags if the image should be computed completely
final boolean copyImg;

public VoronoiSourceGetter(final long[] imgSize, int numPts, boolean copyImg) {
this.imgSize = imgSize;
this.numPts = numPts;
this.copyImg = copyImg;
}

public void run() {
// Useless
}

@Override
public Source get() {
RandomAccessibleInterval voronoi = getVoronoiTestLabelImage(imgSize, numPts, copyImg);
return new RandomAccessibleIntervalSource<>( voronoi, new FloatType(), new AffineTransform3D(), "Voronoi_"+numPts+" Pts_["+imgSize[0]+","+imgSize[1]+","+imgSize[2]+"]" );
}

public static RandomAccessibleInterval<FloatType> getVoronoiTestLabelImage(final long[] imgTestSize, int numPts, boolean copyImg) {

// the interval in which to create random points
FinalInterval interval = new FinalInterval( imgTestSize );

// create an IterableRealInterval
IterableRealInterval< FloatType > realInterval = createRandomPoints( interval, numPts );

// using nearest neighbor search we will be able to return a value an any position in space
NearestNeighborSearch< FloatType > search =
new NearestNeighborSearchOnKDTree<>(
new KDTree<>( realInterval ) );

// make it into RealRandomAccessible using nearest neighbor search
RealRandomAccessible< FloatType > realRandomAccessible =
Views.interpolate( search, new NearestNeighborSearchInterpolatorFactory< FloatType >() );

// convert it into a RandomAccessible which can be displayed
RandomAccessible< FloatType > randomAccessible = Views.raster( realRandomAccessible );

// set the initial interval as area to view
RandomAccessibleInterval< FloatType > labelImage = Views.interval( randomAccessible, interval );

if (copyImg) {
final RandomAccessibleInterval< FloatType > labelImageCopy = new ArrayImgFactory( Util.getTypeFromInterval( labelImage ) ).create( labelImage );

// Image copied to avoid computing it on the fly
// https://github.com/imglib/imglib2-algorithm/blob/47cd6ed5c97cca4b316c92d4d3260086a335544d/src/main/java/net/imglib2/algorithm/util/Grids.java#L221 used for parallel copy

Grids.collectAllContainedIntervals(imgTestSize, new int[]{64, 64, 64}).stream().forEach(blockinterval -> {
copy(labelImage, Views.interval(labelImageCopy, blockinterval));
});

// Alternative non parallel copy
//LoopBuilder.setImages(labelImage, labelImageCopy).forEachPixel(Type::set);
return labelImageCopy;

} else {

return labelImage;
}
}

/**
* Copy from a source that is just RandomAccessible to an IterableInterval. Latter one defines
* size and location of the copy operation. It will query the same pixel locations of the
* IterableInterval in the RandomAccessible. It is up to the developer to ensure that these
* coordinates match.
*
* Note that both, input and output could be Views, Img or anything that implements
* those interfaces.
*
* @param source - a RandomAccess as source that can be infinite
* @param target - an IterableInterval as target
*/
public static < T extends Type< T >> void copy(final RandomAccessible< T > source,
final IterableInterval< T > target )
{
// create a cursor that automatically localizes itself on every move
Cursor< T > targetCursor = target.localizingCursor();
RandomAccess< T > sourceRandomAccess = source.randomAccess();

// iterate over the input cursor
while ( targetCursor.hasNext())
{
// move input cursor forward
targetCursor.fwd();

// set the output cursor to the position of the input cursor
sourceRandomAccess.setPosition( targetCursor );

// set the value of this pixel of the output image, every Type supports T.set( T type )
targetCursor.get().set( sourceRandomAccess.get() );
}

}

/**
* Create a number of n-dimensional random points in a certain interval
* having a random intensity 0...1
*
* @param interval - the interval in which points are created
* @param numPoints - the amount of points
*
* @return a RealPointSampleList (which is an IterableRealInterval)
*/
public static RealPointSampleList< FloatType > createRandomPoints(
RealInterval interval, int numPoints )
{
// the number of dimensions
int numDimensions = interval.numDimensions();

// a random number generator
Random rnd = new Random( 2001);//System.currentTimeMillis() );

// a list of Samples with coordinates
RealPointSampleList< FloatType > elements =
new RealPointSampleList<>( numDimensions );

for ( int i = 0; i < numPoints; ++i )
{
RealPoint point = new RealPoint( numDimensions );

for ( int d = 0; d < numDimensions; ++d )
point.setPosition( rnd.nextDouble() *
( interval.realMax( d ) - interval.realMin( d ) ) + interval.realMin( d ), d );

// add a new element with a random intensity in the range 0...1
elements.add( point, new FloatType( rnd.nextFloat()*255 ) );
}

return elements;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package sc.fiji.bdvpg.source.importer.samples;

import bdv.viewer.Source;

import java.util.function.Supplier;

public class Wave3DSourceGetter implements Runnable, Supplier<Source> {

@Override
public void run() {
// Useless
}

@Override
public Source get() {
return new Procedural3DImageShort(
p -> (int) ((Math.sin(p[0]/20)*Math.sin(p[1]/40)*Math.sin(p[2]/5)+1)*100)
).getSource("Wave 3D");
}
}

0 comments on commit 63c42d6

Please sign in to comment.