Exemplo n.º 1
0
def matchmaker_delete(institute_id, case_name):
    """Remove a case from MatchMaker"""

    # check that only authorized users can delete patients from MME
    user_obj = store.user(current_user.email)
    if 'mme_submitter' not in user_obj['roles']:
        flash('unauthorized request', 'warning')
        return redirect(request.referrer)

    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    # Required params for sending a delete request to MME:
    mme_base_url = current_app.config.get('MME_URL')
    mme_token = current_app.config.get('MME_TOKEN')
    if not mme_base_url or not mme_token:
        flash('An error occurred reading matchmaker connection parameters. Please check config file!', 'danger')
        return redirect(request.referrer)

    delete_result = controllers.mme_delete(case_obj, mme_base_url, mme_token)

    n_deleted = 0
    category = 'warning'

    for resp in delete_result:
        if resp['status_code'] == 200:
            n_deleted += 1
        else:
            flash(resp['message'], category)
    if n_deleted:
        category = 'success'
        # update case by removing mme submission
        # and create events for patients deletion from MME
        user_obj = store.user(current_user.email)
        store.case_mme_delete(case_obj=case_obj, user_obj=user_obj)
    flash('Number of patients deleted from Matchmaker: {} out of {}'.format(n_deleted, len(delete_result)), category)
    return redirect(request.referrer)
Exemplo n.º 2
0
def assign(institute_id, case_name, user_id=None):
    """Assign and unassign a user from a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    link = url_for('.case', institute_id=institute_id, case_name=case_name)
    if user_id:
        user_obj = store.user(user_id)
    else:
        user_obj = store.user(current_user.email)
    if request.form.get('action') == 'DELETE':
        store.unassign(institute_obj, case_obj, user_obj, link)
    else:
        store.assign(institute_obj, case_obj, user_obj, link)
    return redirect(request.referrer)
Exemplo n.º 3
0
def assign(institute_id, case_name, user_id=None):
    """Assign and unassign a user from a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    link = url_for('.case', institute_id=institute_id, case_name=case_name)
    if user_id:
        user_obj = store.user(user_id)
    else:
        user_obj = store.user(current_user.email)
    if request.form.get('action') == 'DELETE':
        store.unassign(institute_obj, case_obj, user_obj, link)
    else:
        store.assign(institute_obj, case_obj, user_obj, link)
    return redirect(request.referrer)
Exemplo n.º 4
0
def assign(institute_id, case_name, user_id=None, inactivate=False):
    """Assign and unassign a user from a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    link = url_for(".case", institute_id=institute_id, case_name=case_name)
    if user_id:
        user_obj = store.user(user_id)
    else:
        user_obj = store.user(current_user.email)
    if request.form.get("action") == "DELETE":
        store.unassign(institute_obj, case_obj, user_obj, link, inactivate)
    else:
        store.assign(institute_obj, case_obj, user_obj, link)
    return redirect(request.referrer)
Exemplo n.º 5
0
def institutes():
    """Display a list of all user institutes."""
    institute_objs = user_institutes(store, current_user)
    institutes = []
    for ins_obj in institute_objs:
        sanger_recipients = []
        for user_mail in ins_obj.get("sanger_recipients", []):
            user_obj = store.user(user_mail)
            if not user_obj:
                continue
            sanger_recipients.append(user_obj["name"])
        institutes.append({
            "display_name":
            ins_obj["display_name"],
            "internal_id":
            ins_obj["_id"],
            "coverage_cutoff":
            ins_obj.get("coverage_cutoff", "None"),
            "sanger_recipients":
            sanger_recipients,
            "frequency_cutoff":
            ins_obj.get("frequency_cutoff", "None"),
            "phenotype_groups":
            ins_obj.get("phenotype_groups", PHENOTYPE_GROUPS),
            "case_count":
            sum(1 for i in store.cases(collaborator=ins_obj["_id"])),
        })

    data = dict(institutes=institutes)
    return render_template("overview/institutes.html", **data)
Exemplo n.º 6
0
def download_verified():
    """Download all verified variants for user's cases"""

    user_obj = store.user(current_user.email)

    user_institutes = (
        [inst["_id"] for inst in store.institutes()]
        if current_user.is_admin
        else user_obj.get("institutes")
    )
    temp_excel_dir = os.path.join(variants_bp.static_folder, "verified_folder")
    os.makedirs(temp_excel_dir, exist_ok=True)

    if controllers.verified_excel_file(store, user_institutes, temp_excel_dir):
        data = zip_dir_to_obj(temp_excel_dir)

        # remove temp folder with excel files in it
        shutil.rmtree(temp_excel_dir)

        today = datetime.datetime.now().strftime("%Y-%m-%d")
        return send_file(
            data,
            mimetype="application/zip",
            as_attachment=True,
            download_name="_".join(["scout", "verified_variants", today]) + ".zip",
            cache_timeout=0,
        )

    # remove temp folder with excel files in it
    shutil.rmtree(temp_excel_dir)

    flash("No verified variants could be exported for user's institutes", "warning")
    return redirect(request.referrer)
Exemplo n.º 7
0
def institutes():
    """Display a list of all user institutes."""
    institute_objs = user_institutes(store, current_user)
    institutes = []
    for ins_obj in institute_objs:
        sanger_recipients = []
        for user_mail in ins_obj.get('sanger_recipients',[]):
            user_obj = store.user(user_mail)
            if not user_obj:
                continue
            sanger_recipients.append(user_obj['name'])
        institutes.append(
            {
                'display_name': ins_obj['display_name'],
                'internal_id': ins_obj['_id'],
                'coverage_cutoff': ins_obj.get('coverage_cutoff', 'None'),
                'sanger_recipients': sanger_recipients,
                'frequency_cutoff': ins_obj.get('frequency_cutoff', 'None'),
                'phenotype_groups': ins_obj.get('phenotype_groups', PHENOTYPE_GROUPS)
            }
        )

    data = dict(institutes=institutes)
    return render_template(
        'overview/institutes.html', **data)
