Skip to content

Commit

Permalink
Add serialization of the GUI state of the grapher views
Browse files Browse the repository at this point in the history
The following things are restored additionally the window size+position
* Selected X-Axis Feature + Projection
* Selected Y-Axis Feature + Projection
* The ScreenTransform that was used during saving the project
* Whether or not to connect edges

The context chosen by the user can unfortunately not be restored, since the BDV View Windows have no unique ID. However, this is consistent to other views (e.g. TrackScheme), where the context can also not be restored.
  • Loading branch information
stefanhahmann authored and tinevez committed Nov 7, 2024
1 parent 629acdf commit e722e4d
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@
import static org.mastodon.mamut.views.MamutViewFactory.VIEW_TYPE_KEY;
import static org.mastodon.mamut.views.bdv.MamutViewBdvFactory.BDV_STATE_KEY;
import static org.mastodon.mamut.views.bdv.MamutViewBdvFactory.BDV_TRANSFORM_KEY;
import static org.mastodon.mamut.views.grapher.MamutViewGrapherFactory.GRAPHER_TRANSFORM_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_TRANSFORM_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_X_AXIS_FEATURE_IS_EDGE_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_X_AXIS_FEATURE_SPEC_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_X_AXIS_INCOMING_EDGE_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_X_AXIS_FEATURE_PROJECTION_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_SHOW_EDGES_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_Y_AXIS_FEATURE_IS_EDGE_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_Y_AXIS_FEATURE_SPEC_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_Y_AXIS_INCOMING_EDGE_KEY;
import static org.mastodon.mamut.views.grapher.GrapherGuiState.GRAPHER_Y_AXIS_FEATURE_PROJECTION_KEY;
import static org.mastodon.mamut.views.table.MamutViewTableFactory.TABLE_DISPLAYED;
import static org.mastodon.mamut.views.table.MamutViewTableFactory.TABLE_ELEMENT;
import static org.mastodon.mamut.views.table.MamutViewTableFactory.TABLE_NAME;
Expand Down Expand Up @@ -247,6 +256,10 @@ private static Map< String, Object > xmlToMap( final Element viewEl )
case FEATURE_COLOR_MODE_KEY:
case VIEW_TYPE_KEY:
case CHOSEN_CONTEXT_PROVIDER_KEY:
case GRAPHER_X_AXIS_FEATURE_SPEC_KEY:
case GRAPHER_X_AXIS_FEATURE_PROJECTION_KEY:
case GRAPHER_Y_AXIS_FEATURE_SPEC_KEY:
case GRAPHER_Y_AXIS_FEATURE_PROJECTION_KEY:
value = el.getTextTrim();
break;
case TRACKSCHEME_TRANSFORM_KEY:
Expand All @@ -266,6 +279,11 @@ private static Map< String, Object > xmlToMap( final Element viewEl )
case NO_COLORING_KEY:
case SETTINGS_PANEL_VISIBLE_KEY:
case COLORBAR_VISIBLE_KEY:
case GRAPHER_SHOW_EDGES_KEY:
case GRAPHER_X_AXIS_FEATURE_IS_EDGE_KEY:
case GRAPHER_X_AXIS_INCOMING_EDGE_KEY:
case GRAPHER_Y_AXIS_FEATURE_IS_EDGE_KEY:
case GRAPHER_Y_AXIS_INCOMING_EDGE_KEY:
case TRACK_COLORING_KEY:
value = XmlHelpers.getBoolean( viewEl, key );
break;
Expand Down
153 changes: 153 additions & 0 deletions src/main/java/org/mastodon/mamut/views/grapher/GrapherGuiState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package org.mastodon.mamut.views.grapher;

import java.util.Map;

import org.mastodon.Ref;
import org.mastodon.feature.FeatureProjectionSpec;
import org.mastodon.feature.FeatureSpec;
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.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;

