def panel(panel_id): """Display (and add pending updates to) a specific gene panel.""" panel_obj = store.gene_panel(panel_id) or store.panel(panel_id) if request.method == 'POST': raw_hgnc_id = request.form['hgnc_id'] if '|' in raw_hgnc_id: raw_hgnc_id = raw_hgnc_id.split(' | ', 1)[0] hgnc_id = int(raw_hgnc_id) action = request.form['action'] if action == 'add': panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id) if panel_gene: flash("gene already in panel: {}".format(panel_gene['symbol']), 'warning') else: # ask user to fill-in more information about the gene return redirect( url_for('.gene_edit', panel_id=panel_id, hgnc_id=hgnc_id)) elif action == 'delete': log.debug("marking gene to be deleted: %s", hgnc_id) store.add_pending(panel_obj, hgnc_id, action='delete') data = controllers.panel(store, panel_obj) if request.args.get('case_id'): data['case'] = store.case(request.args['case_id']) if request.args.get('institute_id'): data['institute'] = store.institute(request.args['institute_id']) return data
def update_institute_settings(store, institute_obj, form): """Update institute settings with data collected from institute form Args: score(adapter.MongoAdapter) institute_id(str) form(dict) Returns: updated_institute(dict) """ sanger_recipients = [] sharing_institutes = [] phenotype_groups = [] gene_panels = {} group_abbreviations = [] cohorts = [] for email in form.getlist("sanger_emails"): sanger_recipients.append(email.strip()) for inst in form.getlist("institutes"): sharing_institutes.append(inst) for pheno_group in form.getlist("pheno_groups"): phenotype_groups.append(pheno_group.split(" ,")[0]) group_abbreviations.append(pheno_group[pheno_group.find("( ") + 2:pheno_group.find(" )")]) if form.get("hpo_term") and form.get("pheno_abbrev"): phenotype_groups.append(form["hpo_term"].split(" |")[0]) group_abbreviations.append(form["pheno_abbrev"]) for panel_name in form.getlist("gene_panels"): panel_obj = store.gene_panel(panel_name) if panel_obj is None: continue gene_panels[panel_name] = panel_obj["display_name"] for cohort in form.getlist("cohorts"): cohorts.append(cohort.strip()) updated_institute = store.update_institute( internal_id=institute_obj["_id"], sanger_recipients=sanger_recipients, coverage_cutoff=int(form.get("coverage_cutoff")), frequency_cutoff=float(form.get("frequency_cutoff")), display_name=form.get("display_name"), phenotype_groups=phenotype_groups, gene_panels=gene_panels, group_abbreviations=group_abbreviations, add_groups=False, sharing_institutes=sharing_institutes, cohorts=cohorts, loqusdb_ids=form.getlist("loqusdb_id"), alamut_key=form.get("alamut_key"), ) return updated_institute
def panel(panel_id): """Display (and add pending updates to) a specific gene panel.""" panel_obj = store.gene_panel(panel_id) or store.panel(panel_id) if not panel_obj: flash("Panel with id {} not found.".format(panel_id), "warning") return redirect(url_for("panels.panels")) if request.method == "POST": if request.form.get("update_description"): panel_obj["description"] = request.form["panel_description"] if controllers.panel_write_granted(panel_obj, current_user): store.update_panel(panel_obj=panel_obj) else: flash( "Permission denied: please ask a panel maintainer or admin for help.", "danger", ) return redirect(url_for("panels.panel", panel_id=panel_obj["_id"])) raw_hgnc_id = request.form["hgnc_id"] if "|" in raw_hgnc_id: raw_hgnc_id = raw_hgnc_id.split(" | ", 1)[0] hgnc_id = 0 try: hgnc_id = int(raw_hgnc_id) except ValueError: flash("Provided HGNC is not valid : '{}'".format(raw_hgnc_id), "danger") return redirect(request.referrer) action = request.form["action"] gene_obj = store.hgnc_gene_caption( hgnc_identifier=hgnc_id, build="37") or store.hgnc_gene_caption( hgnc_identifier=hgnc_id, build="38") if gene_obj is None: flash("HGNC id not found: {}".format(hgnc_id), "warning") return redirect(request.referrer) if action == "add": panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id) if panel_gene: flash("gene already in panel: {}".format(panel_gene["symbol"]), "warning") else: # ask user to fill-in more information about the gene return redirect( url_for(".gene_edit", panel_id=panel_id, hgnc_id=hgnc_id)) elif action == "delete": LOG.debug("marking gene to be deleted: %s", hgnc_id) panel_obj = store.add_pending(panel_obj, gene_obj, action="delete") data = controllers.panel(store, panel_obj) if request.args.get("case_id"): data["case"] = store.case(request.args["case_id"]) if request.args.get("institute_id"): data["institute"] = store.institute(request.args["institute_id"]) return data
def test_panel_modify_genes(app, real_panel_database): """Test the functionality to modify genes in a gene panel""" # GIVEN a panel in the database panel_obj = store.gene_panels()[0] # WHEN posting a delete gene request to panel page a_gene = panel_obj["genes"][0] # first gene of the panel form_data = {"action": "delete", "hgnc_id": a_gene["hgnc_id"]} # GIVEN an initialized app # GIVEN a valid user and institute with app.test_client() as client: # GIVEN that the user could be logged in resp = client.get(url_for("auto_login")) resp = client.post( url_for("panels.panel", panel_id=panel_obj["_id"]), data=form_data, ) # THEN the pending actions of panel should be updated: panel_obj = store.gene_panels()[0] assert panel_obj["pending"][0]["action"] == "delete" assert panel_obj["pending"][0]["hgnc_id"] == a_gene["hgnc_id"] # WHEN removing that gene using the client new_version = panel_obj["version"] + 1 form_data = {"action": "submit", "version": new_version} resp = client.post( url_for("panels.panel_update", panel_id=panel_obj["_id"]), data=form_data, ) # THEN the new panel object should have the correct new version new_panel_obj = store.gene_panel(panel_obj["panel_name"]) assert new_panel_obj["version"] == new_version # remove gene from panel object using adapter: panel_obj["genes"] = panel_obj["genes"][1:] updated_panel = store.update_panel(panel_obj) # WHEN posting an add gene request to panel page form_data = {"action": "add", "hgnc_id": a_gene["hgnc_id"]} resp = client.post( url_for("panels.panel", panel_id=updated_panel["_id"]), data=form_data, ) # Then response should redirect to gene edit page assert resp.status_code == 302
def coverage_report_contents(base_url, institute_obj, case_obj): """Capture the contents of a case coverage report (chanjo-report), to be displayed in the general case report Args: base_url(str): base url of this application institute_obj(models.Institute) case_obj(models.Case) Returns: html_body_content(str): A string corresponding to the text within the <body> of an HTML chanjo-report page """ request_data = {} # extract sample ids from case_obj and add them to the post request object: request_data["sample_id"] = [ind["individual_id"] for ind in case_obj["individuals"]] # extract default panel names and default genes from case_obj and add them to the post request object distinct_genes = set() panel_names = [] for panel_info in case_obj.get("panels", []): if panel_info.get("is_default") is False: continue panel_obj = store.gene_panel(panel_info["panel_name"], version=panel_info.get("version")) distinct_genes.update([gene["hgnc_id"] for gene in panel_obj.get("genes", [])]) full_name = "{} ({})".format(panel_obj["display_name"], panel_obj["version"]) panel_names.append(full_name) panel_names = " ,".join(panel_names) request_data["gene_ids"] = ",".join([str(gene_id) for gene_id in list(distinct_genes)]) request_data["panel_name"] = panel_names request_data["request_sent"] = datetime.datetime.now() # add institute-specific cutoff level to the post request object request_data["level"] = institute_obj.get("coverage_cutoff", 15) # Collect the coverage report HTML string try: resp = requests.post( base_url + "reports/report", timeout=COVERAGE_REPORT_TIMEOUT, data=request_data ) except requests.Timeout: html_body_content = "<span><b>Coverage report unavailable</b></span>" return html_body_content # Extract the contents between <body> and </body> html_body_content = resp.text.split("<body>")[1].split("</body>")[0] return html_body_content
def panel(panel_id): """Display (and add pending updates to) a specific gene panel.""" panel_obj = store.gene_panel(panel_id) or store.panel(panel_id) if request.method == 'POST': if request.form.get('update_description'): panel_obj['description'] = request.form['panel_description'] store.update_panel(panel_obj=panel_obj) return redirect( url_for('panels.panel', panel_id=panel_obj['_id']) ) raw_hgnc_id = request.form['hgnc_id'] if '|' in raw_hgnc_id: raw_hgnc_id = raw_hgnc_id.split(' | ', 1)[0] hgnc_id = 0 try: hgnc_id = int(raw_hgnc_id) except: flash("Provided HGNC is not valid : '{}'". format(raw_hgnc_id), 'danger') return redirect(request.referrer) action = request.form['action'] gene_obj = store.hgnc_gene(hgnc_id) if gene_obj is None: flash("HGNC id not found: {}".format(hgnc_id), 'warning') return redirect(request.referrer) if action == 'add': panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id) if panel_gene: flash("gene already in panel: {}".format(panel_gene['symbol']), 'warning') else: # ask user to fill-in more information about the gene return redirect(url_for('.gene_edit', panel_id=panel_id, hgnc_id=hgnc_id)) elif action == 'delete': log.debug("marking gene to be deleted: %s", hgnc_id) panel_obj = store.add_pending(panel_obj, gene_obj, action='delete') data = controllers.panel(store, panel_obj) if request.args.get('case_id'): data['case'] = store.case(request.args['case_id']) if request.args.get('institute_id'): data['institute'] = store.institute(request.args['institute_id']) return data
def panel_delete(panel_id): """Remove an existing panel.""" panel_obj = store.gene_panel(panel_id) or store.panel(panel_id) if panel_obj is None: flash( f"Panel object with id '{panel_id}' was not found.", "danger", ) return redirect(request.referrer) if controllers.panel_write_granted(panel_obj, current_user): LOG.info("Mark gene panel: %s as deleted (hidden)" % panel_obj["display_name"]) panel_obj["hidden"] = True store.update_panel(panel_obj=panel_obj) flash("Removed gene panel: %s" % panel_obj["display_name"], "success") else: flash( "Permission denied: please ask a panel maintainer or admin for help.", "danger", ) return redirect(url_for("panels.panels", panel_id=panel_obj["_id"]))
def panel(panel_id): """Display (and add pending updates to) a specific gene panel.""" panel_obj = store.gene_panel(panel_id) or store.panel(panel_id) if request.method == 'POST': raw_hgnc_id = request.form['hgnc_id'] if '|' in raw_hgnc_id: raw_hgnc_id = raw_hgnc_id.split(' | ', 1)[0] hgnc_id = 0 try: hgnc_id = int(raw_hgnc_id) except: flash("Provided HGNC is not valid : '{}'". format(raw_hgnc_id), 'danger') return redirect(request.referrer) action = request.form['action'] gene_obj = store.hgnc_gene(hgnc_id) if gene_obj is None: flash("HGNC id not found: {}".format(hgnc_id), 'warning') return redirect(request.referrer) if action == 'add': panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id) if panel_gene: flash("gene already in panel: {}".format(panel_gene['symbol']), 'warning') else: # ask user to fill-in more information about the gene return redirect(url_for('.gene_edit', panel_id=panel_id, hgnc_id=hgnc_id)) elif action == 'delete': log.debug("marking gene to be deleted: %s", hgnc_id) panel_obj = store.add_pending(panel_obj, gene_obj, action='delete') data = controllers.panel(store, panel_obj) if request.args.get('case_id'): data['case'] = store.case(request.args['case_id']) if request.args.get('institute_id'): data['institute'] = store.institute(request.args['institute_id']) return data
def case(store, institute_obj, case_obj): """Preprocess a single case. Prepare the case to be displayed in the case view. Args: store(adapter.MongoAdapter) institute_obj(models.Institute) case_obj(models.Case) Returns: data(dict): includes the cases, how many there are and the limit. """ # Convert individual information to more readable format case_obj["individual_ids"] = [] for individual in case_obj["individuals"]: try: sex = int(individual.get("sex", 0)) except ValueError as err: sex = 0 individual["sex_human"] = SEX_MAP[sex] pheno_map = PHENOTYPE_MAP if case_obj.get("track", "rare") == "cancer": pheno_map = CANCER_PHENOTYPE_MAP individual["phenotype_human"] = pheno_map.get(individual["phenotype"]) case_obj["individual_ids"].append(individual["individual_id"]) case_obj["assignees"] = [store.user(user_email) for user_email in case_obj.get("assignees", [])] # Provide basic info on alignment files availability for this case case_has_alignments(case_obj) case_has_mt_alignments(case_obj) case_groups = {} case_group_label = {} _populate_case_groups(store, case_obj, case_groups, case_group_label) # Fetch the variant objects for suspects and causatives suspects = [ store.variant(variant_id) or variant_id for variant_id in case_obj.get("suspects", []) ] _populate_assessments(suspects) causatives = [ store.variant(variant_id) or variant_id for variant_id in case_obj.get("causatives", []) ] _populate_assessments(causatives) # get evaluated variants evaluated_variants = store.evaluated_variants(case_obj["_id"], case_obj["owner"]) _populate_assessments(evaluated_variants) # check for partial causatives and associated phenotypes partial_causatives = [] if case_obj.get("partial_causatives"): for var_id, values in case_obj["partial_causatives"].items(): causative_obj = { "variant": store.variant(var_id) or var_id, "omim_terms": values.get("diagnosis_phenotypes"), "hpo_terms": values.get("phenotype_terms"), } partial_causatives.append(causative_obj) _populate_assessments(partial_causatives) # Set of all unique genes in the default gene panels distinct_genes = set() case_obj["panel_names"] = [] case_obj["outdated_panels"] = {} for panel_info in case_obj.get("panels", []): if not panel_info.get("is_default"): continue panel_name = panel_info["panel_name"] panel_version = panel_info.get("version") panel_obj = store.gene_panel(panel_name, version=panel_version) latest_panel = store.gene_panel(panel_name) panel_info["removed"] = False if latest_panel is None else latest_panel.get("hidden", False) if not panel_obj: panel_obj = latest_panel if not panel_obj: flash(f"Case default panel '{panel_name}' could not be found.", "warning") continue flash( f"Case default panel '{panel_name}' version {panel_version} could not be found, using latest existing version", "warning", ) # Check if case-specific panel is up-to-date with latest version of the panel if panel_obj["version"] < latest_panel["version"]: extra_genes, missing_genes = _check_outdated_gene_panel(panel_obj, latest_panel) if extra_genes or missing_genes: case_obj["outdated_panels"][panel_name] = { "missing_genes": missing_genes, "extra_genes": extra_genes, } distinct_genes.update([gene["hgnc_id"] for gene in panel_obj.get("genes", [])]) full_name = "{} ({})".format(panel_obj["display_name"], panel_obj["version"]) case_obj["panel_names"].append(full_name) case_obj["default_genes"] = list(distinct_genes) for hpo_term in itertools.chain( case_obj.get("phenotype_groups", []), case_obj.get("phenotype_terms", []) ): hpo_term["hpo_link"] = "http://hpo.jax.org/app/browse/term/{}".format( hpo_term["phenotype_id"] ) if case_obj.get("rank_model_version"): rank_model_link = "".join( [ current_app.config.get("RANK_MODEL_LINK_PREFIX", ""), str(case_obj["rank_model_version"]), current_app.config.get("RANK_MODEL_LINK_POSTFIX", ""), ] ) case_obj["rank_model_link"] = rank_model_link if case_obj.get("sv_rank_model_version"): case_obj["sv_rank_model_link"] = "".join( [ current_app.config.get("SV_RANK_MODEL_LINK_PREFIX", ""), str(case_obj["sv_rank_model_version"]), current_app.config.get("SV_RANK_MODEL_LINK_POSTFIX", ""), ] ) # other collaborators than the owner of the case o_collaborators = [] for collab_id in case_obj.get("collaborators", []): if collab_id != case_obj["owner"] and store.institute(collab_id): o_collaborators.append(store.institute(collab_id)) case_obj["o_collaborators"] = [ (collab_obj["_id"], collab_obj["display_name"]) for collab_obj in o_collaborators ] collab_ids = None if institute_obj.get("collaborators"): collab_ids = [ (collab["_id"], collab["display_name"]) for collab in store.institutes() if institute_obj.get("collaborators") and collab["_id"] in institute_obj.get("collaborators") ] events = list(store.events(institute_obj, case=case_obj))
def panels(): """Show all panels for a case.""" if request.method == "POST": # update an existing panel csv_file = request.files["csv_file"] content = csv_file.stream.read() lines = None try: if b"\n" in content: lines = content.decode("utf-8-sig", "ignore").split("\n") else: lines = content.decode("windows-1252").split("\r") except Exception as err: flash( "Something went wrong while parsing the panel CSV file! ({})". format(err), "danger", ) return redirect(request.referrer) new_panel_name = request.form.get("new_panel_name") if new_panel_name: # create a new panel new_panel_id = controllers.new_panel( store=store, institute_id=request.form["institute"], panel_name=new_panel_name, display_name=request.form["display_name"], csv_lines=lines, maintainer=[current_user._id], description=request.form["description"], ) if new_panel_id is None: flash( "Something went wrong and the panel list was not updated!", "warning", ) return redirect(request.referrer) flash("new gene panel added, {}!".format(new_panel_name), "success") return redirect(url_for("panels.panel", panel_id=new_panel_id)) # modify an existing panel update_option = request.form["modify_option"] panel_obj = store.gene_panel(request.form["panel_name"]) if panel_obj is None: return abort( 404, "gene panel not found: {}".format(request.form["panel_name"])) if panel_write_granted(panel_obj, current_user): panel_obj = controllers.update_panel( store=store, panel_name=request.form["panel_name"], csv_lines=lines, option=update_option, ) else: flash( "Permission denied: please ask a panel maintainer or admin for help.", "danger", ) return redirect(url_for("panels.panel", panel_id=panel_obj["_id"])) institutes = list(user_institutes(store, current_user)) panel_names = [ name for institute in institutes for name in store.gene_panels( institute_id=institute["_id"]).distinct("panel_name") ] panel_versions = {} for name in panel_names: panel_versions[name] = store.gene_panels(panel_id=name) panel_groups = [] for institute_obj in institutes: institute_panels = store.latest_panels(institute_obj["_id"]) panel_groups.append((institute_obj, institute_panels)) return dict( panel_groups=panel_groups, panel_names=panel_names, panel_versions=panel_versions, institutes=institutes, )