From 0a6d6a247dbc16e8d08e491e967f8eff013b991e Mon Sep 17 00:00:00 2001 From: Stefan Hahmann Date: Fri, 29 Sep 2023 17:45:01 +0200 Subject: [PATCH] Add a frame reduction parameter to the segmentation export plugin * The reason behind this is to reduce data size for big projects --- .../SegmentUsingEllipsoidsController.java | 31 ++++++++++++------- .../ui/SegmentUsingEllipsoidsView.java | 6 +++- .../SegmentUsingEllipsoidsControllerTest.java | 10 +++--- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsController.java b/src/main/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsController.java index 92a639c6b..ec94e9b44 100644 --- a/src/main/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsController.java +++ b/src/main/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsController.java @@ -97,8 +97,11 @@ protected SegmentUsingEllipsoidsController( * @param labelOption the {@link LabelOptions} to use * @param file the file to save the image to * @param showResult whether to show the result in ImageJ + * @param frameRateReduction only use every n-th frame for segmentation. 1 means no reduction. */ - public void saveEllipsoidSegmentationToFile( final LabelOptions labelOption, final File file, boolean showResult ) + public void saveEllipsoidSegmentationToFile( + final LabelOptions labelOption, final File file, boolean showResult, int frameRateReduction + ) { if ( file == null ) throw new IllegalArgumentException( "Cannot write ellipsoid segmentation to file. Given file is null." ); @@ -107,7 +110,7 @@ public void saveEllipsoidSegmentationToFile( final LabelOptions labelOption, fin logger.info( "Save ellipsoid segmentation to file. Label options: {}, file: {}", labelOption, file.getAbsolutePath() ); long[] spatialDimensions = getDimensionsOfSource(); - int frames = timePoints.size(); + int frames = timePoints.size() / frameRateReduction; logger.debug( "number of frames: {}", frames ); DiskCachedCellImg< IntType, ? > img = createCachedImage( spatialDimensions, frames ); @@ -115,15 +118,19 @@ public void saveEllipsoidSegmentationToFile( final LabelOptions labelOption, fin lock.lock(); for ( TimePoint timepoint : timePoints ) { - int timepointId = timepoint.getId(); + int frameId = timepoint.getId(); + if ( frameId % frameRateReduction != 0 ) + continue; AffineTransform3D transform = new AffineTransform3D(); - source.getSourceTransform( timepointId, 0, transform ); - IntervalView< IntType > frame = Views.hyperSlice( img, 3, timepointId ); + source.getSourceTransform( frameId, 0, transform ); + int targetFrameId = frameId / frameRateReduction; + IntervalView< IntType > frame = Views.hyperSlice( img, 3, targetFrameId ); AbstractSource< IntType > frameSource = new RandomAccessibleIntervalSource<>( frame, new IntType(), transform, "Segmentation" ); final EllipsoidIterable< IntType > ellipsoidIterable = new EllipsoidIterable<>( frameSource ); - segmentAllSpotsOfTimepoint( ellipsoidIterable, labelOption, timepointId, frames ); + segmentAllSpotsOfFrame( ellipsoidIterable, labelOption, targetFrameId, frames ); } lock.unlock(); + logger.debug( "Segmentation finished." ); ImgPlus< IntType > imgplus = createImgPlus( img ); if ( showResult ) @@ -146,20 +153,20 @@ private ReentrantReadWriteLock.ReadLock getReadLock( LabelOptions labelOption ) } } - private void segmentAllSpotsOfTimepoint( - final EllipsoidIterable< ? extends RealType< ? > > iterable, final LabelOptions option, final int timepointId, final int frames + private void segmentAllSpotsOfFrame( + final EllipsoidIterable< ? extends RealType< ? > > iterable, final LabelOptions option, final int frameId, final int frames ) { - SpatialIndex< Spot > spots = model.getSpatioTemporalIndex().getSpatialIndex( timepointId ); - int oneBasedTimepointId = timepointId + 1; - logger.trace( "timepoint: {}/{}, spots: {}", oneBasedTimepointId, frames, spots.size() ); + SpatialIndex< Spot > spots = model.getSpatioTemporalIndex().getSpatialIndex( frameId ); + int oneBasedFrameId = frameId + 1; + logger.trace( "frame: {}/{}, spots: {}", oneBasedFrameId, frames, spots.size() ); for ( Spot spot : spots ) { iterable.reset( spot ); iterable.forEach( ( Consumer< RealType< ? > > ) pixel -> pixel.setReal( getLabelId( spot, option ) ) ); } - statusService.showProgress( oneBasedTimepointId, frames ); + statusService.showProgress( oneBasedFrameId, frames ); } private long[] getDimensionsOfSource() diff --git a/src/main/java/org/mastodon/mamut/segment/ui/SegmentUsingEllipsoidsView.java b/src/main/java/org/mastodon/mamut/segment/ui/SegmentUsingEllipsoidsView.java index 6a49caa9a..8482cd557 100644 --- a/src/main/java/org/mastodon/mamut/segment/ui/SegmentUsingEllipsoidsView.java +++ b/src/main/java/org/mastodon/mamut/segment/ui/SegmentUsingEllipsoidsView.java @@ -31,6 +31,10 @@ public class SegmentUsingEllipsoidsView implements Command @Parameter(label = "Label Id", choices = { "Track Id", "BranchSpot Id", "Spot Id" }) private String option; + @SuppressWarnings("unused") + @Parameter(label = "Frame rate reduction", description = "Only use every n-th frame for segmentation. 1 means no reduction.") + private int frameRateReduction; + @SuppressWarnings("unused") @Parameter(label = "Save to") private File saveTo; @@ -52,6 +56,6 @@ public void run() { SegmentUsingEllipsoidsController controller = new SegmentUsingEllipsoidsController( appModel, context ); LabelOptions selectedOption = LabelOptions.getByName( option ); - controller.saveEllipsoidSegmentationToFile( selectedOption, saveTo, showResult ); + controller.saveEllipsoidSegmentationToFile( selectedOption, saveTo, showResult, frameRateReduction ); } } diff --git a/src/test/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsControllerTest.java b/src/test/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsControllerTest.java index 435b8e1ea..345e2ea29 100644 --- a/src/test/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsControllerTest.java +++ b/src/test/java/org/mastodon/mamut/segment/SegmentUsingEllipsoidsControllerTest.java @@ -70,9 +70,9 @@ public void testSaveEllipsoidSegmentationToFile() throws IOException File outputSpot = getTempFile( "resultSpot" ); File outputBranchSpot = getTempFile( "resultBranchSpot" ); File outputTrack = getTempFile( "resultTrack" ); - segmentUsingEllipsoidsController.saveEllipsoidSegmentationToFile( LabelOptions.SPOT_ID, outputSpot, false ); - segmentUsingEllipsoidsController.saveEllipsoidSegmentationToFile( LabelOptions.BRANCH_SPOT_ID, outputBranchSpot, false ); - segmentUsingEllipsoidsController.saveEllipsoidSegmentationToFile( LabelOptions.TRACK_ID, outputTrack, false ); + segmentUsingEllipsoidsController.saveEllipsoidSegmentationToFile( LabelOptions.SPOT_ID, outputSpot, false, 1 ); + segmentUsingEllipsoidsController.saveEllipsoidSegmentationToFile( LabelOptions.BRANCH_SPOT_ID, outputBranchSpot, false, 1 ); + segmentUsingEllipsoidsController.saveEllipsoidSegmentationToFile( LabelOptions.TRACK_ID, outputTrack, false, 1 ); ImgOpener imgOpener = new ImgOpener( context ); SCIFIOImgPlus< IntType > imgSpot = getIntTypeSCIFIOImgPlus( imgOpener, outputSpot ); @@ -114,9 +114,9 @@ public void testExceptions() throws IOException file.deleteOnExit(); assertThrows( IllegalArgumentException.class, - () -> controller.saveEllipsoidSegmentationToFile( LabelOptions.SPOT_ID, null, false ) + () -> controller.saveEllipsoidSegmentationToFile( LabelOptions.SPOT_ID, null, false, 1 ) ); - assertThrows( IllegalArgumentException.class, () -> controller.saveEllipsoidSegmentationToFile( null, file, false ) ); + assertThrows( IllegalArgumentException.class, () -> controller.saveEllipsoidSegmentationToFile( null, file, false, 1 ) ); } private static AbstractSource< IntType > createRandomSource()