From df1ac263ea56fecb80d0b74ee72e06d3e27e7524 Mon Sep 17 00:00:00 2001 From: Stefan Hahmann Date: Wed, 23 Apr 2025 13:08:32 +0200 Subject: [PATCH 01/13] Make MainWindow a bit wider --- src/main/java/org/mastodon/mamut/MainWindow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mastodon/mamut/MainWindow.java b/src/main/java/org/mastodon/mamut/MainWindow.java index 3e3ea15f4..945195da6 100644 --- a/src/main/java/org/mastodon/mamut/MainWindow.java +++ b/src/main/java/org/mastodon/mamut/MainWindow.java @@ -111,7 +111,7 @@ public MainWindow( final ProjectModel appModel ) // Main Panel final JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout( new MigLayout( "wrap 2", "[150px!]10[150px!]" ) ); + buttonsPanel.setLayout( new MigLayout( "wrap 2", "[190px!]10[190px!]" ) ); // Project: final JPanel titlePanel = new JPanel(); From 93d81028d9d82129175c88575333b6562b74a777 Mon Sep 17 00:00:00 2001 From: Stefan Hahmann Date: Thu, 24 Apr 2025 10:50:45 +0200 Subject: [PATCH 02/13] Set the smaller font for Buttons and Labels as default on Linux/Unix systems and make MainWindow a bit smaller again --- .../java/org/mastodon/mamut/MainWindow.java | 2 +- .../mamut/launcher/MastodonLauncher.java | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mastodon/mamut/MainWindow.java b/src/main/java/org/mastodon/mamut/MainWindow.java index 945195da6..63c73a478 100644 --- a/src/main/java/org/mastodon/mamut/MainWindow.java +++ b/src/main/java/org/mastodon/mamut/MainWindow.java @@ -111,7 +111,7 @@ public MainWindow( final ProjectModel appModel ) // Main Panel final JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout( new MigLayout( "wrap 2", "[190px!]10[190px!]" ) ); + buttonsPanel.setLayout( new MigLayout( "wrap 2", "[170px!]10[170px!]" ) ); // Project: final JPanel titlePanel = new JPanel(); diff --git a/src/main/java/org/mastodon/mamut/launcher/MastodonLauncher.java b/src/main/java/org/mastodon/mamut/launcher/MastodonLauncher.java index 324b059bc..a2ebc3d87 100644 --- a/src/main/java/org/mastodon/mamut/launcher/MastodonLauncher.java +++ b/src/main/java/org/mastodon/mamut/launcher/MastodonLauncher.java @@ -28,6 +28,7 @@ */ package org.mastodon.mamut.launcher; +import java.awt.Font; import java.awt.datatransfer.DataFlavor; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; @@ -47,6 +48,7 @@ import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; +import javax.swing.UIManager; import org.jdom2.JDOMException; import org.mastodon.app.MastodonIcons; @@ -94,6 +96,7 @@ public class MastodonLauncher extends JFrame public MastodonLauncher( final Context context ) { super( "Mastodon launcher" ); + setFont(); this.context = Optional.ofNullable( context ).orElse( new Context() ); System.setProperty( "apple.laf.useScreenMenuBar", "true" ); @@ -123,6 +126,27 @@ public MastodonLauncher( final Context context ) setDropTarget( new LauncherDropTarget() ); } + private static void setFont() + { + // Determine the OS and set the font + String os = System.getProperty( "os.name" ).toLowerCase(); + + if ( os.contains( "nix" ) || os.contains( "nux" ) ) + { + Font defaultFont = new Font( "Arial", Font.PLAIN, 12 ); + // Set the font for UI components + UIManager.put( "Label.font", defaultFont ); + UIManager.put( "Button.font", defaultFont ); + UIManager.put( "TextField.font", defaultFont ); + UIManager.put( "TextArea.font", defaultFont ); + UIManager.put( "ComboBox.font", defaultFont ); + UIManager.put( "List.font", defaultFont ); + UIManager.put( "Table.font", defaultFont ); + UIManager.put( "Menu.font", defaultFont ); + UIManager.put( "MenuItem.font", defaultFont ); + } + } + private void importSimi() { gui.clearLog(); From 18a146cf19cf8f6f404a17c84aa2f88695e81421 Mon Sep 17 00:00:00 2001 From: Stefan Hahmann Date: Thu, 24 Apr 2025 11:10:21 +0200 Subject: [PATCH 03/13] Use github action setup-java@v4 instead of v2 * The CI Pipeline was not working anymore. Github seems to require this change to allow the CI to be working again --- .github/workflows/build-main.yml | 2 +- .github/workflows/build-pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml index 0b1538578..92bc2f106 100644 --- a/.github/workflows/build-main.yml +++ b/.github/workflows/build-main.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'zulu' diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 2df3c51a5..149fd4b4f 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'zulu' From 458c7e99195d80e65836f47380cf536c2b1c8217 Mon Sep 17 00:00:00 2001 From: tpietzsch Date: Wed, 30 Jul 2025 11:18:23 -0400 Subject: [PATCH 04/13] typo --- src/main/java/org/mastodon/mamut/model/Model.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mastodon/mamut/model/Model.java b/src/main/java/org/mastodon/mamut/model/Model.java index f4b50ac86..32eaec354 100644 --- a/src/main/java/org/mastodon/mamut/model/Model.java +++ b/src/main/java/org/mastodon/mamut/model/Model.java @@ -233,7 +233,7 @@ public FileIdToGraphMap< Spot, Link > loadRaw( final MamutProject.ProjectReader } /** - * Saves this model to the specified the specified project folder. + * Saves this model to the specified project folder. * * @param writer * writer to save the raw project files. From d3c63c2b6ff865ee0af86e2793a8c4053b598b07 Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 18 Aug 2025 15:12:25 +0200 Subject: [PATCH 05/13] Adapt benchmark for the paper. --- .../revised/CreateLargeModelExample.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java b/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java index e72e29608..c223ad4c0 100644 --- a/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java +++ b/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java @@ -6,13 +6,13 @@ * %% * 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 @@ -28,14 +28,21 @@ */ package org.mastodon.graph.revised; +import java.io.IOException; + +import org.mastodon.mamut.ProjectModel; +import org.mastodon.mamut.WindowManager; import org.mastodon.mamut.io.importer.ModelImporter; +import org.mastodon.mamut.io.project.MamutProject; import org.mastodon.mamut.model.Link; import org.mastodon.mamut.model.Model; import org.mastodon.mamut.model.Spot; +import org.mastodon.views.bdv.SharedBigDataViewerData; +import org.scijava.Context; public class CreateLargeModelExample { - private static final int N_STARTING_CELLS = 6; + private static final int N_STARTING_CELLS = 10; private static final int N_DIVISIONS = 17; @@ -160,8 +167,13 @@ private void addBranch( final Spot start, final double vx, final double vy, fina model.getGraph().releaseRef( link ); } - public static void main( final String[] args ) + public static void main( final String[] args ) throws IOException { + // Print info on the JVM used to run the code. + System.out.println( "JVM: " + System.getProperty( "java.vm.name" ) + " " + System.getProperty( "java.vm.version" ) ); + System.out.println( "Java: " + System.getProperty( "java.version" ) ); + System.out.println( "OS: " + System.getProperty( "os.name" ) + " " + System.getProperty( "os.version" ) + " " + System.getProperty( "os.arch" ) ); + final CreateLargeModelExample clme = new CreateLargeModelExample(); final long start = System.currentTimeMillis(); final Model model = clme.run(); @@ -170,5 +182,22 @@ public static void main( final String[] args ) System.out.println( "Total number of spots: " + model.getGraph().vertices().size() ); System.out.println( String.format( "Total memory used by the model: %.1f MB", ( Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() ) / 1e6d ) ); + + + final Context context = new Context(); + final SharedBigDataViewerData imagedata = SharedBigDataViewerData.fromDummyFilename( "x=1000 y=1000 z=100 sx=1 sy=1 sz=10 t=400.dummy" ); + final MamutProject project = new MamutProject( "./large_model_example.mastodon" ); + final ProjectModel appModel = ProjectModel.create( context, model, imagedata, project ); + final WindowManager wm = new WindowManager( appModel ); + +// start = System.currentTimeMillis(); +// wm.createBigDataViewer(); +// end = System.currentTimeMillis(); +// System.out.println( "Rendering in the main viewer done in " + ( end - start ) / 1000. + " s." ); +// +// start = System.currentTimeMillis(); +// wm.createTrackScheme( ); +// end = System.currentTimeMillis(); +// System.out.println( "Rendering in TrackScheme done in " + ( end - start ) / 1000. + " s." ); } } From 8416b6facdf3891562babdff889c441ce114aadd Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:36:15 +0200 Subject: [PATCH 06/13] Bump to next development cycle Signed-off-by: Jean-Yves TINEVEZ --- .../CommonTrackMateFeatureDeclarations.java | 94 ++++++++++ .../io/importer/trackmate/MamutExporter.java | 176 ++++++++++++++++-- .../importer/trackmate/TrackMateXMLKeys.java | 2 + .../grapher/DataDisplayFrameSupplier.java | 41 ---- .../mamut/views/grapher/GrapherGuiState.java | 49 ++--- .../views/grapher/GrapherInitializer.java | 18 ++ .../views/grapher/MamutBranchViewGrapher.java | 3 +- .../MamutBranchViewGrapherFactory.java | 15 +- .../mamut/views/grapher/MamutViewGrapher.java | 17 +- .../grapher/MamutViewGrapherFactory.java | 15 +- .../views/bdv/overlay/OverlayNavigation.java | 27 ++- .../grapher/display/DataDisplayFrame.java | 14 +- .../grapher/display/GrapherSidePanel.java | 21 ++- .../views/grapher/display/Plotable.java | 10 + 14 files changed, 382 insertions(+), 120 deletions(-) create mode 100644 src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java delete mode 100644 src/main/java/org/mastodon/mamut/views/grapher/DataDisplayFrameSupplier.java create mode 100644 src/main/java/org/mastodon/views/grapher/display/Plotable.java diff --git a/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java b/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java new file mode 100644 index 000000000..5aac6f5cc --- /dev/null +++ b/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java @@ -0,0 +1,94 @@ +package org.mastodon.mamut.io.importer.trackmate; + +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_ATTRIBUTE; +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_DIMENSION_ATTRIBUTE; +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_ISINT_ATTRIBUTE; +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_NAME_ATTRIBUTE; +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_SHORT_NAME_ATTRIBUTE; +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_TAG; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.jdom2.Element; + +public class CommonTrackMateFeatureDeclarations +{ + + public static final List< CommonTrackMateFeatureDeclaration > spotFeatureDeclarations = Arrays.asList( new CommonTrackMateFeatureDeclaration[] { + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.VISIBILITY_FEATURE_NAME, "Visibility", "Visibility", "NONE", true ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.POSITION_X_FEATURE_NAME, "X", "X", "POSITION", false ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.POSITION_Y_FEATURE_NAME, "Y", "Y", "POSITION", false ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.POSITION_Z_FEATURE_NAME, "Z", "Z", "POSITION", false ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.POSITION_T_FEATURE_NAME, "T", "T", "TIME", false ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.FRAME_FEATURE_NAME, "Frame", "Frame", "NONE", true ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.RADIUS_FEATURE_NAME, "Radius", "R", "LENGTH", false ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.QUALITY_FEATURE_NAME, "Quality", "Quality", "QUALITY", false ), + } ); + + public static final List< CommonTrackMateFeatureDeclaration > edgeFeatureDeclarations = Arrays.asList( new CommonTrackMateFeatureDeclaration[] { + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.EDGE_SOURCE_ATTRIBUTE, "Source spot ID", "Source ID", "NONE", true ), + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.EDGE_TARGET_ATTRIBUTE, "Target spot ID", "Target ID", "NONE", true ), + } ); + + public static final List< CommonTrackMateFeatureDeclaration > trackFeatureDeclarations = Arrays.asList( new CommonTrackMateFeatureDeclaration[] { + new CommonTrackMateFeatureDeclaration( TrackMateXMLKeys.TRACK_ID_ATTRIBUTE, "Track ID", "ID", "NONE", true ), + } ); + + public static class CommonTrackMateFeatureDeclaration + { + public final String key; + + public final String name; + + public final String shortName; + + public final String dimension; + + public final boolean isInt; + + public CommonTrackMateFeatureDeclaration( final String key, final String name, final String shortName, final String dimension, final boolean isInt ) + { + this.key = key; + this.name = name; + this.shortName = shortName; + this.dimension = dimension; + this.isInt = isInt; + } + + public Element toElement() + { + final Element fel = new Element( FEATURE_TAG ); + fel.setAttribute( FEATURE_ATTRIBUTE, key ); + fel.setAttribute( FEATURE_NAME_ATTRIBUTE, name ); + fel.setAttribute( FEATURE_SHORT_NAME_ATTRIBUTE, shortName ); + fel.setAttribute( FEATURE_DIMENSION_ATTRIBUTE, dimension ); + fel.setAttribute( FEATURE_ISINT_ATTRIBUTE, "" + isInt ); + return fel; + } + } + + /** + * List of Mastodon spot projection keys, translated to the TrackMate export + * name, that are not needed in the exported XML file, as they are already + * exported via TrackMate builtin features. + */ + public static final List< String > redundantSpotProjectionKeys = Arrays.asList( + "Spot_position_X", "Spot_position_Y", "Spot_position_Z", "Spot_radius", "Spot_frame" ); + + /** + * List of Mastodon link projection keys, translated to the TrackMate export + * name, that are not needed in the exported XML file, as they are already + * exported via TrackMate builtin features. + */ + public static final List< String > redundantLinkProjectionKeys = Arrays.asList( + "Link_target_IDs_Source_spot_id", "Link_target_IDs_Target_spot_id" ); + + /** + * List of Mastodon track projection keys, translated to the TrackMate + * export name, that are not needed in the exported XML file, as they are + * already exported via TrackMate builtin features. + */ + public static final List< String > redundantTrackProjectionKeys = Collections.emptyList(); +} diff --git a/src/main/java/org/mastodon/mamut/io/importer/trackmate/MamutExporter.java b/src/main/java/org/mastodon/mamut/io/importer/trackmate/MamutExporter.java index eaf1e69d0..c0b7fb54c 100644 --- a/src/main/java/org/mastodon/mamut/io/importer/trackmate/MamutExporter.java +++ b/src/main/java/org/mastodon/mamut/io/importer/trackmate/MamutExporter.java @@ -54,6 +54,7 @@ import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FOLDER_ATTRIBUTE; import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FRAME_ATTRIBUTE; import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FRAME_FEATURE_NAME; +import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FRAME_INTERVAL_ATTRIBUTE; import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.GUI_STATE_TAG; import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.HEIGHT_ATTRIBUTE; import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.ID_FEATURE_NAME; @@ -361,6 +362,7 @@ private Element imageDataToXml() attributes.add( new Attribute( PIXEL_WIDTH_ATTRIBUTE, Double.toString( pixelWidth ) ) ); attributes.add( new Attribute( PIXEL_HEIGHT_ATTRIBUTE, Double.toString( pixelHeight ) ) ); attributes.add( new Attribute( VOXEL_DEPTH_ATTRIBUTE, Double.toString( voxelDepth ) ) ); + attributes.add( new Attribute( FRAME_INTERVAL_ATTRIBUTE, Double.toString( 1. ) ) ); final Element timePointsElement = document .getRootElement() @@ -424,9 +426,9 @@ private Element[] trackCollectionToXml() public void processVertexLate( final Spot vertex, final DepthFirstSearch< Spot, Link > search ) { /* - * 1 root = 1 track, unless a track has several roots. Add - * the iterated vertex to the list of root to skip if - * needed. + * 1 root = 1 track, unless a track has several + * roots. Add the iterated vertex to the list of + * root to skip if needed. */ if ( vertex.incomingEdges().isEmpty() ) toSkip.add( vertex ); @@ -520,6 +522,15 @@ private Element spotCollectionToXml() return spotCollectionElement; } + /** + * Collection of link feature names that we want to export in the mamut + * file, but computed from the link data currently set in Mastodon. We used + * this collection to avoid exporting a feature with identical name in the + * case a feature imported as the same name. + */ + private final static Set< String > IMPORTED_LINK_BUILTIN_FEATURES = new HashSet<>( Arrays.asList( + EDGE_SOURCE_ATTRIBUTE, EDGE_TARGET_ATTRIBUTE ) ); + private Element edgeToXml( final Link edge, final int sourceSpotID, final int targetSpotID ) { final Collection< Attribute > attributes = new ArrayList<>(); @@ -529,9 +540,45 @@ private Element edgeToXml( final Link edge, final int sourceSpotID, final int ta attributes.add( new Attribute( EDGE_TARGET_ATTRIBUTE, Integer.toString( targetSpotID ) ) ); // Link features. - linkFeatureProjections.forEach( p -> attributes.add( new Attribute( - p.attributeName, - Double.toString( p.projection.value( edge ) ) ) ) ); + for ( final ExportFeatureProjection< Link > p : linkFeatureProjections ) + { + final String origName = p.attributeName; + /* + * Do not export link features that are common TrackMate features + * and that we already exported above. + */ + if ( CommonTrackMateFeatureDeclarations.redundantLinkProjectionKeys.contains( origName ) ) + continue; + + final String attName; + /* + * If the model to export was imported from a TrackMate or a MaMuT + * file, it will already contain features with the same name that + * the builtin feature we added just above. Which will cause an + * error. + * + * To avoid this, rename these imported features. + */ + if ( IMPORTED_LINK_BUILTIN_FEATURES.contains( origName ) ) + { + final String importedAttName = "IMPORTED_" + origName; + attName = importedAttName; + } + else if ( origName.startsWith( "IMPORTED_" ) ) + { + // We skip features that have been re-imported. + continue; + } + else + { + // All good. + attName = origName; + } + + attributes.add( new Attribute( + attName, + Double.toString( p.projection.value( edge ) ) ) ); + } final Element edgeElement = new Element( EDGE_TAG ); edgeElement.setAttributes( attributes ); @@ -556,9 +603,20 @@ private Element trackToXml( final Spot root ) return trackElement; } + /** + * Collection of spot feature names that we want to export in the mamut + * file, but computed from the actual position, etc, currently set in + * Mastodon. We used this collection to avoid exporting a feature with + * identical name in the case a feature imported as the same name. + */ + private final static Set< String > IMPORTED_SPOT_BUILTIN_FEATURES = new HashSet<>( Arrays.asList( ID_FEATURE_NAME, LABEL_FEATURE_NAME, POSITION_X_FEATURE_NAME, + POSITION_Y_FEATURE_NAME, POSITION_Z_FEATURE_NAME, FRAME_FEATURE_NAME, + POSITION_T_FEATURE_NAME, QUALITY_FEATURE_NAME, VISIBILITY_FEATURE_NAME, + RADIUS_FEATURE_NAME ) ); + private Element spotToXml( final Spot spot ) { - final Collection< Attribute > attributes = new ArrayList<>(); + final List< Attribute > attributes = new ArrayList<>(); // Id. attributes.add( new Attribute( ID_FEATURE_NAME, Integer.toString( spot.getInternalPoolIndex() ) ) ); @@ -583,10 +641,54 @@ private Element spotToXml( final Spot spot ) final double meanRadius = Arrays.stream( eig.getRealEigenvalues() ).map( Math::sqrt ).average().getAsDouble(); attributes.add( new Attribute( RADIUS_FEATURE_NAME, Double.toString( meanRadius ) ) ); - // Spot features. - spotFeatureProjections.forEach( p -> attributes.add( new Attribute( - p.attributeName, - Double.toString( p.projection.value( spot ) ) ) ) ); + for (final ExportFeatureProjection< Spot > p : spotFeatureProjections ) + { + final String origName = p.attributeName; + /* + * Do not export spot features that are common TrackMate features + * and that we already exported above. + */ + if ( CommonTrackMateFeatureDeclarations.redundantSpotProjectionKeys.contains( origName ) ) + continue; + + final String attName; + /* + * If the model to export was imported from a TrackMate or a MaMuT + * file, it will already contain features with the same name that + * the builtin feature we added just above. Which will cause an + * error. + * + * To avoid this, rename these imported features. + */ + if ( IMPORTED_SPOT_BUILTIN_FEATURES.contains( origName ) ) + { + final String importedAttName = "IMPORTED_" + origName; + attName = importedAttName; + } + else if ( origName.startsWith( "IMPORTED_" ) ) + { + // We skip features that have been re-imported. + continue; + } + else + { + // All good. + attName = origName; + } + + + String val; + if ( p.projection instanceof IntFeatureProjection ) + { + val = Integer.toString( (int) p.projection.value( spot ) ); + } + else + { + // Assume double. + val = Double.toString( p.projection.value( spot ) ); + } + attributes.add( new Attribute( attName, val ) ); + } final Element spotElement = new Element( SPOT_ELEMENT_TAG ); spotElement.setAttributes( attributes ); @@ -596,6 +698,7 @@ private Element spotToXml( final Spot spot ) private Element featuresDeclarationToXml() { final Element featuresElement = new Element( FEATURE_DECLARATION_TAG ); + appendBasicFeatureDeclarations( featuresElement ); appendFeaturesDeclarationOfClass( Spot.class, featuresElement, SPOT_FEATURE_DECLARATION_TAG ); appendFeaturesDeclarationOfClass( Link.class, featuresElement, EDGE_FEATURE_DECLARATION_TAG ); // Create an empty declaration for track features, for now. @@ -603,21 +706,53 @@ private Element featuresDeclarationToXml() return featuresElement; } + private void appendBasicFeatureDeclarations( final Element featuresElement ) + { + // Spots. + final Element spotFeaturesElement = getOrAddChild( featuresElement, SPOT_FEATURE_DECLARATION_TAG ); + CommonTrackMateFeatureDeclarations.spotFeatureDeclarations.forEach( cf -> spotFeaturesElement.addContent( cf.toElement() ) ); + + // Edges. + final Element edgeFeaturesElement = getOrAddChild( featuresElement, EDGE_FEATURE_DECLARATION_TAG ); + CommonTrackMateFeatureDeclarations.edgeFeatureDeclarations.forEach( cf -> edgeFeaturesElement.addContent( cf.toElement() ) ); + + // Tracks. + final Element trackFeaturesElement = getOrAddChild( featuresElement, TRACK_FEATURE_DECLARATION_TAG ); + CommonTrackMateFeatureDeclarations.trackFeatureDeclarations.forEach( cf -> trackFeaturesElement.addContent( cf.toElement() ) ); + } + @SuppressWarnings( { "unchecked", "rawtypes" } ) private < T > void appendFeaturesDeclarationOfClass( final Class< T > clazz, final Element featuresElement, final String classFeatureDeclarationTag ) { final List< ExportFeatureProjection< T > > projections; + List< String > redundantFeatures; if ( clazz.equals( Spot.class ) ) + { projections = ( List ) spotFeatureProjections; + redundantFeatures = CommonTrackMateFeatureDeclarations.redundantSpotProjectionKeys; + } else if ( clazz.equals( Link.class ) ) + { projections = ( List ) linkFeatureProjections; + redundantFeatures = CommonTrackMateFeatureDeclarations.redundantLinkProjectionKeys; + } else + { projections = Collections.emptyList(); + redundantFeatures = CommonTrackMateFeatureDeclarations.redundantTrackProjectionKeys; + } - final Element classFeaturesElement = new Element( classFeatureDeclarationTag ); + final Element classFeaturesElement = getOrAddChild( featuresElement, classFeatureDeclarationTag ); for ( final ExportFeatureProjection< T > p : projections ) { + /* + * Do not export features that are common TrackMate features and + * that we already declared. + */ + if ( redundantFeatures.contains( p.attributeName ) ) + continue; + final String isint = ( p.projection instanceof IntFeatureProjection ) ? "true" : "false"; @@ -633,7 +768,17 @@ else if ( clazz.equals( Link.class ) ) fel.setAttribute( FEATURE_ISINT_ATTRIBUTE, isint ); classFeaturesElement.addContent( fel ); } - featuresElement.addContent( classFeaturesElement ); + } + + private Element getOrAddChild( final Element parent, final String childName ) + { + Element child = parent.getChild( childName ); + if ( null == child ) + { + child = new Element( childName ); + parent.addContent( child ); + } + return child; } private static Document getSAXParsedDocument( final String fileName ) @@ -652,8 +797,8 @@ private static Document getSAXParsedDocument( final String fileName ) } /** - * Tries to recover the TrackMate dimension from the unit string and the spatial and - * time units. + * Tries to recover the TrackMate dimension from the unit string and the + * spatial and time units. * * @param units * the unit string. @@ -914,4 +1059,5 @@ public static final void export( final File target, final Model model, final Mam exporter.appendGuiState(); exporter.write( target ); } + } diff --git a/src/main/java/org/mastodon/mamut/io/importer/trackmate/TrackMateXMLKeys.java b/src/main/java/org/mastodon/mamut/io/importer/trackmate/TrackMateXMLKeys.java index 9f5dee71f..7028b5f25 100644 --- a/src/main/java/org/mastodon/mamut/io/importer/trackmate/TrackMateXMLKeys.java +++ b/src/main/java/org/mastodon/mamut/io/importer/trackmate/TrackMateXMLKeys.java @@ -125,6 +125,8 @@ public class TrackMateXMLKeys public static final String NFRAMES_ATTRIBUTE = "nframes"; + public static final String FRAME_INTERVAL_ATTRIBUTE = "timeinterval"; + public static final String PIXEL_WIDTH_ATTRIBUTE = "pixelwidth"; public static final String PIXEL_HEIGHT_ATTRIBUTE = "pixelheight"; diff --git a/src/main/java/org/mastodon/mamut/views/grapher/DataDisplayFrameSupplier.java b/src/main/java/org/mastodon/mamut/views/grapher/DataDisplayFrameSupplier.java deleted file mode 100644 index 8c60ed77c..000000000 --- a/src/main/java/org/mastodon/mamut/views/grapher/DataDisplayFrameSupplier.java +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * #%L - * Mastodon - * %% - * Copyright (C) 2014 - 2025 Tobias Pietzsch, Jean-Yves Tinevez - * %% - * 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.mastodon.mamut.views.grapher; - -import org.mastodon.Ref; -import org.mastodon.graph.Edge; -import org.mastodon.graph.Vertex; -import org.mastodon.model.HasLabel; -import org.mastodon.spatial.HasTimepoint; -import org.mastodon.views.grapher.display.DataDisplayFrame; - -public interface DataDisplayFrameSupplier< V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > -{ - DataDisplayFrame< V, E > getFrame(); -} diff --git a/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java b/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java index 9d3c14663..9fd0a3bf8 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java @@ -6,13 +6,13 @@ * %% * 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 @@ -38,10 +38,11 @@ import org.mastodon.model.HasLabel; import org.mastodon.spatial.HasTimepoint; import org.mastodon.views.grapher.datagraph.ScreenTransform; -import org.mastodon.views.grapher.display.DataDisplayFrame; import org.mastodon.views.grapher.display.FeatureGraphConfig; import org.mastodon.views.grapher.display.FeatureSpecPair; import org.mastodon.views.grapher.display.GrapherSidePanel; +import org.mastodon.views.grapher.display.Plotable; +import org.mastodon.views.grapher.display.ScreenTransformState; public class GrapherGuiState { @@ -100,40 +101,39 @@ private GrapherGuiState() */ public static final String GRAPHER_SHOW_EDGES_KEY = "GrapherShowEdges"; - static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > void - writeGuiState( final DataDisplayFrameSupplier< V, E > frameProvider, final Map< String, Object > guiState ) + public static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > void + writeGuiState( final ScreenTransformState screenTransformState, final FeatureGraphConfig config, + final Map< String, Object > guiState ) { - DataDisplayFrame< V, E > frame = frameProvider.getFrame(); // Transform. - final ScreenTransform transform = frame.getDataDisplayPanel().getScreenTransform().get(); + final ScreenTransform transform = screenTransformState.get(); guiState.put( GRAPHER_TRANSFORM_KEY, transform ); // Feature graph config. - writeFeatureGraphConfig( frame, guiState ); + writeFeatureGraphConfig( config, guiState ); } - static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > void - loadGuiState( final DataDisplayFrameSupplier< V, E > frameSupplier, final Map< String, Object > guiState, - final FeatureGraphConfig defaultConfig ) + public static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > void + loadGuiState( final Map< String, Object > guiState, final ScreenTransformState screenTransformState, + final GrapherSidePanel sidePanel, final FeatureGraphConfig defaultConfig, + final Plotable plotable ) { - DataDisplayFrame< V, E > frame = frameSupplier.getFrame(); - // Read Screen Transform. final ScreenTransform screenTransform = ( ScreenTransform ) guiState.get( GRAPHER_TRANSFORM_KEY ); if ( null != screenTransform ) - frame.getDataDisplayPanel().getScreenTransform().set( screenTransform ); + screenTransformState.set( screenTransform ); // Read Feature graph config. - FeatureGraphConfig config = loadFeatureGraphConfig( frame, guiState, defaultConfig ); - frame.getVertexSidePanel().setGraphConfig( config ); + FeatureGraphConfig config = loadFeatureGraphConfig( sidePanel, guiState, defaultConfig ); + sidePanel.setGraphConfig( config ); // Plot with loaded transform and config. - frame.plot( screenTransform ); + if ( plotable != null ) + plotable.plot( screenTransform ); } private static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > void - writeFeatureGraphConfig( final DataDisplayFrame< V, E > frame, final Map< String, Object > guiState ) + writeFeatureGraphConfig( final FeatureGraphConfig config, final Map< String, Object > guiState ) { - FeatureGraphConfig config = frame.getVertexSidePanel().getGraphConfig(); // X-axis feature. FeatureSpecPair featureSpecPairX = config.getXFeature(); guiState.put( GRAPHER_X_AXIS_FEATURE_IS_EDGE_KEY, featureSpecPairX.isEdgeFeature() ); @@ -150,11 +150,12 @@ private GrapherGuiState() guiState.put( GRAPHER_SHOW_EDGES_KEY, config.drawConnected() ); } - private static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > FeatureGraphConfig - loadFeatureGraphConfig( final DataDisplayFrame< V, E > frame, final Map< String, Object > guiState, - final FeatureGraphConfig defaultConfig ) + public static < V extends Vertex< E > & HasTimepoint & HasLabel & Ref< V >, E extends Edge< V > & Ref< E > > FeatureGraphConfig + loadFeatureGraphConfig( + final GrapherSidePanel sidePanel, final Map< String, Object > guiState, + final FeatureGraphConfig defaultConfig + ) { - GrapherSidePanel sidePanel = frame.getVertexSidePanel(); FeatureSpecPair featureSpecPairX = loadFeatureSpecPair( guiState, sidePanel, GRAPHER_X_AXIS_FEATURE_IS_EDGE_KEY, GRAPHER_X_AXIS_FEATURE_SPEC_KEY, GRAPHER_X_AXIS_FEATURE_PROJECTION_KEY, GRAPHER_X_AXIS_INCOMING_EDGE_KEY ); FeatureSpecPair featureSpecPairY = loadFeatureSpecPair( guiState, sidePanel, GRAPHER_Y_AXIS_FEATURE_IS_EDGE_KEY, @@ -165,7 +166,7 @@ private GrapherGuiState() return new FeatureGraphConfig( featureSpecPairX, featureSpecPairY, FeatureGraphConfig.GraphDataItemsSource.CONTEXT, showEdges ); } - private static FeatureSpecPair loadFeatureSpecPair( final Map< String, Object > guiState, final GrapherSidePanel sidePanel, + private static < V extends Vertex< E >, E extends Edge< V > > FeatureSpecPair loadFeatureSpecPair( final Map< String, Object > guiState, final GrapherSidePanel sidePanel, final String edgeKey, final String featureSpecKey, final String projectionKey, final String incomingEdgeKey ) { Boolean isEdgeFeature = ( Boolean ) guiState.get( edgeKey ); diff --git a/src/main/java/org/mastodon/mamut/views/grapher/GrapherInitializer.java b/src/main/java/org/mastodon/mamut/views/grapher/GrapherInitializer.java index 61ca3ce52..a32388f4b 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/GrapherInitializer.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/GrapherInitializer.java @@ -71,6 +71,7 @@ import org.mastodon.ui.coloring.ColorBarOverlay; import org.mastodon.ui.coloring.ColoringModel; import org.mastodon.ui.coloring.GraphColorGeneratorAdapter; +import org.mastodon.ui.commandfinder.CommandFinder; import org.mastodon.views.context.ContextChooser; import org.mastodon.views.grapher.datagraph.DataContextListener; import org.mastodon.views.grapher.datagraph.DataEdge; @@ -275,6 +276,23 @@ void addSearchPanel( final Actions viewActions ) frame.getSettingsPanel().add( searchPanel ); } + void addCommandFinder(final Actions viewActions, final String[] keyConfigContexts) + { + final CommandFinder cf = CommandFinder.build() + .context( appModel.getContext() ) + .inputTriggerConfig( appModel.getKeymap().getConfig() ) + .keyConfigContexts( keyConfigContexts ) + .descriptionProvider( appModel.getWindowManager().getViewFactories().getCommandDescriptions() ) + .register( viewActions ) + .register( appModel.getModelActions() ) + .register( appModel.getProjectActions() ) + .register( appModel.getPlugins().getPluginActions() ) + .modificationListeners( appModel.getKeymap().updateListeners() ) + .parent( frame ) + .installOn( viewActions ); + cf.getDialog().setTitle( cf.getDialog().getTitle() + " - " + frame.getTitle() ); + } + private void registerColoring( final TriFunction< ViewMenuBuilder.JMenuHandle, GraphColorGeneratorAdapter< V, E, DataVertex, DataEdge >, diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapher.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapher.java index 4ab88e809..7120e2b64 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapher.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapher.java @@ -57,7 +57,7 @@ import java.util.function.BiConsumer; public class MamutBranchViewGrapher extends MamutBranchView< DataGraph< BranchSpot, BranchLink >, DataVertex, DataEdge > - implements HasColoringModel, HasColorBarOverlay, DataDisplayFrameSupplier< BranchSpot, BranchLink > + implements HasColoringModel, HasColorBarOverlay { private final GrapherInitializer< BranchSpot, BranchLink > grapherInitializer; @@ -82,6 +82,7 @@ public class MamutBranchViewGrapher extends MamutBranchView< DataGraph< BranchSp setFrame( grapherInitializer.getFrame() ); // this creates viewActions and viewBehaviours thus must be called before installActions grapherInitializer.installActions( viewActions, viewBehaviours ); grapherInitializer.addSearchPanel( viewActions ); + grapherInitializer.addCommandFinder( viewActions, keyConfigContexts ); TriFunction< JMenuHandle, GraphColorGeneratorAdapter< BranchSpot, BranchLink, DataVertex, DataEdge >, DataDisplayPanel< BranchSpot, BranchLink >, ColoringModel > colorModelRegistration = diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java index db0aee0ca..b95fdfa0d 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java @@ -6,13 +6,13 @@ * %% * 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 @@ -31,8 +31,11 @@ import java.util.Map; import org.mastodon.mamut.ProjectModel; +import org.mastodon.mamut.model.branch.BranchLink; +import org.mastodon.mamut.model.branch.BranchSpot; import org.mastodon.mamut.views.AbstractMamutViewFactory; import org.mastodon.mamut.views.MamutViewFactory; +import org.mastodon.views.grapher.display.DataDisplayFrame; import org.scijava.Priority; import org.scijava.plugin.Plugin; @@ -51,7 +54,9 @@ public MamutBranchViewGrapher create( final ProjectModel projectModel ) public Map< String, Object > getGuiState( final MamutBranchViewGrapher view ) { final Map< String, Object > guiState = super.getGuiState( view ); - GrapherGuiState.writeGuiState( view, guiState ); + DataDisplayFrame< BranchSpot, BranchLink > frame = view.getFrame(); + GrapherGuiState.writeGuiState( frame.getDataDisplayPanel().getScreenTransform(), frame.getVertexSidePanel().getGraphConfig(), + guiState ); return guiState; } @@ -59,7 +64,9 @@ public Map< String, Object > getGuiState( final MamutBranchViewGrapher view ) public void restoreGuiState( final MamutBranchViewGrapher view, final Map< String, Object > guiState ) { super.restoreGuiState( view, guiState ); - GrapherGuiState.loadGuiState( view, guiState, MamutBranchViewGrapher.getFeatureGraphConfig() ); + DataDisplayFrame< BranchSpot, BranchLink > frame = view.getFrame(); + GrapherGuiState.loadGuiState( guiState, frame.getDataDisplayPanel().getScreenTransform(), frame.getVertexSidePanel(), + MamutBranchViewGrapher.getFeatureGraphConfig(), view.getFrame() ); } @Override diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java index 6471106a7..14b594c53 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java @@ -59,7 +59,7 @@ import net.imglib2.loops.LoopBuilder; public class MamutViewGrapher extends MamutView< DataGraph< Spot, Link >, DataVertex, DataEdge > - implements HasContextChooser< Spot >, HasColoringModel, HasColorBarOverlay, DataDisplayFrameSupplier< Spot, Link > + implements HasContextChooser< Spot >, HasColoringModel, HasColorBarOverlay { private final GrapherInitializer< Spot, Link > grapherInitializer; @@ -83,6 +83,7 @@ public class MamutViewGrapher extends MamutView< DataGraph< Spot, Link >, DataVe setFrame( grapherInitializer.getFrame() ); // this creates viewActions and viewBehaviours thus must be called before installActions grapherInitializer.installActions( viewActions, viewBehaviours ); grapherInitializer.addSearchPanel( viewActions ); + grapherInitializer.addCommandFinder( viewActions, keyConfigContexts ); final TriFunction< ViewMenuBuilder.JMenuHandle, GraphColorGeneratorAdapter< Spot, Link, DataVertex, DataEdge >, DataDisplayPanel< Spot, Link >, ColoringModel > colorModelRegistration = ( menuHandle, coloringAdaptor, @@ -95,20 +96,6 @@ public class MamutViewGrapher extends MamutView< DataGraph< Spot, Link >, DataVe grapherInitializer.addMenusAndRegisterColors( colorModelRegistration, colorBarRegistration, tagSetMenuRegistration, keyConfigContexts ); grapherInitializer.layout(); - - final CommandFinder cf = CommandFinder.build() - .context( appModel.getContext() ) - .inputTriggerConfig( appModel.getKeymap().getConfig() ) - .keyConfigContexts( keyConfigContexts ) - .descriptionProvider( appModel.getWindowManager().getViewFactories().getCommandDescriptions() ) - .register( viewActions ) - .register( appModel.getModelActions() ) - .register( appModel.getProjectActions() ) - .register( appModel.getPlugins().getPluginActions() ) - .modificationListeners( appModel.getKeymap().updateListeners() ) - .parent( frame ) - .installOn( viewActions ); - cf.getDialog().setTitle( cf.getDialog().getTitle() + " - " + frame.getTitle() ); } static FeatureGraphConfig getFeatureGraphConfig() diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java index 47a945374..e6836fba0 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java @@ -6,13 +6,13 @@ * %% * 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 @@ -31,9 +31,12 @@ import java.util.Map; import org.mastodon.mamut.ProjectModel; +import org.mastodon.mamut.model.Link; +import org.mastodon.mamut.model.Spot; import org.mastodon.mamut.views.AbstractMamutViewFactory; import org.mastodon.mamut.views.MamutViewFactory; import org.mastodon.ui.coloring.ColorBarOverlay.Position; +import org.mastodon.views.grapher.display.DataDisplayFrame; import org.scijava.Priority; import org.scijava.plugin.Plugin; @@ -82,7 +85,9 @@ public MamutViewGrapher create( final ProjectModel projectModel ) public Map< String, Object > getGuiState( final MamutViewGrapher view ) { final Map< String, Object > guiState = super.getGuiState( view ); - GrapherGuiState.writeGuiState( view, guiState ); + DataDisplayFrame< Spot, Link > frame = view.getFrame(); + GrapherGuiState.writeGuiState( frame.getDataDisplayPanel().getScreenTransform(), frame.getVertexSidePanel().getGraphConfig(), + guiState ); return guiState; } @@ -91,7 +96,9 @@ public Map< String, Object > getGuiState( final MamutViewGrapher view ) public void restoreGuiState( final MamutViewGrapher view, final Map< String, Object > guiState ) { super.restoreGuiState( view, guiState ); - GrapherGuiState.loadGuiState( view, guiState, MamutViewGrapher.getFeatureGraphConfig() ); + DataDisplayFrame< Spot, Link > frame = view.getFrame(); + GrapherGuiState.loadGuiState( guiState, frame.getDataDisplayPanel().getScreenTransform(), frame.getVertexSidePanel(), + MamutViewGrapher.getFeatureGraphConfig(), view.getFrame() ); } @Override diff --git a/src/main/java/org/mastodon/views/bdv/overlay/OverlayNavigation.java b/src/main/java/org/mastodon/views/bdv/overlay/OverlayNavigation.java index 073771222..ae4864614 100644 --- a/src/main/java/org/mastodon/views/bdv/overlay/OverlayNavigation.java +++ b/src/main/java/org/mastodon/views/bdv/overlay/OverlayNavigation.java @@ -46,6 +46,10 @@ public class OverlayNavigation< V extends OverlayVertex< V, E >, E extends Overl private NavigationBehaviour< V, E > navigationBehaviour; + private long lastNavigationTime = 0; + + private static final int ANIMATION_DURATION = 300; + public OverlayNavigation( final AbstractViewerPanel panel, final OverlayGraph< V, E > graph ) @@ -82,6 +86,9 @@ public void setNavigationEtiquette( final NavigationEtiquette navigationEtiquett @Override public void navigateToVertex( final V vertex ) { + if (shouldThrottle()) + return; // Throttle navigation requests. + // Always move in T. final int tp = vertex.getTimepoint(); panel.state().setCurrentTimepoint( tp ); @@ -90,17 +97,20 @@ public void navigateToVertex( final V vertex ) final double[] target = navigationBehaviour.navigateToVertex( vertex, currentTransform ); if ( target != null ) { - final TranslationAnimator animator = new TranslationAnimator( currentTransform, target, 300 ); - animator.setTime( System.currentTimeMillis() ); + final TranslationAnimator animator = new TranslationAnimator( currentTransform, target, ANIMATION_DURATION ); + lastNavigationTime = System.currentTimeMillis(); + animator.setTime( lastNavigationTime ); panel.setTransformAnimator( animator ); } - panel.requestRepaint(); } @Override public void navigateToEdge( final E edge ) { + if ( shouldThrottle() ) + return; // Throttle navigation requests. + // Always move in T. final V ref = graph.vertexRef(); final int tp = edge.getTarget( ref ).getTimepoint(); @@ -111,14 +121,21 @@ public void navigateToEdge( final E edge ) final double[] target = navigationBehaviour.navigateToEdge( edge, currentTransform ); if ( target != null ) { - final TranslationAnimator animator = new TranslationAnimator( currentTransform, target, 300 ); - animator.setTime( System.currentTimeMillis() ); + final TranslationAnimator animator = new TranslationAnimator( currentTransform, target, ANIMATION_DURATION ); + lastNavigationTime = System.currentTimeMillis(); + animator.setTime( lastNavigationTime ); panel.setTransformAnimator( animator ); } panel.requestRepaint(); } + private boolean shouldThrottle() + { + final long now = System.currentTimeMillis(); + return ( now - lastNavigationTime < ANIMATION_DURATION ); + } + /* * Navigation behaviours */ diff --git a/src/main/java/org/mastodon/views/grapher/display/DataDisplayFrame.java b/src/main/java/org/mastodon/views/grapher/display/DataDisplayFrame.java index 4ac5060e1..16d98ba38 100644 --- a/src/main/java/org/mastodon/views/grapher/display/DataDisplayFrame.java +++ b/src/main/java/org/mastodon/views/grapher/display/DataDisplayFrame.java @@ -63,13 +63,13 @@ import org.mastodon.views.grapher.datagraph.ScreenTransform; import org.scijava.ui.behaviour.MouseAndKeyHandler; -public class DataDisplayFrame< V extends Vertex< E > & HasTimepoint & HasLabel, E extends Edge< V > > extends ViewFrame +public class DataDisplayFrame< V extends Vertex< E > & HasTimepoint & HasLabel, E extends Edge< V > > extends ViewFrame implements Plotable { private static final long serialVersionUID = 1L; private final DataDisplayPanel< V, E > dataDisplayPanel; - private final GrapherSidePanel sidePanel; + private final GrapherSidePanel sidePanel; private final FeatureModel featureModel; @@ -116,7 +116,7 @@ public DataDisplayFrame( * Side panel. */ - sidePanel = new GrapherSidePanel( nSources, contextChooser ); + sidePanel = new GrapherSidePanel<>( nSources, contextChooser ); sidePanel.getBtnPlot().addActionListener( e -> plot( false ) ); final FeatureModelListener featureModelListener = () -> sidePanel.setFeatures( @@ -183,7 +183,7 @@ public DataDisplayPanel< V, E > getDataDisplayPanel() return dataDisplayPanel; } - public GrapherSidePanel getVertexSidePanel() + public GrapherSidePanel getVertexSidePanel() { return sidePanel; } @@ -194,8 +194,10 @@ public GrapherSidePanel getVertexSidePanel() */ public void plot( boolean keepCurrentScreenTransform ) { - dataDisplayPanel.plot( sidePanel.getGraphConfig(), featureModel, - keepCurrentScreenTransform ? dataDisplayPanel.getScreenTransform().get() : null ); + if ( keepCurrentScreenTransform ) + plot( dataDisplayPanel.getScreenTransform().get() ); + else + plot( null ); } public void plot( final ScreenTransform transform ) diff --git a/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java b/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java index af6ff2f1f..5e5440aeb 100644 --- a/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java +++ b/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java @@ -56,6 +56,8 @@ import org.mastodon.feature.FeatureProjectionSpec; import org.mastodon.feature.FeatureSpec; import org.mastodon.feature.Multiplicity; +import org.mastodon.graph.Edge; +import org.mastodon.graph.Vertex; import org.mastodon.graph.io.RawGraphIO.FileIdToGraphMap; import org.mastodon.mamut.feature.MamutRawFeatureModelIO; import org.mastodon.mamut.io.project.MamutProject; @@ -68,16 +70,17 @@ import org.mastodon.ui.util.EverythingDisablerAndReenabler; import org.mastodon.util.FeatureUtils; import org.mastodon.views.context.ContextChooser; +import org.mastodon.views.context.HasContextChooser; import org.mastodon.views.grapher.display.FeatureGraphConfig.GraphDataItemsSource; import org.scijava.Context; /** * Panel that lets the user specifies what to plot. The user specifications are * bundled as a {@link FeatureGraphConfig} object. - * + * * @author Jean-Yves Tinevez */ -public class GrapherSidePanel extends JPanel +public class GrapherSidePanel< V extends Vertex< E >, E extends Edge< V > > extends JPanel implements HasContextChooser< V > { private static final long serialVersionUID = 1L; @@ -102,10 +105,13 @@ public class GrapherSidePanel extends JPanel private final JButton btnPlot; - public GrapherSidePanel( final int nSources, final ContextChooser< ? > contextChooser ) + private final ContextChooser< V > contextChooser; + + public GrapherSidePanel( final int nSources, final ContextChooser< V > contextChooser ) { this.nSources = nSources; this.specs = new ArrayList<>(); + this.contextChooser = contextChooser; final GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[] { 150, 0 }; @@ -261,7 +267,7 @@ public GrapherSidePanel( final int nSources, final ContextChooser< ? > contextCh /** * Exposes the plot button of this panel. - * + * * @return the plot button. */ public JButton getBtnPlot() @@ -430,6 +436,11 @@ public FeatureProjectionSpec getFeatureProjectionSpec( final String projectionKe return null; } + public ContextChooser< V > getContextChooser() + { + return this.contextChooser; + } + private static final FeatureModel demoFM() { final Model model = new Model(); @@ -463,7 +474,7 @@ public static void main( final String[] args ) throws ClassNotFoundException, In FeatureUtils.collectFeatureMap( fm, Spot.class ); final Map< FeatureSpec< ?, Link >, Feature< Link > > linkFeatures = FeatureUtils.collectFeatureMap( fm, Link.class ); - final GrapherSidePanel gsp = new GrapherSidePanel( 2, new ContextChooser<>( null ) ); + final GrapherSidePanel gsp = new GrapherSidePanel( 2, new ContextChooser<>( null ) ); gsp.setFeatures( spotFeatures, linkFeatures ); final JFrame frame = new JFrame( "Grapher side panel" ); diff --git a/src/main/java/org/mastodon/views/grapher/display/Plotable.java b/src/main/java/org/mastodon/views/grapher/display/Plotable.java new file mode 100644 index 000000000..a23073969 --- /dev/null +++ b/src/main/java/org/mastodon/views/grapher/display/Plotable.java @@ -0,0 +1,10 @@ +package org.mastodon.views.grapher.display; + +import org.mastodon.views.grapher.datagraph.ScreenTransform; + +public interface Plotable +{ + void plot( final ScreenTransform screenTransform ); + + void plot( final boolean keepCurrentScreenTransform ); +} From 49fe757a19af1e94508efc9d08a377675a8882fe Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:53:21 +0200 Subject: [PATCH 07/13] Update parent pom to pom-scijava v42.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4db071598..e0662434e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.scijava pom-scijava - 40.0.0 + 42.0.0 org.mastodon From c3955a406ebf87226c66d7cd2d7528a01240008c Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:53:52 +0200 Subject: [PATCH 08/13] Fix compile errors with new N5 version. --- .../util/mobie/OmeZarrMultiscalesAdapter.java | 1 - .../mamut/launcher/NewFromUrlPanel.java | 29 +++++++------------ 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/mastodon/mamut/io/loader/util/mobie/OmeZarrMultiscalesAdapter.java b/src/main/java/org/mastodon/mamut/io/loader/util/mobie/OmeZarrMultiscalesAdapter.java index 3cb0fcd26..91fd7b11c 100644 --- a/src/main/java/org/mastodon/mamut/io/loader/util/mobie/OmeZarrMultiscalesAdapter.java +++ b/src/main/java/org/mastodon/mamut/io/loader/util/mobie/OmeZarrMultiscalesAdapter.java @@ -45,7 +45,6 @@ public class OmeZarrMultiscalesAdapter implements JsonDeserializer< OmeZarrMultiscales >, JsonSerializer< OmeZarrMultiscales > { - @SuppressWarnings( "serial" ) @Override public OmeZarrMultiscales deserialize( final JsonElement json, final Type typeOfT, final JsonDeserializationContext context ) throws JsonParseException { diff --git a/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java b/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java index f99b6a26c..0a1a1f52b 100644 --- a/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java +++ b/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java @@ -6,13 +6,13 @@ * %% * 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 @@ -66,7 +66,7 @@ import org.janelia.saalfeldlab.n5.metadata.N5ViewerMultichannelMetadata; import org.janelia.saalfeldlab.n5.ui.DatasetSelectorDialog; import org.janelia.saalfeldlab.n5.universe.N5Factory; -import org.janelia.saalfeldlab.n5.universe.N5Factory.StorageFormat; +import org.janelia.saalfeldlab.n5.universe.StorageFormat; import org.janelia.saalfeldlab.n5.universe.metadata.MultiscaleMetadata; import org.janelia.saalfeldlab.n5.universe.metadata.N5Metadata; import org.janelia.saalfeldlab.n5.universe.metadata.N5SingleScaleMetadata; @@ -404,21 +404,14 @@ public N5Reader apply( final String n5UriOrPath ) String rootPath = null; if ( n5UriOrPath.contains( "?" ) ) { - try - { - // need to strip off storage format for n5uri to correctly - // remove query; - final Pair< StorageFormat, URI > fmtUri = N5Factory.StorageFormat.parseUri( n5UriOrPath ); - final StorageFormat format = fmtUri.getA(); - - final N5URI n5uri = new N5URI( URI.create( fmtUri.getB().toString() ) ); - // add the format prefix back if it was present - rootPath = format == null ? n5uri.getContainerPath() : format.toString().toLowerCase() + ":" + n5uri.getContainerPath(); - } - catch ( final URISyntaxException e ) - { - messenger.accept( "The URI is not valid or credentials are missing: " + n5UriOrPath ); - } + // need to strip off storage format for n5uri to correctly + // remove query; + final Pair< StorageFormat, URI > fmtUri = StorageFormat.parseUri( n5UriOrPath ); + final StorageFormat format = fmtUri.getA(); + + final N5URI n5uri = new N5URI( URI.create( fmtUri.getB().toString() ) ); + // add the format prefix back if it was present + rootPath = format == null ? n5uri.getContainerPath() : format.toString().toLowerCase() + ":" + n5uri.getContainerPath(); } if ( rootPath == null ) From 517f0942be238197861f5dab8c2ec72c4afad1fe Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:54:23 +0200 Subject: [PATCH 09/13] Fix minor warnings. --- .../mamut/views/grapher/MamutViewGrapher.java | 1 - .../views/grapher/display/GrapherSidePanel.java | 7 ++++--- .../graph/revised/CreateLargeModelExample.java | 15 +++++---------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java index 14b594c53..9c992e3ed 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapher.java @@ -43,7 +43,6 @@ import org.mastodon.ui.coloring.GraphColorGeneratorAdapter; import org.mastodon.ui.coloring.HasColorBarOverlay; import org.mastodon.ui.coloring.HasColoringModel; -import org.mastodon.ui.commandfinder.CommandFinder; import org.mastodon.ui.keymap.KeyConfigContexts; import org.mastodon.views.context.ContextChooser; import org.mastodon.views.context.HasContextChooser; diff --git a/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java b/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java index 5e5440aeb..6e91e0407 100644 --- a/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java +++ b/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java @@ -6,13 +6,13 @@ * %% * 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 @@ -275,7 +275,7 @@ public JButton getBtnPlot() return btnPlot; } - public < V, E > void setFeatures( + public void setFeatures( final Map< FeatureSpec< ?, V >, Feature< V > > vertexFeatures, final Map< FeatureSpec< ?, E >, Feature< E > > edgeFeatures ) { @@ -436,6 +436,7 @@ public FeatureProjectionSpec getFeatureProjectionSpec( final String projectionKe return null; } + @Override public ContextChooser< V > getContextChooser() { return this.contextChooser; diff --git a/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java b/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java index c223ad4c0..b56967942 100644 --- a/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java +++ b/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java @@ -30,15 +30,10 @@ import java.io.IOException; -import org.mastodon.mamut.ProjectModel; -import org.mastodon.mamut.WindowManager; import org.mastodon.mamut.io.importer.ModelImporter; -import org.mastodon.mamut.io.project.MamutProject; import org.mastodon.mamut.model.Link; import org.mastodon.mamut.model.Model; import org.mastodon.mamut.model.Spot; -import org.mastodon.views.bdv.SharedBigDataViewerData; -import org.scijava.Context; public class CreateLargeModelExample { @@ -184,11 +179,11 @@ public static void main( final String[] args ) throws IOException ( Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() ) / 1e6d ) ); - final Context context = new Context(); - final SharedBigDataViewerData imagedata = SharedBigDataViewerData.fromDummyFilename( "x=1000 y=1000 z=100 sx=1 sy=1 sz=10 t=400.dummy" ); - final MamutProject project = new MamutProject( "./large_model_example.mastodon" ); - final ProjectModel appModel = ProjectModel.create( context, model, imagedata, project ); - final WindowManager wm = new WindowManager( appModel ); +// final Context context = new Context(); +// final SharedBigDataViewerData imagedata = SharedBigDataViewerData.fromDummyFilename( "x=1000 y=1000 z=100 sx=1 sy=1 sz=10 t=400.dummy" ); +// final MamutProject project = new MamutProject( "./large_model_example.mastodon" ); +// final ProjectModel appModel = ProjectModel.create( context, model, imagedata, project ); +// final WindowManager wm = new WindowManager( appModel ); // start = System.currentTimeMillis(); // wm.createBigDataViewer(); From bb861f4bfbb415bff70caab26700e39ead2ed29f Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:54:33 +0200 Subject: [PATCH 10/13] Update test drive path. --- .../java/org/mastodon/StartMastodonDefaultProject.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/mastodon/StartMastodonDefaultProject.java b/src/test/java/org/mastodon/StartMastodonDefaultProject.java index 541b7a434..971b91da0 100644 --- a/src/test/java/org/mastodon/StartMastodonDefaultProject.java +++ b/src/test/java/org/mastodon/StartMastodonDefaultProject.java @@ -6,13 +6,13 @@ * %% * 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 @@ -34,8 +34,8 @@ public class StartMastodonDefaultProject public static void main( final String[] args ) { // final String projectPath = "samples/MaMuT_Parhyale_small.mastodon"; -// final String projectPath = "/Users/tinevez/Google Drive/Mastodon/Datasets/Remote/ParhyaleHawaiensis/MaMuT_Parhyale_demo-mamut.mastodon"; - final String projectPath = "samples/drosophila_crop_LONG_NAME_LONGLONGLONG_SUPERLONG.mastodon"; + final String projectPath = "/Users/tinevez/Library/CloudStorage/GoogleDrive-jeanyves.tinevez@gmail.com/My Drive/Mastodon/Datasets/Remote/BDV/Tribolium/CTC_TRIF_trainingVideo02_jy-GT-done.mastodon"; +// final String projectPath = "samples/drosophila_crop_LONG_NAME_LONGLONGLONG_SUPERLONG.mastodon"; // final String projectPath = "samples/drosophila_crop.mastodon"; StartMastodonOnProject.launch( projectPath ); } From 6ed9ea6ee6f4d4b6f732c014c7cc74b2cb8b5580 Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:56:14 +0200 Subject: [PATCH 11/13] Repository to store script examples. --- scripts/MastodonScriptExample.py | 77 ++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100755 scripts/MastodonScriptExample.py diff --git a/scripts/MastodonScriptExample.py b/scripts/MastodonScriptExample.py new file mode 100755 index 000000000..93728377b --- /dev/null +++ b/scripts/MastodonScriptExample.py @@ -0,0 +1,77 @@ +#@ Context context + +from java.io import File + +from org.mastodon.mamut import WindowManager +from org.mastodon.mamut.project import MamutProject +from org.mastodon.tracking.mamut.trackmate import TrackMate +from org.mastodon.tracking.mamut.trackmate import Settings +from org.mastodon.tracking.mamut.detection import DoGDetectorMamut +from org.mastodon.tracking.mamut.linking import SimpleSparseLAPLinkerMamut +from org.mastodon.tracking.linking import LinkingUtils + +bdv_file = "/Users/tinevez/Development/Mastodon/mastodon/samples/datasethdf5.xml" +project = MamutProject( None, File( bdv_file ) ); + +# Open the project. +wm = WindowManager( context ) +wm.getProjectManager().open( project ) +app_model = wm.getAppModel() + +# Get Mastodon model. +model = app_model.getModel() +selection_model = app_model.getSelectionModel() + +# Get image data. +image_data = app_model.getSharedBdvData() + +# Configure TrackMate. + +# Detector settings. +detector_settings = { + "MIN_TIMEPOINT" : 0, + "MAX_TIMEPOINT" : 1000, + "SETUP" : 0, # The channel or source in the BDV data. + "RADIUS" : 7., # The cell expected radius. + "THRESHOLD" : 200. # Threshold on quality. +} + +# Linker settings. There are too many, so we take the default and edit it. +linker_settings = LinkingUtils.getDefaultLAPSettingsMap() +linker_settings[ "MIN_TIMEPOINT" ] = 0 +linker_settings[ "MAX_TIMEPOINT" ] = 1000 +linker_settings[ "LINKING_MAX_DISTANCE" ] = 10. +linker_settings[ "ALLOW_GAP_CLOSING" ] = True +linker_settings[ "MAX_FRAME_GAP" ] = 2 + +# Create the settings objects. +settings = Settings() \ + .sources( image_data.getSources() ) \ + .detector( DoGDetectorMamut ) \ + .detectorSettings( detector_settings ) \ + .linker( SimpleSparseLAPLinkerMamut ) \ + .linkerSettings( linker_settings ) + +trackmate = TrackMate( settings, model, selection_model ) + +# We need to give a context to TrackMate. +trackmate.setContext( context ) + +# Run TrackMate. +trackmate.run() +if trackmate.isCanceled(): + print( "Calculation was canceled. Reason: " + trackmate.getCancelReason() ) +elif not trackmate.isSuccessful(): + print( "Calculation failed with error message:\n" + trackmate.getErrorMessage() ) +else: + print( "Calculation complete." ); + +wm.createTrackScheme() +wm.createBigDataViewer() + +# Compute features. + + + + +wm.createTable( False ) From d9bb718f0c550def6951fc732b1bb0e96e19bd4b Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:57:06 +0200 Subject: [PATCH 12/13] Update license blurbs --- .../CommonTrackMateFeatureDeclarations.java | 28 +++++++++++++++++++ .../mamut/launcher/NewFromUrlPanel.java | 4 +-- .../mamut/views/grapher/GrapherGuiState.java | 4 +-- .../MamutBranchViewGrapherFactory.java | 4 +-- .../grapher/MamutViewGrapherFactory.java | 4 +-- .../grapher/display/GrapherSidePanel.java | 4 +-- .../views/grapher/display/Plotable.java | 28 +++++++++++++++++++ .../mastodon/StartMastodonDefaultProject.java | 4 +-- .../revised/CreateLargeModelExample.java | 4 +-- 9 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java b/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java index 5aac6f5cc..b2dcb5389 100644 --- a/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java +++ b/src/main/java/org/mastodon/mamut/io/importer/trackmate/CommonTrackMateFeatureDeclarations.java @@ -1,3 +1,31 @@ +/*- + * #%L + * Mastodon + * %% + * Copyright (C) 2014 - 2025 Tobias Pietzsch, Jean-Yves Tinevez + * %% + * 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.mastodon.mamut.io.importer.trackmate; import static org.mastodon.mamut.io.importer.trackmate.TrackMateXMLKeys.FEATURE_ATTRIBUTE; diff --git a/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java b/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java index 0a1a1f52b..2e265716c 100644 --- a/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java +++ b/src/main/java/org/mastodon/mamut/launcher/NewFromUrlPanel.java @@ -6,13 +6,13 @@ * %% * 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 diff --git a/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java b/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java index 9fd0a3bf8..d6af79d9e 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java @@ -6,13 +6,13 @@ * %% * 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 diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java index b95fdfa0d..591a3028f 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutBranchViewGrapherFactory.java @@ -6,13 +6,13 @@ * %% * 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 diff --git a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java index e6836fba0..9aefbcc63 100644 --- a/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java +++ b/src/main/java/org/mastodon/mamut/views/grapher/MamutViewGrapherFactory.java @@ -6,13 +6,13 @@ * %% * 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 diff --git a/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java b/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java index 6e91e0407..5ce4158b6 100644 --- a/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java +++ b/src/main/java/org/mastodon/views/grapher/display/GrapherSidePanel.java @@ -6,13 +6,13 @@ * %% * 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 diff --git a/src/main/java/org/mastodon/views/grapher/display/Plotable.java b/src/main/java/org/mastodon/views/grapher/display/Plotable.java index a23073969..f77780cb4 100644 --- a/src/main/java/org/mastodon/views/grapher/display/Plotable.java +++ b/src/main/java/org/mastodon/views/grapher/display/Plotable.java @@ -1,3 +1,31 @@ +/*- + * #%L + * Mastodon + * %% + * Copyright (C) 2014 - 2025 Tobias Pietzsch, Jean-Yves Tinevez + * %% + * 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.mastodon.views.grapher.display; import org.mastodon.views.grapher.datagraph.ScreenTransform; diff --git a/src/test/java/org/mastodon/StartMastodonDefaultProject.java b/src/test/java/org/mastodon/StartMastodonDefaultProject.java index 971b91da0..27b92cacd 100644 --- a/src/test/java/org/mastodon/StartMastodonDefaultProject.java +++ b/src/test/java/org/mastodon/StartMastodonDefaultProject.java @@ -6,13 +6,13 @@ * %% * 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 diff --git a/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java b/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java index b56967942..358d35f55 100644 --- a/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java +++ b/src/test/java/org/mastodon/graph/revised/CreateLargeModelExample.java @@ -6,13 +6,13 @@ * %% * 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 From f0b7564f26cb9fcb5ef11e8ca131fbca6c111a6b Mon Sep 17 00:00:00 2001 From: Jean-Yves TINEVEZ Date: Mon, 8 Sep 2025 16:59:10 +0200 Subject: [PATCH 13/13] Bump to next development cycle Signed-off-by: Jean-Yves TINEVEZ --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e0662434e..12f04e6bc 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.mastodon mastodon - 1.0.0-beta-35-SNAPSHOT + 1.0.0-beta-36-SNAPSHOT Mastodon Mastodon – a large-scale tracking and track-editing framework for large, multi-view images.