diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/PLogicSCAPE.java b/src/main/java/org/micromanager/lightsheetmanager/model/PLogicSCAPE.java index 3dea83c..e1292ad 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/PLogicSCAPE.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/PLogicSCAPE.java @@ -17,6 +17,7 @@ import org.micromanager.lightsheetmanager.model.devices.vendor.ASIXYStage; import org.micromanager.lightsheetmanager.model.devices.vendor.ASIZStage; import org.micromanager.lightsheetmanager.model.devices.vendor.SingleAxis; +import org.micromanager.lightsheetmanager.model.utils.GeometryUtils; import org.micromanager.lightsheetmanager.model.utils.NumberUtils; import java.awt.Rectangle; @@ -404,17 +405,17 @@ public boolean prepareControllerForAcquisitionSCAPE( // Compute appropriate motor speed in mm/s for the given stage scanning settings public double computeScanSpeed(DefaultAcquisitionSettingsSCAPE settings, final int numScansPerSlice) { //double sliceDuration = settings.timingSettings().sliceDuration(); - //double sliceDuration = 0.0; // TODO: get from SliceTiming - double sliceDuration = getSliceDuration(settings.timingSettings(), numScansPerSlice); // TODO: ??? + // TODO: getSliceDuration only used here, but maybe should be computed elsewhere, and get with method above? + double sliceDuration = getSliceDuration(settings.timingSettings(), numScansPerSlice); if (settings.acquisitionMode() == AcquisitionMode.STAGE_SCAN_INTERLEAVED) { // pretend like our slice takes twice as long so that we move the correct speed - // this has the effect of halving the motor speed - // but keeping the scan distance the same + // this has the effect of halving the motor speed, but keeping the scan distance the same sliceDuration *= 2; } final int channelsPerPass = computeScanChannelsPerPass(settings); - //return settings.getStepSize() * du.getStageGeometricSpeedFactor(settings.firstSideIsA) / sliceDuration / channelsPerPass; - return settings.volumeSettings().sliceStepSize() / sliceDuration / channelsPerPass; // TODO: add getStageGeometricSpeedFactor + final double speedFactor = GeometryUtils.getStageGeometricSpeedFactor( + settings.scanSettings().scanAngleFirstView(), settings.volumeSettings().firstView() == 1); + return settings.volumeSettings().sliceStepSize() * speedFactor / sliceDuration / channelsPerPass; } // compute how many channels we do in each one-way scan diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/XYZGrid.java b/src/main/java/org/micromanager/lightsheetmanager/model/XYZGrid.java index 44c2e73..bb1f6f0 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/XYZGrid.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/XYZGrid.java @@ -104,7 +104,8 @@ public void computeGrid() { if (useX_) { // TODO: update GUI with values, aliases for asb and vsb? - final double speedFactor = GeometryUtils.DISPIM.getStageGeometricSpeedFactor(true); + final double speedFactor = GeometryUtils.getStageGeometricSpeedFactor( + model_.acquisitions().settings().scanSettings().scanAngleFirstView(),true); model_.acquisitions().settingsBuilder().volumeSettingsBuilder().sliceStepSize(Math.abs(deltaX_)/speedFactor); model_.acquisitions().settingsBuilder().volumeSettingsBuilder().slicesPerView(numX); // move to X center if we aren't generating a position list with it @@ -171,7 +172,7 @@ public void setUseX(final boolean state) { } public boolean getUseY() { - return useX_; + return useY_; } public void setUseY(final boolean state) { @@ -179,7 +180,7 @@ public void setUseY(final boolean state) { } public boolean getUseZ() { - return useX_; + return useZ_; } public void setUseZ(final boolean state) { 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 9aaaae5..48ae4c4 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/utils/GeometryUtils.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/utils/GeometryUtils.java @@ -1,56 +1,54 @@ package org.micromanager.lightsheetmanager.model.utils; +// TODO: make this generic for diSPIM/SCOPE or have separate static classes public class GeometryUtils { - public static class DISPIM { - - /*** - * Compute how far we need to shift each image for deskew relative to Z-step size (orthogonal to image) based on user-specified angle - * e.g. with diSPIM, angle is 45 degrees so factor is 1.0, for oSPIM the factor is tan(60 degrees) = sqrt(3), etc. - * if pathA is false then we compute based on Path B angle (assumed to be 90 degrees minus one specified for Path A) - * @param pathA true if using Path A - * @return factor, e.g. 1.0 for 45 degrees, sqrt(3) for 60 degrees, etc. - */ - public static double getStageGeometricShiftFactor(boolean pathA) { - double angle = 1.0; // TODO: props_.getPropValueFloat(Devices.Keys.PLUGIN, Properties.Keys.PLUGIN_STAGESCAN_ANGLE_PATHA); - if (angle < 1) { // case when property not defined - angle = 45.0; - //angle = ASIdiSPIM.oSPIM ? 60.0 : 45.0; - } - if (!pathA) { - angle = 90.0 - angle; - } - return Math.tan(angle/180.0*Math.PI); + /*** + * Compute how far we need to shift each image for deskew relative to Z-step size (orthogonal to image) based on user-specified angle + * e.g. with diSPIM, angle is 45 degrees so factor is 1.0, for oSPIM the factor is tan(60 degrees) = sqrt(3), etc. + * if pathA is false then we compute based on Path B angle (assumed to be 90 degrees minus one specified for Path A) + * @param pathA true if using Path A + * @return factor, e.g. 1.0 for 45 degrees, sqrt(3) for 60 degrees, etc. + */ + public static double getStageGeometricShiftFactor(double angle, final boolean pathA) { + //double angle = 1.0; // TODO: props_.getPropValueFloat(Devices.Keys.PLUGIN, Properties.Keys.PLUGIN_STAGESCAN_ANGLE_PATHA); + if (angle < 1) { // case when property not defined + angle = 45.0; + //angle = ASIdiSPIM.oSPIM ? 60.0 : 45.0; } - - /*** - * Compute fractional size when viewed from above for overview image based on user-specified angle - * e.g. with diSPIM, angle is 45 degrees so factor is cos(45 degrees) = 1/sqrt(2), for oSPIM would be cos(60 degrees) = 0.5, etc. - * if pathA is false then we compute based on Path B angle (assumed to be 90 degrees minus one specified for Path A) - * @param pathA true if using Path A - * @return factor, e.g. 1/sqrt(2) for 45 degrees, 0.5 for 60 degrees, etc. - */ - public static double getStageTopViewCompressFactor(boolean pathA) { - double angle = 1.0; // TODO: props_.getPropValueFloat(Devices.Keys.PLUGIN, Properties.Keys.PLUGIN_STAGESCAN_ANGLE_PATHA); - if (angle < 1) { // case when property not defined - angle = 45.0; - //angle = ASIdiSPIM.oSPIM ? 60.0 : 45.0; - } - if (!pathA) { - angle = 90.0 - angle; - } - return Math.cos(angle/180.0*Math.PI); + if (!pathA) { + angle = 90.0 - angle; } + return Math.tan(angle/180.0*Math.PI); + } - /*** - * Compute how far we need to move the stage relative to the Z-step size (orthogonal to image) based on user-specified angle - * e.g. with diSPIM, angle is 45 degrees so go 1/cos(45deg) = 1.41x faster, with oSPIM, angle is 60 degrees so go 1/cos(60deg) = 2x faster - * if pathA is false then we compute based on Path B angle (assumed to be 90 degrees minus one specified for Path A) - * @param pathA true if using Path A - * @return factor, e.g. 1.41 for 45 degrees, 2 for 60 degrees, etc. - */ - public static double getStageGeometricSpeedFactor(boolean pathA) { - return 1/(getStageTopViewCompressFactor(pathA)); + /*** + * Compute fractional size when viewed from above for overview image based on user-specified angle + * e.g. with diSPIM, angle is 45 degrees so factor is cos(45 degrees) = 1/sqrt(2), for oSPIM would be cos(60 degrees) = 0.5, etc. + * if pathA is false then we compute based on Path B angle (assumed to be 90 degrees minus one specified for Path A) + * @param pathA true if using Path A + * @return factor, e.g. 1/sqrt(2) for 45 degrees, 0.5 for 60 degrees, etc. + */ + public static double getStageTopViewCompressFactor(double angle, final boolean pathA) { + //double angle = 1.0; // TODO: props_.getPropValueFloat(Devices.Keys.PLUGIN, Properties.Keys.PLUGIN_STAGESCAN_ANGLE_PATHA); + if (angle < 1) { // case when property not defined + angle = 45.0; + //angle = ASIdiSPIM.oSPIM ? 60.0 : 45.0; } + if (!pathA) { + angle = 90.0 - angle; + } + return Math.cos(angle/180.0*Math.PI); + } + + /*** + * Compute how far we need to move the stage relative to the Z-step size (orthogonal to image) based on user-specified angle + * e.g. with diSPIM, angle is 45 degrees so go 1/cos(45deg) = 1.41x faster, with oSPIM, angle is 60 degrees so go 1/cos(60deg) = 2x faster + * if pathA is false then we compute based on Path B angle (assumed to be 90 degrees minus one specified for Path A) + * @param pathA true if using Path A + * @return factor, e.g. 1.41 for 45 degrees, 2 for 60 degrees, etc. + */ + public static double getStageGeometricSpeedFactor(final double angle, final boolean pathA) { + return 1/getStageTopViewCompressFactor(angle, pathA); } }