Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix n5 export #172

Merged
merged 17 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/main/java/bdv/gui/sourceList/BigWarpSourceTableModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

Expand Down Expand Up @@ -45,8 +46,8 @@ public static enum SourceType { IMAGEPLUS, DATASET, URL };

private Component container;

public BigWarpSourceTableModel() {

public BigWarpSourceTableModel()
{
this(null);
}

Expand Down
137 changes: 125 additions & 12 deletions src/main/java/bdv/ij/ApplyBigwarpPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@
import net.imglib2.view.Views;

/**
*
* Apply a bigwarp transform to a 2d or 3d ImagePlus
*
*/
public class ApplyBigwarpPlugin implements PlugIn
{
Expand Down Expand Up @@ -825,18 +823,12 @@ public static <T> List<ImagePlus> apply(
final boolean wait,
final WriteDestinationOptions writeOpts) {

// int numChannels = bwData.movingSourceIndexList.size();
final int numChannels = bwData.numMovingSources();
// final List< SourceAndConverter< T >> sourcesxfm = BigWarp.wrapSourcesAsTransformed(
// bwData.sourceInfos,
// landmarks.getNumdims(),
// bwData );

final InvertibleRealTransform invXfm = new BigWarpTransform( landmarks, tranformTypeOption ).getTransformation();
for ( int i = 0; i < numChannels; i++ )
{
final SourceAndConverter< T > movingSource = bwData.getMovingSource( i );
// final int originalIdx = bwData.sources.indexOf(movingSource);
((WarpedSource<?>)(movingSource.getSpimSource())).updateTransform(invXfm);
((WarpedSource<?>)(movingSource.getSpimSource())).setIsTransformed(true);
}
Expand All @@ -858,12 +850,13 @@ public static <T> List<ImagePlus> apply(

if( writeOpts != null && writeOpts.n5Dataset != null && !writeOpts.n5Dataset.isEmpty())
{
final SourceAndConverter<T> src = bwData.getMovingSource(0);
final String unit = ApplyBigwarpPlugin.getUnit( bwData, resolutionOption );
runN5Export( bwData, bwData.sources, fieldOfViewOption,
runN5Export( bwData, src, fieldOfViewOption,
outputIntervalList.get( 0 ), interp,
offset, res, unit,
progressWriter, writeOpts,
Executors.newFixedThreadPool( nThreads ) );
Executors.newFixedThreadPool(nThreads));
return null;
}
else
Expand Down Expand Up @@ -959,6 +952,7 @@ private static double[] physicalOffsetFromPixelInterval(final RealInterval inter
return out;
}

@Deprecated
public static <S, T extends NativeType<T> & NumericType<T>> void runN5Export(
final BigWarpData<S> data,
final List< SourceAndConverter< S >> sources,
Expand All @@ -975,8 +969,12 @@ public static <S, T extends NativeType<T> & NumericType<T>> void runN5Export(
final int nd = BigWarp.detectNumDims( data.sources );
final double[] resolution = limit(nd,resolutionArg);

// final double[] offset = limit(nd,offsetArg);
final double[] offset = physicalOffsetFromPixelInterval(outputInterval, resolution);
final double[] offset = ApplyBigwarpPlugin.getPixelOffset( fieldOfViewOption, offsetArg, resolution,
outputInterval);

System.out.println("resolution: " + Arrays.toString(resolution));
System.out.println("offset : " + Arrays.toString(offset));
System.out.println("interval : " + Intervals.toString(outputInterval));

// setup n5 parameters
final String dataset = writeOpts.n5Dataset;
Expand Down Expand Up @@ -1074,6 +1072,121 @@ public static <S, T extends NativeType<T> & NumericType<T>> void runN5Export(
progressWriter.setProgress( 1.0 );
}

public static <S,T extends NativeType<T> & NumericType<T>> void runN5Export(
final BigWarpData<S> data,
final SourceAndConverter<S> sourceAndConverter,
final String fieldOfViewOption,
final Interval outputInterval,
final Interpolation interp,
final double[] offsetArg,
final double[] resolutionArg,
final String unit,
final ProgressWriter progressWriter,
final WriteDestinationOptions writeOpts,
final ExecutorService exec )
{

final int nd = BigWarp.detectNumDims( data.sources );
final double[] resolution = limit(nd,resolutionArg);

// pixel offset
final double[] offsetPixel = ApplyBigwarpPlugin.getPixelOffset( fieldOfViewOption, offsetArg, resolution,
outputInterval);

// setup n5 parameters
final String dataset = writeOpts.n5Dataset;
final int[] blockSize = writeOpts.blockSize;
final Compression compression = writeOpts.compression;
if( dataset == null || dataset.isEmpty() )
{
System.err.println("Problem with n5 dataset path: " + dataset);
return;
}
N5Writer n5;
try
{
n5 = new N5Factory().openWriter( writeOpts.pathOrN5Root );
}
catch ( final RuntimeException e1 )
{
System.err.println("Could not create n5 writer for: " + writeOpts.pathOrN5Root);
e1.printStackTrace();
return;
}

// build metadata
final OmeNgffMetadataParser parser = new OmeNgffMetadataParser();
final String[] axesLabels = nd == 2 ? new String[]{"x", "y"} : new String[]{"x", "y", "z"};
final Axis[] axes = new Axis[nd];
for (int i = 0; i < nd; i++)
axes[i] = new Axis(Axis.SPACE, axesLabels[i], unit);

// setup physical to pixel transform
final AffineTransform3D resolutionTransform = new AffineTransform3D();
resolutionTransform.set( resolution[ 0 ], 0, 0 );
resolutionTransform.set( resolution[ 1 ], 1, 1 );

if( resolution.length > 2 )
resolutionTransform.set( resolution[ 2 ], 2, 2 );

final double[] offsetPhysical = new double[resolution.length];
offsetPhysical[0] = resolution[0] * offsetPixel[0];
offsetPhysical[1] = resolution[1] * offsetPixel[1];

if( resolution.length > 2 )
offsetPhysical[2] = resolution[2] * offsetPixel[2];

final AffineTransform3D offsetTransform = new AffineTransform3D();
offsetTransform.set( offsetPhysical[ 0 ], 0, 3 );
offsetTransform.set( offsetPhysical[ 1 ], 1, 3 );

if( resolution.length > 2 )
offsetTransform.set( offsetPhysical[ 2 ], 2, 3 );

final AffineTransform3D pixelRenderToPhysical = new AffineTransform3D();
pixelRenderToPhysical.concatenate( resolutionTransform );
pixelRenderToPhysical.concatenate( offsetTransform );

// render and write
final String srcName = sourceAndConverter.getSpimSource().getName();
final BigWarpExporter<?> exporter = BigWarpExporter.getExporter( data,
sourceAndConverter, interp, progressWriter );
exporter.setRenderResolution( resolution );
exporter.setOffset( offsetPixel );
exporter.setInterval(Intervals.zeroMin(outputInterval));
exporter.setSingleChannelNoStack(true);
final RandomAccessibleInterval<T> imgExp = (RandomAccessibleInterval<T>)exporter.exportRai((Source<T>)sourceAndConverter.getSpimSource());
final IntervalView<T> img = Views.translateInverse( imgExp, Intervals.minAsLongArray( imgExp ));

RandomAccessibleInterval<T> imgToWrite;
if( nd == 2 )
imgToWrite = Views.hyperSlice( img, 2, 0 );
else
imgToWrite = img;

final String destDataset = dataset;

final OmeNgffMetadata metadata = OmeNgffMetadata.buildForWriting(nd, srcName, axes, new String[]{"s0"},
new double[][]{resolution}, new double[][]{offsetPhysical});

try
{
N5Utils.save( imgToWrite, n5, destDataset + "/s0", blockSize, compression, exec );
if( parser != null && metadata != null )
parser.writeMetadata( metadata, n5, destDataset );

n5.close();
}
catch ( final Exception e )
{
e.printStackTrace();
}


progressWriter.setProgress( 1.0 );
System.out.println("done");
}

@Override
public void run( final String arg )
{
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/bdv/ij/BigWarpToDeformationFieldPlugIn.java
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,10 @@ public static void writeTpsN5(

final String mvgSpaceName = data != null && data.numMovingSources() > 0 ? data.getMovingSource( 0 ).getSpimSource().getName() : "moving";
final String tgtSpaceName = data != null && data.numTargetSources() > 0 ? data.getTargetSource( 0 ).getSpimSource().getName() : "target";
final String input= mvgSpaceName;
final String output= tgtSpaceName;

// the TPS is an "inverse" transform from target space to moving space
final String input = tgtSpaceName;
final String output = mvgSpaceName;
final String name = input + " to " + output;

final String dataset = (n5Dataset == null) ? "" : n5Dataset;
Expand Down
20 changes: 15 additions & 5 deletions src/main/java/bigwarp/BigWarp.java
Original file line number Diff line number Diff line change
Expand Up @@ -1546,24 +1546,28 @@ public void exportAsImagePlus( boolean virtual, String path )
{
if( writeOpts.n5Dataset != null && !writeOpts.n5Dataset.isEmpty())
{
@SuppressWarnings("rawtypes")
final SourceAndConverter activeSource = getCurrentSourceInActiveViewer();

final String unit = ApplyBigwarpPlugin.getUnit( data, resolutionOption );
// export async
new Thread()
{
@SuppressWarnings("unchecked")
@Override
public void run()
{
progressWriter.setProgress( 0.01 );
ApplyBigwarpPlugin.runN5Export( data, data.sources, fieldOfViewOption,
outputIntervalList.get( 0 ), interp,
ApplyBigwarpPlugin.runN5Export( data, activeSource,
fieldOfViewOption,
outputIntervalList.get(0), interp,
offsetSpec, res, unit,
progressWriter, writeOpts,
Executors.newFixedThreadPool( nThreads ) );
Executors.newFixedThreadPool( nThreads ));

progressWriter.setProgress( 1.00 );
}
}.start();
}
}
else
{
// export
Expand All @@ -1575,6 +1579,12 @@ public void run()
}
}
}

private SourceAndConverter<?> getCurrentSourceInActiveViewer() {

BigWarpViewerFrame activeFrame = viewerFrameP.isActive() ? viewerFrameP : viewerFrameQ;
return activeFrame.getViewerPanel().state().getCurrentSource();
}

public void exportWarpField()
{
Expand Down
45 changes: 23 additions & 22 deletions src/main/java/bigwarp/BigWarpARGBExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,42 +92,43 @@ public boolean isRGB()
return true;
}

@SuppressWarnings("unchecked")
@Override
public RandomAccessibleInterval< ARGBType > exportRai()
{
final ArrayList< RandomAccessibleInterval< ARGBType > > raiList = new ArrayList< RandomAccessibleInterval< ARGBType > >();

buildTotalRenderTransform();
final AffineTransform3D srcXfm = new AffineTransform3D();


final int numChannels = bwData.numMovingSources();
final VoxelDimensions voxdim = new FinalVoxelDimensions( unit,
resolutionTransform.get( 0, 0 ),
resolutionTransform.get( 1, 1 ),
resolutionTransform.get( 2, 2 ));

for ( int i = 0; i < numChannels; i++ )
{
final Source<ARGBType> src = bwData.getMovingSource( i ).getSpimSource();
src.getSourceTransform(0, 0, srcXfm);
raiList.add( (RandomAccessibleInterval<ARGBType>)exportRai(src));
}
final RandomAccessibleInterval< ARGBType > raiStack = Views.stack( raiList );

// in pixel space
final RealRandomAccessible<ARGBType> raiRaw = ( RealRandomAccessible<ARGBType> ) src.getInterpolatedSource( 0, 0, interp );
return raiStack;
}

@Override
public RandomAccessibleInterval<?> exportRai(Source<?> src) {

buildTotalRenderTransform();
final AffineTransform3D srcXfm = new AffineTransform3D();
src.getSourceTransform(0, 0, srcXfm);

// the transform from world to new pixel coordinates
final AffineTransform3D pixelToPhysical = pixelRenderToPhysical.copy().inverse();
// but first need to transform from original pixel to world coordinates
pixelToPhysical.concatenate(srcXfm);
// in pixel space
final RealRandomAccessible<ARGBType> raiRaw = (RealRandomAccessible<ARGBType>)src.getInterpolatedSource(0, 0, interp);

// apply the transformations
final AffineRandomAccessible<ARGBType, AffineGet> rai = RealViews.affine(raiRaw, pixelToPhysical);
// the transform from world to new pixel coordinates
final AffineTransform3D pixelToPhysical = pixelRenderToPhysical.copy().inverse();
// but first need to transform from original pixel to world coordinates
pixelToPhysical.concatenate(srcXfm);

raiList.add( Views.interval( Views.raster( rai ), outputInterval ) );
}
final RandomAccessibleInterval< ARGBType > raiStack = Views.stack( raiList );
// apply the transformations
final AffineRandomAccessible<ARGBType, AffineGet> rai = RealViews.affine(raiRaw, pixelToPhysical);

return Views.interval(Views.raster(rai), outputInterval);

return raiStack;
}

@Override
Expand Down
Loading
Loading