Exemplo n.º 8
0
def verify(institute_id, case_name, variant_id, variant_category, order):
    """Start procedure to validate variant using other techniques."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)

    comment = request.form.get('verification_comment')

    try:
        controllers.variant_verification(
            store=store,
            mail=mail,
            institute_obj=institute_obj,
            case_obj=case_obj,
            user_obj=user_obj,
            comment=comment,
            variant_obj=variant_obj,
            sender=current_app.config['MAIL_USERNAME'],
            variant_url=request.referrer,
            order=order,
            url_builder=url_for)
    except controllers.MissingVerificationRecipientError:
        flash('No verification recipients added to institute.', 'danger')

    return redirect(request.referrer)
Exemplo n.º 9
0
def test_update_tracks_settings(app, user_obj, mocker, mock_redirect):
    """Test the endpoint that updates the IGV track preferences for a user"""

    mocker.patch("scout.server.blueprints.variant.views.redirect", return_value=mock_redirect)

    preferred_tracks = ["Genes", "ClinVar"]
    # GIVEN an initialized app
    with app.test_client() as client:
        # GIVEN that the user could be logged in
        resp = client.get(url_for("auto_login"))

        # GIVEN that the user wants to see only Genes and ClinVar SNVs tracks
        form_data = {
            "user_tracks": preferred_tracks,
        }

        # WHEN sending a POST request to the update
        resp = client.post(
            url_for(
                "variant.update_tracks_settings",
            ),
            data=form_data,
        )

        # THEN the user object in the database should be updated with the right track info
        user_obj = store.user(email=user_obj["email"])
        for track in preferred_tracks:
            assert track in preferred_tracks
Exemplo n.º 10
0
def institutes():
    """Display a list of all user institutes."""
    institute_objs = user_institutes(store, current_user)
    institutes = []
    for ins_obj in institute_objs:
        sanger_recipients = []
        for user_mail in ins_obj.get('sanger_recipients', []):
            user_obj = store.user(user_mail)
            if not user_obj:
                continue
            sanger_recipients.append(user_obj['name'])
        institutes.append({
            'display_name':
            ins_obj['display_name'],
            'internal_id':
            ins_obj['_id'],
            'coverage_cutoff':
            ins_obj.get('coverage_cutoff', 'None'),
            'sanger_recipients':
            sanger_recipients,
            'frequency_cutoff':
            ins_obj.get('frequency_cutoff', 'None'),
            'phenotype_groups':
            ins_obj.get('phenotype_groups', PHENOTYPE_GROUPS)
        })

    data = dict(institutes=institutes)
    return render_template('overview/institutes.html', **data)
Exemplo n.º 11
0
def matchmaker_matches(institute_id, case_name):
    """Show all MatchMaker matches for a given case"""
    # check that only authorized users can access MME patients matches
    user_obj = store.user(current_user.email)
    if 'mme_submitter' not in user_obj['roles']:
        flash('unauthorized request', 'warning')
        return redirect(request.referrer)
    # Required params for getting matches from MME server:
    mme_base_url = current_app.config.get('MME_URL')
    mme_token = current_app.config.get('MME_TOKEN')
    if not mme_base_url or not mme_token:
        flash(
            'An error occurred reading matchmaker connection parameters. Please check config file!',
            'danger')
        return redirect(request.referrer)
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    data = controllers.mme_matches(case_obj, institute_obj, mme_base_url,
                                   mme_token)
    if data and data.get('server_errors'):
        flash(
            'MatchMaker server returned error:{}'.format(
                data['server_errors']), 'danger')
        return redirect(request.referrer)
    elif not data:
        data = {'institute': institute_obj, 'case': case_obj}
    return data
Exemplo n.º 12
0
def phenotypes(institute_id, case_name, phenotype_id=None):
    """Handle phenotypes."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    case_url = url_for('.case', institute_id=institute_id, case_name=case_name)
    is_group = request.args.get('is_group') == 'yes'
    user_obj = store.user(current_user.email)

    if phenotype_id:
        # DELETE a phenotype item/group from case
        store.remove_phenotype(institute_obj, case_obj, user_obj, case_url,
                               phenotype_id, is_group=is_group)
    else:
        try:
            # add a new phenotype item/group to the case
            phenotype_term = request.form['hpo_term']
            if phenotype_term.startswith('HP:') or len(phenotype_term) == 7:
                hpo_term = phenotype_term.split(' | ', 1)[0]
                store.add_phenotype(institute_obj, case_obj, user_obj, case_url,
                                    hpo_term=hpo_term, is_group=is_group)
            else:
                # assume omim id
                store.add_phenotype(institute_obj, case_obj, user_obj, case_url,
                                    omim_term=phenotype_term)
        except ValueError:
            return abort(400, ("unable to add phenotype: {}".format(phenotype_term)))
    return redirect(case_url)
Exemplo n.º 13
0
def case_synopsis(institute_id, case_name):
    """Update (PUT) synopsis of a specific case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    new_synopsis = request.form.get('synopsis')
    controllers.update_synopsis(store, institute_obj, case_obj, user_obj, new_synopsis)
    return redirect(request.referrer)
Exemplo n.º 14
0
def institutes():
    """Returns institutes info available for a user
    Returns:
        data(list): a list of institute dictionaries
    """

    institute_objs = user_institutes(store, current_user)
    institutes = []
    for ins_obj in institute_objs:
        sanger_recipients = []
        for user_mail in ins_obj.get("sanger_recipients", []):
            user_obj = store.user(user_mail)
            if not user_obj:
                continue
            sanger_recipients.append(user_obj["name"])
        institutes.append({
            "display_name":
            ins_obj["display_name"],
            "internal_id":
            ins_obj["_id"],
            "coverage_cutoff":
            ins_obj.get("coverage_cutoff", "None"),
            "sanger_recipients":
            sanger_recipients,
            "frequency_cutoff":
            ins_obj.get("frequency_cutoff", "None"),
            "phenotype_groups":
            ins_obj.get("phenotype_groups", PHENOTYPE_GROUPS),
            "case_count":
            sum(1 for i in store.cases(collaborator=ins_obj["_id"])),
        })
    return institutes
Exemplo n.º 15
0
def events(institute_id, case_name, event_id=None):
    """Handle events."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    link = request.form.get("link")
    content = request.form.get("content")
    variant_id = request.args.get("variant_id")
    user_obj = store.user(current_user.email)

    if event_id:
        # delete the event
        store.delete_event(event_id)
    else:
        if variant_id:
            # create a variant comment
            variant_obj = store.variant(variant_id)
            level = request.form.get("level", "specific")
            store.comment(
                institute_obj,
                case_obj,
                user_obj,
                link,
                variant=variant_obj,
                content=content,
                comment_level=level,
            )
        else:
            # create a case comment
            store.comment(institute_obj,
                          case_obj,
                          user_obj,
                          link,
                          content=content)

    return redirect(request.referrer)
Exemplo n.º 16
0
def reset_research(institute_id, case_name):
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    user_obj = store.user(current_user.email)
    link = url_for(".case", institute_id=institute_id, case_name=case_name)
    store.reset_research(institute_obj, case_obj, user_obj, link)
    return redirect(request.referrer)
Exemplo n.º 17
0
def matchmaker_delete(request, institute_id, case_name):
    """Delete all affected samples for a case from MatchMaker

    Args:
        request(werkzeug.local.LocalProxy)
        institute_id(str): _id of an institute
        case_name(str): display name of a case
    """
    # Check that general MME request requirements are fulfilled
    matchmaker_check_requirements(request)

    _, case_obj = institute_and_case(store, institute_id, case_name)
    # Delete each patient submitted for this case
    for patient in case_obj.get("mme_submission", {}).get("patients", []):
        # Send delete request to server and capture server's response
        patient_id = patient["id"]
        resp = matchmaker.patient_delete(patient_id)
        category = "warning"
        if resp["status_code"] == 200:
            category = "success"
            # update case by removing mme submission
            # and create events for patients deletion from MME
            user_obj = store.user(current_user.email)
            store.case_mme_delete(case_obj=case_obj, user_obj=user_obj)

            flash(
                f"Deleted patient '{patient_id}', case '{case_name}' from MatchMaker",
                "success",
            )
            continue

        flash(f"An error occurred while deleting patient from MatchMaker", "danger")
Exemplo n.º 18
0
def download_verified():
    """Download all verified variants for user's cases"""
    user_obj = store.user(current_user.email)
    user_institutes = user_obj.get('institutes')
    temp_excel_dir = os.path.join(variants_bp.static_folder, 'verified_folder')
    os.makedirs(temp_excel_dir, exist_ok=True)

    written_files = controllers.verified_excel_file(store, user_institutes,
                                                    temp_excel_dir)
    if written_files:
        today = datetime.datetime.now().strftime('%Y-%m-%d')
        # zip the files on the fly and serve the archive to the user
        data = io.BytesIO()
        with zipfile.ZipFile(data, mode='w') as z:
            for f_name in pathlib.Path(temp_excel_dir).iterdir():
                zipfile.ZipFile
                z.write(f_name, os.path.basename(f_name))
        data.seek(0)

        # remove temp folder with excel files in it
        shutil.rmtree(temp_excel_dir)

        return send_file(data,
                         mimetype='application/zip',
                         as_attachment=True,
                         attachment_filename='_'.join(
                             ['scout', 'verified_variants', today]) + '.zip')
    else:
        flash("No verified variants could be exported for user's institutes",
              'warning')
        return redirect(request.referrer)
Exemplo n.º 19
0
def matchmaker_match(institute_id, case_name, target):
    """Starts an internal match or a match against one or all MME external nodes"""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)

    # check that only authorized users can run matches
    user_obj = store.user(current_user.email)
    if 'mme_submitter' not in user_obj['roles']:
        flash('unauthorized request', 'warning')
        return redirect(request.referrer)

    # Required params for sending an add request to MME:
    mme_base_url = current_app.config.get('MME_URL')
    mme_accepts = current_app.config.get('MME_ACCEPTS')
    mme_token = current_app.config.get('MME_TOKEN')
    nodes = current_app.mme_nodes

    if not mme_base_url or not mme_token or not mme_accepts:
        flash('An error occurred reading matchmaker connection parameters. Please check config file!', 'danger')
        return redirect(request.referrer)

    match_results = controllers.mme_match(case_obj, target, mme_base_url, mme_token, nodes, mme_accepts)
    ok_responses = 0
    for match_results in match_results:
        match_results['status_code'] == 200
        ok_responses +=1
    if ok_responses:
        flash("Match request sent. Look for eventual matches in 'Matches' page.", 'info')
    else:
        flash('An error occurred while sending match request.', 'danger')

    return redirect(request.referrer)
Exemplo n.º 20
0
def download_verified():
    """Download all verified variants for user's cases"""
    user_obj = store.user(current_user.email)
    user_institutes = user_obj.get('institutes')
    temp_excel_dir = os.path.join(variants_bp.static_folder, 'verified_folder')
    os.makedirs(temp_excel_dir, exist_ok=True)

    written_files = controllers.verified_excel_file(store, user_institutes, temp_excel_dir)
    if written_files:
        today = datetime.datetime.now().strftime('%Y-%m-%d')
        # zip the files on the fly and serve the archive to the user
        data = io.BytesIO()
        with zipfile.ZipFile(data, mode='w') as z:
            for f_name in pathlib.Path(temp_excel_dir).iterdir():
                zipfile.ZipFile
                z.write(f_name, os.path.basename(f_name))
        data.seek(0)

        # remove temp folder with excel files in it
        shutil.rmtree(temp_excel_dir)

        return send_file(
            data,
            mimetype='application/zip',
            as_attachment=True,
            attachment_filename='_'.join(['scout', 'verified_variants', today])+'.zip'
        )
    else:
        flash("No verified variants could be exported for user's institutes", 'warning')
        return redirect(request.referrer)
Exemplo n.º 21
0
def case_synopsis(institute_id, case_name):
    """Update (PUT) synopsis of a specific case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    new_synopsis = request.form.get('synopsis')
    controllers.update_synopsis(store, institute_obj, case_obj, user_obj, new_synopsis)
    return redirect(request.referrer)
Exemplo n.º 22
0
def mark_causative(institute_id,
                   case_name,
                   variant_id,
                   partial_causative=False):
    """Mark a variant as confirmed causative."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    link = url_for("variant.variant",
                   institute_id=institute_id,
                   case_name=case_name,
                   variant_id=variant_id)
    if request.form["action"] == "ADD":
        if "partial_causative" in request.form:
            omim_terms = request.form.getlist("omim_select")
            hpo_terms = request.form.getlist("hpo_select")
            store.mark_partial_causative(institute_obj, case_obj, user_obj,
                                         link, variant_obj, omim_terms,
                                         hpo_terms)
        else:
            store.mark_causative(institute_obj, case_obj, user_obj, link,
                                 variant_obj)
    elif request.form["action"] == "DELETE":
        if partial_causative == "True":
            store.unmark_partial_causative(institute_obj, case_obj, user_obj,
                                           link, variant_obj)
        else:
            store.unmark_causative(institute_obj, case_obj, user_obj, link,
                                   variant_obj)

    # send the user back to the case that was marked as solved
    case_url = url_for(".case", institute_id=institute_id, case_name=case_name)
    return redirect(request.referrer)
Exemplo n.º 23
0
def matchmaker_matches(institute_id, case_name):
    """Show all MatchMaker matches for a given case"""
    # check that only authorized users can access MME patients matches
    panel = 1
    if request.method == "POST":
        panel = panel = request.form.get("pane_id")
    user_obj = store.user(current_user.email)
    if "mme_submitter" not in user_obj["roles"]:
        flash("unauthorized request", "warning")
        return redirect(request.referrer)
    # Required params for getting matches from MME server:
    mme_base_url = current_app.config.get("MME_URL")
    mme_token = current_app.config.get("MME_TOKEN")
    if not mme_base_url or not mme_token:
        flash(
            "An error occurred reading matchmaker connection parameters. Please check config file!",
            "danger",
        )
        return redirect(request.referrer)
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    data = controllers.mme_matches(case_obj, institute_obj, mme_base_url,
                                   mme_token)
    data["panel"] = panel
    if data and data.get("server_errors"):
        flash(
            "MatchMaker server returned error:{}".format(
                data["server_errors"]),
            "danger",
        )
        return redirect(request.referrer)
    elif not data:
        data = {"institute": institute_obj, "case": case_obj, "panel": panel}
    return data
Exemplo n.º 24
0
def case_diagnosis(institute_id, case_name):
    """Add or remove a diagnosis for a case."""

    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    user_obj = store.user(current_user.email)
    link = url_for(".case", institute_id=institute_id, case_name=case_name)
    level = "phenotype" if "phenotype" in request.form else "gene"
    omim_id = request.form["omim_term"].split("|")[0]

    if not "OMIM:" in omim_id:  # Could be an omim number provided by user
        omim_id = ":".join(["OMIM", omim_id])

    # Make sure omim term exists in database:
    omim_obj = store.disease_term(omim_id.strip())
    if not omim_obj:
        flash("Couldn't find any disease term with id: {}".format(omim_id),
              "warning")

    remove = True if request.args.get("remove") == "yes" else False
    store.diagnose(
        institute_obj,
        case_obj,
        user_obj,
        link,
        level=level,
        omim_id=omim_id,
        remove=remove,
    )
    return redirect(request.referrer)
Exemplo n.º 25
0
def case_diagnosis(institute_id, case_name):
    """Add or remove a diagnosis for a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    user_obj = store.user(current_user.email)
    link = url_for(".case", institute_id=institute_id, case_name=case_name)

    omim_id = request.form["omim_term"].split("|")[0]
    omim_inds = request.form.getlist(
        "omim_inds")  # Individual-level phenotypes

    if not "OMIM:" in omim_id:  # Could be an omim number provided by user
        omim_id = ":".join(["OMIM", omim_id])

    # Make sure omim term exists in database:
    omim_obj = store.disease_term(omim_id.strip())
    if omim_obj is None:
        flash("Couldn't find any disease term with id: {}".format(omim_id),
              "warning")
        return redirect(request.referrer)

    remove = True if request.args.get("remove") == "yes" else False
    store.diagnose(institute_obj, case_obj, user_obj, link, omim_obj,
                   omim_inds, remove)
    return redirect("#".join([link, "omim_assign"]))
Exemplo n.º 26
0
def research(institute_id, case_name):
    """Open the research list for a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    link = url_for('.case', institute_id=institute_id, case_name=case_name)
    store.open_research(institute_obj, case_obj, user_obj, link)
    return redirect(request.referrer)
Exemplo n.º 27
0
def matchmaker_check_requirements(request):
    """Make sure requirements are fulfilled before submitting any request to MatchMaker Exchange

    Args:
        request(werkzeug.local.LocalProxy)
    Returns:
        None, if requirements are fulfilled, otherwise redirects to previous page with error message
    """
    # Make sure all MME connection parameters are available in scout instance
    if (
        any(
            [
                hasattr(matchmaker, "host"),
                hasattr(matchmaker, "accept"),
                hasattr(matchmaker, "token"),
            ]
        )
        is None
    ):
        flash(
            "An error occurred reading matchmaker connection parameters. Please check config file!",
            "danger",
        )
        return redirect(request.referrer)

    # Check that request comes from an authorized user (mme_submitter role)
    user_obj = store.user(current_user.email)
    if "mme_submitter" not in user_obj.get("roles", []):
        flash("unauthorized request", "warning")
        return redirect(request.referrer)
Exemplo n.º 28
0
def call_rerunner(store, institute_id, case_name, metadata):
    """Call rerunner with updated pedigree metadata."""
    # define the data to be passed
    payload = {"case_id": case_name, "sample_ids": [m["sample_id"] for m in metadata]}

    cnf = rerunner.connection_settings
    url = cnf.get("entrypoint")
    if not url:
        raise ValueError("Rerunner API entrypoint not configured")
    auth = HTTPBasicAuth(current_user.email, cnf.get("api_key"))
    LOG.info(f"Sending request -- {url}; params={payload}")
    resp = requests.post(
        url,
        params=payload,
        json=metadata,
        timeout=rerunner.timeout,
        headers={"Content-Type": "application/json"},
        auth=auth,
    )

    if resp.status_code == 200:
        LOG.info(f"Reanalysis was successfully started; case: {case_name}")
        # get institute, case and user objects for adding a notification of the rerun to the database
        institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
        user_obj = store.user(current_user.email)
        link = url_for("cases.case", institute_id=institute_id, case_name=case_name)
        store.request_rerun(institute_obj, case_obj, user_obj, link)
        # notfiy the user of the rerun
        flash(f"Reanalysis was successfully started; case: {case_name}", "info")

    else:
        raise RerunnerError(f"{resp.reason}, {resp.status_code}")
Exemplo n.º 29
0
def authorized():
    oauth_response = None
    try:
        oauth_response = google.authorized_response()
    except OAuthException as error:
        current_app.logger.warn(oauth_response.message)
        flash("{} - try again!".format(oauth_response.message), 'warning')
        return redirect(url_for('public.index'))

    if oauth_response is None:
        flash("Access denied: reason={} error={}"
              .format(request.args.get['error_reason'],
                      request.args['error_description']), 'danger')
        return abort(403)

    # add token to session, do it before validation to be able to fetch
    # additional data (like email) on the authenticated user
    session['google_token'] = (oauth_response['access_token'], '')

    # get additional user info with the access token
    google_user = google.get('userinfo')
    google_data = google_user.data

    user_obj = store.user(google_data['email'])
    if user_obj is None:
        flash('your email is not whitelisted, contact admin.', 'warning')
        return redirect(url_for('public.index'))

    user_obj['name'] = google_data['name']
    user_obj['location'] = google_data['locale']
    user_obj['accessed_at'] = datetime.now()
    store.update_user(user_obj)
    return perform_login(user_obj)
Exemplo n.º 30
0
def phenotypes(institute_id, case_name, phenotype_id=None):
    """Handle phenotypes."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    case_url = url_for('.case', institute_id=institute_id, case_name=case_name)
    is_group = request.args.get('is_group') == 'yes'
    user_obj = store.user(current_user.email)

    if phenotype_id:
        # DELETE a phenotype item/group from case
        store.remove_phenotype(institute_obj, case_obj, user_obj, case_url,
                               phenotype_id, is_group=is_group)
    else:
        try:
            # add a new phenotype item/group to the case
            phenotype_term = request.form['hpo_term']
            if phenotype_term.startswith('HP:') or len(phenotype_term) == 7:
                hpo_term = phenotype_term.split(' | ', 1)[0]
                store.add_phenotype(institute_obj, case_obj, user_obj, case_url,
                                    hpo_term=hpo_term, is_group=is_group)
            else:
                # assume omim id
                store.add_phenotype(institute_obj, case_obj, user_obj, case_url,
                                    omim_term=phenotype_term)
        except ValueError:
            return abort(400, ("unable to add phenotype: {}".format(phenotype_term)))
    return redirect(case_url)
Exemplo n.º 31
0
def update_default_panels(store, current_user, institute_id, case_name, panel_ids):
    """Update default panels for a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    link = url_for("cases.case", institute_id=institute_id, case_name=case_name)
    panel_objs = [store.panel(panel_id) for panel_id in panel_ids]
    store.update_default_panels(institute_obj, case_obj, user_obj, link, panel_objs)
Exemplo n.º 32
0
def add_case_group(store, current_user, institute_id, case_name, group=None):
    """Bind a case group in a selected a case, creating it in current institute if not given.

    Args:
        current_user    (user)current user
        institute_id    (str)institute id
        case_name       (str)case display name
        group           (str)case group id - converts to ObjectId
    Returns:
        updated_case    (InsertOneResult)
    """

    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    link = url_for("cases.case", institute_id=institute_id, case_name=case_name)
    user_obj = store.user(current_user.email)

    if not group:
        group = store.init_case_group(institute_id)

    current_group_ids = set(case_obj.get("group", []))
    current_group_ids.add(ObjectId(group))

    updated_case = store.update_case_group_ids(
        institute_obj, case_obj, user_obj, link, list(current_group_ids)
    )
    return updated_case
Exemplo n.º 33
0
def research(institute_id, case_name):
    """Open the research list for a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    link = url_for('.case', institute_id=institute_id, case_name=case_name)
    store.open_research(institute_obj, case_obj, user_obj, link)
    return redirect(request.referrer)
Exemplo n.º 34
0
def variant_update(institute_id, case_name, variant_id):
    """Update user-defined information about a variant: manual rank & ACMG."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    link = request.referrer

    manual_rank = request.form.get('manual_rank')
    if manual_rank:
        new_manual_rank = int(manual_rank) if manual_rank != '-1' else None
        store.update_manual_rank(institute_obj, case_obj, user_obj, link,
                                 variant_obj, new_manual_rank)
        if new_manual_rank:
            flash("updated variant tag: {}".format(new_manual_rank), 'info')
        else:
            flash("reset variant tag: {}".format(variant_obj['manual_rank']),
                  'info')
    elif request.form.get('acmg_classification'):
        new_acmg = request.form['acmg_classification']
        acmg_classification = variant_obj.get('acmg_classification')
        if isinstance(acmg_classification,
                      int) and (new_acmg == ACMG_MAP[acmg_classification]):
            new_acmg = None
        store.update_acmg(institute_obj, case_obj, user_obj, link, variant_obj,
                          new_acmg)
        flash("updated ACMG classification: {}".format(new_acmg), 'info')
    return redirect(request.referrer)
