From 1d34f8f253b55c8a66f0d2074ad636cba61f66e8 Mon Sep 17 00:00:00 2001 From: Stephan Preibisch Date: Sat, 19 Oct 2024 11:22:06 -0400 Subject: [PATCH] analyze error popup now also highlights the two worst views --- .../mvrecon/fiji/plugin/Analyze_Errors.java | 12 +- .../FilteredAndGroupedExplorerPanel.java | 2 +- .../explorer/ViewSetupExplorerPanel.java | 4 +- .../explorer/popup/AnalyzeErrorPopup.java | 162 ++++++++++++++++++ 4 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/popup/AnalyzeErrorPopup.java diff --git a/src/main/java/net/preibisch/mvrecon/fiji/plugin/Analyze_Errors.java b/src/main/java/net/preibisch/mvrecon/fiji/plugin/Analyze_Errors.java index 887267b7..d058ef4c 100644 --- a/src/main/java/net/preibisch/mvrecon/fiji/plugin/Analyze_Errors.java +++ b/src/main/java/net/preibisch/mvrecon/fiji/plugin/Analyze_Errors.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import ij.ImageJ; import ij.gui.GenericDialog; @@ -97,13 +98,14 @@ public static ArrayList< Pair< Pair< ViewId, ViewId >, Double > > getErrors( viewIds.parallelStream().forEach( viewId -> { final ViewInterestPointLists vip = data.getViewInterestPoints().getViewInterestPointLists( viewId ); - labelAndWeights.forEach( (l,w) -> { - if ( vip.getInterestPointList( l ) != null ) + for ( final Entry e : labelAndWeights.entrySet() ) + { + if ( vip.getInterestPointList( e.getKey() ) != null ) { - vip.getInterestPointList( l ).getInterestPointsCopy(); - vip.getInterestPointList( l ).getCorrespondingInterestPointsCopy(); + vip.getInterestPointList( e.getKey() ).getInterestPointsCopy(); + vip.getInterestPointList( e.getKey() ).getCorrespondingInterestPointsCopy(); } - }); + } }); // go over all pairs of tiles and compute the error in parallel diff --git a/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/FilteredAndGroupedExplorerPanel.java b/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/FilteredAndGroupedExplorerPanel.java index 1c0a5e9a..a5df080e 100644 --- a/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/FilteredAndGroupedExplorerPanel.java +++ b/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/FilteredAndGroupedExplorerPanel.java @@ -99,7 +99,7 @@ public abstract class FilteredAndGroupedExplorerPanel< AS extends SpimData2 > public JLabel xmlLabel; - final protected HashSet< List< BasicViewDescription< ? > > > selectedRows; + final public HashSet< List< BasicViewDescription< ? > > > selectedRows; protected BasicViewDescription< ? > firstSelectedVD; public FilteredAndGroupedExplorerPanel(final FilteredAndGroupedExplorer< AS > explorer, final AS data, final URI xml, final XmlIoSpimData2 io) diff --git a/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/ViewSetupExplorerPanel.java b/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/ViewSetupExplorerPanel.java index c3daf1a2..3c47fd71 100644 --- a/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/ViewSetupExplorerPanel.java +++ b/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/ViewSetupExplorerPanel.java @@ -126,8 +126,8 @@ public class ViewSetupExplorerPanel< AS extends SpimData2 > extends FilteredAndG IOFunctions.printIJLog = true; } - protected JCheckBox groupTilesCheckbox; - protected JCheckBox groupIllumsCheckbox; + public JCheckBox groupTilesCheckbox; + public JCheckBox groupIllumsCheckbox; private static long colorOffset = 0; @Override diff --git a/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/popup/AnalyzeErrorPopup.java b/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/popup/AnalyzeErrorPopup.java new file mode 100644 index 00000000..c9ac0849 --- /dev/null +++ b/src/main/java/net/preibisch/mvrecon/fiji/spimdata/explorer/popup/AnalyzeErrorPopup.java @@ -0,0 +1,162 @@ +/*- + * #%L + * Software for the reconstruction of multi-view microscopic acquisitions + * like Selective Plane Illumination Microscopy (SPIM) Data. + * %% + * Copyright (C) 2012 - 2024 Multiview Reconstruction developers. + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +package net.preibisch.mvrecon.fiji.spimdata.explorer.popup; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import javax.swing.JMenuItem; + +import mpicbg.spim.data.generic.sequence.BasicViewDescription; +import mpicbg.spim.data.sequence.ViewId; +import net.imglib2.multithreading.SimpleMultiThreading; +import net.imglib2.util.Pair; +import net.preibisch.legacy.io.IOFunctions; +import net.preibisch.mvrecon.fiji.plugin.Analyze_Errors; +import net.preibisch.mvrecon.fiji.spimdata.explorer.ExplorerWindow; +import net.preibisch.mvrecon.fiji.spimdata.explorer.ViewSetupExplorerPanel; +import net.preibisch.mvrecon.fiji.spimdata.explorer.interestpoint.InterestPointExplorer; +import net.preibisch.mvrecon.process.interestpointregistration.TransformationTools; +import net.preibisch.mvrecon.process.interestpointregistration.pairwise.constellation.grouping.Group; + +public class AnalyzeErrorPopup extends JMenuItem implements ExplorerWindowSetable +{ + private static final long serialVersionUID = 7784076140119163902L; + + ViewSetupExplorerPanel< ? > panel; + InterestPointExplorer< ? > ipe = null; + + public AnalyzeErrorPopup() + { + super( "Analyze Alignment Errors ..." ); + + this.addActionListener( new MyActionListener() ); + } + + @Override + public JMenuItem setExplorerWindow( final ExplorerWindow< ? > panel ) + { + this.panel = (ViewSetupExplorerPanel< ? >)panel; + return this; + } + + public class MyActionListener implements ActionListener + { + @Override + public void actionPerformed( final ActionEvent e ) + { + if ( panel == null ) + { + IOFunctions.println( "Panel not set for " + this.getClass().getSimpleName() ); + return; + } + + new Thread( new Runnable() + { + @Override + public void run() + { + final List< ViewId > viewIds = + ApplyTransformationPopup.getSelectedViews( panel ); + + final HashMap labelAndWeights = + Analyze_Errors.getParameters( panel.getSpimData(), viewIds ); + + final ArrayList, Double>> errors = + Analyze_Errors.getErrors( panel.getSpimData(), viewIds, labelAndWeights ); + + if ( errors.size() > 0 ) + { + errors.forEach( e -> IOFunctions.println( Group.pvid( e.getA().getA() ) + " <-> " + Group.pvid( e.getA().getB() ) + ": " + e.getB() + " px.") ); + + // disable coloring + final BDVPopup p = panel.bdvPopup(); + if ( p != null && p.bdv != null && p.bdv.getViewerFrame().isVisible() ) + panel.updateBDV( p.bdv, false, panel.getSpimData(), null, panel.selectedRows ); + + // ungroup everything + ((ViewSetupExplorerPanel)panel).groupTilesCheckbox.setSelected( false ); + ((ViewSetupExplorerPanel)panel).groupIllumsCheckbox.setSelected( false ); + + panel.getTableModel().clearGroupingFactors(); + panel.updateContent(); + + // wait until the table is updated (otherwise there might be an exception thrown) + SimpleMultiThreading.threadWait( 100 ); + + final Pair, Double> worstError = errors.get( 0 ); + + // select the two rows + boolean setFirst = false; + for ( int r = 0; r < panel.table.getRowCount(); ++r ) + { + //System.out.println( panel.table.getValueAt( r, 0 ) + ", " + Integer.parseInt( (String)panel.table.getValueAt( r, 0 ) ) ); + //System.out.println( panel.table.getValueAt( r, 1 ) + ", " + Integer.parseInt( (String)panel.table.getValueAt( r, 1 ) ) ); + //System.out.println(); + + final int tp = Integer.parseInt( (String)panel.table.getValueAt( r, 0 ) ); + final int vs = Integer.parseInt( (String)panel.table.getValueAt( r, 1 ) ); + //System.out.println( tp + ", " + vs ); + + if ( tp == worstError.getA().getA().getTimePointId() && vs == worstError.getA().getA().getViewSetupId() || + tp == worstError.getA().getB().getTimePointId() && vs == worstError.getA().getB().getViewSetupId()) + { + System.out.println( "setting" ); + if ( setFirst ) + panel.table.addRowSelectionInterval(r, r); + else + { + setFirst = true; + panel.table.setRowSelectionInterval(r, r); + } + } + } + + // wait until the table is updated (otherwise there might be an exception thrown) + SimpleMultiThreading.threadWait( 100 ); + + // TODO: zoom into the two + if ( p != null && p.bdv != null && p.bdv.getViewerFrame().isVisible() ) + { + TransformationTools.reCenterViews( p.bdv, + panel.selectedRows.stream().collect( + HashSet< BasicViewDescription< ? > >::new, + ( a, b ) -> a.addAll( b ), ( a, b ) -> a.addAll( b ) ), + panel.getSpimData().getViewRegistrations() ); + } + + // TODO: color both red + } + else + { + IOFunctions.println( "No corresponding interest points found." ); + } + } + }).start(); + } + } +}