зеркало из
				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=[ | ||||||
|                         dcc.Checklist( |                         dbc.Row( | ||||||
|                             ["Analyse text"], |                             dcc.Checklist( | ||||||
|                             ["Analyse text"], |                                 ["Analyse text"], | ||||||
|                             id="setting_Text_analyse_text", |                                 ["Analyse text"], | ||||||
|                         ), |                                 id="setting_Text_analyse_text", | ||||||
|                         html.Div( |                                 style={"margin-bottom": "10px"}, | ||||||
|  |                             ), | ||||||
|  |                         ),  # row 1 | ||||||
|  |                         # text row 2 | ||||||
|  |                         dbc.Row( | ||||||
|                             [ |                             [ | ||||||
|                                 html.Div( |                                 dbc.Col( | ||||||
|                                     "Select models for text_summary, text_sentiment, text_NER or leave blank for default:", |                                     [ | ||||||
|                                     style={ |                                         html.P( | ||||||
|                                         "height": "30px", |                                             "Select models for text_summary, text_sentiment, text_NER or leave blank for default:", | ||||||
|                                         "margin-top": "5px", |                                             # style={"width": "45%"}, | ||||||
|                                     }, |                                         ), | ||||||
|  |                                     ] | ||||||
|  |                                 ),  # | ||||||
|  |                                 dbc.Col( | ||||||
|  |                                     [ | ||||||
|  |                                         html.P( | ||||||
|  |                                             "Select model revision number for text_summary, text_sentiment, text_NER or leave blank for default:" | ||||||
|  |                                         ), | ||||||
|  |                                     ] | ||||||
|                                 ), |                                 ), | ||||||
|                                 dcc.Input( |                             ] | ||||||
|                                     type="text", |                         ),  # row 2 | ||||||
|                                     id="setting_Text_model_names", |                         #  input row 3 | ||||||
|                                     style={"height": "auto", "margin-bottom": "auto"}, |                         dbc.Row( | ||||||
|                                 ), |  | ||||||
|                             ], |  | ||||||
|                             style={ |  | ||||||
|                                 "width": "33%", |  | ||||||
|                                 "display": "inline-block", |  | ||||||
|                                 "margin-top": "10px", |  | ||||||
|                             }, |  | ||||||
|                         ), |  | ||||||
|                         html.Div( |  | ||||||
|                             [ |                             [ | ||||||
|                                 html.Div( |                                 dbc.Col( | ||||||
|                                     "Select model revision number for text_summary, text_sentiment, text_NER or leave blank for default:", |                                     dcc.Input( | ||||||
|                                     style={ |                                         type="text", | ||||||
|                                         "height": "30px", |                                         id="setting_Text_model_names", | ||||||
|                                         "margin-top": "5px", |                                         style={"width": "100%"}, | ||||||
|                                     }, |                                     ), | ||||||
|                                 ), |                                 ), | ||||||
|                                 dcc.Input( |                                 dbc.Col( | ||||||
|                                     type="text", |                                     dcc.Input( | ||||||
|                                     id="setting_Text_revision_numbers", |                                         type="text", | ||||||
|                                     style={"height": "auto", "margin-bottom": "auto"}, |                                         id="setting_Text_revision_numbers", | ||||||
|  |                                         style={"width": "100%"}, | ||||||
|  |                                     ), | ||||||
|                                 ), |                                 ), | ||||||
|                             ], |                             ] | ||||||
|                             style={ |                         ),  # row 3 | ||||||
|                                 "width": "33%", |  | ||||||
|                                 "display": "inline-block", |  | ||||||
|                                 "margin-top": "10px", |  | ||||||
|                             }, |  | ||||||
|                         ), |  | ||||||
|                     ], |                     ], | ||||||
|                 ), |                 ),  # text summary end | ||||||
|  |                 # start emotion detector | ||||||
|                 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( | ||||||
|  |                                             value=50, | ||||||
|  |                                             type="number", | ||||||
|  |                                             max=100, | ||||||
|  |                                             min=0, | ||||||
|  |                                             id="setting_Emotion_emotion_threshold", | ||||||
|  |                                             style={"width": "100%"}, | ||||||
|  |                                         ), | ||||||
|  |                                     ], | ||||||
|  |                                     align="start", | ||||||
|                                 ), |                                 ), | ||||||
|                                 dcc.Input( |                                 dbc.Col( | ||||||
|                                     value=50, |                                     [ | ||||||
|                                     type="number", |                                         html.P("Race threshold"), | ||||||
|                                     max=100, |                                         dcc.Input( | ||||||
|                                     min=0, |                                             type="number", | ||||||
|                                     id="setting_Emotion_emotion_threshold", |                                             value=50, | ||||||
|                                     style={"height": "auto", "margin-bottom": "auto"}, |                                             max=100, | ||||||
|  |                                             min=0, | ||||||
|  |                                             id="setting_Emotion_race_threshold", | ||||||
|  |                                             style={"width": "100%"}, | ||||||
|  |                                         ), | ||||||
|  |                                     ], | ||||||
|  |                                     align="start", | ||||||
|                                 ), |                                 ), | ||||||
|                             ], |                             ], | ||||||
|                             style={"width": "49%", "display": "inline-block"}, |                             style={"width": "100%"}, | ||||||
|                         ), |  | ||||||
|                         html.Div( |  | ||||||
|                             [ |  | ||||||
|                                 html.Div( |  | ||||||
|                                     "Race threshold", |  | ||||||
|                                     style={ |  | ||||||
|                                         "height": "30px", |  | ||||||
|                                         "margin-top": "5px", |  | ||||||
|                                     }, |  | ||||||
|                                 ), |  | ||||||
|                                 dcc.Input( |  | ||||||
|                                     type="number", |  | ||||||
|                                     value=50, |  | ||||||
|                                     max=100, |  | ||||||
|                                     min=0, |  | ||||||
|                                     id="setting_Emotion_race_threshold", |  | ||||||
|                                     style={"height": "auto", "margin-bottom": "auto"}, |  | ||||||
|                                 ), |  | ||||||
|                             ], |  | ||||||
|                             style={ |  | ||||||
|                                 "width": "49%", |  | ||||||
|                                 "display": "inline-block", |  | ||||||
|                                 "margin-top": "10px", |  | ||||||
|                             }, |  | ||||||
|                         ), |                         ), | ||||||
|                     ], |                     ], | ||||||
|                 ), |                 ),  # 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( | ||||||
|                             [ |                             [ | ||||||
|                                 dcc.Dropdown( |                                 dbc.Row([html.P("Analysis type:")]), | ||||||
|                                     options=SUMMARY_ANALYSIS_TYPE, |                                 dbc.Row([html.P("Model type:")]), | ||||||
|                                     value="summary_and_questions", |                                 dbc.Row([html.P("Analysis question:")]), | ||||||
|                                     id="setting_Summary_analysis_type", |  | ||||||
|                                 ) |  | ||||||
|                             ], |                             ], | ||||||
|                             style={ |  | ||||||
|                                 "width": "33%", |  | ||||||
|                                 "display": "inline-block", |  | ||||||
|                             }, |  | ||||||
|                         ), |                         ), | ||||||
|                         html.Div( |                         dbc.Col( | ||||||
|                             [ |                             [ | ||||||
|                                 dcc.Dropdown( |                                 dbc.Row( | ||||||
|                                     options=SUMMARY_MODEL, |                                     dcc.Dropdown( | ||||||
|                                     value="base", |                                         options=SUMMARY_ANALYSIS_TYPE, | ||||||
|                                     id="setting_Summary_model", |                                         value="summary_and_questions", | ||||||
|                                 ) |                                         id="setting_Summary_analysis_type", | ||||||
|                             ], |                                     ) | ||||||
|                             style={ |  | ||||||
|                                 "width": "33%", |  | ||||||
|                                 "display": "inline-block", |  | ||||||
|                                 "margin-top": "10px", |  | ||||||
|                             }, |  | ||||||
|                         ), |  | ||||||
|                         html.Div( |  | ||||||
|                             [ |  | ||||||
|                                 html.Div( |  | ||||||
|                                     "Please enter a question", |  | ||||||
|                                     style={ |  | ||||||
|                                         "height": "50px", |  | ||||||
|                                         "margin-top": "5px", |  | ||||||
|                                     }, |  | ||||||
|                                 ), |                                 ), | ||||||
|                                 dcc.Input( |                                 dbc.Row( | ||||||
|                                     type="text", |                                     dcc.Dropdown( | ||||||
|                                     id="setting_Summary_list_of_questions", |                                         options=SUMMARY_MODEL, | ||||||
|                                     style={"height": "auto", "margin-bottom": "auto"}, |                                         value="base", | ||||||
|  |                                         id="setting_Summary_model", | ||||||
|  |                                     ) | ||||||
|                                 ), |                                 ), | ||||||
|                             ], |                                 dbc.Row( | ||||||
|                             style={ |                                     dcc.Input( | ||||||
|                                 "width": "33%", |                                         type="text", | ||||||
|                                 "display": "inline-block", |                                         id="setting_Summary_list_of_questions", | ||||||
|                                 "margin-top": "10px", |                                         style={ | ||||||
|                             }, |                                             "height": "auto", | ||||||
|  |                                             "margin-left": "11px", | ||||||
|  |                                         }, | ||||||
|  |                                     ), | ||||||
|  |                                 ), | ||||||
|  |                             ] | ||||||
|                         ), |                         ), | ||||||
|                     ], |                     ], | ||||||
|                 ), |                 ), | ||||||
|             ], |             ], | ||||||
|  |             style={"width": "100%", "display": "inline-block"}, | ||||||
|         ) |         ) | ||||||
|         return settings_layout |         return settings_layout | ||||||
| 
 | 
 | ||||||