public class GrapherGuiState
{
private GrapherGuiState()
{
// Prevent instantiation.
}

/**
* Key for the transform in a Grapher view. Value is a Grapher ScreenTransform instance.
*/
public static final String GRAPHER_TRANSFORM_KEY = "GrapherTransform";

/**
* Key for the selected feature for the X axis in a Grapher view. Value is a Boolean.
*/
public static final String GRAPHER_X_AXIS_FEATURE_IS_EDGE_KEY = "GrapherXAxisFeatureIsEdge";

/**
* Key for the selected feature spec for the X axis in a Grapher view. Value is a string.
*/
public static final String GRAPHER_X_AXIS_FEATURE_SPEC_KEY = "GrapherXAxisFeatureSpec";

/**
* Key for the selected projection for the X axis in a Grapher view. Value is a string.
*/
public static final String GRAPHER_X_AXIS_FEATURE_PROJECTION_KEY = "GrapherXAxisFeatureProjection";

/**
* Key for the selected incoming edge for the X axis in a Grapher view. Value is a boolean.
*/
public static final String GRAPHER_X_AXIS_INCOMING_EDGE_KEY = "GrapherXAxisFeatureIsIncomingEdge";

/**
* Key for the selected feature for the Y axis in a Grapher view. Value is a Boolean.
*/
public static final String GRAPHER_Y_AXIS_FEATURE_IS_EDGE_KEY = "GrapherYAxisFeatureIsEdge";

/**
* Key for the selected feature spec for the Y axis in a Grapher view. Value is a string.
*/
public static final String GRAPHER_Y_AXIS_FEATURE_SPEC_KEY = "GrapherYAxisFeatureSpec";

/**
* Key for the selected projection for the Y axis in a Grapher view. Value is a string.
*/
public static final String GRAPHER_Y_AXIS_FEATURE_PROJECTION_KEY = "GrapherYAxisFeatureProjection";

/**
* Key for the selected incoming edge for the Y axis in a Grapher view. Value is a boolean.
*/
public static final String GRAPHER_Y_AXIS_INCOMING_EDGE_KEY = "GrapherYAxisFeatureIsIncomingEdge";

/**
* Key for whether show edges is checked in a Grapher view. Value is a boolean.
*/
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 )
{
DataDisplayFrame< V, E > frame = frameProvider.getFrame();
// Transform.
final ScreenTransform transform = frame.getDataDisplayPanel().getScreenTransform().get();
guiState.put( GRAPHER_TRANSFORM_KEY, transform );
// Feature graph config.
writeFeatureGraphConfig( frame, 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 )
{
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 );

// Read Feature graph config.
FeatureGraphConfig config = loadFeatureGraphConfig( frame, guiState, defaultConfig );
frame.getVertexSidePanel().setGraphConfig( config );

// Plot with loaded transform and config.
frame.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 )
{
FeatureGraphConfig config = frame.getVertexSidePanel().getGraphConfig();
// X-axis feature.
FeatureSpecPair featureSpecPairX = config.getXFeature();
guiState.put( GRAPHER_X_AXIS_FEATURE_IS_EDGE_KEY, featureSpecPairX.isEdgeFeature() );
guiState.put( GRAPHER_X_AXIS_FEATURE_SPEC_KEY, featureSpecPairX.getFeatureSpecKey() );
guiState.put( GRAPHER_X_AXIS_FEATURE_PROJECTION_KEY, featureSpecPairX.projectionKey().toString() );
guiState.put( GRAPHER_X_AXIS_INCOMING_EDGE_KEY, featureSpecPairX.isIncomingEdge() );
// Y-axis feature.
FeatureSpecPair featureSpecPairY = config.getYFeature();
guiState.put( GRAPHER_Y_AXIS_FEATURE_IS_EDGE_KEY, featureSpecPairY.isEdgeFeature() );
guiState.put( GRAPHER_Y_AXIS_FEATURE_SPEC_KEY, featureSpecPairY.getFeatureSpecKey() );
guiState.put( GRAPHER_Y_AXIS_FEATURE_PROJECTION_KEY, featureSpecPairY.projectionKey().toString() );
guiState.put( GRAPHER_Y_AXIS_INCOMING_EDGE_KEY, featureSpecPairY.isIncomingEdge() );
// Show edges.
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 )
{
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,
GRAPHER_Y_AXIS_FEATURE_SPEC_KEY, GRAPHER_Y_AXIS_FEATURE_PROJECTION_KEY, GRAPHER_Y_AXIS_INCOMING_EDGE_KEY );
Boolean showEdges = ( Boolean ) guiState.get( GRAPHER_SHOW_EDGES_KEY );
if ( featureSpecPairX == null || featureSpecPairY == null || showEdges == null )
return defaultConfig;
return new FeatureGraphConfig( featureSpecPairX, featureSpecPairY, FeatureGraphConfig.GraphDataItemsSource.CONTEXT, showEdges );
}

