diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java b/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java index 37ab9f1..74ef6ed 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/UserSettings.java @@ -118,6 +118,11 @@ public void load() { public void loadFromJson(final String json, final boolean notify) { // TODO: switch this based on microscope geometry type var settings = ScapeAcquisitionSettings.fromJson(json, ScapeAcquisitionSettings.class); + // useHardwareTimePoints is a DERIVED value. It is serialized as part of the acquisition settings, + // but must never be trusted when reloaded: a stale "true" persisted from an earlier short-interval run + // would otherwise seed acqSettings_ across a plugin restart and be read before the next run recomputes it. + // Force it false on load; the engine recomputes it each run. + settings = new ScapeAcquisitionSettings.Builder(settings).useHardwareTimePoints(false).build(); model_.acquisitions().updateSettings(settings); if (notify) { notifyListeners(settings); // update the ui diff --git a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineDispim.java b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineDispim.java index 08f4213..d72fdd7 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineDispim.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineDispim.java @@ -701,6 +701,12 @@ private boolean doHardwareCalculations(PLogicDispim plc) { // } // } + // FREEZE POINT: (mirror of AcquisitionEngineScape): rebuild the run-time snapshot from asb_ + // before arming the controller, so the hardware is armed from the same settings the AcqEngJ event + // loop uses. See AcquisitionEngineScape.doHardwareCalculations() for the full rationale. + // TODO(IMMUTABLE-RUN): remove once acqSettings_ is the single run-time source of truth. + updateSettings(); + double extraChannelOffset = 0.0; plc.prepareControllerForAcquisition(acqSettings_, extraChannelOffset); return true; 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 70ad162..1e3a9bf 100644 --- a/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java +++ b/src/main/java/org/micromanager/lightsheetmanager/model/acquisitions/AcquisitionEngineScape.java @@ -1021,6 +1021,17 @@ private boolean doHardwareCalculations(PLogicScape plc) { camera.setExposure(exposureTime); } + // FREEZE POINT: rebuild the run-time snapshot from asb_ before arming the controller. + // run() reaches this method (via doHardwareCalculations) BEFORE it rebuilds acqSettings_ with + // updateSettings(). Without this rebuild the controller is armed from a stale acqSettings_, e.g. + // useHardwareTimePoints left true by a prior short-interval reject, while the AcqEngJ event loop + // later runs from the fresh (false) value, so the hardware is armed for hardware timepoints while + // the software issues software timepoints ("stopped at first timepoint"). Rebuilding here is + // strictly fresher: doHardwareCalculations only mutates asb_ (the flag reset above + recalculated + // timing), never acqSettings_ directly. + // TODO(IMMUTABLE-RUN): remove once acqSettings_ is the single run-time source of truth. + updateSettings(); + double extraChannelOffset = 0.0; return plc.prepareControllerForAcquisition(acqSettings_, extraChannelOffset); }