diff --git a/pom.xml b/pom.xml index e61cf40..a5487c5 100644 --- a/pom.xml +++ b/pom.xml @@ -120,7 +120,7 @@ 1.5.0 --> - 7.0.7 + 8.1.1 1.0.2 1.6.5 diff --git a/src/main/java/net/preibisch/stitcher/algorithm/globalopt/ExecuteGlobalOpt.java b/src/main/java/net/preibisch/stitcher/algorithm/globalopt/ExecuteGlobalOpt.java index f34e8a3..64ea31e 100644 --- a/src/main/java/net/preibisch/stitcher/algorithm/globalopt/ExecuteGlobalOpt.java +++ b/src/main/java/net/preibisch/stitcher/algorithm/globalopt/ExecuteGlobalOpt.java @@ -76,7 +76,7 @@ public void run() } final boolean isSavedFaG = savedFiltering != null; - final GlobalOptimizationParameters params = expertMode ? GlobalOptimizationParameters.askUserForParameters(!isSavedFaG) : GlobalOptimizationParameters.askUserForSimpleParameters(); + final GlobalOptimizationParameters params = GlobalOptimizationParameters.askUserForSimpleParameters(); if ( params == null ) return; diff --git a/src/main/java/net/preibisch/stitcher/algorithm/globalopt/GlobalOptStitcher.java b/src/main/java/net/preibisch/stitcher/algorithm/globalopt/GlobalOptStitcher.java index 0f6ca51..84911e8 100644 --- a/src/main/java/net/preibisch/stitcher/algorithm/globalopt/GlobalOptStitcher.java +++ b/src/main/java/net/preibisch/stitcher/algorithm/globalopt/GlobalOptStitcher.java @@ -191,6 +191,7 @@ public List< ViewId > getDefaultFixedViews() { HashMap< ViewId, mpicbg.models.Tile< TranslationModel3D > > globalOptResults = GlobalOptTwoRound.computeTiles( new TranslationModel3D(), + true,// preAlign new ImageCorrelationPointMatchCreator( results ), new SimpleIterativeConvergenceStrategy( Double.MAX_VALUE, params.relativeThreshold, params.absoluteThreshold ), @@ -222,6 +223,7 @@ else if ( params.method == GlobalOptType.ONE_ROUND_ITERATIVE) { HashMap< ViewId, mpicbg.models.Tile< TranslationModel3D > > globalOptResults = GlobalOptIterative.computeTiles( new TranslationModel3D(), + true,// preAlign new ImageCorrelationPointMatchCreator( results ), new SimpleIterativeConvergenceStrategy( Double.MAX_VALUE, params.relativeThreshold, params.absoluteThreshold ), @@ -246,6 +248,7 @@ else if ( params.method == GlobalOptType.ONE_ROUND_ITERATIVE) { final HashMap< ViewId, mpicbg.models.Tile< TranslationModel3D > > globalOptResults = GlobalOpt.computeTiles( new TranslationModel3D(), + true,// preAlign new ImageCorrelationPointMatchCreator( results ), new SimpleIterativeConvergenceStrategy( Double.MAX_VALUE, params.relativeThreshold, params.absoluteThreshold ), diff --git a/src/main/java/net/preibisch/stitcher/algorithm/globalopt/TransformationTools.java b/src/main/java/net/preibisch/stitcher/algorithm/globalopt/TransformationTools.java index 6251185..0195835 100644 --- a/src/main/java/net/preibisch/stitcher/algorithm/globalopt/TransformationTools.java +++ b/src/main/java/net/preibisch/stitcher/algorithm/globalopt/TransformationTools.java @@ -750,6 +750,7 @@ public static void main( String[] args ) GlobalOpt.computeTiles( new TranslationModel3D(), + true,// preAlign new ImageCorrelationPointMatchCreator( results, 0.5 ), new ConvergenceStrategy( 5.0 ), fixedViews, diff --git a/src/main/java/net/preibisch/stitcher/gui/StitchingExplorerPanel.java b/src/main/java/net/preibisch/stitcher/gui/StitchingExplorerPanel.java index 1cb5d87..5832e5a 100644 --- a/src/main/java/net/preibisch/stitcher/gui/StitchingExplorerPanel.java +++ b/src/main/java/net/preibisch/stitcher/gui/StitchingExplorerPanel.java @@ -265,6 +265,15 @@ public boolean illumsGrouped() return true; } + @Override + protected void clearGroupingCheckboxes() + { + if ( checkboxGroupChannels != null ) + checkboxGroupChannels.setSelected( false ); + if ( checkboxGroupIllums != null ) + checkboxGroupIllums.setSelected( false ); + } + void quitLinkExplorer() diff --git a/src/main/java/net/preibisch/stitcher/gui/popup/CalculatePCPopupExpertBatch.java b/src/main/java/net/preibisch/stitcher/gui/popup/CalculatePCPopupExpertBatch.java index c369cf5..74adaef 100644 --- a/src/main/java/net/preibisch/stitcher/gui/popup/CalculatePCPopupExpertBatch.java +++ b/src/main/java/net/preibisch/stitcher/gui/popup/CalculatePCPopupExpertBatch.java @@ -31,10 +31,10 @@ public class CalculatePCPopupExpertBatch extends JMenu implements ExplorerWindowSetable { + private static final long serialVersionUID = 804355154792175254L; final CalculatePCPopup phaseCorrSimple; final CalculatePCPopup phaseCorr; final CalculatePCPopup lucasKanade; - final PairwiseInterestPointRegistrationPopup interestPoint; boolean wizardMode; public CalculatePCPopupExpertBatch( String description, boolean wizardMode ) @@ -50,13 +50,11 @@ public CalculatePCPopupExpertBatch( String description, boolean wizardMode ) phaseCorr = new CalculatePCPopup( wizardMode ? "Phase Correlation" : "Phase Correlation (expert)", false, Method.PHASECORRELATION, wizardMode ); lucasKanade = new CalculatePCPopup( "Lucas-Kanade", false, Method.LUCASKANADE, wizardMode ); - interestPoint = new PairwiseInterestPointRegistrationPopup( "Interest point based", wizardMode ); if(!wizardMode) this.add(phaseCorrSimple); this.add( phaseCorr ); this.add( lucasKanade ); - this.add( interestPoint ); } @Override @@ -66,7 +64,6 @@ public JComponent setExplorerWindow( ExplorerWindow< ? > panel ) this.phaseCorrSimple.setExplorerWindow( panel ); this.phaseCorr.setExplorerWindow( panel ); this.lucasKanade.setExplorerWindow( panel ); - this.interestPoint.setExplorerWindow( panel ); return this; } diff --git a/src/main/java/net/preibisch/stitcher/gui/popup/PairwiseInterestPointRegistrationPopup.java b/src/main/java/net/preibisch/stitcher/gui/popup/PairwiseInterestPointRegistrationPopup.java deleted file mode 100644 index 1595308..0000000 --- a/src/main/java/net/preibisch/stitcher/gui/popup/PairwiseInterestPointRegistrationPopup.java +++ /dev/null @@ -1,227 +0,0 @@ -/*- - * #%L - * Multiview stitching of large datasets. - * %% - * Copyright (C) 2016 - 2025 Big Stitcher 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.stitcher.gui.popup; - -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; - -import mpicbg.spim.data.sequence.Channel; -import mpicbg.spim.data.sequence.Illumination; -import mpicbg.spim.data.sequence.Tile; -import mpicbg.spim.data.sequence.ViewId; -import net.preibisch.legacy.io.IOFunctions; -import net.preibisch.mvrecon.fiji.spimdata.SpimData2; -import net.preibisch.mvrecon.fiji.spimdata.explorer.ExplorerWindow; -import net.preibisch.mvrecon.fiji.spimdata.explorer.FilteredAndGroupedExplorerPanel; -import net.preibisch.mvrecon.fiji.spimdata.explorer.GroupedRowWindow; -import net.preibisch.mvrecon.fiji.spimdata.explorer.popup.ExplorerWindowSetable; -import net.preibisch.mvrecon.fiji.spimdata.interestpoints.ViewInterestPoints; -import net.preibisch.stitcher.algorithm.SpimDataFilteringAndGrouping; -import net.preibisch.stitcher.gui.StitchingExplorerPanel; -import net.preibisch.stitcher.gui.StitchingUIHelper; -import net.preibisch.stitcher.plugin.Calculate_Pairwise_Shifts; - -public class PairwiseInterestPointRegistrationPopup extends JMenu implements ExplorerWindowSetable -{ - - private static final long serialVersionUID = -396274656320474433L; - ExplorerWindow< ? > panel; - - private JMenuItem withDetection; - private JMenuItem withoutDetection; - private JCheckBoxMenuItem expertGrouping; - - private boolean wizardMode; - - public PairwiseInterestPointRegistrationPopup(String description, boolean wizardMode ) - { - super( description ); - this.addActionListener( new MyActionListener(false) ); - - this.wizardMode = wizardMode; - - withDetection = new JMenuItem( "With new Interest Points" ); - withoutDetection = new JMenuItem( "With existing Interest Points" ); - expertGrouping = new JCheckBoxMenuItem( "Show expert grouping Options", false ); - - withDetection.addActionListener( new MyActionListener( false ) ); - withoutDetection.addActionListener( new MyActionListener( true ) ); - - this.add( withDetection ); - this.add( withoutDetection ); - this.addSeparator(); - this.add( expertGrouping ); - - this.addMenuListener( new MenuListener() - { - @Override - public void menuSelected(MenuEvent e) - { - if (SpimData2.class.isInstance( panel.getSpimData() )) - { - final List< ViewId > selectedViews = ((GroupedRowWindow)panel).selectedRowsViewIdGroups().stream().reduce( new ArrayList<>(), (x,y) -> {x.addAll( y ); return x;} ); - boolean allHaveIPs = true; - final ViewInterestPoints viewInterestPoints = ((SpimData2)panel.getSpimData()).getViewInterestPoints(); - for (ViewId vid : selectedViews) - if (panel.getSpimData().getSequenceDescription().getMissingViews() != null && - !panel.getSpimData().getSequenceDescription().getMissingViews().getMissingViews().contains( vid )) - { - if (!viewInterestPoints.getViewInterestPoints().containsKey( vid ) || - viewInterestPoints.getViewInterestPoints().get( vid ).getHashMap().size() < 1) - { - allHaveIPs = false; - break; - } - } - withoutDetection.setEnabled( allHaveIPs ); - } - } - - @Override - public void menuDeselected(MenuEvent e){} - - @Override - public void menuCanceled(MenuEvent e){} - - } ); - } - - @Override - public JComponent setExplorerWindow( final ExplorerWindow< ? > panel ) - { - this.panel = panel; - return this; - } - - public class MyActionListener implements ActionListener - { - private boolean existingInterestPoints; - - public MyActionListener(boolean existingInterestPoints) - { - this.existingInterestPoints = existingInterestPoints; - } - - @Override - public void actionPerformed(ActionEvent e) - { - if ( panel == null ) - { - IOFunctions.println( "Panel not set for " + this.getClass().getSimpleName() ); - return; - } - - if ( !SpimData2.class.isInstance( panel.getSpimData() ) ) - { - IOFunctions.println( "Only supported for SpimData2 objects: " + this.getClass().getSimpleName() ); - return; - } - - if (!GroupedRowWindow.class.isInstance( panel )) - { - IOFunctions.println( "Only supported for GroupedRowWindow panels: " + this.getClass().getSimpleName() ); - return; - } - - new Thread( () -> - { - // get selected groups, filter missing views, get all present and selected vids - final SpimData2 data = (SpimData2) panel.getSpimData(); - @SuppressWarnings("unchecked") - FilteredAndGroupedExplorerPanel< SpimData2 > panelFG = (FilteredAndGroupedExplorerPanel< SpimData2 >) panel; - SpimDataFilteringAndGrouping< SpimData2 > filteringAndGrouping = new SpimDataFilteringAndGrouping<>( (SpimData2) panel.getSpimData() ); - - if (!expertGrouping.isSelected()) - { - // use whatever is selected in panel as filters - filteringAndGrouping.addFilters( panelFG.selectedRowsGroups().stream().reduce( new ArrayList<>(), (x,y ) -> {x.addAll( y ); return x;}) ); - } - else - { - filteringAndGrouping.askUserForFiltering( panelFG ); - if (filteringAndGrouping.getDialogWasCancelled()) - return; - } - - if (!expertGrouping.isSelected()) - { - // get the grouping from panel and compare Tiles - panelFG.getTableModel().getGroupingFactors().forEach( g -> filteringAndGrouping.addGroupingFactor( g )); - filteringAndGrouping.addComparisonAxis( Tile.class ); - - // compare by Channel if channels were ungrouped in UI - if (!panelFG.getTableModel().getGroupingFactors().contains( Channel.class )) - filteringAndGrouping.addComparisonAxis( Channel.class ); - - // compare by Illumination if illums were ungrouped in UI - if (!panelFG.getTableModel().getGroupingFactors().contains( Illumination.class )) - filteringAndGrouping.addComparisonAxis( Illumination.class ); - } - else - { - filteringAndGrouping.addComparisonAxis( Tile.class ); - filteringAndGrouping.askUserForGrouping( panelFG ); - if (filteringAndGrouping.getDialogWasCancelled()) - return; - } - - boolean allViews2D = StitchingUIHelper.allViews2D( filteringAndGrouping.getFilteredViews() ); - if (allViews2D) - { - IOFunctions.println( "Interest point-based registration is currenty not supported for 2D: " + this.getClass().getSimpleName() ); - return; - } - - - if (Calculate_Pairwise_Shifts.processInterestPoint( data, filteringAndGrouping, existingInterestPoints )) - if (wizardMode) - { - // ask user if they want to switch to preview mode - if (panel instanceof StitchingExplorerPanel) - { - final int choice = JOptionPane.showConfirmDialog( (Component) panel, "Pairwise shift calculation done. Switch to preview mode?", "Preview Mode", JOptionPane.YES_NO_OPTION ); - if (choice == JOptionPane.YES_OPTION) - { - ((StitchingExplorerPanel< ? >) panel).setSavedFilteringAndGrouping( filteringAndGrouping ); - ((StitchingExplorerPanel< ? >) panel).togglePreviewMode(false); - } - } - } - - }).start(); - - panel.updateContent(); - } - } - -} diff --git a/src/main/java/net/preibisch/stitcher/gui/popup/RefineWithICPPopup.java b/src/main/java/net/preibisch/stitcher/gui/popup/RefineWithICPPopup.java index ca6a393..8a71b23 100644 --- a/src/main/java/net/preibisch/stitcher/gui/popup/RefineWithICPPopup.java +++ b/src/main/java/net/preibisch/stitcher/gui/popup/RefineWithICPPopup.java @@ -32,6 +32,7 @@ import net.preibisch.legacy.io.IOFunctions; import net.preibisch.mvrecon.fiji.plugin.interestpointregistration.global.GlobalOptimizationParameters; +import net.preibisch.mvrecon.fiji.plugin.interestpointregistration.global.GlobalOptimizationParameters.PreAlign; import net.preibisch.mvrecon.fiji.plugin.util.MouseOverPopUpStateChanger; import net.preibisch.mvrecon.fiji.plugin.util.MouseOverPopUpStateChanger.StateChanger; import net.preibisch.mvrecon.fiji.spimdata.SpimData2; @@ -243,7 +244,7 @@ public void actionPerformed( ActionEvent e ) if ( !ICPRefinement.getGUIParametersSimple( icpType, data, params, downsamplingChoice, thresholdChoice, distanceChoice ) ) return; - globalOptParams = GlobalOptimizationParameters.getGlobalOptimizationParametersForSelection( GlobalOptimizationParameters.defaultSimple ); + globalOptParams = GlobalOptimizationParameters.getGlobalOptimizationParametersForSelection( GlobalOptimizationParameters.defaultSimple, false ); } if ( globalOptParams == null ) diff --git a/src/main/java/net/preibisch/stitcher/headless/registration/TestGlobalOptTwoRound.java b/src/main/java/net/preibisch/stitcher/headless/registration/TestGlobalOptTwoRound.java index 4dfe38e..333f0aa 100644 --- a/src/main/java/net/preibisch/stitcher/headless/registration/TestGlobalOptTwoRound.java +++ b/src/main/java/net/preibisch/stitcher/headless/registration/TestGlobalOptTwoRound.java @@ -148,6 +148,7 @@ public static void main( String[] args ) final HashMap< ViewId, TranslationModel3D > computeResults = GlobalOptTwoRound.computeModels( new TranslationModel3D(), + true,// preAlign pmc, cs, new MaxErrorLinkRemoval(), diff --git a/src/main/java/net/preibisch/stitcher/plugin/Calculate_Pairwise_Shifts.java b/src/main/java/net/preibisch/stitcher/plugin/Calculate_Pairwise_Shifts.java index 19e2b15..c10c849 100644 --- a/src/main/java/net/preibisch/stitcher/plugin/Calculate_Pairwise_Shifts.java +++ b/src/main/java/net/preibisch/stitcher/plugin/Calculate_Pairwise_Shifts.java @@ -81,9 +81,7 @@ public class Calculate_Pairwise_Shifts implements PlugIn private final static String[] methodChoices = { "Phase Correlation", - "Lucas-Kanade", - "Interest-Point Registration (with existing Interest Points)", - "Interest-Point Registration (with new Interest Points)"}; + "Lucas-Kanade" }; private static boolean expertGrouping; private static boolean expertAlgorithmParameters; @@ -139,28 +137,20 @@ public void run(String arg) grouping.getAxesOfComparison().addAll( defaultComparisonFactors ); } - if (defaultMethodIdx >= 2) + grouping.askUserForGroupingAggregator(); + final long[] ds = StitchingUIHelper.askForDownsampling( data, is2d ); + + if (defaultMethodIdx == 0) // Phase Correlation { - if (!processInterestPoint( data, grouping, defaultMethodIdx == 2 )) + PairwiseStitchingParameters params = expertAlgorithmParameters ? PairwiseStitchingParameters.askUserForParameters() : new PairwiseStitchingParameters(); + if (!processPhaseCorrelation( data, grouping, params, ds )) return; } - else + else if (defaultMethodIdx == 1) // Lucas-Kanade { - grouping.askUserForGroupingAggregator(); - final long[] ds = StitchingUIHelper.askForDownsampling( data, is2d ); - - if (defaultMethodIdx == 0) // Phase Correlation - { - PairwiseStitchingParameters params = expertAlgorithmParameters ? PairwiseStitchingParameters.askUserForParameters() : new PairwiseStitchingParameters(); - if (!processPhaseCorrelation( data, grouping, params, ds )) - return; - } - else if (defaultMethodIdx == 1) // Lucas-Kanade - { - LucasKanadeParameters params = expertAlgorithmParameters ? LucasKanadeParameters.askUserForParameters() : new LucasKanadeParameters( WarpFunctionType.TRANSLATION ); - if (!processLucasKanade( data, grouping, params, ds )) - return; - } + LucasKanadeParameters params = expertAlgorithmParameters ? LucasKanadeParameters.askUserForParameters() : new LucasKanadeParameters( WarpFunctionType.TRANSLATION ); + if (!processLucasKanade( data, grouping, params, ds )) + return; } // update XML @@ -269,199 +259,4 @@ public static boolean processLucasKanade( return true; } - - - public static boolean processInterestPoint(final SpimData2 data, - final SpimDataFilteringAndGrouping< SpimData2 > filteringAndGrouping, - boolean existingInterestPoints) - { - - // detect new interest points if requested - if (!existingInterestPoints) - { - // by default the registration suggests what is selected in the dialog - Interest_Point_Detection.defaultGroupTiles = filteringAndGrouping.getGroupingFactors().contains( Tile.class ); - Interest_Point_Detection.defaultGroupIllums = filteringAndGrouping.getGroupingFactors().contains( Illumination.class ); - new Interest_Point_Detection().detectInterestPoints( data, filteringAndGrouping.getFilteredViews() ); - } - - // by default the registration suggests what is selected in the dialog - // (and was passed to filteringAndGrouping) - Interest_Point_Registration.defaultGroupTiles = filteringAndGrouping.getGroupingFactors() - .contains( Tile.class ); - Interest_Point_Registration.defaultGroupIllums = filteringAndGrouping.getGroupingFactors() - .contains( Illumination.class ); - Interest_Point_Registration.defaultGroupChannels = filteringAndGrouping.getGroupingFactors() - .contains( Channel.class ); - - // which timepoints are part of the data (we dont necessarily need them, - // but basicRegistrationParameters GUI wants them) - List< ? extends ViewId > viewIds = filteringAndGrouping.getFilteredViews(); - final List< TimePoint > timepointToProcess = SpimData2.getAllTimePointsSorted( data, viewIds ); - final int nAllTimepoints = data.getSequenceDescription().getTimePoints().size(); - - // query basic registration parameters - final BasicRegistrationParameters brp = new Interest_Point_Registration().basicRegistrationParameters( - timepointToProcess, nAllTimepoints, data, (List< ViewId >) viewIds ); - if ( brp == null ) - return false; - - // query algorithm parameters - GenericDialog gd = new GenericDialog( "Registration Parameters" ); - - gd.addMessage( "Algorithm parameters [" + brp.pwr.getDescription() + "]", - new Font( Font.SANS_SERIF, Font.BOLD, 12 ) ); - gd.addMessage( "" ); - - brp.pwr.presetTransformationModel( new TransformationModelGUI( 0 ) ); - brp.pwr.addQuery( gd ); - - gd.showDialog(); - - if ( gd.wasCanceled() ) - return false; - if ( !brp.pwr.parseDialog( gd ) ) - return false; - - // get all possible group pairs - List< ? extends Pair< ? extends Group< ? extends ViewId >, ? extends Group< ? extends ViewId > > > pairs = filteringAndGrouping - .getComparisons(); - - // remove old results - // this is just a cast of pairs to Group - final List< ValuePair< Group< ViewId >, Group< ViewId > > > castPairs = pairs.stream().map( p -> { - final Group< ViewId > vidGroupA = new Group<>( - p.getA().getViews().stream().map( v -> (ViewId) v ).collect( Collectors.toSet() ) ); - final Group< ViewId > vidGroupB = new Group<>( - p.getB().getViews().stream().map( v -> (ViewId) v ).collect( Collectors.toSet() ) ); - return new ValuePair<>( vidGroupA, vidGroupB ); - } ).collect( Collectors.toList() ); - - for ( ValuePair< Group< ViewId >, Group< ViewId > > pair : castPairs ) - { - // try to remove a -> b and b -> a, just to make sure - data.getStitchingResults().getPairwiseResults().remove( pair ); - data.getStitchingResults().getPairwiseResults().remove( new ValuePair<>( pair.getB(), pair.getA() ) ); - } - - // remove non-overlapping comparisons - final List< Pair< Group< ViewId >, Group< ViewId > > > removedPairs = TransformationTools - .filterNonOverlappingPairs( (List< Pair< Group< ViewId >, Group< ViewId > > >) pairs, - data.getViewRegistrations(), data.getSequenceDescription() ); - removedPairs - .forEach( p -> System.out.println( "Skipping non-overlapping pair: " + p.getA() + " -> " + p.getB() ) ); - - for ( final Pair< Group< ViewId >, Group< ViewId > > pair : (List< Pair< Group< ViewId >, Group< ViewId > > >) pairs ) - { - // all views in group pair - final HashSet< ViewId > vids = new HashSet< ViewId >(); - vids.addAll( pair.getA().getViews() ); - vids.addAll( pair.getB().getViews() ); - - // simple PairwiseSetup with just two groups (fully connected to - // each other) - Set> groups = new HashSet<>(); - groups.add( pair.getA() ); - groups.add( pair.getB() ); - final PairwiseSetup< ViewId > setup = new PairwiseSetup< ViewId >( new ArrayList<>( vids ), groups ) - { - - @Override - protected List< Pair< ViewId, ViewId > > definePairsAbstract() - { - // all possible links between groups - final List< Pair< ViewId, ViewId > > res = new ArrayList<>(); - for ( final ViewId vidA : pair.getA() ) - for ( final ViewId vidB : pair.getB() ) - res.add( new ValuePair< ViewId, ViewId >( vidA, vidB ) ); - return res; - } - - @Override - public List< ViewId > getDefaultFixedViews() - { - // first group will remain fixed -> we get the transform to - // align second group to this target - return new ArrayList<>( pair.getA().getViews() ); - } - }; - - // prepare setup - setup.definePairs(); - setup.detectSubsets(); - - // get copies of view registrations (as they will be modified) and - // interest points - final Map< ViewId, ViewRegistration > registrationMap = new HashMap<>(); - final Map< ViewId, ViewInterestPointLists > ipMap = new HashMap<>(); - for ( ViewId vid : vids ) - { - final ViewRegistration vrOld = data.getViewRegistrations().getViewRegistration( vid ); - final ViewInterestPointLists iplOld = data.getViewInterestPoints().getViewInterestPointLists( vid ); - registrationMap.put( vid, new ViewRegistration( vid.getTimePointId(), vid.getViewSetupId(), - new ArrayList<>( vrOld.getTransformList() ) ) ); - ipMap.put( vid, iplOld ); - } - - final Interest_Point_Registration reg = new Interest_Point_Registration(); - // run the registration for this pair, skip saving results if it did not work - if ( !reg.processRegistration( - setup, - data.getSequenceDescription().getViewSetups(), - brp.pwr, - InterestpointGroupingType.ADD_ALL, - InterestPointOverlapType.ALL, - 0.0, - pair.getA().getViews(), - null, - null, - registrationMap, - data.getSequenceDescription().getViewDescriptions(), - ipMap, - brp.labelMap, - new GlobalOptimizationParameters(Double.MAX_VALUE, Double.MAX_VALUE, GlobalOptType.ONE_ROUND_SIMPLE, false ), - false, //matchacrosslabels - true ) ) - continue; - - // get newest Transformation of groupB (the accumulative transform - // determined by registration) - final ViewTransform vtB = registrationMap.get( pair.getB().iterator().next() ).getTransformList().get( 0 ); - - List< Pair< Pair< ViewId, ViewId >, ? extends PairwiseResult< ? > > > stats = reg.getStatistics(); - - // TODO: is this correct? - // since the grouped IP are split up again in the statistics, can we just sum inliers & candidates - // to get the total cands/inliers. or are we counting some twice? - double candidates = 0; - double inliers = 0; - for (final Pair< Pair< ViewId, ViewId >, ? extends PairwiseResult< ? > > stat : stats) - { - candidates += stat.getB().getCandidates().size(); - inliers += stat.getB().getInliers().size(); - } - - - final AffineTransform3D result = new AffineTransform3D(); - result.set( vtB.asAffine3D().getRowPackedCopy() ); - IOFunctions.println( "resulting transformation: " + Util.printCoordinates( result.getRowPackedCopy() ) ); - - // get Overlap Bounding Box, which we need for stitching results - final List< List< ViewId > > groupListsForOverlap = new ArrayList<>(); - groupListsForOverlap.add( new ArrayList<>( pair.getA().getViews() ) ); - groupListsForOverlap.add( new ArrayList<>( pair.getB().getViews() ) ); - BoundingBoxMaximalGroupOverlap< ViewId > bbDet = new BoundingBoxMaximalGroupOverlap< ViewId >( - groupListsForOverlap, data.getSequenceDescription(), data.getViewRegistrations() ); - BoundingBox bbOverlap = bbDet.estimate( "Max Overlap" ); - - final double oldTransformHash = PairwiseStitchingResult.calculateHash( - data.getViewRegistrations().getViewRegistration( pair.getA().getViews().iterator().next() ), - data.getViewRegistrations().getViewRegistration( pair.getA().getViews().iterator().next() ) ); - data.getStitchingResults().getPairwiseResults().put( pair, - new PairwiseStitchingResult<>( pair, bbOverlap, result, inliers/candidates, oldTransformHash ) ); - } - - return true; - } - } diff --git a/src/main/java/net/preibisch/stitcher/plugin/Global_Optimization_Stitching.java b/src/main/java/net/preibisch/stitcher/plugin/Global_Optimization_Stitching.java index f508e4a..aef72d2 100644 --- a/src/main/java/net/preibisch/stitcher/plugin/Global_Optimization_Stitching.java +++ b/src/main/java/net/preibisch/stitcher/plugin/Global_Optimization_Stitching.java @@ -35,6 +35,7 @@ import mpicbg.spim.data.sequence.ViewId; import net.imglib2.util.Pair; import net.preibisch.mvrecon.fiji.plugin.interestpointregistration.global.GlobalOptimizationParameters; +import net.preibisch.mvrecon.fiji.plugin.interestpointregistration.global.GlobalOptimizationParameters.PreAlign; import net.preibisch.mvrecon.fiji.plugin.queryXML.LoadParseQueryXML; import net.preibisch.mvrecon.fiji.spimdata.SpimData2; import net.preibisch.mvrecon.fiji.spimdata.XmlIoSpimData2; @@ -66,7 +67,7 @@ public void run(String arg) final HashSet< Class< ? extends Entity > > defaultComparisonFactors = new HashSet<>(); defaultComparisonFactors.add( Tile.class ); - GlobalOptimizationParameters params = GlobalOptimizationParameters.askUserForParameters(true); + GlobalOptimizationParameters params = GlobalOptimizationParameters.askUserForParameters( true, PreAlign.ASK ); if (params.showExpertGrouping) grouping.askUserForGrouping( diff --git a/src/main/java/net/preibisch/stitcher/process/ICPRefinement.java b/src/main/java/net/preibisch/stitcher/process/ICPRefinement.java index 84ebfee..37ad286 100644 --- a/src/main/java/net/preibisch/stitcher/process/ICPRefinement.java +++ b/src/main/java/net/preibisch/stitcher/process/ICPRefinement.java @@ -436,7 +436,7 @@ public static void refine( } // load & transform all interest points - final Map< ViewId, HashMap< String, List< InterestPoint > > > interestpoints = + final Map< ViewId, HashMap< String, Collection< InterestPoint > > > interestpoints = TransformationTools.getAllTransformedInterestPoints( params.viewIds, data.getViewRegistrations().getViewRegistrations(), @@ -519,7 +519,7 @@ public static void refine( public static final HashMap< ViewId, mpicbg.models.Tile > pairSubset( final SpimData2 spimData, final Subset< ViewId > subset, - final Map< ViewId, HashMap< String, List< InterestPoint > > > interestpoints, + final Map< ViewId, HashMap< String, Collection< InterestPoint > > > interestpoints, final Map< ViewId, HashMap< String, Double > > labelMap, final IterativeClosestPointParameters icpp, final List< ViewId > fixedViews, @@ -594,6 +594,7 @@ public static final HashMap< ViewId, mpicbg.models.Tile > pairSubset( { models = (HashMap< ViewId, mpicbg.models.Tile >)(Object)GlobalOpt.computeTiles( (Model)(Object)icpp.getModel().copy(), + globalOptParameters.preAlign, pmc, new ConvergenceStrategy( icpp.getMaxDistance() ), fixedViews, @@ -603,6 +604,7 @@ else if ( globalOptParameters.method == GlobalOptType.ONE_ROUND_ITERATIVE ) { models = (HashMap< ViewId, mpicbg.models.Tile >)(Object)GlobalOptIterative.computeTiles( (Model)(Object)icpp.getModel().copy(), + globalOptParameters.preAlign, pmc, new SimpleIterativeConvergenceStrategy( icpp.getMaxDistance(), globalOptParameters.relativeThreshold, globalOptParameters.absoluteThreshold ), new MaxErrorLinkRemoval(), @@ -614,6 +616,7 @@ else if ( globalOptParameters.method == GlobalOptType.ONE_ROUND_ITERATIVE ) { models = (HashMap< ViewId, mpicbg.models.Tile >)(Object)GlobalOptTwoRound.computeTiles( (Model & Affine3D)(Object)icpp.getModel().copy(), + globalOptParameters.preAlign, pmc, new SimpleIterativeConvergenceStrategy( icpp.getMaxDistance(), globalOptParameters.relativeThreshold, globalOptParameters.absoluteThreshold ), // if it's simple, both will be Double.MAX new MaxErrorLinkRemoval(), @@ -635,7 +638,7 @@ else if ( globalOptParameters.method == GlobalOptType.ONE_ROUND_ITERATIVE ) public static HashMap< ViewId, mpicbg.models.Tile > groupedSubset( final SpimData2 spimData, final Subset< ViewId > subset, - final Map< ViewId, HashMap< String, List< InterestPoint > > > interestpoints, + final Map< ViewId, HashMap< String, Collection< InterestPoint > > > interestpoints, final Map< ViewId, HashMap< String, Double > > labelMap, final IterativeClosestPointParameters icpp, final List< ViewId > fixedViews, @@ -646,7 +649,7 @@ public static HashMap< ViewId, mpicbg.models.Tile > groupedSubset( final boolean matchAcrossLabels ) { final List< Pair< Group< ViewId >, Group< ViewId > > > groupedPairs = subset.getGroupedPairs(); - final Map< Group< ViewId >, HashMap< String, List< GroupedInterestPoint< ViewId > > > > groupedInterestpoints = new HashMap<>(); + final Map< Group< ViewId >, HashMap< String, Collection< GroupedInterestPoint< ViewId > > > > groupedInterestpoints = new HashMap<>(); final InterestPointGrouping< ViewId > ipGrouping = new InterestPointGroupingMinDistance<>( interestpoints ); if ( groupedPairs.size() <= 0 ) @@ -714,6 +717,7 @@ public static HashMap< ViewId, mpicbg.models.Tile > groupedSubset( { models = (HashMap< ViewId, mpicbg.models.Tile >)(Object)GlobalOpt.computeTiles( (Model)(Object)icpp.getModel().copy(), + globalOptParameters.preAlign, pmc, new ConvergenceStrategy( icpp.getMaxDistance() ), fixedViews, @@ -723,6 +727,7 @@ else if ( globalOptParameters.method == GlobalOptType.ONE_ROUND_ITERATIVE ) { models = (HashMap< ViewId, mpicbg.models.Tile >)(Object)GlobalOptIterative.computeTiles( (Model)(Object)icpp.getModel().copy(), + globalOptParameters.preAlign, pmc, new SimpleIterativeConvergenceStrategy( icpp.getMaxDistance(), globalOptParameters.relativeThreshold, globalOptParameters.absoluteThreshold ), new MaxErrorLinkRemoval(), @@ -734,6 +739,7 @@ else if ( globalOptParameters.method == GlobalOptType.ONE_ROUND_ITERATIVE ) { models = (HashMap< ViewId, mpicbg.models.Tile >)(Object)GlobalOptTwoRound.computeTiles( (Model & Affine3D)(Object)icpp.getModel().copy(), + globalOptParameters.preAlign, pmc, new SimpleIterativeConvergenceStrategy( icpp.getMaxDistance(), globalOptParameters.relativeThreshold, globalOptParameters.absoluteThreshold ), // if it's simple, both will be Double.MAX new MaxErrorLinkRemoval(), diff --git a/src/main/resources/BigStitcher/Help.html b/src/main/resources/BigStitcher/Help.html index 2101dca..57dc2f7 100644 --- a/src/main/resources/BigStitcher/Help.html +++ b/src/main/resources/BigStitcher/Help.html @@ -61,7 +61,19 @@

BigStitcher

For general help regarding usage of BigStitcher please go to the following webpage: http://imagej.net/BigStitcher.

-
+ +
+

💡 Important Usage Information

+

+All functionality is available by right-clicking on the views you want to process. +Simply select one or more views in the Stitching Explorer table, then right-click +to access all processing options. +

+

+For macro recording: Please use the Fiji BigStitcher plugins menu instead of the +interactive explorer interface, as the explorer does not support macro recording. +

+

Key Bindings for BigStitcher

@@ -79,8 +91,14 @@

Key Bindings for BigStitcher

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
F1Show this help window.
C Switch between fused mode and random coloring of image stacks.
VToggle ViewSetup ID overlay in BigDataViewer (shows setup IDs on screen).
L Display links between images used for registation @@ -88,6 +106,45 @@

Key Bindings for BigStitcher

R Re-orient BigDataViewer onto the currently selected tiles.
Cmd+A (Mac)
Ctrl+A (Win/Linux)
Select all views in the table.
+Open selection dialog to filter views by criteria (ranges, comma-separated values, AND/OR logic).
< or ,Navigate backward in selection history (undo selection).
> or .Navigate forward in selection history (redo selection).
EEnable fly-through recording mode (Easter Egg). Once enabled, the following keys become active:
aAdd current BDV view as keypoint for fly-through.
xClear all keypoints.
dDelete last keypoint.
jJump BDV to the last keypoint.
rStart recording fly-through animation.
sSave all keypoints to file.
lLoad keypoints from file.
RMake a high-resolution screenshot with user-defined resolution.