applied new functions and fixed bugs
This commit is contained in:
+98
-22
@@ -1,12 +1,16 @@
|
|||||||
from dash import Dash, Input, Output
|
from dash import Dash, Input, Output, State, ALL
|
||||||
import dash_bootstrap_components as dbc
|
import dash_bootstrap_components as dbc
|
||||||
import logging
|
import logging
|
||||||
|
from typing import List
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
from .layout import app_layout
|
from .layout import app_layout
|
||||||
from src.database import (
|
from src.database import (
|
||||||
connect,
|
connect,
|
||||||
get_visual_communication,
|
get_visual_communication,
|
||||||
NoDocumentFoundException
|
NoDocumentFoundException,
|
||||||
|
upsert_annotations,
|
||||||
|
ModelOutputs
|
||||||
)
|
)
|
||||||
|
|
||||||
# setup app
|
# setup app
|
||||||
@@ -27,39 +31,111 @@ collection, db, client = connect()
|
|||||||
def show_alert(
|
def show_alert(
|
||||||
msg: str | None
|
msg: str | None
|
||||||
):
|
):
|
||||||
if msg is None:
|
if msg is None or msg == "":
|
||||||
return False, ""
|
return False, ""
|
||||||
|
logging.info(f"updated alert message: {msg}")
|
||||||
return True, msg
|
return True, msg
|
||||||
|
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output("alert-message", "data"),
|
Output("alert-message", "data"),
|
||||||
Output("visual-communication-name", "data"),
|
Output("vis-com-name", "data"),
|
||||||
Output("image-container", "src"),
|
Output("image-container", "src"),
|
||||||
|
Output({"type": "annotation", "index": ALL}, "value"),
|
||||||
Input("next-button", "n_clicks"),
|
Input("next-button", "n_clicks"),
|
||||||
prevent_initial_call=True
|
State("vis-com-name", "data"),
|
||||||
|
State("image-container", "src"),
|
||||||
|
State({"type": "annotation", "index": ALL}, "id"),
|
||||||
|
State({"type": "annotation", "index": ALL}, "value"),
|
||||||
|
prevent_initial_call=True,
|
||||||
)
|
)
|
||||||
def load_unannotated_visual_communication_data(
|
def cycle_visual_communication_data(
|
||||||
n_clicks: int
|
n_clicks: int,
|
||||||
|
vis_com_name: str,
|
||||||
|
image_src: str,
|
||||||
|
annotation_keys: List,
|
||||||
|
annotation_values: List,
|
||||||
):
|
):
|
||||||
|
logging.info("began cycling visual communication data")
|
||||||
global collection
|
global collection
|
||||||
|
# prepare default response
|
||||||
|
response = [
|
||||||
|
"",
|
||||||
|
vis_com_name,
|
||||||
|
image_src,
|
||||||
|
annotation_values
|
||||||
|
]
|
||||||
|
# check if next-button clicked
|
||||||
|
if n_clicks == 0:
|
||||||
|
logging.info("stopping early: next-button has not yet been clicked")
|
||||||
|
return response
|
||||||
|
# check if visual communication name is set
|
||||||
|
if len(vis_com_name) > 0:
|
||||||
|
logging.info("saving annotations to database: %s", vis_com_name)
|
||||||
|
try:
|
||||||
|
# extract option keys
|
||||||
|
annotation_keys = [
|
||||||
|
elem["index"]
|
||||||
|
for elem in annotation_keys
|
||||||
|
]
|
||||||
|
# ensure all options are set
|
||||||
|
logging.info(annotation_keys)
|
||||||
|
for option, value in zip(annotation_keys, annotation_values):
|
||||||
|
if value is None:
|
||||||
|
raise ValueError(f"{option} is not set")
|
||||||
|
# prepare data to save
|
||||||
|
annotation_keys = [
|
||||||
|
elem.replace(' ', '_')
|
||||||
|
for elem
|
||||||
|
in annotation_keys
|
||||||
|
]
|
||||||
|
annotation_values = [
|
||||||
|
elem.replace(' ', '_').lower()
|
||||||
|
for elem
|
||||||
|
in annotation_values
|
||||||
|
]
|
||||||
|
annotations = {
|
||||||
|
key: value
|
||||||
|
for key, value
|
||||||
|
in zip(annotation_keys, annotation_values)
|
||||||
|
}
|
||||||
|
# instantiate ModelOutputs object
|
||||||
|
annotations = ModelOutputs.from_annotations(**annotations)
|
||||||
|
# save data to
|
||||||
|
upsert_annotations(
|
||||||
|
collection=collection,
|
||||||
|
vis_com_name=vis_com_name,
|
||||||
|
annotations=annotations
|
||||||
|
)
|
||||||
|
except (ValueError, ValidationError) as exc:
|
||||||
|
msg = f"failed saving annotation: {exc}"
|
||||||
|
logging.warning(msg)
|
||||||
|
response[0] = msg
|
||||||
|
return tuple(response)
|
||||||
|
# get new visual communication
|
||||||
|
logging.info("trying to get new visual communication")
|
||||||
try:
|
try:
|
||||||
|
# get data
|
||||||
vis_com = get_visual_communication(
|
vis_com = get_visual_communication(
|
||||||
collection=collection,
|
collection=collection,
|
||||||
with_annotation=False
|
with_annotation=False
|
||||||
)
|
)
|
||||||
|
# set variables
|
||||||
|
vis_com_name = vis_com.name
|
||||||
|
image_src = vis_com.webencoded_image()
|
||||||
|
if vis_com.prediction is not None:
|
||||||
|
# TODO: update to use optional predictions
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# reset annotations
|
||||||
|
annotation_values = [None for elem in annotation_values]
|
||||||
except NoDocumentFoundException:
|
except NoDocumentFoundException:
|
||||||
return (
|
msg = f"no unannotated data in database"
|
||||||
"Did not find any unannotated data in database",
|
logging.warning(msg)
|
||||||
None,
|
response[0] = msg
|
||||||
""
|
return tuple(response)
|
||||||
)
|
else:
|
||||||
# prepare return values
|
response[1] = vis_com_name
|
||||||
alert_message = None
|
response[2] = image_src
|
||||||
vis_com_name = vis_com.name
|
response[3] = annotation_values
|
||||||
img_src = f"data:image/png;base64, {vis_com.webencoded_image()}"
|
logging.info("finished getting visual communication: %s", vis_com_name)
|
||||||
logging.info("updated visual communication")
|
return tuple(response)
|
||||||
return (
|
|
||||||
alert_message,
|
|
||||||
vis_com_name,
|
|
||||||
img_src
|
|
||||||
)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user