Skip to content

Commit

Permalink
Merge branch 'main' into version_4.60
Browse files Browse the repository at this point in the history
  • Loading branch information
northwestwitch authored Oct 12, 2022
2 parents 8fb3397 + b2330d9 commit 96baccc
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 51 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ About changelog [here](https://keepachangelog.com/en/1.0.0/)
### Added
- Mitochondrial deletion signatures (mitosign) can be uploaded and shown with mtDNA report
- A `Type of analysis` column on Causatives and Validated variants pages
- List of "safe" gene panels available for matching causatives and managed variants in institute settings, to avoid secondary findings
### Changed
- Hide removed gene panels by default in panels page
- Removed option for filtering cancer SVs by Tumor and Normal alt AF
Expand Down
72 changes: 35 additions & 37 deletions scout/adapter/mongo/institute.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def update_institute(
remove_sanger=None,
phenotype_groups=None,
gene_panels=None,
gene_panels_matching=None,
group_abbreviations=None,
add_groups=None,
sharing_institutes=None,
Expand All @@ -63,6 +64,7 @@ def update_institute(
remove_sanger(str): Email adress for sanger user to be removed
phenotype_groups(iterable(str)): New phenotype groups
gene_panels(dict): a dictionary of panels with key=panel_name and value=display_name
gene_panels_matching(dict): panels to limit search of matching variants (managed, causatives) to. Dict with key=panel_name and value=display_name
group_abbreviations(iterable(str))
add_groups(bool): If groups should be added. If False replace groups
sharing_institutes(list(str)): Other institutes to share cases with
Expand Down Expand Up @@ -94,9 +96,6 @@ def update_institute(
)
updates["$push"] = {"sanger_recipients": sanger_recipient}

if sanger_recipients is not None:
updates["$set"]["sanger_recipients"] = sanger_recipients # can be empty list

if remove_sanger:
LOG.info(
"Removing sanger recipient {0} from institute: {1}".format(
Expand All @@ -105,27 +104,21 @@ def update_institute(
)
updates["$pull"] = {"sanger_recipients": remove_sanger}

if coverage_cutoff:
LOG.info(
"Updating coverage cutoff for institute: {0} to {1}".format(
internal_id, coverage_cutoff
)
)
updates["$set"]["coverage_cutoff"] = coverage_cutoff

if frequency_cutoff:
LOG.info(
"Updating frequency cutoff for institute: {0} to {1}".format(
internal_id, frequency_cutoff
)
)
updates["$set"]["frequency_cutoff"] = frequency_cutoff

if display_name:
LOG.info(
"Updating display name for institute: {0} to {1}".format(internal_id, display_name)
)
updates["$set"]["display_name"] = display_name
# Set a number of items
GENERAL_SETTINGS = {
"cohorts": cohorts,
"collaborators": sharing_institutes,
"coverage_cutoff": coverage_cutoff,
"display_name": display_name,
"frequency_cutoff": frequency_cutoff,
"gene_panels": gene_panels,
"gene_panels_matching": gene_panels_matching,
"loqusdb_id": loqusdb_ids,
"sanger_recipients": sanger_recipients,
}
for key, value in GENERAL_SETTINGS.items():
if value not in [None, ""]:
updates["$set"][key] = value

if phenotype_groups is not None:
if group_abbreviations:
Expand All @@ -145,19 +138,6 @@ def update_institute(
existing_groups[hpo_term] = {"name": description, "abbr": abbreviation}
updates["$set"]["phenotype_groups"] = existing_groups

if gene_panels is not None:
updates["$set"]["gene_panels"] = gene_panels

if sharing_institutes is not None:
updates["$set"]["collaborators"] = sharing_institutes

if cohorts is not None:
updates["$set"]["cohorts"] = cohorts

if loqusdb_ids:
LOG.warning("Updating loqusdb id for institute: %s to %s", internal_id, loqusdb_ids)
updates["$set"]["loqusdb_id"] = loqusdb_ids

if alamut_key is not None:
updates["$set"]["alamut_key"] = (
alamut_key if alamut_key != "" else None
Expand Down Expand Up @@ -192,6 +172,24 @@ def institute(self, institute_id):

return institute_obj

def safe_genes_filter(self, institute_id):
"""Returns a list of "safe" HGNC IDs to filter variants with. These genes are retrieved from the institute.gene_panels_matching
Can be used to limit secondary findings when retrieving other causatives or matching managed variants
Args:
institute_id(str): _id of an institute
Returns:
safe_genes(list of HGNC ids)
"""
safe_genes = []
institute_obj = self.institute(institute_id)
if not institute_obj:
return safe_genes # return an empty list
for panel_name in institute_obj.get("gene_panels_matching", {}).keys():
safe_genes += self.panel_to_genes(panel_name=panel_name, gene_format="hgnc_id")
return safe_genes

def institutes(self, institute_ids=None):
"""Fetch all institutes.
Expand Down
11 changes: 9 additions & 2 deletions scout/server/blueprints/cases/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,12 +329,19 @@ def case(store, institute_obj, case_obj):
for img in case_obj["custom_images"][img_section]:
img["data"] = b64encode(img["data"]).decode("utf-8")

# Limit secondary findings according to institute settings
limit_genes = store.safe_genes_filter(institute_obj["_id"])

data = {
"institute": institute_obj,
"case": case_obj,
"status_class": STATUS_MAP.get(case_obj["status"]),
"other_causatives": [var for var in store.check_causatives(case_obj=case_obj)],
"managed_variants": [var for var in store.check_managed(case_obj=case_obj)],
"other_causatives": [
var for var in store.check_causatives(case_obj=case_obj, limit_genes=limit_genes)
],
"managed_variants": [
var for var in store.check_managed(case_obj=case_obj, limit_genes=limit_genes)
],
"comments": store.events(institute_obj, case=case_obj, comments=True),
"hpo_groups": pheno_groups,
"case_groups": case_groups,
Expand Down
10 changes: 9 additions & 1 deletion scout/server/blueprints/cases/templates/cases/case.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,17 @@ <h4 class="">
<span class="badge bg-sm bg-secondary">Internal ID: {{case._id}}</span>
</h4>
</div>
<div class="col-sm-8">
<div class="col-sm-6">
{{ variants_buttons() }}
</div>
<div class="col-sm-2">
Safe variant matching:
{% if institute.gene_panels_matching %}
<span class="badge rounded-pill bg-warning text-dark" data-bs-toggle="tooltip" data-bs-placement="left" title="To avoid incidental findings, eventual matching causatives and managed variants displayed on case page are filteres using a list of 'safe' panels. Modify institute settings to edit list of 'safe' panels. Current safe panels: {{ institute.gene_panels_matching.values()|list }}">on</span>
{% else %}
<span class="badge rounded-pill bg-info" data-bs-toggle="tooltip" data-bs-placement="left" title="Matching causatives and managed variants displayed on case page are NOT filtered by gene panel. Use caution to avoid incidental findings.">off</span>
{% endif %}
</div>
</div> <!--end of div class="row" -->
</div>

Expand Down
9 changes: 9 additions & 0 deletions scout/server/blueprints/institutes/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ def populate_institute_form(form, institute_obj):
for panel in available_panels:
panel_set.add((panel["panel_name"], panel["display_name"]))
form.gene_panels.choices = sorted(panel_set, key=lambda tup: tup[1])
form.gene_panels_matching.choices = sorted(panel_set, key=lambda tup: tup[1])

return default_phenotypes

Expand All @@ -294,6 +295,7 @@ def update_institute_settings(store, institute_obj, form):
sharing_institutes = []
phenotype_groups = []
gene_panels = {}
gene_panels_matching = {}
group_abbreviations = []
cohorts = []

Expand All @@ -317,6 +319,12 @@ def update_institute_settings(store, institute_obj, form):
continue
gene_panels[panel_name] = panel_obj["display_name"]

for panel_name in form.getlist("gene_panels_matching"):
panel_obj = store.gene_panel(panel_name)
if panel_obj is None:
continue
gene_panels_matching[panel_name] = panel_obj["display_name"]

for cohort in form.getlist("cohorts"):
cohorts.append(cohort.strip())

Expand All @@ -328,6 +336,7 @@ def update_institute_settings(store, institute_obj, form):
display_name=form.get("display_name"),
phenotype_groups=phenotype_groups,
gene_panels=gene_panels,
gene_panels_matching=gene_panels_matching,
group_abbreviations=group_abbreviations,
add_groups=False,
sharing_institutes=sharing_institutes,
Expand Down
7 changes: 6 additions & 1 deletion scout/server/blueprints/institutes/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ class InstituteForm(FlaskForm):
pheno_abbrev = StringField("Abbreviation", validators=[validators.Optional()])

gene_panels = NonValidatingSelectMultipleField(
"Gene panels for variants filtering", validators=[validators.Optional()]
"Gene panels available for variants filtering", validators=[validators.Optional()]
)

gene_panels_matching = NonValidatingSelectMultipleField(
"Gene panels available for other variants matching (managed and causatives variants)",
validators=[validators.Optional()],
)

pheno_groups = NonValidatingSelectMultipleField("Custom phenotype groups", choices=hpo_tuples)
Expand Down
33 changes: 23 additions & 10 deletions scout/server/blueprints/institutes/templates/overview/utils.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ <h3 class="header">General Institute Settings</h3>

<div class="row mt-3 d-flex align-items-center">

<div class="col-4">
{{ form.institutes.label(class="control-label",data_bs_toggle="tooltip", data_bs_placement="top", title="Allow case sharing only with preselected institutes.") }}
<select multiple="multiple" class="selectpicker" name="institutes" data-style="btn-secondary">
{% for choice in form.institutes.choices %}
<option value="{{choice[0]}}" {% if choice[0] in institute.get("collaborators", []) %} selected {% endif %}>{{choice[1]}}</option>
{% endfor %}
</select>
</div>

<div class="col-4">
{{ form.gene_panels.label(class="control-label",data_bs_toggle="tooltip", data_bs_placement="top", title="Select gene panels that will be available for variants filtering.") }}
<select multiple="multiple" name="gene_panels" class="selectpicker ml-3" data-style="btn-secondary">
Expand All @@ -95,6 +104,19 @@ <h3 class="header">General Institute Settings</h3>
</div>

<div class="col-4">
{{ form.gene_panels_matching.label(class="control-label",data_bs_toggle="tooltip", data_bs_placement="top", title="Limit incidental findings by looking for matching managed and causatives variants only in these panels") }}
<select multiple="multiple" name="gene_panels_matching" class="selectpicker ml-3" data-style="btn-secondary">
{% for choice in form.gene_panels_matching.choices or [] %}
<option value="{{choice[0]}}" {% if institute.gene_panels_matching and choice[0] in institute.gene_panels_matching.keys() %} selected {% endif %}>{{choice[1]}}</option>
{% endfor %}
</select>
</div>

<div>

<div class="row mt-3 d-flex align-items-center">

<div class="col-5">
{{ form.pheno_groups.label(class="control-label",data_bs_toggle="tooltip", data_bs_placement="top", title="Phenotype groups are used to quickly assign a certain phenotype to a case, on the case page.") }}
<select multiple="multiple" name="pheno_groups" class="selectpicker" data-style="btn-secondary">
{% for choice in form.pheno_groups.choices or [] %}
Expand All @@ -103,7 +125,7 @@ <h3 class="header">General Institute Settings</h3>
</select>
</div>

<div class="col-4">
<div class="col-7">
<div class="col-3">
{{form.cohorts.label(class="control-label",data_bs_toggle="tooltip", data_bs_placement="top", title="Categories used to subdivide patients")}}
</div>
Expand All @@ -115,18 +137,9 @@ <h3 class="header">General Institute Settings</h3>
</select>
</div>
</div>

</div>

<div class="row mt-3 d-flex align-items-center">
<div class="col-4">
{{ form.institutes.label(class="control-label",data_bs_toggle="tooltip", data_bs_placement="top", title="Allow case sharing only with preselected institutes.") }}
<select multiple="multiple" class="selectpicker" name="institutes" data-style="btn-secondary">
{% for choice in form.institutes.choices %}
<option value="{{choice[0]}}" {% if choice[0] in institute.get("collaborators", []) %} selected {% endif %}>{{choice[1]}}</option>
{% endfor %}
</select>
</div>
{% if "admin" in current_user.roles %}
<!-- Admins can modify loqusdb settings -->
<div class="col-4">
Expand Down

0 comments on commit 96baccc

Please sign in to comment.