diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/data/AcquisitionMode.java b/src/main/java/org/micromanager/lightsheetmanager/api/data/AcquisitionMode.java index aa579f4..b6c0f8e 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/data/AcquisitionMode.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/data/AcquisitionMode.java @@ -15,7 +15,9 @@ // Note: Each text string must be unique to support reliable lookup in fromString(). /** - * Acquisition modes for all microscope geometry types. + * Acquisition modes for all microscope geometries. + *

+ * Use the {@code modesByType} method to get valid modes based on {@link GeometryType}. */ public enum AcquisitionMode { NO_SCAN("No scan (fixed sheet)"), @@ -71,7 +73,7 @@ public String toString() { } /** - * Returns {@code true} if the {@link AcquisitionMode} is a stage scan mode. + * Returns {@code true} if the {@code AcquisitionMode} is a stage scan mode. * * @return {@code true} if the mode is stage scan mode */ @@ -85,13 +87,13 @@ public boolean isStageScanMode() { * This list is filtered based on hardware capabilities: if {@code hasStageScanning} * is {@code false}, all stage-scan related modes are excluded. * - * @param geometry the {@link GeometryType} to query; if {@code null}, an empty list is returned + * @param geometryType the {@link GeometryType} to query; if {@code null}, an empty list is returned * @param hasStageScanning {@code true} if stage scan hardware is available - * @return a {@code List} of {@link AcquisitionMode} constants + * @return an array of {@code AcquisitionMode} constants */ - public static AcquisitionMode[] getValidModes(final GeometryType geometry, final boolean hasStageScanning) { - return Optional.ofNullable(geometry) - .map(MODES_BY_GEOMETRY::get) // returns null if geometry is not in map + public static AcquisitionMode[] modesByType(final GeometryType geometryType, final boolean hasStageScanning) { + return Optional.ofNullable(geometryType) + .map(MODES_BY_GEOMETRY::get) // returns null if geometryType is not in map .orElse(Collections.emptyList()) .stream() .filter(mode -> hasStageScanning || !mode.isStageScanMode()) diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraData.java b/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraData.java index 9f7abe0..e3dcff7 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraData.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraData.java @@ -35,4 +35,10 @@ public static boolean isCameraActive(final CameraData[] cameras, final String ca } return false; } + + @Override + public String toString() { + return String.format("%s[name=%s]", getClass().getSimpleName(), name_); + } + } diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraMode.java b/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraMode.java index 6b968b3..9b86ea9 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraMode.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/data/CameraMode.java @@ -1,7 +1,6 @@ package org.micromanager.lightsheetmanager.api.data; import java.util.ArrayList; -import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -10,8 +9,6 @@ /** * Camera trigger modes. - * - *

All modes should use hardware triggering. */ public enum CameraMode { INTERNAL("Internal"), @@ -23,7 +20,7 @@ public enum CameraMode { private final String text_; - private static final Map stringToEnum = + private static final Map STRING_TO_ENUM = Stream.of(values()).collect(Collectors.toUnmodifiableMap(Object::toString, e -> e)); CameraMode(final String text) { @@ -31,7 +28,7 @@ public enum CameraMode { } public static CameraMode fromString(final String symbol) { - return stringToEnum.getOrDefault(symbol, CameraMode.EDGE); + return STRING_TO_ENUM.getOrDefault(symbol, CameraMode.EDGE); } /** @@ -53,11 +50,11 @@ public static boolean hasOverlapTrigger(final CameraLibrary camLib) { * @param camLib the camera device adapter * @return {@code true} if the camera supports the mode */ - private static boolean hasPseudoOverlapTrigger(CameraLibrary camLib) { + private static boolean hasPseudoOverlapTrigger(final CameraLibrary camLib) { return camLib == CameraLibrary.PCOCAMERA || camLib == CameraLibrary.PVCAM; } - private static boolean hasLevelTrigger(CameraLibrary camLib) { + private static boolean hasLevelTrigger(final CameraLibrary camLib) { return camLib == CameraLibrary.HAMAMATSU || camLib == CameraLibrary.ANDORSDK3 || camLib == CameraLibrary.PCOCAMERA; @@ -69,37 +66,35 @@ private static boolean hasLevelTrigger(CameraLibrary camLib) { * @param camLib the camera device adapter * @return {@code true} if the camera supports the mode */ - private static boolean hasLightSheetTrigger(CameraLibrary camLib) { + private static boolean hasLightSheetTrigger(final CameraLibrary camLib) { return camLib == CameraLibrary.HAMAMATSU || camLib == CameraLibrary.ANDORSDK3 || camLib == CameraLibrary.PVCAM || // not sure about this camLib == CameraLibrary.DEMOCAMERA; // for testing only } - public static boolean isCameraValid(CameraLibrary camLib) { + public static boolean isCameraValid(final CameraLibrary camLib) { return camLib != CameraLibrary.UNKNOWN; } - public static CameraMode[] getAvailableModes(CameraLibrary camLib) { + public static CameraMode[] modesByDeviceLibrary(final CameraLibrary cameraLibrary) { ArrayList modes = new ArrayList<>(); - if (isCameraValid(camLib)) { + if (isCameraValid(cameraLibrary)) { modes.add(CameraMode.EDGE); - if (hasLevelTrigger(camLib)) { + if (hasLevelTrigger(cameraLibrary)) { modes.add(CameraMode.LEVEL); } - if (hasOverlapTrigger(camLib)) { + if (hasOverlapTrigger(cameraLibrary)) { modes.add(CameraMode.OVERLAP); } - if (hasPseudoOverlapTrigger(camLib)) { + if (hasPseudoOverlapTrigger(cameraLibrary)) { modes.add(CameraMode.PSEUDO_OVERLAP); } - if (hasLightSheetTrigger(camLib)) { + if (hasLightSheetTrigger(cameraLibrary)) { modes.add(CameraMode.VIRTUAL_SLIT); } } - return modes.stream() - .map(CameraMode::toString) - .toArray(CameraMode[]::new); + return modes.toArray(CameraMode[]::new); } @Override diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettings.java b/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettings.java index c494d67..a6aeab2 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettings.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettings.java @@ -5,8 +5,6 @@ import org.micromanager.lightsheetmanager.api.AcquisitionSettings; import org.micromanager.lightsheetmanager.model.DataStorage; -// TODO: make public instead of abstract? use this in demo mode? - /** * Base acquisition settings for all microscopes. */ @@ -14,8 +12,8 @@ public abstract class DefaultAcquisitionSettings implements AcquisitionSettings public abstract static class Builder> implements AcquisitionSettings.Builder { - private String saveDirectory_ = ""; - private String saveNamePrefix_ = ""; + private String saveDirectory_ = System.getProperty("user.home"); + private String saveNamePrefix_ = "Experiment"; private boolean saveDuringAcq_ = false; private boolean demoMode_ = false; private DataStorage.SaveMode saveMode_ = DataStorage.SaveMode.ND_TIFF; diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java index 74e1a8d..2a7fe97 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/CheckBox.java @@ -9,6 +9,8 @@ public class CheckBox extends JCheckBox { public static final int LEFT = SwingConstants.LEFT; public static final int RIGHT = SwingConstants.RIGHT; + private boolean isLocked_ = false; + public CheckBox(final String text, final boolean defaultState) { super(text, defaultState); setHorizontalTextPosition(RIGHT); @@ -28,8 +30,59 @@ public CheckBox(final String text, final int fontSize, final boolean defaultStat setFocusPainted(false); } + /** + * Set the locked state, in the locked state the {@code CheckBox} + * will not respond to button presses or mouse clicks. + * + * @param locked the locked state + */ + public void setLocked(final boolean locked) { + isLocked_ = locked; + if (locked) { + setFont(getFont().deriveFont(java.awt.Font.BOLD)); + } else { + setFont(getFont().deriveFont(java.awt.Font.PLAIN)); + } + } + + /** + * Sets the selected state of the {@code CheckBox}. + * + * @param state the new selection state + * @param shouldFire {@code true} fires events, {@code false} updates silently + */ + public void setSelected(boolean state, boolean shouldFire) { + if (shouldFire) { + // Standard behavior: updates state and triggers events + super.setSelected(state); + } else { + // "Silent" behavior: updates state via model without firing ActionEvents + getModel().setSelected(state); + } + } + public void registerListener(final Method method) { - addItemListener(method::run); + addActionListener(method::run); + } + + @Override + public void setSelected(boolean state) { + // default to true, always fires events + setSelected(state, true); + } + + @Override + protected void processMouseEvent(java.awt.event.MouseEvent e) { + if (!isLocked_) { + super.processMouseEvent(e); + } + } + + @Override + protected void processKeyEvent(java.awt.event.KeyEvent e) { + if (!isLocked_) { + super.processKeyEvent(e); + } } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java b/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java index 4ce2f23..c24d375 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/components/RadioButton.java @@ -79,7 +79,8 @@ public void setSelected(final String text, final boolean state) { } } - public String getSelectedButtonText() { + // Returns the text of the selected button. + public String getSelectedText() { for (final JRadioButton button : buttons) { if (button.isSelected()) { return button.getText(); @@ -88,6 +89,16 @@ public String getSelectedButtonText() { return ""; } + // Returns the selected index or -1 if nothing is selected. + public int getSelectedIndex() { + for (int i = 0; i < buttons.size(); i++) { + if (buttons.get(i).isSelected()) { + return i; + } + } + return -1; + } + public void registerListener(final Method method) { for (final JRadioButton button : buttons) { button.addActionListener(method::run); diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java index 8f2d2c2..0a30a48 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/AcquisitionTab.java @@ -166,7 +166,8 @@ private void createUserInterface() { // acquisition mode combo box final boolean isUsingScanSettings = model_.devices().isUsingStageScanning(); final GeometryType geometryType = model_.devices().adapter().geometry(); - cmbAcquisitionModes_ = new ComboBox<>(AcquisitionMode.getValidModes(geometryType, isUsingScanSettings), + cmbAcquisitionModes_ = new ComboBox<>( + AcquisitionMode.modesByType(geometryType, isUsingScanSettings), acqSettings.acquisitionMode(), 180, 24); diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/CameraTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/CameraTab.java index cf19cf5..d1c2cd8 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/CameraTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/CameraTab.java @@ -33,6 +33,7 @@ public class CameraTab extends Panel implements ListeningPanel { private RadioButton radPrimaryCamera_; private CheckBox cbxUseSimultaneousCameras_; private List cbxCameras_; + private int selectedIndex_; private final TabPanel tabPanel_; private final LightSheetManager model_; @@ -71,7 +72,7 @@ private void createUserInterface() { final CameraBase camera = model_.devices().firstImagingCamera(); if (camera != null) { final CameraLibrary camLib = CameraLibrary.fromString(camera.getDeviceLibrary()); - modes = CameraMode.getAvailableModes(camLib); + modes = CameraMode.modesByDeviceLibrary(camLib); } cmbCameraTriggerMode_ = new ComboBox<>(modes, @@ -112,6 +113,11 @@ private void createUserInterface() { cbxCameras_.add(checkBox); } + // we can only set this after we load the settings + selectedIndex_ = radPrimaryCamera_.getSelectedIndex(); + // must not disable the primary camera + cbxCameras_.get(selectedIndex_).setLocked(true); + final Panel pnlCameraSelectionRow = new Panel(); pnlCameraSelectionRow.add(new JLabel("Select Primary Camera"), "wrap"); pnlCameraSelectionRow.add(radPrimaryCamera_, ""); @@ -177,31 +183,37 @@ private boolean[] activeCameras() { return active; } + // Change the order of the imaging camera array based on user input. private void computeCameraOrder() { - // change the order of the imaging camera array - final String selected = radPrimaryCamera_.getSelectedButtonText(); - final String[] cameraNames = model_.devices().imagingCameraNames(); - final ArrayList cameraData = new ArrayList<>(cameraNames.length); + // cache the previous index + final int lastSelectedIndex = selectedIndex_; - // check if the selected primary camera is active before changing the array order - boolean isSelectedActive = true; - final boolean[] active = activeCameras(); - for (int i = 0; i < cameraNames.length; i++) { - if (cameraNames[i].equals(selected)) { - isSelectedActive = active[i]; - break; - } - } + // unlock the checkbox for the old primary camera + cbxCameras_.get(lastSelectedIndex).setLocked(false); + + // lock the checkbox for the new primary camera + final String selected = radPrimaryCamera_.getSelectedText(); + selectedIndex_ = radPrimaryCamera_.getSelectedIndex(); + cbxCameras_.get(selectedIndex_).setSelected(true, false); + cbxCameras_.get(selectedIndex_).setLocked(true); // the first array index is the primary camera - cameraData.add(new CameraData(selected, isSelectedActive)); + final String[] cameraNames = model_.devices().imagingCameraNames(); + final ArrayList cameraData = new ArrayList<>(cameraNames.length); + cameraData.add(new CameraData(selected, true)); + // TODO(Brandon): uses simple ordering that works for 2 cameras, - // but needs additional work to support 4. Use a reorderable JTable? + // but needs additional work to support 4. + + // add cameras in a linear order for now + final boolean[] active = activeCameras(); for (int i = 0; i < cameraNames.length; i++) { if (!selected.equals(cameraNames[i])) { cameraData.add(new CameraData(cameraNames[i], active[i])); } } + + // update camera order model_.acquisitions().settingsBuilder() .imagingCameraOrder(cameraData.toArray(CameraData[]::new)); } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/DialogUtils.java b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/DialogUtils.java index 37bb73b..b647470 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/DialogUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/DialogUtils.java @@ -10,7 +10,12 @@ * A utility class for making dialog boxes. * */ -public class DialogUtils { +public final class DialogUtils { + + /** This class should not be instantiated. */ + private DialogUtils() { + throw new AssertionError("Utility class; do not instantiate."); + } /**Standard error reporting or delegate to JTextArea component. */ public static boolean SEND_ERROR_TO_COMPONENT = false; diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java index d219672..87a4b21 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/utils/WindowUtils.java @@ -7,6 +7,11 @@ public final class WindowUtils { + /** This class should not be instantiated. */ + private WindowUtils() { + throw new AssertionError("Utility class; do not instantiate."); + } + /** * Returns true if the window is displayable and not null. * diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineSCAPE.java b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineSCAPE.java index 1691088..1b3aecf 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineSCAPE.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineSCAPE.java @@ -85,15 +85,6 @@ boolean setup() { // return false; // } - // we must have an active camera if we are using simultaneous cameras - if (model_.acquisitions().settings().isUsingSimultaneousCameras()) { - final CameraData[] cameras = model_.acquisitions().settings().imagingCameraOrder(); - if (cameras.length > 0 && !cameras[0].isActive()) { - studio_.logs().showError("The primary camera MUST be active in simultaneous cameras mode!"); - return false; - } - } - // set the "Core-Camera" property to the first logical camera device final String cameraName = model_.devices().firstImagingCamera().getDeviceName(); try { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/AndorCamera.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/AndorCamera.java index 4680f13..be2eae8 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/AndorCamera.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/AndorCamera.java @@ -8,7 +8,7 @@ /** * Support for Andor cameras. - *

Devices Adapter: AndorSDK3 + *

Device Adapter: AndorSDK3 *

Camera Support: Andor Zyla 4.2, Andor Zyla 5.5 */ public class AndorCamera extends CameraBase implements LightSheetCamera { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/DemoCamera.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/DemoCamera.java index dbdf3a9..74046a0 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/DemoCamera.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/DemoCamera.java @@ -9,7 +9,7 @@ /** * Support for the DemoCamera in DHub. *

Note: this is for demo configurations. - *

Devica Adapter: DHub + *

Device Adapter: DHub *

Camera Support: DemoCamera */ public class DemoCamera extends CameraBase implements LightSheetCamera { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/HamamatsuCamera.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/HamamatsuCamera.java index eecdff1..d16347c 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/HamamatsuCamera.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/HamamatsuCamera.java @@ -8,7 +8,7 @@ /** * Support for Hamamatsu cameras. - *

Devices Adapter: HamamatsuHam + *

Device Adapter: HamamatsuHam *

Camera Support: ORCA-Flash4, ORCA-Fusion, ORCA-Fusion BT */ public class HamamatsuCamera extends CameraBase implements LightSheetCamera { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PCOCamera.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PCOCamera.java index 663d221..1dc1a7c 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PCOCamera.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PCOCamera.java @@ -9,8 +9,8 @@ /** * Support for PCO cameras. - * Devices Adapter: PCO_Camera - * Camera Support: Edge 5.5, Panda + *

Device Adapter: PCO_Camera + *

Camera Support: Edge 5.5, Panda */ public class PCOCamera extends CameraBase implements LightSheetCamera { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PVCamera.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PVCamera.java index 4a4e71f..9d0d51e 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PVCamera.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/cameras/PVCamera.java @@ -8,7 +8,7 @@ /** * Support for Teledyne Photometrics cameras. - *

Devices Adapter: PVCAM + *

Device Adapter: PVCAM *

Camera Support: Kinetix, Prime 95B, Prime */ public class PVCamera extends CameraBase implements LightSheetCamera { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/utils/FileUtils.java b/src/main/java/org/micromanager/lightsheetmanager/model/utils/FileUtils.java index 5eb2fd3..325a50c 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/utils/FileUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/utils/FileUtils.java @@ -1,16 +1,19 @@ package org.micromanager.lightsheetmanager.model.utils; +import org.micromanager.internal.MMStudio; + import java.io.File; import java.io.IOException; -// TODO: show errors! -// TODO: better name - - /** - * Read and write to text files using Apache Commons. + * Utilities to read and write to files. */ -public class FileUtils { +public final class FileUtils { + + /** This class should not be instantiated. */ + private FileUtils() { + throw new AssertionError("Utility class; do not instantiate."); + } /** * Reads a text file with UTF-8 encoding into a String. @@ -23,7 +26,7 @@ public static String readFileToString(final String filePath) { try { result = org.apache.commons.io.FileUtils.readFileToString(new File(filePath), "UTF-8"); } catch (IOException e) { - //ReportingUtils.showError("IOException: " + e.getMessage()); + MMStudio.getInstance().logs().logError("FileUtils: readFileToString error"); } return result; } @@ -38,7 +41,7 @@ public static void writeStringToFile(final String filePath, final String content try { org.apache.commons.io.FileUtils.writeStringToFile(new File(filePath), contents, "UTF-8"); } catch (IOException e) { - //ReportingUtils.showError("IOException: " + e.getMessage()); + MMStudio.getInstance().logs().logError("FileUtils: writeStringToFile error"); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/utils/GeometryUtils.java b/src/main/java/org/micromanager/lightsheetmanager/model/utils/GeometryUtils.java index 48ae4c4..0e075f9 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/utils/GeometryUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/utils/GeometryUtils.java @@ -1,7 +1,12 @@ package org.micromanager.lightsheetmanager.model.utils; // TODO: make this generic for diSPIM/SCOPE or have separate static classes -public class GeometryUtils { +public final class GeometryUtils { + + /** This class should not be instantiated. */ + private GeometryUtils() { + throw new AssertionError("Utility class; do not instantiate."); + } /*** * Compute how far we need to shift each image for deskew relative to Z-step size (orthogonal to image) based on user-specified angle diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/utils/JsonUtils.java b/src/main/java/org/micromanager/lightsheetmanager/model/utils/JsonUtils.java index cbd6da2..d075927 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/utils/JsonUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/utils/JsonUtils.java @@ -5,7 +5,12 @@ import java.util.Objects; -public class JsonUtils { +public final class JsonUtils { + + /** This class should not be instantiated. */ + private JsonUtils() { + throw new AssertionError("Utility class; do not instantiate."); + } public static void putJson(JSONObject json, final String property, final Object value) { Objects.requireNonNull(json); diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/utils/MathUtils.java b/src/main/java/org/micromanager/lightsheetmanager/model/utils/MathUtils.java index 867f5f5..d389b28 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/utils/MathUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/utils/MathUtils.java @@ -3,10 +3,11 @@ /** * Math utilities. */ -public class MathUtils { +public final class MathUtils { + /** This class should not be instantiated. */ private MathUtils() { - // prevent instantiation + throw new AssertionError("Utility class; do not instantiate."); } /** diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/utils/NumberUtils.java b/src/main/java/org/micromanager/lightsheetmanager/model/utils/NumberUtils.java index 12fe8ec..a6304a1 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/utils/NumberUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/utils/NumberUtils.java @@ -7,7 +7,12 @@ /** * Utilities for dealing with double precision floating point numbers. */ -public class NumberUtils { +public final class NumberUtils { + + /** This class should not be instantiated. */ + private NumberUtils() { + throw new AssertionError("Utility class; do not instantiate."); + } /** * Return true if the two doubles are equal according to Apache commons-math3 library.