diff --git a/pom.xml b/pom.xml
index 04f284fbe..43d91eae2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.embl.mobie
mobie-viewer-fiji
- 5.0.9
+ 5.0.11
diff --git a/src/main/java/org/embl/mobie/command/context/AbstractTransformationCommand.java b/src/main/java/org/embl/mobie/command/context/AbstractTransformationCommand.java
index 6e37089d4..d3903fa69 100644
--- a/src/main/java/org/embl/mobie/command/context/AbstractTransformationCommand.java
+++ b/src/main/java/org/embl/mobie/command/context/AbstractTransformationCommand.java
@@ -66,8 +66,9 @@ public abstract class AbstractTransformationCommand extends DynamicCommand imple
public String selectedSourceName;
@Parameter ( label = "Transformed image(s) suffix",
- description = "Upon transformation this suffix will be appended to the moving image(s).\n" +
- "Carefully choose a meaningful suffix here that will create a unique new image name.")
+ description = "Upon transformation this suffix will be appended to the moving image name.\n" +
+ "Carefully choose a meaningful suffix here that will create a unique new image name.\n" +
+ "If you leave this empty the input image view will be overwritten.")
public String suffix = "transformed";
// Too complex to maintain right now
@@ -134,7 +135,9 @@ protected void createAndSaveAffineTransformedImages(
{
for ( Image< ? > movingImage : movingImages )
{
- String transformedImageName = movingImage.getName() + "-" + suffix;
+ String transformedImageName = movingImage.getName();
+ if ( ! suffix.isEmpty() )
+ transformedImageName += "-" + suffix;
AffineTransformation affineTransformation = new AffineTransformation(
suffix,
diff --git a/src/main/java/org/embl/mobie/command/context/ManualTransformationCommand.java b/src/main/java/org/embl/mobie/command/context/ManualTransformationCommand.java
index 37e7528c3..11274d1cc 100644
--- a/src/main/java/org/embl/mobie/command/context/ManualTransformationCommand.java
+++ b/src/main/java/org/embl/mobie/command/context/ManualTransformationCommand.java
@@ -80,7 +80,7 @@ public void startManualTransform()
transformationEditor.setActive( true );
getInfo().getMutableInput( "status", String.class )
- .setValue( this, "Status: You are transforming " + selectedSourceName + "...");
+ .setValue( this, "Status: You are transforming \"" + selectedSourceName + "\"...");
}
private void acceptManualTransform()
diff --git a/src/main/java/org/embl/mobie/command/open/OpenBlobsCommand.java b/src/main/java/org/embl/mobie/command/open/OpenBlobsCommand.java
deleted file mode 100644
index 448338d9a..000000000
--- a/src/main/java/org/embl/mobie/command/open/OpenBlobsCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * #%L
- * Fiji viewer for MoBIE projects
- * %%
- * Copyright (C) 2018 - 2024 EMBL
- * %%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * #L%
- */
-package org.embl.mobie.command.open;
-
-import ij.IJ;
-import org.embl.mobie.command.CommandConstants;
-import org.scijava.command.Command;
-import org.scijava.plugin.Plugin;
-
-@Plugin(type = Command.class, menuPath = CommandConstants.MOBIE_PLUGIN_OPEN + "Open Blobs..." )
-public class OpenBlobsCommand implements Command {
-
- static { net.imagej.patcher.LegacyInjector.preinit(); }
-
- @Override
- public void run()
- {
- IJ.run("Blobs (25K)");
- }
-
-}
diff --git a/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectCommand.java b/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectCommand.java
index 870b37b34..ba1a2cad5 100644
--- a/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectCommand.java
+++ b/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectCommand.java
@@ -32,11 +32,13 @@
import org.embl.mobie.MoBIE;
import org.embl.mobie.MoBIESettings;
import org.embl.mobie.command.CommandConstants;
+import org.embl.mobie.lib.MoBIEHelper;
import org.embl.mobie.lib.io.DataFormats;
import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
+import java.io.File;
import java.io.IOException;
@@ -46,7 +48,7 @@ public class OpenMoBIEProjectCommand implements Command
static { net.imagej.patcher.LegacyInjector.preinit(); }
@Parameter ( label = "Project Location" )
- public String projectLocation = "https://github.com/mobie/platybrowser-datasets";
+ public File projectLocation = new File( "https://github.com/mobie/platybrowser-datasets" );
@Parameter ( label = "Preferentially Fetch Data From", choices = {"Remote", "Local"} )
public String location = "Remote";
@@ -60,7 +62,7 @@ public void run()
try
{
- new MoBIE( projectLocation, settings );
+ new MoBIE( MoBIEHelper.toURI( projectLocation ), settings );
}
catch ( IOException e )
{
diff --git a/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectExpertCommand.java b/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectExpertCommand.java
index 327d216a7..93c645084 100644
--- a/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectExpertCommand.java
+++ b/src/main/java/org/embl/mobie/command/open/project/OpenMoBIEProjectExpertCommand.java
@@ -29,20 +29,23 @@
package org.embl.mobie.command.open.project;
import org.embl.mobie.command.CommandConstants;
+import org.embl.mobie.lib.MoBIEHelper;
import org.embl.mobie.lib.ThreadHelper;
import org.embl.mobie.lib.bdv.view.SliceViewer;
import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
+import java.io.File;
+
@Plugin(type = Command.class, menuPath = CommandConstants.MOBIE_PLUGIN_OPEN_PROJECT + "Open MoBIE Project Expert Mode..." )
public class OpenMoBIEProjectExpertCommand extends OpenMoBIEProjectBranchCommand
{
@Parameter ( label = "Image Data Location" )
- public String imageDataLocation = "https://github.com/platybrowser/platybrowser";
+ public File imageDataLocation = new File( "https://github.com/platybrowser/platybrowser" );
@Parameter ( label = "Table Data Location" )
- public String tableDataLocation = "https://github.com/platybrowser/platybrowser";
+ public File tableDataLocation = new File( "https://github.com/platybrowser/platybrowser" );
@Parameter ( label = "Table Data Branch" )
public String tableDataBranch = "master";
@@ -60,8 +63,8 @@ public void run()
ThreadHelper.setNumIoThreads( numThreads );
settings.gitProjectBranch( projectBranch )
- .imageDataLocation( imageDataLocation )
- .tableDataLocation( tableDataLocation )
+ .imageDataLocation( MoBIEHelper.toURI( imageDataLocation ) )
+ .tableDataLocation( MoBIEHelper.toURI( tableDataLocation ) )
.gitTablesBranch( tableDataBranch );
super.run();
diff --git a/src/main/java/org/embl/mobie/lib/MoBIEHelper.java b/src/main/java/org/embl/mobie/lib/MoBIEHelper.java
index 28a4adcdf..e044dac2c 100644
--- a/src/main/java/org/embl/mobie/lib/MoBIEHelper.java
+++ b/src/main/java/org/embl/mobie/lib/MoBIEHelper.java
@@ -35,6 +35,8 @@
import net.imglib2.Cursor;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.type.numeric.RealType;
+import net.imglib2.util.Intervals;
+import net.imglib2.util.ValuePair;
import net.imglib2.view.Views;
import org.embl.mobie.io.ImageDataOpener;
import org.embl.mobie.io.github.GitHubUtils;
@@ -47,10 +49,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
@@ -312,6 +311,25 @@ public static List< String > getFullPaths( String regex, String root )
}
}
+ public static double[] estimateMinMax(
+ RandomAccessibleInterval extends RealType> > rai)
+ {
+ Cursor extends RealType>> cursor = Views.iterable(rai).cursor();
+ if (!cursor.hasNext()) return new double[]{0, 255};
+ long stepSize = Intervals.numElements(rai) / 10000 + 1;
+ int randomLimit = (int) Math.min(Integer.MAX_VALUE, stepSize);
+ Random random = new Random(42);
+ double min = cursor.next().getRealDouble();
+ double max = min;
+ while (cursor.hasNext()) {
+ double value = cursor.get().getRealDouble();
+ cursor.jumpFwd(stepSize + random.nextInt(randomLimit));
+ min = Math.min(min, value);
+ max = Math.max(max, value);
+ }
+ return new double[]{min, max};
+ }
+
public static > double[] computeMinMax( RandomAccessibleInterval rai) {
Cursor cursor = Views.iterable(rai).cursor();
diff --git a/src/main/java/org/embl/mobie/lib/create/ui/ProjectsCreatorUI.java b/src/main/java/org/embl/mobie/lib/create/ui/ProjectsCreatorUI.java
index d2c347ade..1c0f87f75 100644
--- a/src/main/java/org/embl/mobie/lib/create/ui/ProjectsCreatorUI.java
+++ b/src/main/java/org/embl/mobie/lib/create/ui/ProjectsCreatorUI.java
@@ -336,14 +336,14 @@ private void addButtonsPanel() {
remoteButton.addActionListener( e ->
{
- new Thread( () -> { remoteMetadataSettingsDialog(); } ).start();
+ new Thread( this::remoteMetadataSettingsDialog ).start();
} );
openMoBIEButton.addActionListener( e ->
{
new Thread( () -> {
OpenMoBIEProjectCommand openMoBIE = new OpenMoBIEProjectCommand();
- openMoBIE.projectLocation = this.projectCreator.getProjectLocation().getAbsolutePath();
+ openMoBIE.projectLocation = new File( this.projectCreator.getProjectLocation().getAbsolutePath() );
openMoBIE.run();
} ).start();
} );
diff --git a/src/main/java/org/embl/mobie/lib/files/ImageFileSources.java b/src/main/java/org/embl/mobie/lib/files/ImageFileSources.java
index 4285cb855..9860d7f7f 100644
--- a/src/main/java/org/embl/mobie/lib/files/ImageFileSources.java
+++ b/src/main/java/org/embl/mobie/lib/files/ImageFileSources.java
@@ -35,6 +35,7 @@
import net.imglib2.Volatile;
import net.imglib2.realtransform.AffineTransform3D;
import org.apache.commons.io.FilenameUtils;
+import org.embl.mobie.DataStore;
import org.embl.mobie.MoBIE;
import org.embl.mobie.io.ImageDataOpener;
import org.embl.mobie.io.imagedata.ImageData;
@@ -51,6 +52,7 @@
import tech.tablesaw.api.StringColumn;
import tech.tablesaw.api.Table;
+import javax.xml.crypto.Data;
import java.io.File;
import java.util.*;
@@ -180,17 +182,19 @@ protected static boolean isCellProfilerColumn( String column, Table table )
private void setMetadata( Integer channelIndex )
{
metadataSource = nameToFullPath.keySet().iterator().next();
- IJ.log( "Fetching metadata from " + nameToFullPath.get( metadataSource ) );
+ IJ.log( "Fetching metadata for channel " + channelIndex + "..." );
+ IJ.log( "...from image file " + nameToFullPath.get( metadataSource ) );
+ // FIXME: Cache the image data, because for multiple images it is now reloaded!
ImageData< ? > imageData = ImageDataOpener.open( nameToFullPath.get( metadataSource ) );
CanonicalDatasetMetadata canonicalDatasetMetadata = imageData.getMetadata( channelIndex );
metadata = new Metadata( canonicalDatasetMetadata );
Source< ? > source = imageData.getSourcePair( channelIndex ).getA();
metadata.numZSlices = (int) source.getSource( 0, 0 ).dimension( 2 );
metadata.numTimePoints = SourceHelper.getNumTimePoints( source );
- metadata.contrastLimits = MoBIEHelper.computeMinMax( ( RandomAccessibleInterval ) source.getSource( 0, source.getNumMipmapLevels() -1 ) );
+ metadata.contrastLimits = MoBIEHelper.estimateMinMax( ( RandomAccessibleInterval ) source.getSource( 0, source.getNumMipmapLevels() -1 ) );
IJ.log( "Slices: " + metadata.numZSlices );
IJ.log( "Frames: " + metadata.numTimePoints );
- IJ.log( "Min, max: " + Arrays.toString( metadata.contrastLimits ) );
+ IJ.log( "Contrast limits: " + Arrays.toString( metadata.contrastLimits ) );
}
private static String applyPathMapping( String pathMapping, String path )
diff --git a/src/main/java/org/embl/mobie/lib/source/SourceHelper.java b/src/main/java/org/embl/mobie/lib/source/SourceHelper.java
index f8719bcd9..ae9b97b74 100644
--- a/src/main/java/org/embl/mobie/lib/source/SourceHelper.java
+++ b/src/main/java/org/embl/mobie/lib/source/SourceHelper.java
@@ -38,19 +38,18 @@
import bdv.viewer.Source;
import mpicbg.spim.data.sequence.FinalVoxelDimensions;
import mpicbg.spim.data.sequence.VoxelDimensions;
-import net.imglib2.FinalRealInterval;
-import net.imglib2.Interval;
-import net.imglib2.Point;
-import net.imglib2.RandomAccessibleInterval;
-import net.imglib2.RealInterval;
-import net.imglib2.RealPoint;
+import net.imglib2.*;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.roi.RealMaskRealInterval;
import net.imglib2.roi.geom.GeomMasks;
import net.imglib2.roi.geom.real.WritableBox;
+import net.imglib2.type.numeric.RealType;
import net.imglib2.util.Intervals;
+import net.imglib2.util.ValuePair;
+import net.imglib2.view.Views;
import org.embl.mobie.lib.bdv.CalibratedMousePositionProvider;
import org.jetbrains.annotations.NotNull;
+import sc.fiji.bdvpg.sourceandconverter.SourceAndConverterHelper;
import java.lang.reflect.Field;
import java.util.*;
@@ -60,7 +59,6 @@
public abstract class SourceHelper
{
-
public static < T > T unwrapSource( Source source, Class< T > clazz )
{
if ( source == null )
@@ -375,4 +373,5 @@ public static boolean isPositionWithinSourceInterval( Source< ? > source, RealPo
// }
// else {
}
+
}
diff --git a/src/main/java/org/embl/mobie/ui/UserInterfaceHelper.java b/src/main/java/org/embl/mobie/ui/UserInterfaceHelper.java
index 4a36da0c2..dc4f815b8 100644
--- a/src/main/java/org/embl/mobie/ui/UserInterfaceHelper.java
+++ b/src/main/java/org/embl/mobie/ui/UserInterfaceHelper.java
@@ -37,6 +37,7 @@
import de.embl.cba.tables.SwingUtils;
import ij.IJ;
import ij.gui.GenericDialog;
+import net.imglib2.RandomAccessibleInterval;
import net.imglib2.converter.Converter;
import net.imglib2.display.ColorConverter;
import net.imglib2.realtransform.AffineTransform3D;
@@ -44,6 +45,7 @@
import org.embl.mobie.command.context.ConfigureSegmentRenderingCommand;
import org.embl.mobie.io.util.IOHelper;
import org.embl.mobie.MoBIE;
+import org.embl.mobie.lib.MoBIEHelper;
import org.embl.mobie.lib.io.FileLocation;
import org.embl.mobie.lib.MoBIEInfo;
import org.embl.mobie.lib.Services;
@@ -488,7 +490,6 @@ public static JFrame showOpacityAndContrastLimitsDialog(
selection.setUpdateListener( opacityUpdateListener );
panel.add( opacitySlider );
-
if ( addContrastLimitUI )
{
// Contrast Limits
@@ -503,7 +504,6 @@ public static JFrame showOpacityAndContrastLimitsDialog(
.map( sac -> sac.getConverter() )
.collect( Collectors.toList() );
-
final double currentContrastLimitsMin = converterSetups.get( 0 ).getDisplayRangeMin();
final double currentContrastLimitsMax = converterSetups.get( 0 ).getDisplayRangeMax();
final double absCurrentRange = Math.abs( currentContrastLimitsMax - currentContrastLimitsMin );
@@ -548,6 +548,18 @@ public static JFrame showOpacityAndContrastLimitsDialog(
panel.add( minSlider );
panel.add( maxSlider );
+ JButton autoButton = new JButton("Auto Min Max");
+ autoButton.addActionListener( e ->
+ {
+ Source< ? > source = sacs.get( 0 ).getSpimSource();
+ RandomAccessibleInterval< ? > rai = source.getSource( bdvHandle.getViewerPanel().state().getCurrentTimepoint(),
+ source.getNumMipmapLevels() - 1 );
+ double[] minMax = MoBIEHelper.estimateMinMax( ( RandomAccessibleInterval ) rai );
+ min.setCurrentValue( minMax[ 0 ] );
+ max.setCurrentValue( minMax[ 1 ] );
+ });
+ panel.add( autoButton );
+
boolean isInvert = false;
for ( Converter< ?, ARGBType > converter : converters )
{
diff --git a/src/test/java/projects/muscle_patterning_drosophila/OpenTeresaData.java b/src/test/java/projects/muscle_patterning_drosophila/OpenTeresaData.java
index 7213ae5d6..c0b926cbe 100644
--- a/src/test/java/projects/muscle_patterning_drosophila/OpenTeresaData.java
+++ b/src/test/java/projects/muscle_patterning_drosophila/OpenTeresaData.java
@@ -41,15 +41,37 @@ public static void main( String[] args )
final ImageJ imageJ = new ImageJ();
imageJ.ui().showUI();
+// OpenTableCommand command = new OpenTableCommand();
+// command.table = new File( "/Users/tischer/Desktop/teresa/summary_calculated1_subset.txt" );
+// command.root = command.table.getParentFile();
+// command.images = "FileName_Result.Image_IMG"; // Result.Image.Zarr
+// command.gridType = GridType.Transformed; // TODO: not working with Stitched!
+// command.run();
+
OpenTableCommand command = new OpenTableCommand();
- //command.table = new File( "/Volumes/almf/group/Aliaksandr/User_data/Furlong_CrispR/test_data_20231018/20231004/20231004-172458/summary_calculated1.txt" );
- //command.table = new File( "/Volumes/almf/group/Aliaksandr/User_data/Furlong_CrispR/test_data_20231018/20231004/20231004-172458/summary_calculated1_subset.txt" );
- command.table = new File( "/Users/tischer/Desktop/teresa/summary_calculated1_subset.txt" );
- //command.table = new File( "/Volumes/cba/exchange/furlong_test/summary_calculated1_subset_zarr.txt" );
- //command.images = "Result.Image.Zarr"; // Result.Image.Zarr
+ command.table = new File( "/Volumes/CRISPR_project_data/test_data_new/20231122-170451/summary_new.txt" );
command.root = command.table.getParentFile();
- command.images = "FileName_Result.Image_IMG"; // Result.Image.Zarr
+ command.images = "FileName_Result.Image_IMG";
command.gridType = GridType.Transformed; // TODO: not working with Stitched!
command.run();
+
+ /*
+ TODO:
+
+ Why is it fetching so much metadata?? It is opening the same data again for all channels.
+
+ Also initialisation is slow...
+
+ Min, max: [6.0, 2608.0]
+ Fetching metadata from /Volumes/CRISPR_project_data/test_data_new/20231122-170451/Result-Image/Result-Image--WA01--P0001--T0001.oir
+ Slices: 11
+ Frames: 1
+ Min, max: [13.0, 981.0]
+ Fetching metadata from /Volumes/CRISPR_project_data/test_data_new/20231122-170451/Result-Image/Result-Image--WA01--P0001--T0001.oir
+ Slices: 11
+ Frames: 1
+ Min, max: [7.0, 2060.0]
+ */
+
}
}
diff --git a/src/test/resources/minimal-mobie-project/data/blobs/dataset.json b/src/test/resources/minimal-mobie-project/data/blobs/dataset.json
index 9b32751a2..2dd3ba7f6 100644
--- a/src/test/resources/minimal-mobie-project/data/blobs/dataset.json
+++ b/src/test/resources/minimal-mobie-project/data/blobs/dataset.json
@@ -42,26 +42,35 @@
}
}
],
- "sourceTransforms": [],
- "viewerTransform": {
- "normalizedAffine": [
- 0.0016175016000465467,
- 0.0,
- 0.0,
- -0.20623145400593473,
- 0.0,
- 0.0016175016000465467,
- 0.0,
- -0.20461395240588817,
- 0.0,
- 0.0,
- 0.0016175016000465467,
- 0.0
- ],
- "timepoint": 0
- },
- "isExclusive": true,
- "description": ""
+ "sourceTransforms": [
+ {
+ "affine": {
+ "parameters": [
+ 1.0000000000000002,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0000000000000002,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0000000000000002,
+ 0.0
+ ],
+ "name": "",
+ "sources": [
+ "blobs"
+ ],
+ "sourceNamesAfterTransform": [
+ "blobs"
+ ]
+ }
+ }
+ ],
+ "isExclusive": false,
+ "description": "blobs, overwrite"
},
"default": {
"uiSelectionGroup": "bookmark",