From 84d12e7040774d04bd0a592821a5e98de8a468ed Mon Sep 17 00:00:00 2001 From: Jean-Yves Tinevez Date: Tue, 13 Jun 2023 11:22:42 +0200 Subject: [PATCH] Export label images on 32-bit float type. The float type can accomodate integers at least up to 16M, which is a gig improvement on the 65k limit that we have with unsigned short so far. We could possibly go beyond, but let's see if this is enough. https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Precision_limitations_on_integer_values Fix #267 --- .../plugin/trackmate/action/CTCExporter.java | 4 +-- .../trackmate/action/LabelImgExporter.java | 34 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/fiji/plugin/trackmate/action/CTCExporter.java b/src/main/java/fiji/plugin/trackmate/action/CTCExporter.java index 676372af7..376f63213 100644 --- a/src/main/java/fiji/plugin/trackmate/action/CTCExporter.java +++ b/src/main/java/fiji/plugin/trackmate/action/CTCExporter.java @@ -314,7 +314,7 @@ public static void exportSegmentationData( final String exportRootFolder, final for ( int frame = 0; frame < dims[ 3 ]; frame++ ) { final ImgPlus< UnsignedShortType > imgCT = TMUtils.hyperSlice( labelImg, 0, frame ); - final SpotRoiWriter spotWriter = new SpotRoiWriter( imgCT ); + final SpotRoiWriter< UnsignedShortType > spotWriter = new SpotRoiWriter<>( imgCT ); for ( final Spot spot : model.getSpots().iterable( frame, true ) ) { @@ -446,7 +446,7 @@ public static String exportTrackingData( final String exportRootFolder, final in { final long frame = spot.getFeature( Spot.FRAME ).longValue(); final ImgPlus< UnsignedShortType > imgCT = TMUtils.hyperSlice( labelImg, 0, frame ); - final SpotRoiWriter spotRoiWriter = new SpotRoiWriter( imgCT ); + final SpotRoiWriter< UnsignedShortType > spotRoiWriter = new SpotRoiWriter<>( imgCT ); spotRoiWriter.write( spot, currentID ); } diff --git a/src/main/java/fiji/plugin/trackmate/action/LabelImgExporter.java b/src/main/java/fiji/plugin/trackmate/action/LabelImgExporter.java index 6174c3c0c..4cf72a988 100644 --- a/src/main/java/fiji/plugin/trackmate/action/LabelImgExporter.java +++ b/src/main/java/fiji/plugin/trackmate/action/LabelImgExporter.java @@ -50,7 +50,9 @@ import net.imglib2.RandomAccess; import net.imglib2.img.Img; import net.imglib2.img.display.imagej.ImageJFunctions; +import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.Util; import net.imglib2.view.Views; @@ -395,7 +397,7 @@ public static final ImagePlus createLabelImagePlus( * * @return a new {@link Img}. */ - public static final Img< UnsignedShortType > createLabelImg( + public static final Img< FloatType > createLabelImg( final Model model, final long[] dimensions, final double[] calibration, @@ -435,7 +437,7 @@ public static final Img< UnsignedShortType > createLabelImg( * * @return a new {@link Img}. */ - public static final Img< UnsignedShortType > createLabelImg( + public static final Img< FloatType > createLabelImg( final Model model, final long[] dimensions, final double[] calibration, @@ -448,13 +450,13 @@ public static final Img< UnsignedShortType > createLabelImg( * Create target image. */ final Dimensions targetSize = FinalDimensions.wrap( dimensions ); - final Img< UnsignedShortType > lblImg = Util.getArrayOrCellImgFactory( targetSize, new UnsignedShortType() ).create( targetSize ); + final Img< FloatType > lblImg = Util.getArrayOrCellImgFactory( targetSize, new FloatType() ).create( targetSize ); final AxisType[] axes = new AxisType[] { Axes.X, Axes.Y, Axes.Z, Axes.TIME }; - final ImgPlus< UnsignedShortType > imgPlus = new ImgPlus<>( lblImg, "LblImg", axes, calibration ); + final ImgPlus< FloatType > imgPlus = new ImgPlus<>( lblImg, "LblImg", axes, calibration ); /* * Determine the starting id for spots not in tracks. @@ -475,10 +477,10 @@ public static final Img< UnsignedShortType > createLabelImg( logger.log( "Writing label image.\n" ); for ( int frame = 0; frame < dimensions[ 3 ]; frame++ ) { - final ImgPlus< UnsignedShortType > imgCT = TMUtils.hyperSlice( imgPlus, 0, frame ); + final ImgPlus< FloatType > imgCT = TMUtils.hyperSlice( imgPlus, 0, frame ); final SpotWriter spotWriter = exportSpotsAsDots - ? new SpotAsDotWriter( imgCT ) - : new SpotRoiWriter( imgCT ); + ? new SpotAsDotWriter<>( imgCT ) + : new SpotRoiWriter<>( imgCT ); for ( final Spot spot : model.getSpots().iterable( frame, true ) ) { @@ -554,12 +556,12 @@ public static interface SpotWriter public void write( Spot spot, int id ); } - public static final class SpotRoiWriter implements SpotWriter + public static final class SpotRoiWriter< T extends RealType< T > > implements SpotWriter { - private final ImgPlus< UnsignedShortType > img; + private final ImgPlus< T > img; - public SpotRoiWriter( final ImgPlus< UnsignedShortType > img ) + public SpotRoiWriter( final ImgPlus< T > img ) { this.img = img; } @@ -567,21 +569,21 @@ public SpotRoiWriter( final ImgPlus< UnsignedShortType > img ) @Override public void write( final Spot spot, final int id ) { - for ( final UnsignedShortType pixel : SpotUtil.iterable( spot, img ) ) - pixel.set( id ); + for ( final T pixel : SpotUtil.iterable( spot, img ) ) + pixel.setReal( id ); } } - public static final class SpotAsDotWriter implements SpotWriter + public static final class SpotAsDotWriter< T extends RealType< T > > implements SpotWriter { private final double[] calibration; private final long[] center; - private final RandomAccess< UnsignedShortType > ra; + private final RandomAccess< T > ra; - public SpotAsDotWriter( final ImgPlus< UnsignedShortType > img ) + public SpotAsDotWriter( final ImgPlus< T > img ) { this.calibration = TMUtils.getSpatialCalibration( img ); this.center = new long[ img.numDimensions() ]; @@ -595,7 +597,7 @@ public void write( final Spot spot, final int id ) center[ d ] = Math.round( spot.getFeature( Spot.POSITION_FEATURES[ d ] ).doubleValue() / calibration[ d ] ); ra.setPosition( center ); - ra.get().set( id ); + ra.get().setReal( id ); } } }