Move background detect settings into SlideScan
This commit is contained in:
parent
bfef998300
commit
4da05b1869
7 changed files with 59 additions and 171 deletions
|
|
@ -44,6 +44,7 @@ from openflexure_microscope_server.ui import (
|
|||
Accordion,
|
||||
HTMLBlock,
|
||||
UIElementList,
|
||||
action_button_for,
|
||||
property_control_for,
|
||||
)
|
||||
|
||||
|
|
@ -560,6 +561,28 @@ class HistoScanWorkflow(RectGridWorkflow[HistoScanSettingsModel]):
|
|||
|
||||
return imaged, focus_height
|
||||
|
||||
@lt.action
|
||||
def check_background(self) -> str:
|
||||
"""Check if sample is background.
|
||||
|
||||
This action is a pre-run check for feeding back to the user.
|
||||
"""
|
||||
image_array = self._cam.grab_as_array(stream_name="lores")
|
||||
is_sample, bg_message = self._background_detector.image_is_sample(image_array)
|
||||
label = "sample" if is_sample else "background"
|
||||
|
||||
return f"Current image is {label} ({bg_message})"
|
||||
|
||||
@lt.action
|
||||
def set_background(self) -> None:
|
||||
"""Set the background for this background detector.
|
||||
|
||||
This sets the background for this workflows background detector as opposed to
|
||||
the active background detector for the camera.
|
||||
"""
|
||||
image_array = self._cam.grab_as_array(stream_name="lores")
|
||||
self._background_detector.set_background(image_array)
|
||||
|
||||
@lt.endpoint("get", "settings_ui", responses=UI_ELEMENT_RESPONSE)
|
||||
def settings_ui(self) -> UIElementList:
|
||||
"""Return the UI for the workflow's settings in the scan tab."""
|
||||
|
|
@ -593,13 +616,32 @@ class HistoScanWorkflow(RectGridWorkflow[HistoScanSettingsModel]):
|
|||
),
|
||||
]
|
||||
)
|
||||
background_ui = self._background_detector.settings_ui()
|
||||
set_bg_button = action_button_for(
|
||||
self,
|
||||
"set_background",
|
||||
poll_interval=0.1,
|
||||
submit_label="Set Background",
|
||||
can_terminate=False,
|
||||
notify_on_success=True,
|
||||
success_message="Background image has been updated",
|
||||
)
|
||||
check_bg_button = action_button_for(
|
||||
self,
|
||||
"check_background",
|
||||
poll_interval=0.1,
|
||||
submit_label="Check Current Image",
|
||||
can_terminate=False,
|
||||
notify_on_success=True,
|
||||
response_is_success_message=True,
|
||||
)
|
||||
|
||||
background_ui.root += [set_bg_button, check_bg_button]
|
||||
|
||||
return UIElementList(
|
||||
[
|
||||
HTMLBlock(html=f"<h4>{self.display_name}</h4><p>{self.ui_blurb}<p>"),
|
||||
Accordion(
|
||||
title="Background Detect",
|
||||
children=self._background_detector.settings_ui(),
|
||||
),
|
||||
Accordion(title="Background Detect", children=background_ui),
|
||||
Accordion(
|
||||
title="Scan Settings",
|
||||
children=scan_settings,
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ class ActionButton(BaseModel):
|
|||
action: str
|
||||
"""The name of the action to be triggered."""
|
||||
|
||||
poll_interval: int = 1
|
||||
poll_interval: float = 1
|
||||
"""The interval for polling in seconds."""
|
||||
|
||||
submit_label: str = "Submit"
|
||||
|
|
@ -171,6 +171,12 @@ class ActionButton(BaseModel):
|
|||
notify_on_success: bool = False
|
||||
"""Specify whether to a notification on successful completion."""
|
||||
|
||||
response_is_success_message: bool = False
|
||||
"""Set True to use the action response as the success message.
|
||||
|
||||
If set ``success_message`` has is never used.
|
||||
"""
|
||||
|
||||
success_message: str = "Success!"
|
||||
"""The message to show on successful completion."""
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ import tabContent from "./genericComponents/tabContent.vue";
|
|||
|
||||
// Import new content components
|
||||
import aboutContent from "./tabContentComponents/aboutContent.vue";
|
||||
import backgroundDetectContent from "./tabContentComponents/backgroundDetectContent.vue";
|
||||
import controlContent from "./tabContentComponents/controlContent.vue";
|
||||
import loggingContent from "./tabContentComponents/loggingContent.vue";
|
||||
import powerContent from "./tabContentComponents/powerContent.vue";
|
||||
|
|
@ -150,15 +149,6 @@ export default {
|
|||
component: markRaw(controlContent),
|
||||
requiredThings: [],
|
||||
},
|
||||
{
|
||||
id: "background-detect",
|
||||
title: "Background Detect",
|
||||
icon: "background_replace",
|
||||
component: markRaw(backgroundDetectContent),
|
||||
// While stage isn't needed; automatic background detect has little function
|
||||
// for a manual microscope.
|
||||
requiredThings: ["stage"],
|
||||
},
|
||||
{
|
||||
id: "slide-scan",
|
||||
title: "Slide Scan",
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ export default {
|
|||
*/
|
||||
actionResponse: function (response) {
|
||||
if (this.actionData.notify_on_success) {
|
||||
this.modalNotify(this.actionData.success_message);
|
||||
if (this.actionData.response_is_success_message) {
|
||||
this.modalNotify(response.output);
|
||||
} else {
|
||||
this.modalNotify(this.actionData.success_message);
|
||||
}
|
||||
this.$emit("response", response);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
/>
|
||||
<server-specified-action-button
|
||||
v-else-if="element.element_type === 'action_button'"
|
||||
:property-data="element"
|
||||
:action-data="element"
|
||||
/>
|
||||
<simple-accordion v-else-if="element.element_type === 'accordion'" :title="element.title">
|
||||
<server-specified-interface :elements="element.children" />
|
||||
|
|
|
|||
|
|
@ -1,129 +0,0 @@
|
|||
<template>
|
||||
<div ref="backgroundDetectContent" class="uk-padding-small">
|
||||
<div>
|
||||
<ul uk-accordion="multiple: true">
|
||||
<li>
|
||||
<a class="uk-accordion-title" href="#">Configure</a>
|
||||
<div class="uk-accordion-content">
|
||||
<h4 v-if="backgroundDetectorDisplayName" class="detector-name">
|
||||
{{ backgroundDetectorDisplayName }}
|
||||
</h4>
|
||||
<server-specified-property-control
|
||||
v-for="(setting, index) in backgroundDetectorSettings"
|
||||
:key="'detector_setting' + index"
|
||||
:property-data="setting"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="uk-margin">
|
||||
<action-button
|
||||
thing="camera"
|
||||
action="set_background"
|
||||
submit-label="Set Background"
|
||||
:can-terminate="false"
|
||||
:poll-interval="0.1"
|
||||
@response="alertBackgroundSet"
|
||||
@error="modalError"
|
||||
/>
|
||||
</div>
|
||||
<div class="uk-margin">
|
||||
<!--Once status is read this should be disabled if not ready..-->
|
||||
<action-button
|
||||
thing="camera"
|
||||
action="image_is_sample"
|
||||
submit-label="Check Current Image"
|
||||
:is-disabled="!ready"
|
||||
:can-terminate="false"
|
||||
:poll-interval="0.1"
|
||||
@response="alertImageLabel"
|
||||
@error="modalError"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ActionButton from "../../labThingsComponents/actionButton.vue";
|
||||
import ServerSpecifiedPropertyControl from "../../labThingsComponents/serverSpecifiedPropertyControl.vue";
|
||||
import { useIntersectionObserver } from "@vueuse/core";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ActionButton,
|
||||
ServerSpecifiedPropertyControl,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
ready: false,
|
||||
backgroundDetectorName: undefined,
|
||||
backgroundDetectorDisplayName: undefined,
|
||||
backgroundDetectorSettings: [],
|
||||
animate: false,
|
||||
};
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.readSettings();
|
||||
},
|
||||
|
||||
mounted() {
|
||||
useIntersectionObserver(
|
||||
this.$refs.backgroundDetectContent,
|
||||
([{ isIntersecting }]) => {
|
||||
this.visibilityChanged(isIntersecting);
|
||||
},
|
||||
{
|
||||
threshold: 0.0,
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
methods: {
|
||||
async safeReadSettings() {
|
||||
if (!this.$store.state.connected) return;
|
||||
|
||||
try {
|
||||
await this.readSettings();
|
||||
} catch (error) {
|
||||
console.error("Error reading background detector settings:", error);
|
||||
}
|
||||
},
|
||||
|
||||
visibilityChanged(isVisible) {
|
||||
if (isVisible) {
|
||||
this.safeReadSettings();
|
||||
}
|
||||
},
|
||||
alertBackgroundSet() {
|
||||
this.modalNotify(`Background image has been updated`);
|
||||
},
|
||||
alertImageLabel(r) {
|
||||
let label = r.output[0] ? "sample" : "background";
|
||||
this.modalNotify(`Current image is ${label} (${r.output[1]})`);
|
||||
},
|
||||
readSettings: async function () {
|
||||
this.backgroundDetectorName = await this.readThingProperty(
|
||||
"camera",
|
||||
"background_detector_name",
|
||||
);
|
||||
if (this.backgroundDetectorName) {
|
||||
this.ready = await this.readThingProperty(this.backgroundDetectorName, "ready");
|
||||
this.backgroundDetectorSettings =
|
||||
(await this.getThingEndpoint(this.backgroundDetectorName, "settings_ui")) || [];
|
||||
this.backgroundDetectorDisplayName = await this.readThingProperty(
|
||||
this.backgroundDetectorName,
|
||||
"display_name",
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.detector-name {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<template>
|
||||
<!-- Grid managing tab content -->
|
||||
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove">
|
||||
<div class="control-component">
|
||||
<paneBackgroundDetect />
|
||||
</div>
|
||||
<div class="view-component uk-width-expand">
|
||||
<streamDisplay />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import paneBackgroundDetect from "./backgroundDetectComponents/paneBackgroundDetect";
|
||||
import streamDisplay from "./streamContent.vue";
|
||||
|
||||
export default {
|
||||
name: "BackgroundDetectContent",
|
||||
|
||||
components: {
|
||||
paneBackgroundDetect,
|
||||
streamDisplay,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue