Пример #1
0
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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
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
Пример #7
0
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"]))
Пример #8
0
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
Пример #9
0
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))
Пример #10
0
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,
    )