| @ -356,38 +326,59 @@ class AnalysisExplorer: | |||||||
|         """ |         """ | ||||||
|         right_layout = html.Div( |         right_layout = html.Div( | ||||||
|             [ |             [ | ||||||
|                 dcc.Loading( |                 dbc.Col( | ||||||
|                     id="loading-2", |                     [ | ||||||
|                     children=[ |                         dbc.Row( | ||||||
|                         html.Div( |                             dcc.Dropdown( | ||||||
|                             [ |                                 options=[ | ||||||
|                                 dcc.Dropdown( |                                     "TextDetector", | ||||||
|                                     options=[ |                                     "ObjectDetector", | ||||||
|                                         "TextDetector", |                                     "EmotionDetector", | ||||||
|                                         "ObjectDetector", |                                     "SummaryDetector", | ||||||
|                                         "EmotionDetector", |                                     "ColorDetector", | ||||||
|                                         "SummaryDetector", |                                 ], | ||||||
|                                         "ColorDetector", |                                 value="TextDetector", | ||||||
|                                     ], |                                 id="Dropdown_select_Detector", | ||||||
|                                     value="TextDetector", |                                 style={"width": "60%"}, | ||||||
|                                     id="Dropdown_select_Detector", |                             ), | ||||||
|                                 ), |                             justify="start", | ||||||
|                                 html.Div( |                         ), | ||||||
|                                     children=[self._create_setting_layout()], |                         dbc.Row( | ||||||
|                                     id="div_detector_args", |                             children=[self._create_setting_layout()], | ||||||
|                                 ), |                             id="div_detector_args", | ||||||
|                                 html.Button("Run Detector", id="button_run"), |                             justify="start", | ||||||
|                                 dash_renderjson.DashRenderjson( |                         ), | ||||||
|                                     id="right_json_viewer", |                         dbc.Row( | ||||||
|                                     data={}, |                             html.Button( | ||||||
|                                     max_depth=-1, |                                 "Run Detector", | ||||||
|                                     theme=self.theme, |                                 id="button_run", | ||||||
|                                     invert_theme=True, |                                 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( | ||||||
|  |                                         id="right_json_viewer", | ||||||
|  |                                         data={}, | ||||||
|  |                                         max_depth=-1, | ||||||
|  |                                         theme=self.theme, | ||||||
|  |                                         invert_theme=True, | ||||||
|  |                                     ), | ||||||
|  |                                 ], | ||||||
|  |                                 type="circle", | ||||||
|  |                             ), | ||||||
|  |                             justify="start", | ||||||
|  |                         ), | ||||||
|                     ], |                     ], | ||||||
|                     type="circle", |                     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
	 GwydionJon
						GwydionJon