Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public abstract class AcquisitionEngine implements AcquisitionManager, MMAcquist

private final AutofocusAdapter autofocus_;

protected Datastore datastore_;
// visibility: written on the acquisition thread, read on the edt when a window asks to close
protected volatile Datastore datastore_;
protected Pipeline curPipeline_;
protected long nextWakeTime_ = -1;

Expand Down Expand Up @@ -640,10 +641,9 @@ public boolean abortRequest() {
if (acq == null) {
return true; // nothing is running, so there is nothing to protect
}
// always refuse while a run is live: Micro-Manager vetoes the close, and that veto is what
// keeps it from racing the abort into finish(), whose save closes the same datastore from
// the acquisition thread. answering yes only aborts, so the close succeeds on the next
// attempt. the display's abort button also lands here and ignores the result.
// always refuse while a run is live: closing the live window would close the datastore
// the run is still writing. answering yes only aborts, so the close succeeds on the next
// attempt.
if (model_.logging().confirmOrDefault("Abort Acquisition",
"Abort the current acquisition task?", false)) {
acq.abort();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
import org.micromanager.data.SummaryMetadata;
import org.micromanager.data.internal.DefaultDatastore;
import org.micromanager.data.internal.DefaultSummaryMetadata;
import org.micromanager.data.internal.PropertyKey;
import org.micromanager.display.DataViewer;
import org.micromanager.display.DataViewerListener;
import org.micromanager.display.DisplaySettings;
import org.micromanager.display.DisplayWindow;
import org.micromanager.display.internal.DefaultDisplayManager;
import org.micromanager.display.internal.RememberedDisplaySettings;
import org.micromanager.lightsheetmanager.api.data.AcquisitionMode;
import org.micromanager.lightsheetmanager.api.data.CameraLibrary;
import org.micromanager.lightsheetmanager.api.data.CameraMode;
Expand Down Expand Up @@ -64,6 +71,20 @@ public class AcquisitionEngineScape extends AcquisitionEngine {
private double scanAccelX_;
private boolean isPolling_; // true if polling was enabled at the start of an acquisition

// Vetoes closing the running acquisition's window unless the user confirms an abort. Otherwise
// the display manager closes the store under the running acquisition and every later image
// is dropped without an abort.
private final DataViewerListener liveWindowCloseGuard_ = new DataViewerListener() {
@Override
public boolean canCloseViewer(final DataViewer viewer) {
final Datastore live = datastore_;
if (live == null || viewer.getDataProvider() != live) {
return true; // not the running acquisition's window
}
return abortRequest();
}
};

public AcquisitionEngineScape(final LightSheetManager model) {
super(Objects.requireNonNull(model));
}
Expand Down Expand Up @@ -307,7 +328,8 @@ boolean run() {

// TODO(Brandon): where should i get this from?
SequenceSettings.Builder sequenceSettingsBuilder = new SequenceSettings.Builder();
sequenceSettingsBuilder.shouldDisplayImages(true);
// LSM opens the window itself, see createAcquisitionDisplay()
sequenceSettingsBuilder.shouldDisplayImages(false);
// Write images to disk as they arrive instead of accumulating the run in memory.
// MMAcquisition swaps StorageRAM for the preferred save mode set above only when both
// save() and root() are set, so setting them here is what selects streaming. This is what
Expand Down Expand Up @@ -359,6 +381,8 @@ && new File(saveDir + File.separator + datasetName).isDirectory()) {
}
}

createAcquisitionDisplay(dsmd);

studio_.events().registerForEvents(this);
// commented because this is prob specific to MM MDAs
// studio_.events().post(new DefaultAcquisitionStartedEvent(datastore_, this,
Expand Down Expand Up @@ -855,6 +879,44 @@ private Double readBaseFocusPosition(final ScapeAcquisitionSettings settings) {
}
}

/**
* Opens the acquisition's window, with the settings and position MMAcquisition would use.
* MMAcquisition's own window is not used because its abort and pause buttons are never
* unsubscribed after an LSM acquisition, so every window it opens stays in memory after it is
* closed.
*
* @param summary the summary metadata the dataset was created with, which names its channels
*/
private void createAcquisitionDisplay(final SummaryMetadata summary) {
// before the window: closing the last window closes the store only if it is managed
studio_.displays().manage(datastore_);

// start from the settings of the last acquisition window that was closed
final String profileKey = PropertyKey.ACQUISITION_DISPLAY_SETTINGS.key();
final DisplaySettings remembered =
studio_.displays().displaySettingsFromProfile(profileKey);
final DisplaySettings.Builder builder = remembered != null
? remembered.copyBuilder()
: studio_.displays().displaySettingsBuilder();
final List<String> channelNames = summary.getChannelNameList();
if (channelNames.size() == 1) {
builder.colorModeGrayscale();
} else if (channelNames.size() > 1) {
builder.colorModeComposite();
}
for (int i = 0; i < channelNames.size(); i++) {
builder.channel(i, RememberedDisplaySettings.loadChannel(studio_,
summary.getChannelGroup(), channelNames.get(i), null));
}

final DisplayWindow display =
studio_.displays().createDisplay(datastore_, null, builder.build());
display.setWindowPositionKey(DefaultDisplayManager.MDA_DISPLAY);
display.setDisplaySettingsProfileKey(profileKey);
// ahead of the display manager's listener at 100, which is the one that closes the store
display.addListener(liveWindowCloseGuard_, 1);
}

@Override
void finish() {
// finish() runs on EVERY path (the requestRun finally), even a setup-abort where the
Expand Down
Loading