def check_case(institute_id, case_name): """Mark a case that is has been checked. This means to set case['needs_check'] to False """ institute_obj, case_obj = institute_and_case(store, institute_id, case_name) store.case_collection.find_one_and_update({'_id':case_obj['_id']}, {'$set': {'needs_check': False}}) return redirect(request.referrer)
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)
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)
def mt_report(institute_id, case_name): institute_obj, case_obj = institute_and_case(store, institute_id, case_name) # create a temp folder to write excel files into temp_excel_dir = os.path.join(cases_bp.static_folder, '_'.join([case_name, 'mt_reports'])) os.makedirs(temp_excel_dir, exist_ok=True) # create mt excel files, one for each sample n_files = controllers.mt_excel_files(store, case_obj, temp_excel_dir) if n_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', case_name, 'MT_report', today])+'.zip' ) else: flash('No MT report excel file could be exported for this sample', 'warning') return redirect(request.referrer)
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)
def multiqc(store, institute_id, case_name): """Find MultiQC report for the case.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) return dict( institute=institute_obj, case=case_obj, )
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)
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)
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)
def vcf2cytosure(store, institute_id, case_name, individual_id): """vcf2cytosure CGH file for inidividual.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) for individual in case_obj['individuals']: if individual['individual_id'] == individual_id: individual_obj = individual return (individual_obj['display_name'], individual_obj['vcf2cytosure'])
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) 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(case_url)
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)
def vcf2cytosure(store, institute_id, case_name, individual_id): """vcf2cytosure CGH file for inidividual.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) for individual in case_obj["individuals"]: if individual["individual_id"] == individual_id: individual_obj = individual return (individual_obj["display_name"], individual_obj["vcf2cytosure"])
def variant_acmg(store, institute_id, case_name, variant_id): """Collect data relevant for rendering ACMG classification form.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) variant_obj = store.variant(variant_id) return dict(institute=institute_obj, case=case_obj, variant=variant_obj, CRITERIA=ACMG_CRITERIA, ACMG_OPTIONS=ACMG_OPTIONS)
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") category = "sv" # Define case and institute objects institute_obj, case_obj = institute_and_case(store, institute_id, case_name) if request.form.get("hpo_clinical_filter"): case_obj["hpo_clinical_filter"] = True if request.form.getlist("dismiss"): # dismiss a list of variants controllers.dismiss_variant_list( store, institute_obj, case_obj, "variant.sv_variant", request.form.getlist("dismiss"), request.form.getlist("dismiss_choices"), ) # update status of case if visited for the first time controllers.activate_case(store, institute_obj, case_obj, current_user) form = controllers.populate_sv_filters_form(store, institute_obj, case_obj, category, request) cytobands = store.cytoband_by_chrom(case_obj.get("genome_build")) variants_query = store.variants(case_obj["_id"], category=category, query=form.data) # Setup variant count session with variant count by category controllers.variant_count_session(store, institute_id, case_obj["_id"], variant_type, category) result_size = store.count_variants(case_obj["_id"], form.data, None, category) session["filtered_variants"] = result_size # if variants should be exported if request.form.get("export"): return controllers.download_variants(store, case_obj, variants_query) data = controllers.sv_variants( store, institute_obj, case_obj, variants_query, result_size, page ) return dict( institute=institute_obj, case=case_obj, dismiss_variant_options=DISMISS_VARIANT_OPTIONS, variant_type=variant_type, form=form, cytobands=cytobands, severe_so_terms=SEVERE_SO_TERMS, manual_rank_options=MANUAL_RANK_OPTIONS, page=page, expand_search=str(request.method == "POST"), **data, )
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)
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)
def manual_rank(institute_id, case_name, variant_id): """Update the manual variant rank for a variant.""" 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) new_manual_rank = int(request.form['manual_rank']) link = request.referrer store.update_manual_rank(institute_obj, case_obj, user_obj, link, variant_obj, new_manual_rank) return redirect(request.referrer)
def case(institute_id, case_name): """Display one case.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) if not case_obj: flash("Case {} does not exist in database!".format(case_name)) return redirect(request.referrer) data = controllers.case(store, institute_obj, case_obj) return dict(**data, )
def update_clinical_filter_hpo(store, current_user, institute_id, case_name, hpo_clinical_filter): """Update HPO clinical filter use 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) store.update_clinical_filter_hpo(institute_obj, case_obj, user_obj, link, hpo_clinical_filter)
def variant(institute_id, case_name, variant_id): """Display a specific SNV variant.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) data = controllers.variant(store, institute_obj, case_obj, variant_id) if data is None: return abort(404) if current_app.config.get('LOQUSDB_SETTINGS'): data['observations'] = controllers.observations( store, loqusdb, case_obj, data['variant']) return dict(institute=institute_obj, case=case_obj, **data)
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)
def check_case(institute_id, case_name): """Mark a case that is has been checked. This means to set case['needs_check'] to False """ institute_obj, case_obj = institute_and_case(store, institute_id, case_name) store.case_collection.find_one_and_update({"_id": case_obj["_id"]}, {"$set": { "needs_check": False }}) return redirect(request.referrer)
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)
def gene_variants(institute_id): """Display a list of SNV variants.""" page = int(request.form.get('page', 1)) institute_obj = institute_and_case(store, institute_id) # populate form, conditional on request method if(request.method == "POST"): form = GeneVariantFiltersForm(request.form) else: form = GeneVariantFiltersForm(request.args) variant_type = form.data.get('variant_type', 'clinical') # check if supplied gene symbols exist hgnc_symbols = [] non_clinical_symbols = [] not_found_symbols = [] not_found_ids = [] data = {} 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 log.debug("query {}".format(form.data)) variants_query = store.gene_variants(query=form.data, category='snv', variant_type=variant_type) data = controllers.gene_variants(store, variants_query, page) return dict(institute=institute_obj, form=form, page=page, **data)
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)
def sanger(institute_id, case_name, variant_id): """Send Sanger email for confirming a variant.""" 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) try: controllers.sanger(store, mail, institute_obj, case_obj, user_obj, variant_obj, current_app.config['MAIL_USERNAME']) except controllers.MissingSangerRecipientError: flash('No sanger recipients added to institute.', 'danger') return redirect(request.referrer)
def cases(institute_id): """Display a list of cases for an institute.""" institute_obj = institute_and_case(store, institute_id) query = request.args.get("query") limit = 100 if request.args.get("limit"): limit = int(request.args.get("limit")) skip_assigned = request.args.get("skip_assigned") is_research = request.args.get("is_research") all_cases = store.cases( collaborator=institute_id, name_query=query, skip_assigned=skip_assigned, is_research=is_research, ) sort_by = request.args.get("sort") sort_order = request.args.get("order") or "asc" if sort_by: pymongo_sort = pymongo.ASCENDING if sort_order == "desc": pymongo_sort = pymongo.DESCENDING if sort_by == "analysis_date": all_cases.sort("analysis_date", pymongo_sort) elif sort_by == "track": all_cases.sort("track", pymongo_sort) elif sort_by == "status": all_cases.sort("status", pymongo_sort) LOG.debug("Prepare all cases") prioritized_cases = store.prioritized_cases(institute_id=institute_id) data = controllers.cases(store, all_cases, prioritized_cases, limit) data["sort_order"] = sort_order data["sort_by"] = sort_by data["nr_cases"] = store.nr_cases(institute_id=institute_id) sanger_unevaluated = controllers.get_sanger_unevaluated( store, institute_id, current_user.email) if len(sanger_unevaluated) > 0: data["sanger_unevaluated"] = sanger_unevaluated return dict( institute=institute_obj, skip_assigned=skip_assigned, is_research=is_research, query=query, **data, )
def clinvar_submissions(institute_id): """Handle clinVar submission objects and files""" institute_obj = institute_and_case(store, institute_id) data = { "submissions": controllers.clinvar_submissions(store, institute_id), "institute": institute_obj, "variant_header_fields": CLINVAR_HEADER, "casedata_header_fields": CASEDATA_HEADER, } return data
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)
def rerun_monitor(institute_id, case_name): """Request a case to be monitored for future reruns.""" 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) if request.form.get("rerun_monitoring") == "monitor": store.monitor(institute_obj, case_obj, user_obj, link) else: store.unmonitor(institute_obj, case_obj, user_obj, link) return redirect(request.referrer)
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) try: controllers.variant_verification(store=store, mail=mail, institute_obj=institute_obj, case_obj=case_obj, user_obj=user_obj, 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)
def upload_panel(store, institute_id, case_name, stream): """Parse out HGNC symbols from a stream.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) raw_symbols = [line.strip().split('\t')[0] for line in stream if line and not line.startswith('#')] # check if supplied gene symbols exist hgnc_symbols = [] for raw_symbol in raw_symbols: if store.hgnc_genes(raw_symbol).count() == 0: flash("HGNC symbol not found: {}".format(raw_symbol), 'warning') else: hgnc_symbols.append(raw_symbol) return hgnc_symbols
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("#".join([request.referrer, "cohorts"]))
def cases(institute_id): """Display a list of cases for an institute.""" institute_obj = institute_and_case(store, institute_id) query = request.args.get('query') skip_assigned = request.args.get('skip_assigned') all_cases = store.cases(institute_id, name_query=query, skip_assigned=skip_assigned) data = controllers.cases(store, all_cases) return dict(institute=institute_obj, skip_assigned=skip_assigned, query=query, **data)
def delivery_report(institute_id, case_name): """Display delivery report.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) if case_obj.get("delivery_report") is None: return abort(404) date_str = request.args.get("date") if date_str is not None: delivery_report = None for analysis_data in case_obj.get("analyses", []): if str(analysis_data["date"].date()) == date_str: delivery_report = analysis_data["delivery_report"] if delivery_report is None: return abort(404) else: delivery_report = case_obj["delivery_report"] out_dir = os.path.abspath(os.path.dirname(delivery_report)) filename = os.path.basename(delivery_report) report_format = request.args.get("format", "html") if report_format == "pdf": try: # file could not be available html_file = open(delivery_report, "r") source_code = html_file.read() bytes_file = html_to_pdf_file(source_code, "portrait", 300) file_name = "_".join([ case_obj["display_name"], datetime.datetime.now().strftime("%Y-%m-%d"), "scout_delivery.pdf", ]) return send_file( bytes_file, download_name=file_name, mimetype="application/pdf", as_attachment=True, ) except Exception as ex: flash( "An error occurred while downloading delivery report {} -- {}". format(delivery_report, ex), "warning", ) LOG.error( f"An error occurred while downloading delivery report {delivery_report} -- {ex}" ) return send_from_directory(out_dir, filename)
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)
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)
def case(institute_id, case_name): """Display one case.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) if not case_obj: flash("Case {} does not exist in database!".format(case_name)) return redirect(request.referrer) data = controllers.case(store, institute_obj, case_obj) return dict(institute=institute_obj, case=case_obj, mme_nodes=current_app.mme_nodes, tissue_types=SAMPLE_SOURCE, **data)
def cancer_variants(store, request_args, institute_id, case_name): """Fetch data related to cancer variants for a case.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) form = CancerFiltersForm(request_args) variants_query = store.variants(case_obj['_id'], category='cancer', query=form.data).limit(50) data = dict( institute=institute_obj, case=case_obj, variants=(parse_variant(store, institute_obj, case_obj, variant, update=True) for variant in variants_query), form=form, variant_type=request_args.get('variant_type', 'clinical'), ) return data
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)
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)
def variant(institute_id, case_name, variant_id): """Display a specific SNV variant.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) log.debug("Variants view requesting data for variant {}".format(variant_id)) data = controllers.variant(store, institute_obj, case_obj, variant_id=variant_id) if data is None: log.warning("An error occurred: variants view requesting data for variant {}".format(variant_id)) flash('An error occurred while retrieving variant object', 'danger') return redirect(request.referrer) if current_app.config.get('LOQUSDB_SETTINGS'): data['observations'] = controllers.observations(store, loqusdb, case_obj, data['variant']) data['cancer'] = request.args.get('cancer') == 'yes' return dict(institute=institute_obj, case=case_obj, **data)
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)
def pdf_case_report(institute_id, case_name): """Download a pdf report for a case""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) data = controllers.case_report_content(store, institute_obj, case_obj) # add coverage report on the bottom of this report if current_app.config.get('SQLALCHEMY_DATABASE_URI'): data['coverage_report'] = controllers.coverage_report_contents(store, institute_obj, case_obj, request.url_root) # workaround to be able to print the case pedigree to pdf if case_obj.get('madeline_info') is not None: with open(os.path.join(cases_bp.static_folder, 'madeline.svg'), 'w') as temp_madeline: temp_madeline.write(case_obj['madeline_info']) html_report = render_template('cases/case_report.html', institute=institute_obj, case=case_obj, format='pdf', **data) return render_pdf(HTML(string=html_report), download_filename=case_obj['display_name']+'_'+datetime.datetime.now().strftime("%Y-%m-%d")+'_scout.pdf')
def causatives(institute_id): institute_obj = institute_and_case(store, institute_id) variants = store.check_causatives(institute_obj=institute_obj) all_variants = {} all_cases = {} for variant_obj in variants: if variant_obj['case_id'] not in all_cases: case_obj = store.case(variant_obj['case_id']) all_cases[variant_obj['case_id']] = case_obj else: case_obj = all_cases[variant_obj['case_id']] if variant_obj['variant_id'] not in all_variants: all_variants[variant_obj['variant_id']] = [] all_variants[variant_obj['variant_id']].append((case_obj, variant_obj)) return dict(institute=institute_obj, variant_groups=all_variants)
def str_variants(institute_id, case_name): """Display a list of STR variants.""" page = int(request.args.get('page', 1)) variant_type = request.args.get('variant_type', 'clinical') form = StrFiltersForm(request.args) institute_obj, case_obj = institute_and_case(store, institute_id, case_name) query = form.data query['variant_type'] = variant_type variants_query = store.variants(case_obj['_id'], category='str', query=query) data = controllers.str_variants(store, institute_obj, case_obj, variants_query, page) return dict(institute=institute_obj, case=case_obj, variant_type = variant_type, form=form, page=page, **data)
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)
def delivery_report(institute_id, case_name): """Display delivery report.""" institute_obj, case_obj = institute_and_case(store, institute_id, case_name) if case_obj.get('delivery_report') is None: return abort(404) date_str = request.args.get('date') if date_str: delivery_report = None analysis_date = parse_date(date_str) for analysis_data in case_obj['analyses']: if analysis_data['date'] == analysis_date: delivery_report = analysis_data['delivery_report'] if delivery_report is None: return abort(404) else: delivery_report = case_obj['delivery_report'] out_dir = os.path.dirname(delivery_report) filename = os.path.basename(delivery_report) return send_from_directory(out_dir, filename)
def cases(institute_id): """Display a list of cases for an institute.""" institute_obj = institute_and_case(store, institute_id) query = request.args.get('query') limit = 100 if request.args.get('limit'): limit = int(request.args.get('limit')) skip_assigned = request.args.get('skip_assigned') is_research = request.args.get('is_research') all_cases = store.cases(collaborator=institute_id, name_query=query, skip_assigned=skip_assigned, is_research=is_research) data = controllers.cases(store, all_cases, limit) sanger_unevaluated = controllers.get_sanger_unevaluated(store, institute_id, current_user.email) if len(sanger_unevaluated)> 0: data['sanger_unevaluated'] = sanger_unevaluated return dict(institute=institute_obj, skip_assigned=skip_assigned, is_research=is_research, query=query, **data)
def rerun(store, mail, current_user, institute_id, case_name, sender, recipient): """Request a rerun by email.""" 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) # this should send a JSON document to the SuSy API in the future html = """ <p>{institute}: {case} ({case_id})</p> <p>Re-run requested by: {name}</p> """.format(institute=institute_obj['display_name'], case=case_obj['display_name'], case_id=case_obj['_id'], name=user_obj['name'].encode()) # compose and send the email message msg = Message(subject=("SCOUT: request RERUN for {}" .format(case_obj['display_name'])), html=html, sender=sender, recipients=[recipient], # cc the sender of the email for confirmation cc=[user_obj['email']]) mail.send(msg)
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)