Exemplo n.º 35
0
def phenotypes_actions(institute_id, case_name):
    """Perform actions on multiple phenotypes."""
    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    case_url = url_for(".case", institute_id=institute_id, case_name=case_name)
    action = request.form["action"]
    hpo_ids = request.form.getlist("hpo_id")
    user_obj = store.user(current_user.email)

    if action == "PHENOMIZER":
        if len(hpo_ids) == 0:
            hpo_ids = [
                term["phenotype_id"]
                for term in case_obj.get("phenotype_terms", [])
            ]

        username = current_app.config["PHENOMIZER_USERNAME"]
        password = current_app.config["PHENOMIZER_PASSWORD"]
        diseases = controllers.hpo_diseases(username, password, hpo_ids)
        if diseases:
            return render_template(
                "cases/diseases.html",
                diseases=diseases,
                institute=institute_obj,
                case=case_obj,
            )

    if action == "DELETE":
        for hpo_id in hpo_ids:
            # DELETE a phenotype from the list
            store.remove_phenotype(institute_obj, case_obj, user_obj, case_url,
                                   hpo_id)

    if action == "ADDGENE":
        hgnc_ids = parse_raw_gene_ids(request.form.getlist("genes"))
        store.update_dynamic_gene_list(case_obj,
                                       hgnc_ids=list(hgnc_ids),
                                       add_only=True)

    if action == "GENES":
        hgnc_symbols = parse_raw_gene_symbols(request.form.getlist("genes"))
        store.update_dynamic_gene_list(case_obj,
                                       hgnc_symbols=list(hgnc_symbols))

    if action == "GENERATE":
        if len(hpo_ids) == 0:
            hpo_ids = [
                term["phenotype_id"]
                for term in case_obj.get("phenotype_terms", [])
            ]
        results = store.generate_hpo_gene_list(*hpo_ids)
        # determine how many HPO terms each gene must match
        hpo_count = int(request.form.get("min_match") or 1)
        hgnc_ids = [result[0] for result in results if result[1] >= hpo_count]
        store.update_dynamic_gene_list(case_obj,
                                       hgnc_ids=hgnc_ids,
                                       phenotype_ids=hpo_ids)

    return redirect("#".join([case_url, "phenotypes_panel"]))
Exemplo n.º 36
0
def update_tracks_settings():
    """Update custom track settings for a user according to form choices"""
    user_obj = store.user(email=current_user.email)
    selected_tracks = request.form.getlist("user_tracks") or []
    # update user in database with custom tracks info
    user_obj["igv_tracks"] = selected_tracks
    store.update_user(user_obj)
    return redirect(request.referrer)
Exemplo n.º 37
0
def mark_validation(institute_id, case_name, variant_id):
    """Mark a variant as sanger validated."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    validate_type = request.form['type'] or None
    link = url_for('variants.variant', institute_id=institute_id, case_name=case_name,
                   variant_id=variant_id)
    store.validate(institute_obj, case_obj, user_obj, link, variant_obj, validate_type)
    return redirect(request.referrer or link)
Exemplo n.º 38
0
def matchmaker_delete(institute_id, case_name):
    """Remove a case from MatchMaker"""

    # check that only authorized users can delete patients from MME
    user_obj = store.user(current_user.email)
    if "mme_submitter" not in user_obj["roles"]:
        flash("unauthorized request", "warning")
        return redirect(request.referrer)

    institute_obj, case_obj = institute_and_case(store, institute_id,
                                                 case_name)
    # Required params for sending a delete request to MME:
    mme_base_url = current_app.config.get("MME_URL")
    mme_token = current_app.config.get("MME_TOKEN")
    if not mme_base_url or not mme_token:
        flash(
            "An error occurred reading matchmaker connection parameters. Please check config file!",
            "danger",
        )
        return redirect(request.referrer)

    delete_result = controllers.mme_delete(case_obj, mme_base_url, mme_token)

    n_deleted = 0
    category = "warning"

    for resp in delete_result:
        if resp["status_code"] == 200:
            n_deleted += 1
        else:
            flash(resp["message"], category)
    if n_deleted:
        category = "success"
        # update case by removing mme submission
        # and create events for patients deletion from MME
        user_obj = store.user(current_user.email)
        store.case_mme_delete(case_obj=case_obj, user_obj=user_obj)
    flash(
        "Number of patients deleted from Matchmaker: {} out of {}".format(
            n_deleted, len(delete_result)),
        category,
    )
    return redirect(request.referrer)
Exemplo n.º 39
0
def mark_validation(institute_id, case_name, variant_id):
    """Mark a variant as sanger validated."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    validate_type = request.form['type'] or None
    link = url_for('variants.variant', institute_id=institute_id, case_name=case_name,
                   variant_id=variant_id)
    store.validate(institute_obj, case_obj, user_obj, link, variant_obj, validate_type)
    return redirect(request.referrer or link)
Exemplo n.º 40
0
def case_diagnosis(institute_id, case_name):
    """Add or remove a diagnosis for a case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    link = url_for('.case', institute_id=institute_id, case_name=case_name)
    level = 'phenotype' if 'phenotype' in request.form else 'gene'
    omim_id = request.form['omim_id']
    remove = True if request.args.get('remove') == 'yes' else False
    store.diagnose(institute_obj, case_obj, user_obj, link, level=level,
                   omim_id=omim_id, remove=remove)
    return redirect(request.referrer)
Exemplo n.º 41
0
def cohorts(institute_id, case_name):
    """Add/remove institute tags."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    link = url_for('.case', institute_id=institute_id, case_name=case_name)
    cohort_tag = request.form['cohort_tag']
    if request.args.get('remove') == 'yes':
        store.remove_cohort(institute_obj, case_obj, user_obj, link, cohort_tag)
    else:
        store.add_cohort(institute_obj, case_obj, user_obj, link, cohort_tag)
    return redirect(request.referrer)
