-
Notifications
You must be signed in to change notification settings - Fork 1
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
color selection for enrichment analysis bar plot #556
base: dev
Are you sure you want to change the base?
Changes from 9 commits
c91a2c7
d518327
e44e366
0a1e836
37bdd44
bce8482
8852b60
3861cd8
4a8c210
6b4b2f2
4d04989
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 |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
from django.forms.widgets import CheckboxInput, SelectMultiple | ||
from django.utils.html import format_html | ||
from django.utils.safestring import SafeText, mark_safe | ||
from django.template.loader import render_to_string | ||
|
||
# Custom widgets | ||
|
||
|
@@ -87,6 +88,69 @@ def __init__(self, choices: Enum | list, initial=None, *args, **kwargs): | |
def clean(self, value: list[str] | None): | ||
return [el for el in value if el != "hidden"] if value else None | ||
|
||
class CustomCheckboxMultipleChoiceField(MultipleChoiceField): | ||
def __init__(self, choices: Enum | list, colors: Enum | list, initial=None, *args, **kwargs): | ||
if isinstance(choices, list): | ||
super().__init__(choices=choices, initial=initial, *args, **kwargs) | ||
else: | ||
super().__init__( | ||
choices=[(el.value, el.value) for el in choices], | ||
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. Das "el in choices" ist nicht so clean, benenne das lieber in sowas wie choice in choices um. Gerne dann auch für den Rest der Datei 👍 |
||
initial=initial, | ||
*args, | ||
**kwargs, | ||
) | ||
self.widget = CustomCheckboxSelectMultipleWidget() | ||
self.widget.colors = colors | ||
self.widget.attrs.update({"class": "form-select mb-2"}) | ||
|
||
|
||
def clean(self, value: list[str] | None): | ||
if not value: | ||
return None | ||
|
||
gen_sets = [] | ||
colors = {} | ||
result = {} | ||
|
||
for element in value: | ||
if element.startswith("color_"): | ||
_,gen_set,color = element.split('_', 2) | ||
colors[gen_set] = color | ||
else: | ||
gen_sets.append(element) | ||
|
||
for gen_set in sorted(gen_sets): | ||
if gen_set in colors: | ||
result[gen_set] = colors[gen_set] | ||
|
||
return result | ||
|
||
|
||
class CustomCheckboxSelectMultipleWidget(SelectMultiple): | ||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.colors = [] | ||
|
||
def render(self, name, value, attrs=None, renderer=None) -> SafeText: | ||
if isinstance(value, dict): | ||
reformat_value = [] | ||
for gen_set, color in value.items(): | ||
reformat_value.append(gen_set) | ||
reformat_value.append(f"color_{gen_set}_{color}") | ||
value = reformat_value | ||
|
||
return mark_safe( | ||
render_to_string( | ||
"runs/field_component_color_selection.html", | ||
context={ | ||
"name": name, | ||
"choices": self.choices, | ||
"colors": self.colors, | ||
"values": value, | ||
} | ||
) | ||
) | ||
|
||
|
||
class CustomFileField(FileField): | ||
def __init__(self, *args, **kwargs): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ | |
CustomFloatField, | ||
CustomMultipleChoiceField, | ||
CustomNumberField, | ||
CustomCheckboxMultipleChoiceField, | ||
) | ||
|
||
PROTEIN_DF = "protein_df" | ||
|
@@ -539,7 +540,8 @@ class PlotGOEnrichmentBarPlotForm(MethodForm): | |
input_df_step_instance = CustomChoiceField( | ||
choices=[], label="Choose dataframe to be plotted" | ||
) | ||
gene_sets = CustomMultipleChoiceField(choices=[], label="Sets to be plotted") | ||
# TODO: update PLOT_COLOR_SEQUENCE (color, color) for color in PLOT_COLOR_SEQUENCE | ||
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. Schön schonmal an die kommenden Schritte gedacht, aber mach bitte noch ne Karte im Notion draus und referenziere im Todo, wann genau das umgesetzt werden kann. |
||
gene_sets = CustomCheckboxMultipleChoiceField(choices=[], colors=[(v, k[4:]) for k, v, in list(mcolors.TABLEAU_COLORS.items())], label="Sets to be plotted") | ||
value = CustomChoiceField( | ||
choices=GOEnrichmentBarPlotValue, | ||
label="Value (bars will be plotted as -log10(value)), fdr only for GO analysis with STRING, p_value is adjusted if available", | ||
|
@@ -561,15 +563,7 @@ class PlotGOEnrichmentBarPlotForm(MethodForm): | |
) | ||
title = CustomCharField(label="Title of the plot (optional)", required=False) | ||
|
||
colors = CustomMultipleChoiceField( | ||
choices=[], label="Colors for the plot (optional)" | ||
) # TODO this should not have to be set in fill_form | ||
|
||
def fill_form(self, run: Run) -> None: | ||
self.fields["colors"].choices = [ | ||
(v, k) for k, v, in mcolors.CSS4_COLORS.items() | ||
] | ||
|
||
self.fields["input_df_step_instance"].choices = fill_helper.get_choices( | ||
run, "enrichment_df" | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<div class="checkbox-container border p-3 rounded"> | ||
{% for option_value, option_label in choices %} | ||
<div class="d-flex" style="align-items: center"> | ||
<div class="checkbox-item px-2 w-50"> | ||
<input type="checkbox" id="{{ name }}_{{ option_label}}_checkbox" name="{{ name }}" value="{{ option_value }}" {% if option_value in values %}checked{% endif %}> | ||
<label for="{{ name }}_{{ option_label}}_checkbox">{{ option_label }}</label> | ||
</div> | ||
<div class="ms-auto px-2 w-50"> | ||
<select class="form-select" name="{{ name }}"> | ||
{% for color, color_label in colors %} | ||
{% with color_value="color_"|add:option_value|add:"_"|add:color %} | ||
<option value={{ color_value }} | ||
{% if values %} | ||
{% if color_value in values %}selected{% endif %} | ||
{% else %} | ||
{% if forloop.parentloop.counter0 == forloop.counter0 %}selected{% endif %} | ||
{% endif %} | ||
> | ||
{{ color_label }} | ||
</option> | ||
{% endwith %} | ||
{% endfor %} | ||
</select> | ||
</div> | ||
</div> | ||
{% endfor %} | ||
</div> |
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.
Die ganzen Hex-Strings gerne als Variable zusammengefasst, sodass man die mit einem Mal alle ändern kann.
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.
Vielen Dank für die Idee, aber diese wäre an dieser Stelle nicht passend, da es sich um eine Test-Datei handelt. Die erstellten Plots werden nicht visuell betrachtet. An dieser Stelle ist viel mehr wichtig, dass sich der Dateityp von List zu Dict geändert hat und direkt ersichtlich werden soll, dass es sich um einen HEX-Farbwert handelt. Bei einem fehlgeschlagenen Test ist somit direkt klar, welche Parameter zu einem Fail geführt haben.