зеркало из
https://github.com/ssciwr/AMMICO.git
synced 2025-10-30 21:46:04 +02:00
Fix dash layout (#143)
* force_rounding_of_all_colors * update test * fixed bug in color analysis * changed color rounding to seperate loop * updated to new dash layout using dbc * removed dash server from test * added dash version to pyproject.toml * changed something to get codecov to work * changed something else to get codecov to work.. * added test_right_output_analysis_text * fix type in dependencies * removed test_text from display --------- Co-authored-by: Inga Ulusoy <inga.ulusoy@uni-heidelberg.de>
Этот коммит содержится в:
родитель
d98a5d3c0e
Коммит
e120c10d9f
@ -5,9 +5,9 @@ import ammico.colors as colors
|
|||||||
from ammico.utils import is_interactive
|
from ammico.utils import is_interactive
|
||||||
import ammico.summary as summary
|
import ammico.summary as summary
|
||||||
import dash_renderjson
|
import dash_renderjson
|
||||||
from dash import html, Input, Output, dcc, State
|
from dash import html, Input, Output, dcc, State, Dash
|
||||||
import jupyter_dash
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
import dash_bootstrap_components as dbc
|
||||||
|
|
||||||
|
|
||||||
COLOR_SCHEMES = [
|
COLOR_SCHEMES = [
|
||||||
@ -37,7 +37,7 @@ class AnalysisExplorer:
|
|||||||
mydict (dict): A nested dictionary containing image data for all images.
|
mydict (dict): A nested dictionary containing image data for all images.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.app = jupyter_dash.JupyterDash(__name__)
|
self.app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
||||||
self.mydict = mydict
|
self.mydict = mydict
|
||||||
self.theme = {
|
self.theme = {
|
||||||
"scheme": "monokai",
|
"scheme": "monokai",
|
||||||
@ -63,36 +63,24 @@ class AnalysisExplorer:
|
|||||||
# Setup the layout
|
# Setup the layout
|
||||||
app_layout = html.Div(
|
app_layout = html.Div(
|
||||||
[
|
[
|
||||||
# Top
|
# Top row, only file explorer
|
||||||
html.Div(
|
dbc.Row(
|
||||||
[self._top_file_explorer(mydict)],
|
[dbc.Col(self._top_file_explorer(mydict))],
|
||||||
id="Div_top",
|
id="Div_top",
|
||||||
style={
|
style={
|
||||||
"width": "30%",
|
"width": "30%",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
# Middle
|
# second row, middle picture and right output
|
||||||
html.Div(
|
dbc.Row(
|
||||||
[self._middle_picture_frame()],
|
[
|
||||||
id="Div_middle",
|
# first column: picture
|
||||||
style={
|
dbc.Col(self._middle_picture_frame()),
|
||||||
"width": "50%",
|
dbc.Col(self._right_output_json()),
|
||||||
"display": "inline-block",
|
]
|
||||||
"verticalAlign": "top",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
# Right
|
|
||||||
html.Div(
|
|
||||||
[self._right_output_json()],
|
|
||||||
id="Div_right",
|
|
||||||
style={
|
|
||||||
"width": "45%",
|
|
||||||
"display": "inline-block",
|
|
||||||
"verticalAlign": "top",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
style={"width": "95%", "display": "inline-block"},
|
# style={"width": "95%", "display": "inline-block"},
|
||||||
)
|
)
|
||||||
self.app.layout = app_layout
|
self.app.layout = app_layout
|
||||||
|
|
||||||
@ -170,106 +158,100 @@ class AnalysisExplorer:
|
|||||||
def _create_setting_layout(self):
|
def _create_setting_layout(self):
|
||||||
settings_layout = html.Div(
|
settings_layout = html.Div(
|
||||||
[
|
[
|
||||||
|
# text summary start
|
||||||
html.Div(
|
html.Div(
|
||||||
id="settings_TextDetector",
|
id="settings_TextDetector",
|
||||||
style={"display": "none"},
|
style={"display": "none"},
|
||||||
children=[
|
children=[
|
||||||
|
dbc.Row(
|
||||||
dcc.Checklist(
|
dcc.Checklist(
|
||||||
["Analyse text"],
|
["Analyse text"],
|
||||||
["Analyse text"],
|
["Analyse text"],
|
||||||
id="setting_Text_analyse_text",
|
id="setting_Text_analyse_text",
|
||||||
|
style={"margin-bottom": "10px"},
|
||||||
),
|
),
|
||||||
html.Div(
|
), # row 1
|
||||||
|
# text row 2
|
||||||
|
dbc.Row(
|
||||||
[
|
[
|
||||||
html.Div(
|
dbc.Col(
|
||||||
|
[
|
||||||
|
html.P(
|
||||||
"Select models for text_summary, text_sentiment, text_NER or leave blank for default:",
|
"Select models for text_summary, text_sentiment, text_NER or leave blank for default:",
|
||||||
style={
|
# style={"width": "45%"},
|
||||||
"height": "30px",
|
|
||||||
"margin-top": "5px",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
]
|
||||||
|
), #
|
||||||
|
dbc.Col(
|
||||||
|
[
|
||||||
|
html.P(
|
||||||
|
"Select model revision number for text_summary, text_sentiment, text_NER or leave blank for default:"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
), # row 2
|
||||||
|
# input row 3
|
||||||
|
dbc.Row(
|
||||||
|
[
|
||||||
|
dbc.Col(
|
||||||
dcc.Input(
|
dcc.Input(
|
||||||
type="text",
|
type="text",
|
||||||
id="setting_Text_model_names",
|
id="setting_Text_model_names",
|
||||||
style={"height": "auto", "margin-bottom": "auto"},
|
style={"width": "100%"},
|
||||||
),
|
),
|
||||||
],
|
|
||||||
style={
|
|
||||||
"width": "33%",
|
|
||||||
"display": "inline-block",
|
|
||||||
"margin-top": "10px",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
html.Div(
|
|
||||||
[
|
|
||||||
html.Div(
|
|
||||||
"Select model revision number for text_summary, text_sentiment, text_NER or leave blank for default:",
|
|
||||||
style={
|
|
||||||
"height": "30px",
|
|
||||||
"margin-top": "5px",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
dbc.Col(
|
||||||
dcc.Input(
|
dcc.Input(
|
||||||
type="text",
|
type="text",
|
||||||
id="setting_Text_revision_numbers",
|
id="setting_Text_revision_numbers",
|
||||||
style={"height": "auto", "margin-bottom": "auto"},
|
style={"width": "100%"},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
), # row 3
|
||||||
],
|
],
|
||||||
style={
|
), # text summary end
|
||||||
"width": "33%",
|
# start emotion detector
|
||||||
"display": "inline-block",
|
|
||||||
"margin-top": "10px",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
html.Div(
|
html.Div(
|
||||||
id="settings_EmotionDetector",
|
id="settings_EmotionDetector",
|
||||||
style={"display": "none"},
|
style={"display": "none"},
|
||||||
children=[
|
children=[
|
||||||
html.Div(
|
dbc.Row(
|
||||||
[
|
[
|
||||||
html.Div(
|
dbc.Col(
|
||||||
"Emotion threshold",
|
[
|
||||||
style={"height": "30px", "margin-top": "5px"},
|
html.P("Emotion threshold"),
|
||||||
),
|
|
||||||
dcc.Input(
|
dcc.Input(
|
||||||
value=50,
|
value=50,
|
||||||
type="number",
|
type="number",
|
||||||
max=100,
|
max=100,
|
||||||
min=0,
|
min=0,
|
||||||
id="setting_Emotion_emotion_threshold",
|
id="setting_Emotion_emotion_threshold",
|
||||||
style={"height": "auto", "margin-bottom": "auto"},
|
style={"width": "100%"},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
style={"width": "49%", "display": "inline-block"},
|
align="start",
|
||||||
),
|
),
|
||||||
html.Div(
|
dbc.Col(
|
||||||
[
|
[
|
||||||
html.Div(
|
html.P("Race threshold"),
|
||||||
"Race threshold",
|
|
||||||
style={
|
|
||||||
"height": "30px",
|
|
||||||
"margin-top": "5px",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
dcc.Input(
|
dcc.Input(
|
||||||
type="number",
|
type="number",
|
||||||
value=50,
|
value=50,
|
||||||
max=100,
|
max=100,
|
||||||
min=0,
|
min=0,
|
||||||
id="setting_Emotion_race_threshold",
|
id="setting_Emotion_race_threshold",
|
||||||
style={"height": "auto", "margin-bottom": "auto"},
|
style={"width": "100%"},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
style={
|
align="start",
|
||||||
"width": "49%",
|
|
||||||
"display": "inline-block",
|
|
||||||
"margin-top": "10px",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
style={"width": "100%"},
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
), # end emotion detector
|
||||||
html.Div(
|
html.Div(
|
||||||
id="settings_ColorDetector",
|
id="settings_ColorDetector",
|
||||||
style={"display": "none"},
|
style={"display": "none"},
|
||||||
@ -294,57 +276,45 @@ class AnalysisExplorer:
|
|||||||
id="settings_Summary_Detector",
|
id="settings_Summary_Detector",
|
||||||
style={"display": "none"},
|
style={"display": "none"},
|
||||||
children=[
|
children=[
|
||||||
html.Div(
|
dbc.Col(
|
||||||
[
|
[
|
||||||
|
dbc.Row([html.P("Analysis type:")]),
|
||||||
|
dbc.Row([html.P("Model type:")]),
|
||||||
|
dbc.Row([html.P("Analysis question:")]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
dbc.Col(
|
||||||
|
[
|
||||||
|
dbc.Row(
|
||||||
dcc.Dropdown(
|
dcc.Dropdown(
|
||||||
options=SUMMARY_ANALYSIS_TYPE,
|
options=SUMMARY_ANALYSIS_TYPE,
|
||||||
value="summary_and_questions",
|
value="summary_and_questions",
|
||||||
id="setting_Summary_analysis_type",
|
id="setting_Summary_analysis_type",
|
||||||
)
|
)
|
||||||
],
|
|
||||||
style={
|
|
||||||
"width": "33%",
|
|
||||||
"display": "inline-block",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
html.Div(
|
dbc.Row(
|
||||||
[
|
|
||||||
dcc.Dropdown(
|
dcc.Dropdown(
|
||||||
options=SUMMARY_MODEL,
|
options=SUMMARY_MODEL,
|
||||||
value="base",
|
value="base",
|
||||||
id="setting_Summary_model",
|
id="setting_Summary_model",
|
||||||
)
|
)
|
||||||
],
|
|
||||||
style={
|
|
||||||
"width": "33%",
|
|
||||||
"display": "inline-block",
|
|
||||||
"margin-top": "10px",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
html.Div(
|
|
||||||
[
|
|
||||||
html.Div(
|
|
||||||
"Please enter a question",
|
|
||||||
style={
|
|
||||||
"height": "50px",
|
|
||||||
"margin-top": "5px",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
dbc.Row(
|
||||||
dcc.Input(
|
dcc.Input(
|
||||||
type="text",
|
type="text",
|
||||||
id="setting_Summary_list_of_questions",
|
id="setting_Summary_list_of_questions",
|
||||||
style={"height": "auto", "margin-bottom": "auto"},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
style={
|
style={
|
||||||
"width": "33%",
|
"height": "auto",
|
||||||
"display": "inline-block",
|
"margin-left": "11px",
|
||||||
"margin-top": "10px",
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
style={"width": "100%", "display": "inline-block"},
|
||||||
)
|
)
|
||||||
return settings_layout
|
return settings_layout
|
||||||
|
|
||||||
@ -356,11 +326,9 @@ class AnalysisExplorer:
|
|||||||
"""
|
"""
|
||||||
right_layout = html.Div(
|
right_layout = html.Div(
|
||||||
[
|
[
|
||||||
dcc.Loading(
|
dbc.Col(
|
||||||
id="loading-2",
|
|
||||||
children=[
|
|
||||||
html.Div(
|
|
||||||
[
|
[
|
||||||
|
dbc.Row(
|
||||||
dcc.Dropdown(
|
dcc.Dropdown(
|
||||||
options=[
|
options=[
|
||||||
"TextDetector",
|
"TextDetector",
|
||||||
@ -371,12 +339,32 @@ class AnalysisExplorer:
|
|||||||
],
|
],
|
||||||
value="TextDetector",
|
value="TextDetector",
|
||||||
id="Dropdown_select_Detector",
|
id="Dropdown_select_Detector",
|
||||||
|
style={"width": "60%"},
|
||||||
),
|
),
|
||||||
html.Div(
|
justify="start",
|
||||||
|
),
|
||||||
|
dbc.Row(
|
||||||
children=[self._create_setting_layout()],
|
children=[self._create_setting_layout()],
|
||||||
id="div_detector_args",
|
id="div_detector_args",
|
||||||
|
justify="start",
|
||||||
),
|
),
|
||||||
html.Button("Run Detector", id="button_run"),
|
dbc.Row(
|
||||||
|
html.Button(
|
||||||
|
"Run Detector",
|
||||||
|
id="button_run",
|
||||||
|
style={
|
||||||
|
"margin-top": "15px",
|
||||||
|
"margin-bottom": "15px",
|
||||||
|
"margin-left": "11px",
|
||||||
|
"width": "30%",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
justify="start",
|
||||||
|
),
|
||||||
|
dbc.Row(
|
||||||
|
dcc.Loading(
|
||||||
|
id="loading-2",
|
||||||
|
children=[
|
||||||
dash_renderjson.DashRenderjson(
|
dash_renderjson.DashRenderjson(
|
||||||
id="right_json_viewer",
|
id="right_json_viewer",
|
||||||
data={},
|
data={},
|
||||||
@ -384,10 +372,13 @@ class AnalysisExplorer:
|
|||||||
theme=self.theme,
|
theme=self.theme,
|
||||||
invert_theme=True,
|
invert_theme=True,
|
||||||
),
|
),
|
||||||
]
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
type="circle",
|
type="circle",
|
||||||
|
),
|
||||||
|
justify="start",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
align="start",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -396,18 +387,12 @@ class AnalysisExplorer:
|
|||||||
def run_server(self, port: int = 8050) -> None:
|
def run_server(self, port: int = 8050) -> None:
|
||||||
"""Run the Dash server to start the analysis explorer.
|
"""Run the Dash server to start the analysis explorer.
|
||||||
|
|
||||||
This method should only be called in an interactive environment like Jupyter notebooks.
|
|
||||||
Raises an EnvironmentError if not called in an interactive environment.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
port (int, optional): The port number to run the server on (default: 8050).
|
port (int, optional): The port number to run the server on (default: 8050).
|
||||||
"""
|
"""
|
||||||
if not is_interactive():
|
|
||||||
raise EnvironmentError(
|
|
||||||
"Dash server should only be called in an interactive environment like Jupyter notebooks."
|
|
||||||
)
|
|
||||||
|
|
||||||
self.app.run_server(debug=True, mode="inline", port=port)
|
self.app.run_server(debug=True, port=port)
|
||||||
|
|
||||||
# Dash callbacks
|
# Dash callbacks
|
||||||
def update_picture(self, img_path: str):
|
def update_picture(self, img_path: str):
|
||||||
@ -492,7 +477,9 @@ class AnalysisExplorer:
|
|||||||
# copy image so prvious runs don't leave their default values in the dict
|
# copy image so prvious runs don't leave their default values in the dict
|
||||||
image_copy = self.mydict[image_id].copy()
|
image_copy = self.mydict[image_id].copy()
|
||||||
|
|
||||||
|
# detector value is the string name of the chosen detector
|
||||||
identify_function = identify_dict[detector_value]
|
identify_function = identify_dict[detector_value]
|
||||||
|
|
||||||
if detector_value == "TextDetector":
|
if detector_value == "TextDetector":
|
||||||
analyse_text = (
|
analyse_text = (
|
||||||
True if settings_text_analyse_text == ["Analyse text"] else False
|
True if settings_text_analyse_text == ["Analyse text"] else False
|
||||||
@ -508,6 +495,7 @@ class AnalysisExplorer:
|
|||||||
else None,
|
else None,
|
||||||
)
|
)
|
||||||
elif detector_value == "EmotionDetector":
|
elif detector_value == "EmotionDetector":
|
||||||
|
print("test")
|
||||||
detector_class = identify_function(
|
detector_class = identify_function(
|
||||||
image_copy,
|
image_copy,
|
||||||
race_threshold=setting_emotion_race_threshold,
|
race_threshold=setting_emotion_race_threshold,
|
||||||
|
|||||||
@ -184,6 +184,7 @@ class EmotionDetector(AnalysisMethod):
|
|||||||
"""
|
"""
|
||||||
# Find (multiple) faces in the image and cut them
|
# Find (multiple) faces in the image and cut them
|
||||||
retinaface_model.get()
|
retinaface_model.get()
|
||||||
|
|
||||||
faces = RetinaFace.extract_faces(self.subdict["filename"])
|
faces = RetinaFace.extract_faces(self.subdict["filename"])
|
||||||
# If no faces are found, we return empty keys
|
# If no faces are found, we return empty keys
|
||||||
if len(faces) == 0:
|
if len(faces) == 0:
|
||||||
|
|||||||
@ -105,23 +105,3 @@ def test_right_output_analysis_summary(get_AE, get_options):
|
|||||||
"base",
|
"base",
|
||||||
"How many people are in the picture?",
|
"How many people are in the picture?",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_right_output_analysis_colors(get_AE, get_options):
|
|
||||||
get_AE._right_output_analysis(
|
|
||||||
2,
|
|
||||||
get_options[3],
|
|
||||||
get_options[0],
|
|
||||||
"ColorDetector",
|
|
||||||
True,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
50,
|
|
||||||
50,
|
|
||||||
"CIE 1976",
|
|
||||||
"summary_and_questions",
|
|
||||||
"base",
|
|
||||||
"How many people are in the picture?",
|
|
||||||
)
|
|
||||||
with pytest.raises(EnvironmentError):
|
|
||||||
get_AE.run_server(port=8050)
|
|
||||||
|
|||||||
@ -20,10 +20,11 @@ classifiers = [
|
|||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: MIT License",
|
||||||
]
|
]
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bertopic<=0.14.1",
|
"bertopic<=0.14.1",
|
||||||
"cvlib",
|
"cvlib",
|
||||||
"dash",
|
"dash>=2.11.0",
|
||||||
"dash_renderjson",
|
"dash_renderjson",
|
||||||
"deepface<=0.0.75",
|
"deepface<=0.0.75",
|
||||||
"googletrans==3.1.0a0",
|
"googletrans==3.1.0a0",
|
||||||
@ -53,8 +54,8 @@ dependencies = [
|
|||||||
"setuptools",
|
"setuptools",
|
||||||
"opencv-contrib-python",
|
"opencv-contrib-python",
|
||||||
"dash",
|
"dash",
|
||||||
"jupyter_dash",
|
|
||||||
"dash_renderjson",
|
"dash_renderjson",
|
||||||
|
"dash_bootstrap_components",
|
||||||
"colorgram.py",
|
"colorgram.py",
|
||||||
"webcolors",
|
"webcolors",
|
||||||
"colour-science",
|
"colour-science",
|
||||||
|
|||||||
Загрузка…
x
Ссылка в новой задаче
Block a user