-
Notifications
You must be signed in to change notification settings - Fork 1
Adding Settings Menu #552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding Settings Menu #552
Changes from all commits
c4e102e
8d76417
c1fd7d9
d8653e0
701b0a7
7e4aedc
49bb332
33fc8ac
9c4dd4d
813bcd1
fc14808
c3f87f7
b52c7cd
85e0129
8acc7d7
c962278
c49b60a
06cade2
451ce4e
893a935
7697fe1
a42961f
0ffe07b
1fd2d8c
6f0aeaa
da9e056
33ccabe
7ffbf4c
27d4c46
b4c837a
42aac62
f905a24
cc450ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,8 @@ | |
| from pathlib import Path | ||
|
|
||
| import pandas as pd | ||
| import plotly | ||
| import plotly.io as pio | ||
| import plotly.graph_objects as go | ||
| from PIL import Image | ||
|
|
||
| from protzilla.utilities import format_trace | ||
|
|
@@ -277,33 +278,47 @@ def __repr__(self): | |
| def empty(self) -> bool: | ||
| return len(self.plots) == 0 | ||
|
|
||
| def export(self, format_): | ||
| def export(self, settings: dict) -> list: | ||
| """ | ||
| Converts all plots from this step to files according to the format and size in the Plotly template. | ||
| An exported plot is represented as BytesIO object containing binary image data. | ||
| :param settings: Dict containing the plot settings. | ||
| :return: List of all exported plots. | ||
| """ | ||
| from ui.settings.plot_template import get_scale_factor | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ist es absichtlich, dass das erst hier importiert wird?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ja, tatsächlich Absicht. Wenn ich das oben importiert habe, kam dieser Error (hier nur ein Ausschnitt): Also steps.py möchte Messages, Output, etc. und get_scale_factor aus dem plot_template.py importieren. Dort wird der YamlOperator aus disk_operator.py importiert, der wiederum möchte unter anderem Step aus steps.py importieren, wo dann wieder Messages, Output, etc. importiert werden soll und da fängt das ganze wieder von vorne an ... Also vermeidet das Importieren an dieser Stelle diesen circular import, weil es erst geladen wird, wenn es benötigt wird. :) Ich fand diesen Workaround auch etwas befremdlich, habe es aber hier gefunden:
(Sorry für die lange Antwort, aber finde es irgendwie total nice, wie wir in unseren Teilaufgaben so random stuff lernen - und vielleicht ist das ja für noch wen interessant. ^^)
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oki danke für die Erklärung!! Ja, das habe ich auch erst mit Protzilla gelernt, dass man das tatsächlich so macht :D
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also ich fand die lange Antwort interessant :D
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ach, du liest hier auch mit? 👋 Das freut mich zu hören haha (: |
||
| exports = [] | ||
| format_ = settings["file_format"] | ||
|
|
||
| for plot in self.plots: | ||
| if isinstance(plot, plotly.graph_objs.Figure): | ||
| if format_ in ["eps", "tiff"]: | ||
| png_binary = plotly.io.to_image(plot, format="png", scale=4) | ||
| img = Image.open(BytesIO(png_binary)).convert("RGB") | ||
| scale_factor = get_scale_factor(plot, settings) | ||
| # For Plotly GO Figure | ||
| if isinstance(plot, go.Figure): | ||
| if format_ in ["tiff", "eps"]: | ||
| binary_png = pio.to_image(plot, format="png", scale=scale_factor) | ||
| img = Image.open(BytesIO(binary_png)).convert("RGB") | ||
| binary = BytesIO() | ||
| if format_ == "tiff": | ||
| img.save(binary, format="tiff", compression="tiff_lzw") | ||
| else: | ||
| elif format_ == "eps": | ||
| img.save(binary, format=format_) | ||
| binary.seek(0) | ||
| exports.append(binary) | ||
| else: | ||
| binary_string = plotly.io.to_image(plot, format=format_, scale=4) | ||
| exports.append(BytesIO(binary_string)) | ||
| binary_png = pio.to_image(plot, format=format_, scale=scale_factor) | ||
| exports.append(BytesIO(binary_png)) | ||
| elif isinstance(plot, dict) and "plot_base64" in plot: | ||
| plot = plot["plot_base64"] | ||
|
|
||
| if isinstance(plot, bytes): # base64 encoded plots | ||
| if format_ in ["eps", "tiff"]: | ||
| # TO DO: Include scale_factor here | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ist das ToDo noch aktuell?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, ich habe aktuell keinen Überblick, wo wir diese andere Art von Plots verwenden und wäre stark dafür, sie einfach rauszunehmen und stattdessen einheitlich Plotly verwenden. Es existiert bereits das Issue "Use Plotly Template in all Sections #549", kann aber gerne noch einen Hinweis auf dieses To Do dort einfügen. |
||
| # For base64 encoded plot | ||
| if isinstance(plot, bytes): | ||
| if format_ in ["tiff", "eps"]: | ||
| img = Image.open(BytesIO(base64.b64decode(plot))).convert("RGB") | ||
| binary = BytesIO() | ||
| if format_ == "tiff": | ||
| img.save(binary, format="tiff", compression="tiff_lzw") | ||
| else: | ||
| img.save(binary, format=format_) | ||
| elif format_ == "eps": | ||
| img.save(binary, format="eps") | ||
| binary.seek(0) | ||
| exports.append(binary) | ||
| elif format_ in ["png", "jpg"]: | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |
| import pandas as pd | ||
| import psutil | ||
|
|
||
| from django.http import QueryDict | ||
|
|
||
| # recipie from https://docs.python.org/3/library/itertools.html | ||
| def unique_justseen(iterable, key=None): | ||
|
|
@@ -136,3 +137,47 @@ def get_file_name_from_upload_path(upload_path: str) -> str: | |
| base_name = file_name_randomized.split("_")[0] | ||
| file_extension = file_name_randomized.split(".")[-1] | ||
| return f"{base_name}.{file_extension}" | ||
|
|
||
|
|
||
| def parameters_from_post(post: QueryDict) -> dict: | ||
| """ | ||
| Removes token from dict and converts the remaining entries into suitable data formats. | ||
| :param post: Django dict containing POST data. | ||
| :return: Dict containing the parameters in suitable formats. | ||
| """ | ||
| d = dict(post) | ||
| if "csrfmiddlewaretoken" in d: | ||
| del d["csrfmiddlewaretoken"] | ||
| parameters = {} | ||
| for k, v in d.items(): | ||
| if len(v) > 1: | ||
| # only used for named_output parameters and multiselect fields | ||
| parameters[k] = v | ||
| else: | ||
| parameters[k] = convert_str_if_possible(v[0]) | ||
| return parameters | ||
|
|
||
|
|
||
| def convert_str_if_possible(s): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hier gerne auch doc-string und return type :)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as for
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Danke, dass du es trotzdem ergänzt hast ^^ |
||
| """ | ||
| Converts an input value into suitable representation as a string. | ||
| :param s: Input value. | ||
| :return: Converted input value. | ||
| """ | ||
| try: | ||
| f = float(s) | ||
| return int(f) if int(f) == f else f | ||
| except ValueError: | ||
| if s == "checked": | ||
| # s is a checkbox | ||
| return True | ||
| if re.fullmatch(r"\d+(\.\d+)?(\|\d+(\.\d+)?)*", s): | ||
| # s is a multi-numeric input e.g. 1-0.12-5 | ||
| numbers_str = re.findall(r"\d+(?:\.\d+)?", s) | ||
| numbers = [] | ||
| for num in numbers_str: | ||
| num = float(num) | ||
| num = int(num) if int(num) == num else num | ||
| numbers.append(num) | ||
| return numbers | ||
| return s | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import pytest | ||
| import plotly.graph_objects as go | ||
|
|
||
| from protzilla.constants.colors import PLOT_PRIMARY_COLOR, PLOT_SECONDARY_COLOR | ||
| from protzilla.constants.paths import SETTINGS_PATH | ||
| from ui.settings.plot_template import ( | ||
| determine_font, | ||
| resize_for_display, | ||
| get_scale_factor | ||
| ) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def sample_params(): | ||
| return { | ||
| "section_id": "plots", | ||
| "file_format": "png", | ||
| "width": 85, | ||
| "height": 60, | ||
| "custom_font": "Ubuntu Mono", | ||
| "font": "Arial", | ||
| "heading_size": 11, | ||
| "text_size": 8 | ||
| } | ||
|
|
||
| def test_determine_font(sample_params): | ||
| assert determine_font(sample_params) == "Arial" | ||
| sample_params["font"] = "Custom" | ||
| assert determine_font(sample_params) == "Ubuntu Mono" | ||
|
|
||
| def test_resize_for_display(sample_params): | ||
| result = resize_for_display(sample_params) | ||
| assert result["display_width"] == 600 # SCALED_WIDTH | ||
| assert result["display_heading_size"] == 27 | ||
|
|
||
| def test_get_scale_factor(sample_params): | ||
| fig = go.Figure() | ||
| fig.update_layout(width=600) | ||
| scale = get_scale_factor(fig, sample_params) | ||
| assert isinstance(scale, float) | ||
| assert round(scale, 3) == 1.673 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vielleicht noch hinzufügen was genau ein exportierter Plot ist, also ob es die raw files sind oder metadaten als Plot objekt oder so?