diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/data/MultiChannelMode.java b/src/main/java/org/micromanager/lightsheetmanager/api/data/MultiChannelMode.java index 714c5d9..c522e48 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/data/MultiChannelMode.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/data/MultiChannelMode.java @@ -2,18 +2,18 @@ import java.util.Arrays; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; public enum MultiChannelMode { - NONE("None"), VOLUME("Every Volume"), VOLUME_HW("Every Volume (PLogic)"), SLICE_HW("Every Slice (PLogic)"); private final String text_; - private static final Map stringToEnum = + private static final Map STRING_TO_ENUM = Stream.of(values()).collect(Collectors.toMap(Object::toString, e -> e)); MultiChannelMode(final String text) { @@ -25,10 +25,6 @@ public String toString() { return text_; } - public static MultiChannelMode fromString(final String symbol) { - return stringToEnum.getOrDefault(symbol, MultiChannelMode.NONE); - } - public static MultiChannelMode getByIndex(final int index) { return values()[index]; } @@ -39,4 +35,8 @@ public static String[] toArray() { .toArray(String[]::new); } + public static Optional fromString(final String str) { + return Optional.ofNullable(str).map(STRING_TO_ENUM::get); + } + } diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettingsDISPIM.java b/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettingsDISPIM.java index f0aff61..8e3369f 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettingsDISPIM.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultAcquisitionSettingsDISPIM.java @@ -17,7 +17,7 @@ public static class Builder extends DefaultAcquisitionSettings.Builder private DefaultSheetCalibration.Builder[] shcb_ = new DefaultSheetCalibration.Builder[2]; private DefaultSliceCalibration.Builder[] slcb_ = new DefaultSliceCalibration.Builder[2]; private AcquisitionMode acquisitionMode_ = AcquisitionMode.NO_SCAN; - private MultiChannelMode channelMode_ = MultiChannelMode.NONE; + private MultiChannelMode channelMode_ = MultiChannelMode.VOLUME; private CameraMode cameraMode_ = CameraMode.EDGE; private boolean useChannels_ = false; diff --git a/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultChannelSettings.java b/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultChannelSettings.java index 73f6c9d..5150e98 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultChannelSettings.java +++ b/src/main/java/org/micromanager/lightsheetmanager/api/internal/DefaultChannelSettings.java @@ -12,7 +12,7 @@ public class DefaultChannelSettings implements ChannelSettings { public static class Builder implements ChannelSettings.Builder { private String channelGroup_ = ""; - private MultiChannelMode channelMode_ = MultiChannelMode.NONE; + private MultiChannelMode channelMode_ = MultiChannelMode.VOLUME; private HashMap groups_ = new HashMap<>(); public Builder() { diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/DeviceManager.java b/src/main/java/org/micromanager/lightsheetmanager/model/DeviceManager.java index 76f748a..cb26a54 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/DeviceManager.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/DeviceManager.java @@ -279,18 +279,35 @@ public T requiredDevice(final String name, final Class } public CameraBase firstImagingCamera() { - final LightSheetDeviceManager adapter = model_.devices().adapter(); String deviceKey; - if (adapter.numSimultaneousCameras() > 1 && adapter.numImagingPaths() == 1) { - deviceKey = "ImagingCamera1"; - } else if (adapter.numSimultaneousCameras() > 1) { - deviceKey = "Imaging1Camera1"; - } else if (adapter.numImagingPaths() > 1) { - deviceKey = "Imaging1Camera"; + if (model_.acquisitions().settings().isUsingSimultaneousCameras()) { + deviceKey = firstActiveCameraName(); } else { - deviceKey = "ImagingCamera"; + final LightSheetDeviceManager adapter = model_.devices().adapter(); + if (adapter.numSimultaneousCameras() > 1 && adapter.numImagingPaths() == 1) { + deviceKey = "ImagingCamera1"; + } else if (adapter.numSimultaneousCameras() > 1) { + deviceKey = "Imaging1Camera1"; + } else if (adapter.numImagingPaths() > 1) { + deviceKey = "Imaging1Camera"; + } else { + deviceKey = "ImagingCamera"; + } + } + return (CameraBase) deviceMap_.get(deviceKey); + } + + // TODO: active needs to be synchronized with the order, since order changes but active does not + // For simultaneous cameras + public String firstActiveCameraName() { + final String[] cameras = model_.acquisitions().settings().imagingCameraOrder(); + final boolean[] active = model_.acquisitions().settings().imagingCamerasActive(); + for (int i = 0; i < cameras.length; i++) { + if (active[i]) { + return cameras[i]; + } } - return (CameraBase)deviceMap_.get(deviceKey); + return ""; } public CameraBase imagingCamera(final int view, final int num) { @@ -328,7 +345,21 @@ public String[] imagingCameraNames() { } public CameraBase[] imagingCameras() { - return Arrays.stream(imagingCameraNames()) + String[] cameraNames; + if (model_.acquisitions().settings().isUsingSimultaneousCameras()) { + ArrayList names = new ArrayList<>(); + final String[] cameras = model_.acquisitions().settings().imagingCameraOrder(); + final boolean[] active = model_.acquisitions().settings().imagingCamerasActive(); + for (int i = 0; i < cameras.length; i++) { + if (active[i]) { + names.add(cameras[i]); + } + } + cameraNames = names.toArray(String[]::new); + } else { + cameraNames = imagingCameraNames(); + } + return Arrays.stream(cameraNames) .map(name -> (CameraBase)deviceMap_.get(name)) .filter(Objects::nonNull) .toArray(CameraBase[]::new); 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 5cbf21d..1ec0ccf 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineSCAPE.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineSCAPE.java @@ -43,6 +43,7 @@ import java.awt.geom.Point2D; import java.io.IOException; import java.util.ArrayList; +import java.util.stream.IntStream; public class AcquisitionEngineSCAPE extends AcquisitionEngine { @@ -65,6 +66,18 @@ public AcquisitionEngineSCAPE(final LightSheetManager model) { @Override boolean setup() { + isPolling_ = model_.positions().isPolling(); + if (isPolling_) { + model_.positions().stopPolling(); + studio_.logs().logMessage("stopped position polling"); + } + + asb_.sheetCalibrationBuilder(1).useAutoSheetWidth(true); + asb_.sheetCalibrationBuilder(1).autoSheetWidthPerPixel(0.0); + + // make settings current + updateAcquisitionSettings(); + // // check pixel size // if (core_.getPixelSizeUm() < 1e-6) { // studio_.logs().showError( @@ -72,6 +85,16 @@ boolean setup() { // return false; // } + // we must have an active camera if we are using simultaneous cameras + if (model_.acquisitions().settings().isUsingSimultaneousCameras()) { + final boolean[] active = model_.acquisitions().settings().imagingCamerasActive(); + if (IntStream.range(0, active.length).noneMatch(i -> active[i])) { + studio_.logs().showError("Using simultaneous cameras and no cameras are active!"); + return false; + } + // TODO: primary camera must be active + } + // this is needed for LSMAcquisitionEvents to work with multiple positions if (core_.getFocusDevice().isEmpty() && acqSettings_.isUsingMultiplePositions()) { @@ -94,17 +117,6 @@ boolean setup() { @Override boolean run() { - isPolling_ = model_.positions().isPolling(); - if (isPolling_) { - model_.positions().stopPolling(); - studio_.logs().logMessage("stopped position polling"); - } - - asb_.sheetCalibrationBuilder(1).useAutoSheetWidth(true); - asb_.sheetCalibrationBuilder(1).autoSheetWidthPerPixel(0.0); - - // make settings current - updateAcquisitionSettings(); // TODO: delete later, this is the settings before everything is set up in doHardwareCalculations (used to debug) //studio_.logs().logMessage("debug info:\n" + acqSettings_.toPrettyJson()); @@ -545,15 +557,12 @@ public void close() { // multiple simultaneous cameras if (model_.acquisitions().settings().isUsingSimultaneousCameras()) { // use 2 cameras - String secondCamera = "ImagingCamera2"; - final String primaryCamera = "ImagingCamera1";//model_.acquisitions().settings().primaryCamera(); - if (primaryCamera.equals(secondCamera)) { - secondCamera = "ImagingCamera1"; + final ArrayList names = new ArrayList<>(); + final CameraBase[] cameraList = model_.devices().imagingCameras(); + for (CameraBase camera: cameraList) { + names.add(camera.getDeviceName()); } - cameraNames = new String[] { - model_.devices().device(primaryCamera).getDeviceName(), - model_.devices().device(secondCamera).getDeviceName() - }; + cameraNames = names.toArray(String[]::new); } else { // use 1 camera final String camera = "ImagingCamera1"; // model_.acquisitions().settings().primaryCamera(); @@ -693,7 +702,7 @@ boolean finish() { // Stop all cameras sequences try { - for (CameraBase camera : model_.devices().imagingCameras()) { + for (CameraBase camera : cameras) { if (core_.isSequenceRunning(camera.getDeviceName())) { core_.stopSequenceAcquisition(camera.getDeviceName()); }