Exemplo n.º 42
0
def pin_variant(institute_id, case_name, variant_id):
    """Pin and unpin variants to/from the list of suspects."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    link = url_for('variants.variant', institute_id=institute_id, case_name=case_name,
                   variant_id=variant_id)
    if request.form['action'] == 'ADD':
        store.pin_variant(institute_obj, case_obj, user_obj, link, variant_obj)
    elif request.form['action'] == 'DELETE':
        store.unpin_variant(institute_obj, case_obj, user_obj, link, variant_obj)
    return redirect(request.referrer or link)
Exemplo n.º 43
0
def variant_update(institute_id, case_name, variant_id):
    """Update user-defined information about a variant: manual rank & ACMG."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    link = request.referrer

    manual_rank = request.form.get('manual_rank')
    if manual_rank:
        new_manual_rank = int(manual_rank) if manual_rank != '-1' else None
        store.update_manual_rank(institute_obj, case_obj, user_obj, link, variant_obj,
                                 new_manual_rank)
        if new_manual_rank:
            flash("updated variant tag: {}".format(new_manual_rank), 'info')
        else:
            flash("reset variant tag: {}".format(variant_obj.get('manual_rank', 'NA')), 'info')
    elif request.form.get('acmg_classification'):
        new_acmg = request.form['acmg_classification']
        acmg_classification = variant_obj.get('acmg_classification')
        if isinstance(acmg_classification, int) and (new_acmg == ACMG_MAP[acmg_classification]):
            new_acmg = None
        store.update_acmg(institute_obj, case_obj, user_obj, link, variant_obj, new_acmg)
        flash("updated ACMG classification: {}".format(new_acmg), 'info')

    new_dismiss = request.form.getlist('dismiss_variant')
    if request.form.getlist('dismiss_variant'):
        store.update_dismiss_variant(institute_obj, case_obj, user_obj, link, variant_obj,
                                     new_dismiss)
        if new_dismiss:
            flash("Dismissed variant: {}".format(new_dismiss), 'info')

    if variant_obj.get('dismiss_variant') and not new_dismiss:
        if 'dismiss' in request.form:
            store.update_dismiss_variant(institute_obj, case_obj, user_obj, link, variant_obj,
                                     new_dismiss)
            flash("Reset variant dismissal: {}".format(variant_obj.get('dismiss_variant')), 'info')
        else:
            log.debug("DO NOT reset variant dismissal: {}".format(variant_obj.get('dismiss_variant')), 'info')

    mosaic_tags = request.form.getlist('mosaic_tags')
    if mosaic_tags:
        store.update_mosaic_tags(institute_obj, case_obj, user_obj, link, variant_obj,
                                     mosaic_tags)
        if new_dismiss:
            flash("Added mosaic tags: {}".format(mosaic_tags), 'info')

    if variant_obj.get('mosaic_tags') and not mosaic_tags:
        if 'mosaic' in request.form:
            store.update_mosaic_tags(institute_obj, case_obj, user_obj, link, variant_obj,
                                     mosaic_tags)
            flash("Reset mosaic tags: {}".format(variant_obj.get('mosaic_tags')), 'info')

    return redirect(request.referrer)
Exemplo n.º 44
0
def authorized():
    oauth_response = None
    try:
        oauth_response = google.authorized_response()
    except OAuthException as error:
        current_app.logger.warn(oauth_response.message)
        flash("{} - try again!".format(oauth_response.message), 'warning')
        return redirect(url_for('public.index'))

    if oauth_response is None:
        flash("Access denied: reason={} error={}"
              .format(request.args.get['error_reason'],
                      request.args['error_description']), 'danger')
        return abort(403)

    # add token to session, do it before validation to be able to fetch
    # additional data (like email) on the authenticated user
    session['google_token'] = (oauth_response['access_token'], '')

    # get additional user info with the access token
    google_user = google.get('userinfo')
    google_data = google_user.data

    user_obj = store.user(google_data['email'])

    # Try again with lower-cased email address if no match
    if user_obj is None:
        user_obj = store.user(google_data['email'].lower())
        
    if user_obj is None:
        flash("email not whitelisted: {}".format(google_data['email']), 'warning')
        return redirect(url_for('public.index'))

    user_obj['name'] = google_data['name']
    user_obj['location'] = google_data['locale']
    user_obj['accessed_at'] = datetime.now()
    store.update_user(user_obj)
    return perform_login(user_obj)
Exemplo n.º 45
0
def status(institute_id, case_name):
    """Update status of a specific case."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)

    status = request.form.get('status', case_obj['status'])
    link = url_for('.case', institute_id=institute_id, case_name=case_name)

    if status == 'archive':
        store.archive_case(institute_obj, case_obj, user_obj, status, link)
    else:
        store.update_status(institute_obj, case_obj, user_obj, status, link)

    return redirect(request.referrer)
Exemplo n.º 46
0
def share(institute_id, case_name):
    """Share a case with a different institute."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    user_obj = store.user(current_user.email)
    collaborator_id = request.form['collaborator']
    revoke_access = 'revoke' in request.form
    link = url_for('.case', institute_id=institute_id, case_name=case_name)

    if revoke_access:
        store.unshare(institute_obj, case_obj, collaborator_id, user_obj, link)
    else:
        store.share(institute_obj, case_obj, collaborator_id, user_obj, link)

    return redirect(request.referrer)
Exemplo n.º 47
0
def verify(institute_id, case_name, variant_id, variant_category, order):
    """Start procedure to validate variant using other techniques."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)

    comment = request.form.get('verification_comment')
    
    try:
        controllers.variant_verification(store=store, mail=mail, institute_obj=institute_obj, case_obj=case_obj, user_obj=user_obj, comment=comment,
                           variant_obj=variant_obj, sender=current_app.config['MAIL_USERNAME'], variant_url=request.referrer, order=order, url_builder=url_for)
    except controllers.MissingVerificationRecipientError:
        flash('No verification recipients added to institute.', 'danger')

    return redirect(request.referrer)
Exemplo n.º 48
0
def mark_causative(institute_id, case_name, variant_id):
    """Mark a variant as confirmed causative."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_obj = store.variant(variant_id)
    user_obj = store.user(current_user.email)
    link = url_for('variants.variant', institute_id=institute_id, case_name=case_name,
                   variant_id=variant_id)
    if request.form['action'] == 'ADD':
        store.mark_causative(institute_obj, case_obj, user_obj, link, variant_obj)
    elif request.form['action'] == 'DELETE':
        store.unmark_causative(institute_obj, case_obj, user_obj, link, variant_obj)

    # send the user back to the case that was marked as solved
    case_url = url_for('.case', institute_id=institute_id, case_name=case_name)
    return redirect(case_url)
Exemplo n.º 49
0
def login():
    """Login a user if they have access."""
    # store potential next param URL in the session
    if 'next' in request.args:
        session['next_url'] = request.args['next']

    if current_app.config.get('GOOGLE'):
        callback_url = url_for('.authorized', _external=True)
        return google.authorize(callback=callback_url)

    user_email = request.args.get('email')
    user_obj = store.user(user_email)

    if user_obj is None:
        flash("email not whitelisted: {}".format(user_email), 'warning')
        return redirect(url_for('public.index'))

    return perform_login(user_obj)
