diff --git a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java index 587fb3d4..abd58d4b 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java +++ b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerFrame.java @@ -3,6 +3,7 @@ import net.miginfocom.swing.MigLayout; import org.micromanager.lightsheetmanager.api.data.GeometryType; +import org.micromanager.lightsheetmanager.api.data.LightSheetType; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.data.Icons; import org.micromanager.lightsheetmanager.gui.tabs.TabPanel; @@ -45,6 +46,18 @@ public LightSheetManagerFrame(final LightSheetManager model, final boolean isLoa model_.setErrorText("SCAPE geometry does not support multiple imaging paths. " + " Use the \"SimultaneousCameras\" property to support multiple cameras."); createErrorUserInterface(); + return; + } + if (model_.devices().adapter().numIlluminationPaths() > 1) { + model_.setErrorText("SCAPE geometry can only have a single illumination path."); + createErrorUserInterface(); + return; + } + if (model_.devices().adapter().lightSheetType() == LightSheetType.SCANNED) { + model_.setErrorText("Scanned light sheets are not implemented for SCAPE geometry, " + + "please contact the developers if you need this feature."); + createErrorUserInterface(); + return; } createUserInterface(); // update after loading the settings and creating ui diff --git a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java index 8d24b24d..f49b99f5 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java +++ b/src/main/java/org/micromanager/lightsheetmanager/LightSheetManagerPlugin.java @@ -14,7 +14,7 @@ public class LightSheetManagerPlugin implements MenuPlugin, SciJavaPlugin { public static final String copyright = "Applied Scientific Instrumentation (ASI), 2022-2026"; public static final String description = "A plugin to control various types of light sheet microscopes."; public static final String menuName = "Light Sheet Manager"; - public static final String version = "0.6.3"; + public static final String version = "0.6.4"; private Studio studio_; private LightSheetManager model_; 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 f7b0e4a5..60b9f929 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/CameraTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/CameraTab.java @@ -1,14 +1,15 @@ package org.micromanager.lightsheetmanager.gui.tabs; -import org.micromanager.lightsheetmanager.api.data.CameraMode; import org.micromanager.lightsheetmanager.gui.components.Button; -import org.micromanager.lightsheetmanager.gui.components.ComboBox; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.ListeningPanel; import org.micromanager.lightsheetmanager.gui.components.Panel; import org.micromanager.lightsheetmanager.LightSheetManager; +import org.micromanager.lightsheetmanager.gui.components.Spinner; +import org.micromanager.lightsheetmanager.model.devices.cameras.CameraBase; import java.awt.Font; +import java.awt.Rectangle; import java.util.Objects; public class CameraTab extends Panel implements ListeningPanel { @@ -19,9 +20,12 @@ public class CameraTab extends Panel implements ListeningPanel { private Button btnQuarterROI_; private Button btnEigthROI_; private Button btnCustomROI_; - private Button btnGetCurrentROI_; + private Button btnCurrentROI_; - private ComboBox cmbCameraTriggerMode_; + private Spinner spnOffsetX_; + private Spinner spnOffsetY_; + private Spinner spnWidth_; + private Spinner spnHeight_; private final LightSheetManager model_; @@ -36,8 +40,8 @@ private void createUserInterface() { final Panel pnlROI = new Panel("Imaging ROI"); - final Label lblXOffset = new Label("X Offset:"); - final Label lblYOffset = new Label("Y Offset:"); + final Label lblOffsetX = new Label("Offset X:"); + final Label lblOffsetY = new Label("Offset Y:"); final Label lblWidth = new Label("Width:"); final Label lblHeight = new Label("Height:"); @@ -47,7 +51,12 @@ private void createUserInterface() { btnQuarterROI_ = new Button("1/4", 70, 30); btnEigthROI_ = new Button("1/8", 70, 30); btnCustomROI_ = new Button("Custom", 140, 30); - btnGetCurrentROI_ = new Button("Get Current ROI", 140, 30); + btnCurrentROI_ = new Button("Get Current ROI", 140, 30); + + spnOffsetX_ = Spinner.createIntegerSpinner(0, 0, Integer.MAX_VALUE, 1); + spnOffsetY_ = Spinner.createIntegerSpinner(0, 0, Integer.MAX_VALUE, 1); + spnWidth_ = Spinner.createIntegerSpinner(0, 0, Integer.MAX_VALUE, 1); + spnHeight_ = Spinner.createIntegerSpinner(0, 0, Integer.MAX_VALUE, 1); pnlROI.add(btnUnchangedROI_, "span 2, wrap"); pnlROI.add(btnFullROI_, ""); @@ -55,19 +64,95 @@ private void createUserInterface() { pnlROI.add(btnQuarterROI_, ""); pnlROI.add(btnEigthROI_, "wrap"); pnlROI.add(btnCustomROI_, "span 2, wrap"); - pnlROI.add(lblXOffset, "wrap"); - pnlROI.add(lblYOffset, "wrap"); - pnlROI.add(lblWidth, "wrap"); - pnlROI.add(lblHeight, "wrap"); - pnlROI.add(btnGetCurrentROI_, "span 2"); - + pnlROI.add(lblOffsetX, ""); + pnlROI.add(spnOffsetX_, "wrap"); + pnlROI.add(lblOffsetY, ""); + pnlROI.add(spnOffsetY_, "wrap"); + pnlROI.add(lblWidth, ""); + pnlROI.add(spnWidth_, "wrap"); + pnlROI.add(lblHeight, ""); + pnlROI.add(spnHeight_, "wrap"); + pnlROI.add(btnCurrentROI_, "span 2"); add(lblTitle, "wrap"); add(pnlROI, "wrap"); } + // TODO: should change roi for all cameras? private void createEventHandlers() { - //model_.studio().core().setROI(); + // roi is full camera + btnFullROI_.registerListener(() -> { + final CameraBase[] cameras = model_.devices().imagingCameras(); + for (CameraBase camera : cameras) { + camera.setROI(camera.getResolution()); + } + }); + + // roi 1/2 + btnHalfROI_.registerListener(() -> { + final CameraBase[] cameras = model_.devices().imagingCameras(); + for (CameraBase camera : cameras) { + camera.setROI(computeCenterRectangle(camera.getResolution(), 2)); + } + }); + + // roi 1/4 + btnQuarterROI_.registerListener(() -> { + final CameraBase[] cameras = model_.devices().imagingCameras(); + for (CameraBase camera : cameras) { + camera.setROI(computeCenterRectangle(camera.getResolution(), 4)); + } + }); + + // roi 1/8 + btnEigthROI_.registerListener(() -> { + final CameraBase[] cameras = model_.devices().imagingCameras(); + for (CameraBase camera : cameras) { + camera.setROI(computeCenterRectangle(camera.getResolution(), 8)); + } + }); + + // set custom roi + btnCustomROI_.registerListener(() -> { + final CameraBase[] cameras = model_.devices().imagingCameras(); + for (CameraBase camera : cameras) { + camera.setROI(customROI()); + } + }); + + // populate spinner with current roi + btnCurrentROI_.registerListener(() -> { + final Rectangle roi = model_.devices().firstImagingCamera().getROI(); + spnOffsetX_.setValue(roi.x); + spnOffsetY_.setValue(roi.y); + spnWidth_.setValue(roi.width); + spnHeight_.setValue(roi.height); + }); + } + + // Returns the custom ROI set by the spinners. + private Rectangle customROI() { + return new Rectangle( + spnOffsetX_.getInt(), spnOffsetY_.getInt(), + spnWidth_.getInt(), spnHeight_.getInt() + ); + } + + // Computes the ROI based on a scaling factor. + private Rectangle computeCenterRectangle(final Rectangle rect, final int scale) { + if (scale < 1) { + model_.studio().logs().showError("scale must be > 1; could not compute ROI!"); + return rect; + } + if (rect.x != 0 || rect.y != 0) { + model_.studio().logs().showError("position must be (0, 0); could not compute ROI!"); + return rect; + } + final int width = rect.width / scale; + final int height = rect.height / scale; + final int x = (rect.width - width) / 2; + final int y = (rect.height - height) / 2; + return new Rectangle(x, y, width, height); } @Override diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SetupPathTab.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SetupPathTab.java index a36e6d8e..6dfe1838 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SetupPathTab.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/SetupPathTab.java @@ -1,7 +1,6 @@ package org.micromanager.lightsheetmanager.gui.tabs; import org.micromanager.lightsheetmanager.api.data.CameraMode; -import org.micromanager.lightsheetmanager.api.data.GeometryType; import org.micromanager.lightsheetmanager.gui.components.Label; import org.micromanager.lightsheetmanager.gui.components.ListeningPanel; import org.micromanager.lightsheetmanager.gui.components.Panel; @@ -36,15 +35,7 @@ private void createUserInterface() { } public void swapPanels(final CameraMode cameraMode) { - setupPanel_.getBeamSheetPanel().swapPanels(cameraMode); - } - - public int getPathNum() { - return pathNum_; - } - - public SetupPanel getSetupPanel() { - return setupPanel_; + setupPanel_.getLightSheetPanel().swapPanels(cameraMode); } @Override diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/TabPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/TabPanel.java index 0c7a0a2a..8ec172e2 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/TabPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/TabPanel.java @@ -3,7 +3,6 @@ import org.micromanager.lightsheetmanager.api.data.CameraMode; import org.micromanager.lightsheetmanager.LightSheetManagerFrame; import org.micromanager.lightsheetmanager.LightSheetManager; -import org.micromanager.lightsheetmanager.api.data.GeometryType; import org.micromanager.lightsheetmanager.model.DeviceManager; import org.micromanager.lightsheetmanager.gui.components.Panel; import org.micromanager.lightsheetmanager.gui.components.TabbedPane; @@ -13,7 +12,6 @@ /** * The tabbed pane to select between different settings panels. - * */ public class TabPanel extends Panel { @@ -26,7 +24,7 @@ public class TabPanel extends Panel { private final TabbedPane tabbedPane_; - private DeviceManager devices_; + private final DeviceManager devices_; private final LightSheetManager model_; private final LightSheetManagerFrame frame_; @@ -105,18 +103,10 @@ public void swapSetupPathPanels(final CameraMode cameraMode) { } } - public NavigationTab getNavigationTab() { - return navigationTab_; - } - public AcquisitionTab getAcquisitionTab() { return acquisitionTab_; } - public CameraTab getCameraTab() { - return cameraTab_; - } - public SetupPathTab getSetupPathTab(final int view) { return setupPathTabs_.get(view-1); } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CalibrationPanel.java similarity index 97% rename from src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java rename to src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CalibrationPanel.java index 40822a79..275372a3 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/PiezoCalibrationPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/CalibrationPanel.java @@ -15,7 +15,7 @@ import java.awt.Dimension; import java.util.Objects; -public class PiezoCalibrationPanel extends Panel { +public class CalibrationPanel extends Panel { private Button btnTwoPoint_; private Button btnUpdate_; @@ -37,7 +37,7 @@ public class PiezoCalibrationPanel extends Panel { private final PositionPanel panel_; private final LightSheetManager model_; - public PiezoCalibrationPanel(final LightSheetManager model, final PositionPanel panel, final int pathNum) { + public CalibrationPanel(final LightSheetManager model, final PositionPanel panel, final int pathNum) { super("Galvo Piezo Calibration"); model_ = Objects.requireNonNull(model); panel_ = Objects.requireNonNull(panel); diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java index cc8a69d9..168d8b78 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/JoystickPanel.java @@ -3,26 +3,74 @@ import org.micromanager.lightsheetmanager.gui.components.ComboBox; import org.micromanager.lightsheetmanager.gui.components.Panel; import org.micromanager.lightsheetmanager.LightSheetManager; +import org.micromanager.lightsheetmanager.model.devices.vendor.ASIPiezo; +import org.micromanager.lightsheetmanager.model.devices.vendor.ASIScanner; +import org.micromanager.lightsheetmanager.model.devices.vendor.ASIXYStage; +import org.micromanager.lightsheetmanager.model.devices.vendor.ASIZStage; +import org.micromanager.lightsheetmanager.model.devices.vendor.Joystick; import javax.swing.JLabel; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -// TODO: find a better way to organize vendor specific panels/ui elements +/** + * Control an ASI joystick. + */ public class JoystickPanel extends Panel { private ComboBox cmbJoystick_; private ComboBox cmbLeftWheel_; private ComboBox cmbRightWheel_; - private LightSheetManager model_; + private String previousJoystick_; + private String previousLeftWheel_; + private String previousRightWheel_; + private Map methods_; + + private final LightSheetManager model_; public JoystickPanel(final LightSheetManager model) { super("Joystick"); model_ = Objects.requireNonNull(model); + if (model_.devices().isUsingPLogic()) { + createMap(); + } createUserInterface(); createEventHandlers(); } + private void createMap() { + final ASIXYStage xyStage = model_.devices().device("SampleXY"); + final ASIZStage zStage = model_.devices().device("SampleZ"); + final ASIScanner scanner = model_.devices().device("IllumSlice"); + final ASIPiezo piezo = model_.devices().device("ImagingFocus"); + + // set to the default values + previousJoystick_ = "None"; + previousLeftWheel_ = "None"; + previousRightWheel_ = "None"; + + methods_ = new HashMap<>(); + + // joystick keys + methods_.put("None", () -> { /* do nothing */ }); + methods_.put("Scanner", () -> { + scanner.js().inputX(Joystick.Input.NONE); + scanner.js().inputY(Joystick.Input.NONE); + }); + methods_.put("XYStage", () -> xyStage.js().enabled(false)); + + // wheel keys + methods_.put("Imaging Piezo", () -> piezo.js().input(Joystick.Input.NONE)); + methods_.put("Imaging Slice", () -> { + scanner.js().inputX(Joystick.Input.NONE); + scanner.js().inputY(Joystick.Input.NONE); + }); + methods_.put("Light Sheet Tilt", () -> {}); // TODO: impl + methods_.put("Sample Height", () -> zStage.js().input(Joystick.Input.NONE)); + } + private void createUserInterface() { final JLabel lblJoystick = new JLabel("Joystick:"); final JLabel lblLeftWheel = new JLabel("Left Wheel:"); @@ -34,12 +82,23 @@ private void createUserInterface() { "[]5[]" ); - // TODO: enum for combo values - String[] labels = {"Imaging Piezo", "XYStage", "Imaging Slice"}; + final String[] joystickLabels = { + "None", + "Scanner", + "XYStage" + }; - cmbJoystick_ = new ComboBox<>(labels, "XYStage", 100, 20); - cmbLeftWheel_ = new ComboBox<>(labels, "Imaging Piezo", 100, 20); - cmbRightWheel_ = new ComboBox<>(labels, "Imaging Slice", 100, 20); + final String[] wheelLabels = { + "None", + "Imaging Piezo", + "Imaging Slice", + "Light Sheet Tilt", + "Sample Height" + }; + + cmbJoystick_ = new ComboBox<>(joystickLabels, "None", 100, 24); + cmbLeftWheel_ = new ComboBox<>(wheelLabels, "None", 100, 24); + cmbRightWheel_ = new ComboBox<>(wheelLabels, "None", 100, 24); add(lblJoystick, ""); add(cmbJoystick_, "wrap"); @@ -51,17 +110,83 @@ private void createUserInterface() { private void createEventHandlers() { + // select joystick input cmbJoystick_.registerListener(() -> { - + final String selected = cmbJoystick_.getSelected(); + methods_.get(previousJoystick_).run(); // disable the previous device + switch (selected) { + case "None": + return; // early exit => do nothing + case "Scanner": + final ASIScanner scanner = model_.devices().device("IllumSlice"); + scanner.js().inputX(Joystick.Input.JOYSTICK_X); + scanner.js().inputY(Joystick.Input.JOYSTICK_Y); + break; + case "XYStage": + final ASIXYStage xyStage = model_.devices().device("SampleXY"); + xyStage.js().enabled(true); + break; + default: + break; + } + // track the previous device to disable later + previousJoystick_ = selected; }); + // select left wheel input cmbLeftWheel_.registerListener(() -> { - + final String selected = cmbLeftWheel_.getSelected(); + methods_.get(previousLeftWheel_).run(); // disable the previous device + switch (selected) { + case "Imaging Piezo": + final ASIPiezo piezo = model_.devices().device("ImagingFocus"); + piezo.js().input(Joystick.Input.LEFT_WHEEL); + break; + case "Imaging Slice": + final ASIScanner scanner = model_.devices().device("IllumSlice"); + scanner.js().inputX(Joystick.Input.LEFT_WHEEL); + break; + case "Light Sheet Tilt": + //final ASIZStage stage = model_.devices().device("SampleZ"); + //stage.js().input(Joystick.Input.LEFT_WHEEL); + break; + case "Sample Height": + final ASIZStage zStage = model_.devices().device("SampleZ"); + zStage.js().input(Joystick.Input.LEFT_WHEEL); + break; + default: + break; + } + // track the previous device to disable later + previousLeftWheel_ = selected; }); + // select right wheel input cmbRightWheel_.registerListener(() -> { - + final String selected = cmbRightWheel_.getSelected(); + methods_.get(previousRightWheel_).run(); // disable the previous device + switch (selected) { + case "Imaging Piezo": + final ASIPiezo piezo = model_.devices().device("ImagingFocus"); + piezo.js().input(Joystick.Input.RIGHT_WHEEL); + break; + case "Imaging Slice": + final ASIScanner scanner = model_.devices().device("IllumSlice"); + scanner.js().inputX(Joystick.Input.RIGHT_WHEEL); + break; + case "Light Sheet Tilt": + //final ASIZStage stage = model_.devices().device("SampleZ"); + //stage.js().input(Joystick.Input.RIGHT_WHEEL); + break; + case "Sample Height": + final ASIZStage zStage = model_.devices().device("SampleZ"); + zStage.js().input(Joystick.Input.RIGHT_WHEEL); + break; + default: + break; + } + // track the previous device to disable later + previousRightWheel_ = selected; }); - } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/LightSheetPanel.java similarity index 98% rename from src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java rename to src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/LightSheetPanel.java index caf5bebe..5b47f269 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/BeamSheetControlPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/LightSheetPanel.java @@ -13,7 +13,7 @@ import javax.swing.JLabel; import java.util.Objects; -public class BeamSheetControlPanel extends Panel { +public class LightSheetPanel extends Panel { // first panel private TextField txtSlope_; @@ -50,7 +50,7 @@ public class BeamSheetControlPanel extends Panel { private final LightSheetManager model_; - public BeamSheetControlPanel(final LightSheetManager model, final int pathNum) { + public LightSheetPanel(final LightSheetManager model, final int pathNum) { super("Light Sheet Synchronization"); model_ = Objects.requireNonNull(model); pathNum_ = pathNum; diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ScannerPanel.java similarity index 87% rename from src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java rename to src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ScannerPanel.java index 533269da..46afd0f0 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ExcitationPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/ScannerPanel.java @@ -13,7 +13,7 @@ /** * Activate lasers and light sheet. */ -public class ExcitationPanel extends Panel implements ListeningPanel { +public class ScannerPanel extends Panel implements ListeningPanel { private CheckBox cbxBeamExc_; private CheckBox cbxSheetExc_; @@ -24,7 +24,7 @@ public class ExcitationPanel extends Panel implements ListeningPanel { private final LightSheetManager model_; - public ExcitationPanel(final LightSheetManager model) { + public ScannerPanel(final LightSheetManager model) { super("Scanner"); model_ = Objects.requireNonNull(model); createUserInterface(); @@ -78,17 +78,16 @@ private void createEventHandlers() { }); } - cbxSheetExc_.registerListener(() -> { - - }); - - cbxBeamEpi_.registerListener(() -> { - - }); + if (model_.devices().adapter().geometry() == GeometryType.DISPIM) { + cbxSheetExc_.registerListener(() -> { + }); - cbxSheetEpi_.registerListener(() -> { + cbxBeamEpi_.registerListener(() -> { + }); - }); + cbxSheetEpi_.registerListener(() -> { + }); + } } // TODO: only handles SCAPE for now diff --git a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SetupPanel.java b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SetupPanel.java index e5027cdb..e6ccb084 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SetupPanel.java +++ b/src/main/java/org/micromanager/lightsheetmanager/gui/tabs/setup/SetupPanel.java @@ -12,13 +12,13 @@ */ public class SetupPanel extends Panel implements ListeningPanel { - private PiezoCalibrationPanel piezoPanel_; - private BeamSheetControlPanel beamSheetPanel_; + private CalibrationPanel piezoPanel_; + private LightSheetPanel beamSheetPanel_; private PositionPanel positionPanel_; private JoystickPanel joystickPanel_; - private ExcitationPanel excitationPanel_; + private ScannerPanel scannerPanel_; private CameraPanel cameraPanel_; private Panel leftPanel_; @@ -44,17 +44,17 @@ public SetupPanel(final LightSheetManager model, final int pathNum) { leftPanel_ = new Panel(); rightPanel_ = new Panel(); - beamSheetPanel_ = new BeamSheetControlPanel(model_, pathNum); + beamSheetPanel_ = new LightSheetPanel(model_, pathNum); positionPanel_ = new PositionPanel(model_, pathNum); - piezoPanel_ = new PiezoCalibrationPanel(model_, positionPanel_, pathNum); + piezoPanel_ = new CalibrationPanel(model_, positionPanel_, pathNum); joystickPanel_ = new JoystickPanel(model_); - excitationPanel_ = new ExcitationPanel(model_); + scannerPanel_ = new ScannerPanel(model_); cameraPanel_ = new CameraPanel(model_); // TODO: add joystick panel back in - leftPanel_.add(excitationPanel_, "growx, wrap"); - //leftPanel_.add(joystickPanel_, "growx, wrap"); + leftPanel_.add(scannerPanel_, "growx, wrap"); + leftPanel_.add(joystickPanel_, "growx, wrap"); if (model_.devices().adapter().geometry() == GeometryType.SCAPE) { singleAxisPanel_ = new SingleAxisPanel(model_); leftPanel_.add(singleAxisPanel_, "growx, wrap"); @@ -69,7 +69,7 @@ public SetupPanel(final LightSheetManager model, final int pathNum) { add(rightPanel_, "aligny top"); } - public BeamSheetControlPanel getBeamSheetPanel() { + public LightSheetPanel getLightSheetPanel() { return beamSheetPanel_; } @@ -79,7 +79,7 @@ public int getPathNum() { @Override public void selected() { - excitationPanel_.selected(); + scannerPanel_.selected(); } @Override 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 f7a15170..13655585 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java @@ -991,6 +991,13 @@ private boolean doHardwareCalculations(PLogicScape plc) { } } + if (acqSettings_.isUsingMultiplePositions() && acqSettings_.numTimePoints() > 1) { + if (timepointIntervalMs < volumeDuration) { + studio_.logs().showError("Time point interval shorter than the time to collect a single volume."); + return false; + } + } + // set exposure for imaging camera for (CameraBase camera : cameras) { camera.setExposure(exposureTime); 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 d16347c3..fca33679 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 @@ -187,8 +187,8 @@ public double getReadoutTime(final CameraMode cameraMode) { default: break; } -// ReportingUtils.logDebugMessage("camera readout time computed as " + readoutTimeMs + -// " for camera " + devices_.getMMDevice(camKey)); + studio_.logs().logDebugMessage("camera readout time computed as " + + readoutTimeMs + " for camera " + deviceName_); return readoutTimeMs; } @@ -210,8 +210,8 @@ public double getResetTime(final CameraMode cameraMode) { numRowsOverhead = 10; // overhead of 9 rows plus jitter of 1 row } final double resetTimeMs = camReadoutTime + (numRowsOverhead * rowReadoutTime); -// ReportingUtils.logDebugMessage("camera reset time computed as " + resetTimeMs + -// " for camera " + devices_.getMMDevice(camKey)); + studio_.logs().logDebugMessage("camera reset time computed as " + + resetTimeMs + " for camera " + deviceName_); return resetTimeMs; // assume 10ms readout if not otherwise possible to calculate } } 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 50c46434..9f725889 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 @@ -39,12 +39,12 @@ public static class Values { public final static String EDGE_TRIGGER = "Edge Trigger"; } - public PvCamera(Studio studio, String deviceName) { + public PvCamera(final Studio studio, final String deviceName) { super(studio, deviceName); } @Override - public void setTriggerMode(CameraMode cameraMode) { + public void setTriggerMode(final CameraMode cameraMode) { switch (cameraMode) { case EDGE: case PSEUDO_OVERLAP: @@ -99,7 +99,7 @@ public double getRowReadoutTime() { } @Override - public double getReadoutTime(CameraMode cameraMode) { + public double getReadoutTime(final CameraMode cameraMode) { double readoutTimeMs = 10.0; switch (cameraMode) { case OVERLAP: @@ -109,7 +109,7 @@ public double getReadoutTime(CameraMode cameraMode) { if (isKinetix() || isPrime95B()) { final double preTime = getPropertyFloat(Properties.PRE_TRIGGER_TIME); readoutTimeMs = preTime / 1e6; - // for safety we make sure to wait at least a quarter millisecond to trigger + // for safety, we make sure to wait at least a quarter millisecond to trigger // (may have hidden assumptions in other code about at least one tic wait) if (readoutTimeMs < 0.249) { readoutTimeMs = 0.25; @@ -131,17 +131,18 @@ public double getReadoutTime(CameraMode cameraMode) { default: break; } + studio_.logs().logDebugMessage("camera readout time computed as " + + readoutTimeMs + " for camera " + deviceName_); return readoutTimeMs; } @Override - public double getResetTime(CameraMode cameraMode) { + public double getResetTime(final CameraMode cameraMode) { double resetTimeMs; if (cameraMode == CameraMode.VIRTUAL_SLIT) { resetTimeMs = 0.0; } else { // TODO(Jon): Confirm that the Kinetix camera is like the Prime 95B - // Photometrics Prime 95B is very different from other cameras so handle it as special case if (isKinetix() || isPrime95B()) { final double trigToGlobal = getPropertyFloat(Properties.POST_TRIGGER_TIME) @@ -153,6 +154,8 @@ public double getResetTime(CameraMode cameraMode) { resetTimeMs = 14.25; // strange number just to make it easy to find later; I think the original Prime needs to be added } } + studio_.logs().logDebugMessage("camera reset time computed as " + + resetTimeMs + " for camera " + deviceName_); return resetTimeMs; } diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIPiezo.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIPiezo.java index 4e1960dd..2ee7a761 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIPiezo.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIPiezo.java @@ -9,16 +9,22 @@ public class ASIPiezo extends ASITigerBase { private final SingleAxis singleAxis_; + private final Joystick joystick_; public ASIPiezo(final Studio studio, final String deviceName) { super(studio, deviceName); singleAxis_ = new SingleAxis(studio, deviceName); + joystick_ = new Joystick(studio, deviceName); } public SingleAxis sa() { return singleAxis_; } + public Joystick js() { + return joystick_; + } + public void setPosition(final double position) { try { core_.setPosition(deviceName_, position); diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIScanner.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIScanner.java index 78838f82..881f7205 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIScanner.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIScanner.java @@ -7,30 +7,33 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -// TODO: single axis commands and joystick - /** * ASI Scanner Device - * */ public class ASIScanner extends ASITigerBase { - private SingleAxis singleAxis_; + private final SingleAxis singleAxis_; + private final Joystick joystick_; public ASIScanner(Studio studio, final String deviceName) { super(studio, deviceName); singleAxis_ = new SingleAxis(studio, deviceName); + joystick_ = new Joystick(studio, deviceName); } public SingleAxis sa() { return singleAxis_; } + public Joystick js() { + return joystick_; + } + public void setPosition(final double x, final double y) { try { core_.setGalvoPosition(deviceName_, x, y); } catch (Exception e) { - studio_.logs().showError("Could not move scanner!"); + studio_.logs().showError("Could not move the scanner!"); } } @@ -38,7 +41,7 @@ public Point2D.Double getPosition() { try { return core_.getGalvoPosition(deviceName_); } catch (Exception e) { - studio_.logs().showError("Could get the scanner position!"); + studio_.logs().showError("Could not get the scanner position!"); return new Point2D.Double(0.0, 0.0); } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIXYStage.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIXYStage.java index 635d2fa5..86c04212 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIXYStage.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIXYStage.java @@ -9,8 +9,15 @@ public class ASIXYStage extends ASITigerBase { + private final Joystick joystick_; + public ASIXYStage(final Studio studio, final String deviceName) { super(studio, deviceName); + joystick_ = new Joystick(studio, deviceName); + } + + public Joystick js() { + return joystick_; } public void setRelativeXYPosition(final double x, final double y) { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIZStage.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIZStage.java index 366f49df..e877c8fd 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIZStage.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/ASIZStage.java @@ -4,8 +4,15 @@ public class ASIZStage extends ASITigerBase { + private final Joystick joystick_; + public ASIZStage(final Studio studio, final String deviceName) { super(studio, deviceName); + joystick_ = new Joystick(studio, deviceName); + } + + public Joystick js() { + return joystick_; } public void setPosition(final double position) { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/Joystick.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/Joystick.java index 02cbe647..e3981988 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/Joystick.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/Joystick.java @@ -1,13 +1,100 @@ package org.micromanager.lightsheetmanager.model.devices.vendor; +import org.micromanager.Studio; +import org.micromanager.lightsheetmanager.model.devices.DeviceBase; + import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; -public class Joystick { +public class Joystick extends DeviceBase { + + public Joystick(final Studio studio, final String deviceName) { + super(studio, deviceName); + } + + public void enabled(final boolean state) { + setProperty(Properties.ENABLED, state ? Values.YES : Values.NO); + } + + public boolean enabled() { + return getProperty(Properties.ENABLED).equals(Values.YES); + } + + public void input(final Input input) { + setProperty(Properties.INPUT, input.toString()); + } + + public Input input() { + return Input.fromString(getProperty(Properties.INPUT)); + } + + public void inputX(final Input input) { + setProperty(Properties.INPUT_X, input.toString()); + } + + public Input inputX() { + return Input.fromString(getProperty(Properties.INPUT_X)); + } + + public void inputY(final Input input) { + setProperty(Properties.INPUT_Y, input.toString()); + } + + public Input inputY() { + return Input.fromString(getProperty(Properties.INPUT_Y)); + } + + public void fastSpeed(final double speed) { + setProperty(Properties.FAST_SPEED, String.valueOf(speed)); + } + + public double fastSpeed() { + return Double.parseDouble(getProperty(Properties.FAST_SPEED)); + } + + public void slowSpeed(final double speed) { + setProperty(Properties.SLOW_SPEED, String.valueOf(speed)); + } + + public double slowSpeed() { + return Double.parseDouble(getProperty(Properties.SLOW_SPEED)); + } + + public void reverse(final boolean state) { + setProperty(Properties.REVERSE, state ? Values.YES : Values.NO); + } + + public boolean reverse() { + return getProperty(Properties.REVERSE).equals(Values.YES); + } + + public void rotate(final boolean state) { + setProperty(Properties.ROTATE, state ? Values.YES : Values.NO); + } + + public boolean rotate() { + return getProperty(Properties.ROTATE).equals(Values.YES); + } + + public static class Properties { + public static final String ENABLED = "JoystickEnabled"; + public static final String INPUT = "JoystickInput"; + public static final String INPUT_X = "JoystickInputX"; + public static final String INPUT_Y = "JoystickInputY"; + public static final String REVERSE = "JoystickReverse"; + public static final String ROTATE = "JoystickRotate"; + public static final String FAST_SPEED = "JoystickFastSpeed"; + public static final String SLOW_SPEED = "JoystickSlowSpeed"; + } + + public static class Values { + public static final String YES = "Yes"; + public static final String NO = "No"; + } - public enum JoystickInput { - NONE("0 - None"), + public enum Input { + NONE("0 - none"), JOYSTICK_X("2 - joystick X"), JOYSTICK_Y("3 - joystick Y"), RIGHT_WHEEL("22 - right wheel"), @@ -15,10 +102,10 @@ public enum JoystickInput { private final String text_; - private static final Map stringToEnum = + private static final Map stringToEnum = Stream.of(values()).collect(Collectors.toMap(Object::toString, e -> e)); - JoystickInput(final String text) { + Input(final String text) { text_ = text; } @@ -27,8 +114,8 @@ public String toString() { return text_; } - public static JoystickInput fromString(final String symbol) { - return stringToEnum.getOrDefault(symbol, JoystickInput.NONE); + public static Input fromString(final String symbol) { + return stringToEnum.getOrDefault(symbol, Input.NONE); } } } diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/SingleAxis.java b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/SingleAxis.java index 0162bfcf..d711fc4b 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/SingleAxis.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/devices/vendor/SingleAxis.java @@ -10,7 +10,7 @@ public class SingleAxis extends DeviceBase { - public SingleAxis(Studio studio, String deviceName) { + public SingleAxis(final Studio studio, final String deviceName) { super(studio, deviceName); } @@ -204,7 +204,6 @@ public static String[] toArray() { } } - public enum ClockSource { EXTERNAL("external clock"), INTERNAL("internal 4kHz clock"); @@ -228,7 +227,6 @@ public static ClockSource fromString(final String symbol) { } } - public enum ClockPolarity { NEGATIVE("negative edge"), POSITIVE("positive edge");