1616import org .micromanager .Studio ;
1717import org .micromanager .internal .positionlist .utils .ZGenerator ;
1818import org .micromanager .internal .utils .WindowPositioning ;
19+ import org .micromanager .propertymap .MutablePropertyMapView ;
1920
2021/**
2122 * Stand-alone window for Refine Z. Opened from the Explorer dialog's "Refine Z..." button so the
2829 */
2930public class RefineZFrame extends JFrame {
3031
32+ private static final String EDGE_MARGIN = "RefineZEdgeMargin" ;
33+ private static final String AF_METHOD = "RefineZAutofocusMethod" ;
34+
3135 private final Studio studio_ ;
3236 private final ExplorerManager explorerManager_ ;
3337 private final ExplorerFrame explorerFrame_ ;
38+ private final MutablePropertyMapView settings_ ;
3439
3540 private final JRadioButton autoRadio_ ;
3641 private final JRadioButton manualRadio_ ;
3742 private final JComboBox <ZGenerator .Type > interpCombo_ ;
3843 private final JComboBox <String > afCombo_ ;
3944 private final JSpinner pointsSpinner_ ;
45+ private final JSpinner edgeMarginSpinner_ ;
4046 private final JButton startButton_ ;
4147 private final JButton cancelButton_ ;
4248 private final JButton setButton_ ;
@@ -62,6 +68,7 @@ public RefineZFrame(Studio studio, ExplorerManager explorerManager,
6268 studio_ = studio ;
6369 explorerManager_ = explorerManager ;
6470 explorerFrame_ = explorerFrame ;
71+ settings_ = studio_ .profile ().getSettings (RefineZFrame .class );
6572
6673 setTitle ("Refine Z" );
6774 URL iconUrl = getClass ().getResource ("/org/micromanager/icons/microscope.gif" );
@@ -104,6 +111,7 @@ public RefineZFrame(Studio studio, ExplorerManager explorerManager,
104111 afCombo_ .addActionListener (e -> {
105112 Object sel = afCombo_ .getSelectedItem ();
106113 if (sel != null && !syncingAf_ ) {
114+ settings_ .putString (AF_METHOD , sel .toString ());
107115 try {
108116 studio_ .getAutofocusManager ().setAutofocusMethodByName (sel .toString ());
109117 } catch (Exception ex ) {
@@ -112,16 +120,29 @@ public RefineZFrame(Studio studio, ExplorerManager explorerManager,
112120 }
113121 });
114122 panel .add (afCombo_ );
123+ // Created before the Start button so its action listener can read it (final field).
124+ edgeMarginSpinner_ = new JSpinner (new SpinnerNumberModel (
125+ settings_ .getInteger (EDGE_MARGIN , 0 ), 0 , 99 , 1 ));
126+ edgeMarginSpinner_ .setToolTipText (
127+ "Exclude reference points within this many tiles of the grid edge. "
128+ + "Outer tiles often only partially overlap the sample and can fail autofocus. "
129+ + "0 = use all tiles." );
130+ edgeMarginSpinner_ .addChangeListener (e ->
131+ settings_ .putInteger (EDGE_MARGIN , (Integer ) edgeMarginSpinner_ .getValue ()));
115132 startButton_ = new JButton ("Start" );
116133 startButton_ .addActionListener (e -> {
117134 Object af = afCombo_ .getSelectedItem ();
118135 explorerManager_ .startRefineZAutomatic (
119136 (Integer ) pointsSpinner_ .getValue (),
120137 af != null ? af .toString () : null ,
121- explorerFrame_ .isWithinVesselSelected ());
138+ explorerFrame_ .isWithinVesselSelected (),
139+ (Integer ) edgeMarginSpinner_ .getValue ());
122140 });
123141 panel .add (startButton_ , "wrap" );
124142
143+ panel .add (new JLabel ("Exclude edge margin (tiles):" ), "split 2" );
144+ panel .add (edgeMarginSpinner_ , "wrap" );
145+
125146 cancelButton_ = new JButton ("Cancel" );
126147 cancelButton_ .setToolTipText ("Cancel the running automatic Refine Z" );
127148 cancelButton_ .addActionListener (e -> explorerManager_ .cancelRefineZ ());
@@ -155,8 +176,11 @@ public RefineZFrame(Studio studio, ExplorerManager explorerManager,
155176
156177 add (panel , "growx, wrap" );
157178
158- // Populate autofocus methods and select the current interpolation method.
179+ // Populate autofocus methods. Restore the method saved in the profile when it is still
180+ // available, applying it to the main MM window so the two stay in sync; otherwise fall back
181+ // to whatever method MM currently has active.
159182 refreshAfMethods ();
183+ restoreSavedAfMethod ();
160184 explorerManager_ .setRefineZMethod ((ZGenerator .Type ) interpCombo_ .getSelectedItem ());
161185
162186 // Re-sync the AF method from the main window each time this window regains focus, since the
@@ -197,6 +221,25 @@ private void refreshAfMethods() {
197221 }
198222 }
199223
224+ /**
225+ * Selects the autofocus method remembered in the profile (if present and still installed) and
226+ * pushes it to the main MM window. Called once at construction so a remembered choice wins over
227+ * MM's current method; later focus-driven {@link #refreshAfMethods()} calls follow MM.
228+ */
229+ private void restoreSavedAfMethod () {
230+ String saved = settings_ .getString (AF_METHOD , null );
231+ if (saved == null || saved .isEmpty ()) {
232+ return ;
233+ }
234+ for (int i = 0 ; i < afCombo_ .getItemCount (); i ++) {
235+ if (saved .equals (afCombo_ .getItemAt (i ))) {
236+ // Not syncing: we want this selection to propagate to the AutofocusManager.
237+ afCombo_ .setSelectedItem (saved );
238+ return ;
239+ }
240+ }
241+ }
242+
200243 /** Notifies whether an automatic Refine-Z run is in progress; switches to EDT. */
201244 public void setRefineZRunning (boolean running ) {
202245 SwingUtilities .invokeLater (() -> {
@@ -218,6 +261,7 @@ private void updateEnabled() {
218261 autoRadio_ .setEnabled (!running_ );
219262 manualRadio_ .setEnabled (!running_ );
220263 pointsSpinner_ .setEnabled (auto && !running_ );
264+ edgeMarginSpinner_ .setEnabled (auto && !running_ );
221265 afCombo_ .setEnabled (auto && !running_ );
222266 startButton_ .setEnabled (auto && !running_ );
223267 cancelButton_ .setEnabled (auto && running_ );
0 commit comments