private static 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 );
final String yFeatureSpecKey = ( String ) guiState.get( featureSpecKey );
final String yProjectionKey = ( String ) guiState.get( projectionKey );
Boolean incomingEdge = ( Boolean ) guiState.get( incomingEdgeKey );
FeatureSpec< ?, ? > featureSpec = sidePanel.getFeatureSpec( yFeatureSpecKey );
FeatureProjectionSpec projectionSpec = sidePanel.getFeatureProjectionSpec( yProjectionKey );
if ( isEdgeFeature == null || featureSpec == null || projectionSpec == null || incomingEdge == null )
return null;
return new FeatureSpecPair( featureSpec, projectionSpec, isEdgeFeature, incomingEdge );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
*/
package org.mastodon.mamut.views.grapher;

import java.util.Map;

import org.mastodon.mamut.ProjectModel;
import org.mastodon.mamut.views.AbstractMamutViewFactory;
import org.mastodon.mamut.views.MamutViewFactory;
Expand All @@ -45,6 +47,21 @@ public MamutBranchViewGrapher create( final ProjectModel projectModel )
return new MamutBranchViewGrapher( projectModel );
}

@Override
public Map< String, Object > getGuiState( final MamutBranchViewGrapher view )
{
final Map< String, Object > guiState = super.getGuiState( view );
GrapherGuiState.writeGuiState( view, guiState );
return guiState;
}

@Override
public void restoreGuiState( final MamutBranchViewGrapher view, final Map< String, Object > guiState )
{
super.restoreGuiState( view, guiState );
GrapherGuiState.loadGuiState( view, guiState, MamutBranchViewGrapher.getFeatureGraphConfig() );
}

@Override
public String getCommandName()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.mastodon.mamut.views.AbstractMamutViewFactory;
import org.mastodon.mamut.views.MamutViewFactory;
import org.mastodon.ui.coloring.ColorBarOverlay.Position;
import org.mastodon.views.grapher.datagraph.ScreenTransform;
import org.scijava.Priority;
import org.scijava.plugin.Plugin;

Expand Down Expand Up @@ -73,12 +72,6 @@ public class MamutViewGrapherFactory extends AbstractMamutViewFactory< MamutView

public static final String NEW_GRAPHER_VIEW = "new grapher view";

/**
* Key for the transform in a Grapher view. Value is a Grapher
* ScreenTransform instance.
*/
public static final String GRAPHER_TRANSFORM_KEY = "GrapherTransform";

@Override
public MamutViewGrapher create( final ProjectModel projectModel )
{
Expand All @@ -89,10 +82,7 @@ public MamutViewGrapher create( final ProjectModel projectModel )
public Map< String, Object > getGuiState( final MamutViewGrapher view )
{
final Map< String, Object > guiState = super.getGuiState( view );
// Transform.
final ScreenTransform t = view.getFrame().getDataDisplayPanel().getScreenTransform().get();
guiState.put( GRAPHER_TRANSFORM_KEY, t );

GrapherGuiState.writeGuiState( view, guiState );
return guiState;
}

Expand All @@ -101,11 +91,7 @@ public Map< String, Object > getGuiState( final MamutViewGrapher view )
public void restoreGuiState( final MamutViewGrapher view, final Map< String, Object > guiState )
{
super.restoreGuiState( view, guiState );

// Transform.
final ScreenTransform tLoaded = ( ScreenTransform ) guiState.get( GRAPHER_TRANSFORM_KEY );
if ( null != tLoaded )
view.getFrame().getDataDisplayPanel().getScreenTransform().set( tLoaded );
GrapherGuiState.loadGuiState( view, guiState, MamutViewGrapher.getFeatureGraphConfig() );
}

@Override
Expand Down

0 comments on commit e722e4d

Please sign in to comment.