Exemplo n.º 50
0
def phenotypes_actions(institute_id, case_name):
    """Perform actions on multiple phenotypes."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    case_url = url_for('.case', institute_id=institute_id, case_name=case_name)
    action = request.form['action']
    hpo_ids = request.form.getlist('hpo_id')
    user_obj = store.user(current_user.email)

    if action == 'DELETE':
        for hpo_id in hpo_ids:
            # DELETE a phenotype from the list
            store.remove_phenotype(institute_obj, case_obj, user_obj, case_url, hpo_id)
    elif action == 'PHENOMIZER':
        if len(hpo_ids) == 0:
            hpo_ids = [term['phenotype_id'] for term in case_obj.get('phenotype_terms', [])]

        username = current_app.config['PHENOMIZER_USERNAME']
        password = current_app.config['PHENOMIZER_PASSWORD']
        diseases = controllers.hpo_diseases(username, password, hpo_ids)
        return render_template('cases/diseases.html', diseases=diseases,
                               institute=institute_obj, case=case_obj)

    elif action == 'GENES':
        hgnc_symbols = set()
        for raw_symbols in request.form.getlist('genes'):
            # avoid empty lists
            if raw_symbols:
                hgnc_symbols.update(raw_symbol.split(' ', 1)[0] for raw_symbol in
                                    raw_symbols.split('|'))
        store.update_dynamic_gene_list(case_obj, hgnc_symbols=hgnc_symbols)

    elif action == 'GENERATE':
        if len(hpo_ids) == 0:
            hpo_ids = [term['phenotype_id'] for term in case_obj.get('phenotype_terms', [])]
        results = store.generate_hpo_gene_list(*hpo_ids)
        # determine how many HPO terms each gene must match
        hpo_count = int(request.form.get('min_match') or 1)
        hgnc_ids = [result[0] for result in results if result[1] >= hpo_count]
        store.update_dynamic_gene_list(case_obj, hgnc_ids=hgnc_ids, phenotype_ids=hpo_ids)

    return redirect(case_url)
Exemplo n.º 51
0
def events(institute_id, case_name, event_id=None):
    """Handle events."""
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    link = request.form.get('link')
    content = request.form.get('content')
    variant_id = request.args.get('variant_id')
    user_obj = store.user(current_user.email)

    if event_id:
        # delete the event
        store.delete_event(event_id)
    else:
        if variant_id:
            # create a variant comment
            variant_obj = store.variant(variant_id)
            level = request.form.get('level', 'specific')
            store.comment(institute_obj, case_obj, user_obj, link,
                          variant=variant_obj, content=content, comment_level=level)
        else:
            # create a case comment
            store.comment(institute_obj, case_obj, user_obj, link, content=content)

    return redirect(request.referrer)
Exemplo n.º 52
0
def matchmaker_matches(institute_id, case_name):
    """Show all MatchMaker matches for a given case"""
    # check that only authorized users can access MME patients matches
    user_obj = store.user(current_user.email)
    if 'mme_submitter' not in user_obj['roles']:
        flash('unauthorized request', 'warning')
        return redirect(request.referrer)
    # Required params for getting matches from MME server:
    mme_base_url = current_app.config.get('MME_URL')
    mme_token = current_app.config.get('MME_TOKEN')
    if not mme_base_url or not mme_token:
        flash('An error occurred reading matchmaker connection parameters. Please check config file!', 'danger')
        return redirect(request.referrer)
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    data = controllers.mme_matches(case_obj, institute_obj, mme_base_url, mme_token)
    if data and data.get('server_errors'):
        flash('MatchMaker server returned error:{}'.format(data['server_errors']), 'danger')
        return redirect(request.referrer)
    elif not data:
        data = {
            'institute' : institute_obj,
            'case' : case_obj
        }
    return data
Exemplo n.º 53
0
def variants(institute_id, case_name):
    """Display a list of SNV variants."""
    page = int(request.form.get('page', 1))

    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_type = request.args.get('variant_type', 'clinical')

    # Update filter settings if Clinical Filter was requested

    default_panels = []
    for panel in case_obj['panels']:
        if panel.get('is_default'):
            default_panels.append(panel['panel_name'])

    request.form.get('gene_panels')
    if bool(request.form.get('clinical_filter')):
        clinical_filter = MultiDict({
            'variant_type': 'clinical',
            'region_annotations': ['exonic','splicing'],
            'functional_annotations': SEVERE_SO_TERMS,
            'clinsig': [4,5],
            'clinsig_confident_always_returned': True,
            'gnomad_frequency': str(institute_obj['frequency_cutoff']),
            'variant_type': 'clinical',
            'gene_panels': default_panels
             })

    if(request.method == "POST"):
        if bool(request.form.get('clinical_filter')):
            form = FiltersForm(clinical_filter)
            form.csrf_token = request.args.get('csrf_token')
        else:
            form = FiltersForm(request.form)
    else:
        form = FiltersForm(request.args)

    # populate available panel choices
    available_panels = case_obj.get('panels', []) + [
        {'panel_name': 'hpo', 'display_name': 'HPO'}]

    panel_choices = [(panel['panel_name'], panel['display_name'])
                     for panel in available_panels]

    form.gene_panels.choices = panel_choices

    # upload gene panel if symbol file exists
    if (request.files):
        file = request.files[form.symbol_file.name]

    if request.files and file and file.filename != '':
        log.debug("Upload file request files: {0}".format(request.files.to_dict()))
        try:
            stream = io.StringIO(file.stream.read().decode('utf-8'), newline=None)
        except UnicodeDecodeError as error:
            flash("Only text files are supported!", 'warning')
            return redirect(request.referrer)

        hgnc_symbols_set = set(form.hgnc_symbols.data)
        log.debug("Symbols prior to upload: {0}".format(hgnc_symbols_set))
        new_hgnc_symbols = controllers.upload_panel(store, institute_id, case_name, stream)
        hgnc_symbols_set.update(new_hgnc_symbols)
        form.hgnc_symbols.data = hgnc_symbols_set
        # reset gene panels
        form.gene_panels.data = ''

    # update status of case if vistited for the first time
    if case_obj['status'] == 'inactive' and not current_user.is_admin:
        flash('You just activated this case!', 'info')
        user_obj = store.user(current_user.email)
        case_link = url_for('cases.case', institute_id=institute_obj['_id'],
                            case_name=case_obj['display_name'])
        store.update_status(institute_obj, case_obj, user_obj, 'active', case_link)

    # check if supplied gene symbols exist
    hgnc_symbols = []
    non_clinical_symbols = []
    not_found_symbols = []
    not_found_ids = []
    if (form.hgnc_symbols.data) and len(form.hgnc_symbols.data) > 0:
        is_clinical = form.data.get('variant_type', 'clinical') == 'clinical'
        clinical_symbols = store.clinical_symbols(case_obj) if is_clinical else None
        for hgnc_symbol in form.hgnc_symbols.data:
            if hgnc_symbol.isdigit():
                hgnc_gene = store.hgnc_gene(int(hgnc_symbol))
                if hgnc_gene is None:
                    not_found_ids.append(hgnc_symbol)
                else:
                    hgnc_symbols.append(hgnc_gene['hgnc_symbol'])
            elif store.hgnc_genes(hgnc_symbol).count() == 0:
                  not_found_symbols.append(hgnc_symbol)
            elif is_clinical and (hgnc_symbol not in clinical_symbols):
                 non_clinical_symbols.append(hgnc_symbol)
            else:
                hgnc_symbols.append(hgnc_symbol)

    if (not_found_ids):
        flash("HGNC id not found: {}".format(", ".join(not_found_ids)), 'warning')
    if (not_found_symbols):
        flash("HGNC symbol not found: {}".format(", ".join(not_found_symbols)), 'warning')
    if (non_clinical_symbols):
        flash("Gene not included in clinical list: {}".format(", ".join(non_clinical_symbols)), 'warning')
    form.hgnc_symbols.data = hgnc_symbols

    # handle HPO gene list separately
    if form.data['gene_panels'] == ['hpo']:
        hpo_symbols = list(set(term_obj['hgnc_symbol'] for term_obj in
                               case_obj['dynamic_gene_list']))
        form.hgnc_symbols.data = hpo_symbols

    variants_query = store.variants(case_obj['_id'], query=form.data)
    data = {}

    if request.form.get('export'):
        document_header = controllers.variants_export_header(case_obj)
        export_lines = []
        if form.data['chrom'] == 'MT':
            # Return all MT variants
            export_lines = controllers.variant_export_lines(store, case_obj, variants_query)
        else:
            # Return max 500 variants
            export_lines = controllers.variant_export_lines(store, case_obj, variants_query.limit(500))

        def generate(header, lines):
            yield header + '\n'
            for line in lines:
                yield line + '\n'

        headers = Headers()
        headers.add('Content-Disposition','attachment', filename=str(case_obj['display_name'])+'-filtered_variants.csv')

        # return a csv with the exported variants
        return Response(generate(",".join(document_header), export_lines), mimetype='text/csv',
                        headers=headers)

    data = controllers.variants(store, institute_obj, case_obj, variants_query, page)

    return dict(institute=institute_obj, case=case_obj, form=form,
                    severe_so_terms=SEVERE_SO_TERMS, page=page, **data)
Exemplo n.º 54
0
def sv_variants(institute_id, case_name):
    """Display a list of structural variants."""
    page = int(request.form.get('page', 1))

    variant_type = request.args.get('variant_type', 'clinical')

    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)

    form = SvFiltersForm(request.form)

    default_panels = []
    for panel in case_obj['panels']:
        if panel['is_default']:
            default_panels.append(panel['panel_name'])

    request.form.get('gene_panels')
    if bool(request.form.get('clinical_filter')):
        clinical_filter = MultiDict({
            'variant_type': 'clinical',
            'region_annotations': ['exonic','splicing'],
            'functional_annotations': SEVERE_SO_TERMS,
            'thousand_genomes_frequency': str(institute_obj['frequency_cutoff']),
            'variant_type': 'clinical',
            'clingen_ngi': 10,
            'swegen': 10,
            'size': 100,
            'gene_panels': default_panels
             })

    if(request.method == "POST"):
        if bool(request.form.get('clinical_filter')):
            form = SvFiltersForm(clinical_filter)
            form.csrf_token = request.args.get('csrf_token')
        else:
            form = SvFiltersForm(request.form)
    else:
        form = SvFiltersForm(request.args)

    available_panels = case_obj.get('panels', []) + [
        {'panel_name': 'hpo', 'display_name': 'HPO'}]

    panel_choices = [(panel['panel_name'], panel['display_name'])
                     for panel in available_panels]
    form.gene_panels.choices = panel_choices

    if form.data['gene_panels'] == ['hpo']:
        hpo_symbols = list(set(term_obj['hgnc_symbol'] for term_obj in
                               case_obj['dynamic_gene_list']))
        form.hgnc_symbols.data = hpo_symbols

    # update status of case if vistited for the first time
    if case_obj['status'] == 'inactive' and not current_user.is_admin:
        flash('You just activated this case!', 'info')
        user_obj = store.user(current_user.email)
        case_link = url_for('cases.case', institute_id=institute_obj['_id'],
                            case_name=case_obj['display_name'])
        store.update_status(institute_obj, case_obj, user_obj, 'active', case_link)

    variants_query = store.variants(case_obj['_id'], category='sv',
                                    query=form.data)
    data = {}
    # if variants should be exported
    if request.form.get('export'):
        document_header = controllers.variants_export_header(case_obj)
        export_lines = []
        # Return max 500 variants
        export_lines = controllers.variant_export_lines(store, case_obj, variants_query.limit(500))

        def generate(header, lines):
            yield header + '\n'
            for line in lines:
                yield line + '\n'

        headers = Headers()
        headers.add('Content-Disposition','attachment', filename=str(case_obj['display_name'])+'-filtered_sv-variants.csv')
        return Response(generate(",".join(document_header), export_lines), mimetype='text/csv', headers=headers) # return a csv with the exported variants

    else:
        data = controllers.sv_variants(store, institute_obj, case_obj,
                                       variants_query, page)

    return dict(institute=institute_obj, case=case_obj, variant_type=variant_type,
                form=form, severe_so_terms=SEVERE_SO_TERMS, page=page, **data)
Exemplo n.º 55
0
def matchmaker_add(institute_id, case_name):
    """Add or update a case in MatchMaker"""

    # check that only authorized users can add patients to MME
    user_obj = store.user(current_user.email)
    if 'mme_submitter' not in user_obj['roles']:
        flash('unauthorized request', 'warning')
        return redirect(request.referrer)

    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    causatives = False
    features = False
    if case_obj.get('suspects') and len(case_obj.get('suspects'))>3:
        flash('At the moment it is not possible to save to MatchMaker more than 3 pinned variants', 'warning')
        return redirect(request.referrer)
    elif case_obj.get('suspects'):
        causatives = True
    if case_obj.get('phenotype_terms'):
        features = True

    mme_save_options = ['sex', 'features', 'disorders']
    for index, item in enumerate(mme_save_options):
        if item in request.form:
            log.info('item {} is in request form'.format(item))
            mme_save_options[index] = True
        else:
            mme_save_options[index] = False
    genomic_features = request.form.get('genomicfeatures')
    genes_only = True # upload to matchmaker only gene names
    if genomic_features == 'variants':
        genes_only = False # upload to matchmaker both variants and gene names

    # If there are no genomic features nor HPO terms to share for this case, abort
    if (not case_obj.get('suspects') and not mme_save_options[1]) or (causatives is False and features is False):
        flash('In order to upload a case to MatchMaker you need to pin a variant or at least assign a phenotype (HPO term)', 'danger')
        return redirect(request.referrer)

    user_obj = store.user(current_user.email)

    # Required params for sending an add request to MME:
    mme_base_url = current_app.config.get('MME_URL')
    mme_accepts = current_app.config.get('MME_ACCEPTS')
    mme_token = current_app.config.get('MME_TOKEN')

    if not mme_base_url or not mme_accepts or not mme_token:
        flash('An error occurred reading matchmaker connection parameters. Please check config file!', 'danger')
        return redirect(request.referrer)

    add_result = controllers.mme_add(store=store, user_obj=user_obj, case_obj=case_obj,
        add_gender=mme_save_options[0], add_features=mme_save_options[1],
            add_disorders=mme_save_options[2], genes_only=genes_only,
            mme_base_url = mme_base_url, mme_accepts=mme_accepts, mme_token=mme_token)

    # flash MME responses (one for each patient posted)
    n_succes_response = 0
    n_inserted = 0
    n_updated = 0
    category = 'warning'

    for resp in add_result['server_responses']:
        message = resp.get('message')
        if resp.get('status_code') == 200:
            n_succes_response += 1
        else:
            flash('an error occurred while adding patient to matchmaker: {}'.format(message), 'warning')
        if message == 'Patient was successfully updated.':
            n_updated +=1
        elif message == 'Patient was successfully inserted into database.':
            n_inserted +=1

    # if at least one patient was inserted or updated into matchmaker, save submission at the case level:
    if n_inserted or n_updated:
        category = 'success'
        store.case_mme_update(case_obj=case_obj, user_obj=user_obj, mme_subm_obj=add_result)
    flash('Number of new patients in matchmaker:{0}, number of updated records:{1}, number of failed requests:{2}'.format(
            n_inserted, n_updated, len(add_result.get('server_responses')) - n_succes_response), category)

    return redirect(request.referrer)
Exemplo n.º 56
0
def load_user(user_email):
    """Returns the currently active user as an object."""
    user_obj = store.user(user_email)
    user_inst = LoginUser(user_obj) if user_obj else None
    return user_inst