Skip to content

Commit

Permalink
Merge pull request #1 from saalfeldlab/master
Browse files Browse the repository at this point in the history
update paintera
  • Loading branch information
ssinhaleite authored May 7, 2018
2 parents 149e865 + 42f8fb1 commit 7aab79c
Show file tree
Hide file tree
Showing 28 changed files with 1,970 additions and 1,238 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ java -Xmx16G -XX:+UseConcMarkSweepGC -jar target/paintera-0.1.0-SNAPSHOT-shaded.
```
Replace `16G` with the maximum amount of memory that Paintera should use.

#### Display help message and command line parameters
```shell
$ java -jar target/paintera-0.1.0-SNAPSHOT-shaded.jar --help
Usage: Paintera [-h] [--height=HEIGHT] [--width=WIDTH]
[--label-source=LABEL_SOURCE]... [--raw-source=RAW_SOURCE]...
--height=HEIGHT Initial height of viewer. Defaults to 600.
--label-source=LABEL_SOURCE
Open label source at start-up. Has to be [file://]
/path/to/<n5-or-hdf5>:path/to/dataset
--raw-source=RAW_SOURCE
Open raw source at start-up. Has to be [file://]
/path/to/<n5-or-hdf5>:path/to/dataset
--width=WIDTH Initial width of viewer. Defaults to 800.
-h, --help Display this help message.
```

## Usage

| Action | Description |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

public class NumericSliderWithField
{

private final Slider slider;

private final TextField field;
Expand Down

Large diffs are not rendered by default.

98 changes: 81 additions & 17 deletions src/main/java/org/janelia/saalfeldlab/paintera/Paintera.java
Original file line number Diff line number Diff line change
@@ -1,42 +1,35 @@
package org.janelia.saalfeldlab.paintera;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Optional;
import java.util.regex.Pattern;

import org.janelia.saalfeldlab.fx.event.KeyTracker;
import org.janelia.saalfeldlab.fx.ortho.OrthogonalViews;
import org.janelia.saalfeldlab.n5.N5Writer;
import org.janelia.saalfeldlab.paintera.data.DataSource;
import org.janelia.saalfeldlab.paintera.viewer3d.Viewer3DFX;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import bdv.viewer.ViewerOptions;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;
import net.imglib2.Volatile;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import picocli.CommandLine;

public class Paintera extends Application
{

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

private final PainteraBaseView baseView = new PainteraBaseView(
Math.min( 8, Math.max( 1, Runtime.getRuntime().availableProcessors() / 2 ) ),
ViewerOptions.options().screenScales( new double[] { 1.0, 0.5, 0.25 } ),
si -> s -> si.getState( s ).interpolationProperty().get() );

private final OrthogonalViews< Viewer3DFX > orthoViews = baseView.orthogonalViews();

private final KeyTracker keyTracker = new KeyTracker();

final BorderPaneWithStatusBars paneWithStatus = new BorderPaneWithStatusBars(
baseView,
keyTracker );

final PainteraDefaultHandlers defaultHandlers = new PainteraDefaultHandlers( baseView, keyTracker, paneWithStatus );


@Override
public void start( final Stage stage ) throws Exception
{
Expand All @@ -49,17 +42,51 @@ public void start( final Stage stage ) throws Exception

if ( !parsedSuccessfully )
{
baseView.stop();
Platform.exit();
return;
}

int maxSize = 0;
for ( final Screen screen : Screen.getScreens() )
{
Rectangle2D bounds = screen.getVisualBounds();
maxSize = Math.max( ( int )bounds.getWidth(), maxSize );
maxSize = Math.max( ( int )bounds.getHeight(), maxSize );
}

LOG.debug( "max screen size = {}", maxSize );

final double[] screenScales = maxSize < 2500 ?
new double [] { 1.0 / 1.0, 1.0 / 2.0, 1.0 / 4.0, 1.0 / 8.0}:
new double [] { 1.0 / 2.0, 1.0 / 4.0, 1.0 / 8.0, 1.0 / 16.0};

final PainteraBaseView baseView = new PainteraBaseView(
Math.min( 8, Math.max( 1, Runtime.getRuntime().availableProcessors() / 2 ) ),
ViewerOptions.options().screenScales( screenScales ),
si -> s -> si.getState( s ).interpolationProperty().get() );

final OrthogonalViews< Viewer3DFX > orthoViews = baseView.orthogonalViews();

final KeyTracker keyTracker = new KeyTracker();

final BorderPaneWithStatusBars paneWithStatus = new BorderPaneWithStatusBars(
baseView,
keyTracker );

final PainteraDefaultHandlers defaultHandlers = new PainteraDefaultHandlers( baseView, keyTracker, paneWithStatus );

final Scene scene = new Scene( paneWithStatus.getPane() );
if ( LOG.isDebugEnabled() )
{
scene.focusOwnerProperty().addListener( ( obs, oldv, newv ) -> LOG.debug( "Focus changed: old={} new={}", oldv, newv ) );
}

for ( final String source : painteraArgs.rawSources() )
addRawFromString( baseView, source );

for ( final String source : painteraArgs.labelSources() )
addLabelFromString( baseView, source );

setFocusTraversable( orthoViews, false );

stage.setOnCloseRequest( event -> baseView.stop() );
Expand All @@ -86,4 +113,41 @@ private static void setFocusTraversable(
view.grid().getBottomRight().setFocusTraversable( isTraversable );
}

private static < D extends RealType< D > & NativeType< D >, T extends Volatile< D > & RealType< T > > Optional< DataSource< D, T > > addRawFromString(
final PainteraBaseView pbv,
final String identifier ) throws IOException
{
if ( !Pattern.matches( "^[a-z]+://.+", identifier ) )
return addRawFromString( pbv, "file://" + identifier );

if ( Pattern.matches( "^file://.+", identifier ) )
{
final String[] split = identifier.replaceFirst( "file://", "" ).split( ":" );
final N5Writer n5 = N5Helpers.n5Writer( split[ 0 ], 64, 64, 64 );
return pbv.addRawSource( n5, split[ 1 ] );
}

LOG.warn( "Unable to generate raw source from {}", identifier );
return Optional.empty();
}

private static void addLabelFromString( final PainteraBaseView pbv, final String identifier ) throws IOException
{
if ( !Pattern.matches( "^[a-z]+://.+", identifier ) )
{
addLabelFromString( pbv, "file://" + identifier );
return;
}

if ( Pattern.matches( "^file://.+", identifier ) )
{
final String[] split = identifier.replaceFirst( "file://", "" ).split( ":" );
final N5Writer n5 = N5Helpers.n5Writer( split[ 0 ], 64, 64, 64 );
final String dataset = split[ 1 ];
final double[] resolution = Optional.ofNullable( n5.getAttribute( dataset, "resolution", double[].class ) ).orElse( new double[] { 1.0, 1.0, 1.0 } );
final double[] offset = Optional.ofNullable( n5.getAttribute( dataset, "offset", double[].class ) ).orElse( new double[] { 0.0, 0.0, 0.0 } );
pbv.addLabelSource( n5, dataset, resolution, offset );
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.util.stream.Stream;

import org.janelia.saalfeldlab.fx.ortho.OrthogonalViews;
import org.janelia.saalfeldlab.n5.DataType;
import org.janelia.saalfeldlab.n5.DatasetAttributes;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.N5Writer;
import org.janelia.saalfeldlab.paintera.composition.ARGBCompositeAlphaAdd;
Expand All @@ -39,7 +41,6 @@
import org.janelia.saalfeldlab.paintera.state.GlobalTransformManager;
import org.janelia.saalfeldlab.paintera.stream.HighlightingStreamConverter;
import org.janelia.saalfeldlab.paintera.stream.ModalGoldenAngleSaturatedHighlightingARGBStream;
import org.janelia.saalfeldlab.paintera.ui.opendialog.N5Helpers;
import org.janelia.saalfeldlab.paintera.viewer3d.Viewer3DFX;
import org.janelia.saalfeldlab.util.Colors;
import org.janelia.saalfeldlab.util.HashWrapper;
Expand All @@ -53,6 +54,7 @@
import bdv.viewer.SourceAndConverter;
import bdv.viewer.ViewerOptions;
import gnu.trove.set.hash.TLongHashSet;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
Expand Down Expand Up @@ -162,6 +164,35 @@ public GlobalTransformManager manager()
return this.manager;
}

public < T extends RealType< T > & NativeType< T >, U extends Volatile< T > & RealType< U > > Optional< DataSource< T, U > > addRawSource(
final N5Reader n5,
final String dataset ) throws IOException
{
final DatasetAttributes attributes = n5.getDatasetAttributes(
N5Helpers.isMultiScale( n5, dataset )
? Paths.get( dataset, N5Helpers.listAndSortScaleDatasets( n5, dataset )[ 0 ] ).toString()
: dataset );
final DataType type = attributes.getDataType();
return addRawSource( n5, dataset, Color.WHITE, N5Helpers.minForType( type ), N5Helpers.maxForType( type ) );
}

public < T extends RealType< T > & NativeType< T >, U extends Volatile< T > & RealType< U > > Optional< DataSource< T, U > > addRawSource(
final N5Reader n5,
final String dataset,
final Color color,
final double min,
final double max ) throws IOException
{
return addRawSource(
n5,
dataset,
N5Helpers.getResolution( n5, dataset ),
N5Helpers.getOffset( n5, dataset ),
color,
min,
max );
}

public < T extends RealType< T > & NativeType< T >, U extends Volatile< T > & RealType< U > > Optional< DataSource< T, U > > addRawSource(
final N5Reader n5,
final String dataset,
Expand Down Expand Up @@ -227,6 +258,17 @@ public < T extends RealType< T >, U extends RealType< U > > void addRawSource(
}
}

public < D extends Type< D >, T extends Type< T > > Optional< DataSource< D, T > > addLabelSource(
final N5Writer n5,
final String dataset ) throws IOException
{
return addLabelSource(
n5,
dataset,
N5Helpers.getResolution( n5, dataset ),
N5Helpers.getOffset( n5, dataset ) );
}

public < D extends Type< D >, T extends Type< T > > Optional< DataSource< D, T > > addLabelSource(
final N5Writer n5,
final String dataset,
Expand All @@ -238,7 +280,7 @@ public < D extends Type< D >, T extends Type< T > > Optional< DataSource< D, T >

if ( !N5Helpers.isMultiScale( n5, dataset ) && !N5Helpers.isLabelMultisetType( n5, Paths.get( dataset, N5Helpers.listAndSortScaleDatasets( n5, dataset )[ 0 ] ).toString() ) )
{
LOG.debug( "Only multiscale label multisets supported at the moment. Not adding any data set" );
LOG.warn( "Only multiscale label multisets supported at the moment. Not adding any data set" );
return Optional.empty();
}

Expand Down Expand Up @@ -337,6 +379,8 @@ public < D extends Type< D >, T extends Type< T > > void addLabelSource(
viewer3D.meshesGroup(),
fragmentsInSelection,
new SimpleIntegerProperty(),
new SimpleDoubleProperty(),
new SimpleIntegerProperty(),
meshManagerExecutorService,
meshWorkerExecutorService );

Expand Down Expand Up @@ -514,7 +558,6 @@ public static double[][] scaleFactorsFromAffineTransforms( final Source< ? > sou
factors[ 2 ] = transform.get( 2, 2 ) / reference.get( 2, 2 );
}

if ( LOG.isDebugEnabled() )
{
LOG.debug( "Generated scaling factors:" );
Arrays.stream( scaleFactors ).map( Arrays::toString ).forEach( LOG::debug );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,35 @@

import java.util.concurrent.Callable;

import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command( name = "Paintera" )
public class PainteraCommandLineArgs implements Callable< Boolean >
{

@Option( names = { "--width" }, required = false, description = "Initial width of viewer. Defaults to 800." )
@Option( names = { "--width" }, paramLabel = "WIDTH", required = false, description = "Initial width of viewer. Defaults to 800." )
private int width = -1;

@Option( names = { "--height" }, required = false, description = "Initial height of viewer. Defaults to 600." )
@Option( names = { "--height" }, paramLabel = "HEIGHT", required = false, description = "Initial height of viewer. Defaults to 600." )
private int height = -1;

@Option( names = { "-h", "--help" }, usageHelp = true, description = "Display this help message." )
private boolean helpRequested;

@Option( names = { "--raw-source" }, paramLabel = "RAW_SOURCE", required = false, description = "Open raw source at start-up. Has to be [file://]/path/to/<n5-or-hdf5>:path/to/dataset" )
private String[] rawSources;

@Option( names = { "--label-source" }, paramLabel = "LABEL_SOURCE", required = false, description = "Open label source at start-up. Has to be [file://]/path/to/<n5-or-hdf5>:path/to/dataset" )
private String[] labelSources;

@Override
public Boolean call() throws Exception
{
width = width <= 0 ? 800 : width;
height = height <= 0 ? 600 : height;
rawSources = rawSources == null ? new String[] {} : rawSources;
labelSources = labelSources == null ? new String[] {} : labelSources;
return true;
}

Expand All @@ -34,4 +44,14 @@ public int height()
return height;
}

public String[] rawSources()
{
return rawSources.clone();
}

public String[] labelSources()
{
return labelSources.clone();
}

}
Loading

0 comments on commit 7aab79c

Please sign in to comment.