def _update_subpanel(subpanel_obj, supb_changes): """Update the checkboxes of a subpanel according to checkboxes checked in the model preview. Args: subpanel_obj(dict): a subpanel object supb_changes(dict): terms to keep under a parent term. example: {"HP:0001250": [(HP:0020207, HP:0020215, HP:0001327]} Returns: subpanel_obj(dict): an updated subpanel object """ checkboxes = subpanel_obj.get("checkboxes", {}) new_checkboxes = {} for parent, children_list in supb_changes.items(): # create mini tree obj from terms in changes dict. Add all nodes at the top level initially root = Node(id="root", name="root", parent=None) all_terms = {} # loop over the terms to keep into the checboxes dict for child in children_list: if child.startswith("OMIM"): new_checkboxes[child] = checkboxes[child] continue custom_name = None term_title = None if child in checkboxes: custom_name = checkboxes[child].get("custom_name") term_title = checkboxes[child].get("term_title") term_obj = store.hpo_term( child) # else it's an HPO term, and might have nested term: node = None try: node = Node(child, parent=root, description=term_obj["description"]) except Exception as ex: flash(f"Term {child} could not be find in database") continue all_terms[child] = term_obj if custom_name: node.custom_name = custom_name if term_title: node.term_title = term_title # Rearrange tree nodes according the HPO ontology root = store.organize_tree(all_terms, root) LOG.info(f"Updated HPO tree:{root}:\n{RenderTree(root)}") exporter = DictExporter() for child_node in root.children: # export node to dict node_dict = exporter.export(child_node) new_checkboxes[child_node.name] = node_dict subpanel_obj["checkboxes"] = new_checkboxes subpanel_obj["updated"] = datetime.datetime.now() return subpanel_obj
def _subpanel_hpo_checkgroup_add(model_dict, user_form): """Add an HPO term (and eventually his children) to a phenotype subpanel Args: model_dict(dict): a dictionary coresponding to a phenotype model user_form(request.form): a POST request form object Returns: model_dict(dict): an updated phenotype model dictionary to be saved to database """ hpo_id = user_form.get("hpo_term").split(" ")[0] hpo_obj = store.hpo_term(hpo_id) if hpo_obj is None: # user didn't provide a valid HPO term flash("Please specify a valid HPO term", "warning") return subpanel_id = user_form.get("hpo_subpanel_id") tree_dict = {} checkboxes = model_dict["subpanels"][subpanel_id].get("checkboxes", {}) if hpo_id in checkboxes: # Do not include duplicated HPO terms in checkbox items flash(f"Subpanel contains already HPO term '{hpo_id}'", "warning") return if user_form.get( "includeChildren"): # include HPO terms children in the checkboxes tree_dict = store.build_phenotype_tree(hpo_id) if tree_dict is None: flash(f"An error occurred while creating HPO tree from '{hpo_id}'", "danger") return else: # include just HPO term as a standalone checkbox: tree_dict = dict(name=hpo_obj["_id"], description=hpo_obj["description"]) tree_dict["checkbox_type"] = "hpo" if user_form.get("hpoTermTitle"): tree_dict["term_title"] = user_form.get("hpoTermTitle") if user_form.get("hpo_custom_name"): tree_dict["custom_name"] = user_form.get("hpo_custom_name") checkboxes[hpo_id] = tree_dict model_dict["subpanels"][subpanel_id]["checkboxes"] = checkboxes model_dict["subpanels"][subpanel_id]["updated"] = datetime.datetime.now() return model_dict
def test_institute_settings(app, user_obj, institute_obj): """Test function that creates institute update form and updates an institute""" # GIVEN a gene panel test_panel = store.panel_collection.find_one() assert test_panel # AND 2 mock HPO terms in database mock_disease_terms = [ { "_id": "HP:0001298", "description": "Encephalopathy", "hpo_id": "HP:0001298" }, { "_id": "HP:0001250", "description": "Seizures", "hpo_id": "HP:0001250" }, ] for term in mock_disease_terms: store.load_hpo_term(term) assert store.hpo_term(term["_id"]) # GIVEN an initialized app # GIVEN a valid user and institute with app.test_client() as client: client.get(url_for("auto_login")) # WHEN accessing the cases page (GET method) resp = client.get( url_for("overview.institute_settings", institute_id=institute_obj["internal_id"])) # THEN it should return a page assert resp.status_code == 200 # WHEN updating an institute using the following form form_data = { "display_name": "updated name", "sanger_emails": ["*****@*****.**"], "coverage_cutoff": "15", "frequency_cutoff": "0.001", "cohorts": ["test cohort 1", "test cohort 2"], "institutes": ["cust111", "cust222"], "pheno_groups": [ "HP:0001298 , Encephalopathy ( ENC )", "HP:0001250 , Seizures ( EP )", ], "gene_panels": [test_panel["panel_name"]], } # via POST request resp = client.post( url_for("overview.institute_settings", institute_id=institute_obj["internal_id"]), data=form_data, ) assert resp.status_code == 200 # THEN the institute object should be updated with the provided form data updated_institute = store.institute_collection.find_one() assert updated_institute["display_name"] == form_data["display_name"] assert updated_institute["sanger_recipients"] == form_data[ "sanger_emails"] assert updated_institute["coverage_cutoff"] == int( form_data["coverage_cutoff"]) assert updated_institute["frequency_cutoff"] == float( form_data["frequency_cutoff"]) assert updated_institute["cohorts"] == form_data["cohorts"] assert updated_institute["collaborators"] == form_data["institutes"] assert len(updated_institute["phenotype_groups"] ) == 2 # one for each HPO term assert updated_institute["gene_panels"] == { test_panel["panel_name"]: test_panel["display_name"] }
def phenotypes_genes(store, case_obj, is_clinical=True): """Generate a dictionary consisting of phenotype terms with associated genes from the case HPO panel Args: store(adapter.MongoAdapter) case_obj(dict): models.Case is_clinical(bool): if True, only list genes from HPO that are among the case clinical_symbols Returns: hpo_genes(dict): a dictionary with HPO term IDs as keys and HPO terms and genes as values If the dynamic phenotype panel is empty, or has been intersected to some level, use dynamic gene list directly instead. """ build = case_obj["genome_build"] # Make sure build is either "37" or "38" if "38" in str(build): build = "38" else: build = "37" dynamic_gene_list = [gene["hgnc_id"] for gene in case_obj.get("dynamic_gene_list", [])] hpo_genes = {} clinical_symbols = store.clinical_symbols(case_obj) if is_clinical else None unique_genes = hpo_genes_from_dynamic_gene_list(case_obj, is_clinical, clinical_symbols) by_phenotype = True # display genes by phenotype hpo_gene_list = case_obj.get("dynamic_panel_phenotypes", []) if not hpo_gene_list and dynamic_gene_list: by_phenotype = False all_hpo_gene_list_genes = set() # Loop over the dynamic phenotypes of a case for hpo_id in hpo_gene_list: hpo_term = store.hpo_term(hpo_id) # Check that HPO term exists in database if hpo_term is None: LOG.warning(f"Could not find HPO term with ID '{hpo_id}' in database") continue # Create a list with all gene symbols (or HGNC ID if symbol is missing) associated with the phenotype gene_list = [] for gene_id in hpo_term.get("genes", []): gene_caption = store.hgnc_gene_caption(gene_id, build) if gene_caption is None: continue if gene_id not in dynamic_gene_list: # gene was filtered out because min matching phenotypes > 1 (or the panel was generated with older genotype-phenotype mapping) by_phenotype = False # do not display genes by phenotype continue add_symbol = gene_caption.get("hgnc_symbol", f"hgnc:{gene_id}") if is_clinical and (add_symbol not in clinical_symbols): continue gene_list.append(add_symbol) all_hpo_gene_list_genes.add(add_symbol) hpo_genes[hpo_id] = { "description": hpo_term.get("description"), "genes": ", ".join(sorted(gene_list)), } if by_phenotype is True: # if some gene was manually added (or is left on dynamic panel for other reasons) non_hpo_genes = unique_genes - all_hpo_gene_list_genes if len(non_hpo_genes) > 0: hpo_genes["Analysed genes"] = { "description": "Non HPO panel genes", "genes": ", ".join(sorted(non_hpo_genes)), } if by_phenotype is False: hpo_genes = {} hpo_genes["Analysed genes"] = { "description": "HPO panel", "genes": ", ".join(sorted(unique_genes)), } return hpo_genes