def _update_individual(consanguinity, gender: Sex, genes, hpos: List[tuple], individual: Individual): """ Updates tables: phenopolis.individual: col(gender) phenopolis.individual_feature: col(feature_id) # hpo_ids phenopolis.individual_gene: col(gene_id) # maps hgnc_symbol -> gene.identifier given hgnc_symbol MUST exactly match hgnc_symbols in ensembl.gene table otherwise returns [] """ individual.sex = gender individual.consanguinity = consanguinity hpo_ids = [h[0] for h in hpos] with get_db() as conn: with conn.cursor() as cur: cur.execute( """ delete from phenopolis.individual_feature where individual_id = %(id)s and "type" = any('{observed,simplified}'); insert into phenopolis.individual_feature (individual_id, feature_id, type) select %(id)s as individual_id, unnest(%(hpo_ids)s::int[]) as feature_id, 'observed' as type; insert into phenopolis.individual_feature (individual_id, feature_id, type) select %(id)s as individual_id, unnest(%(hpo_ids)s::int[]) as feature_id, 'simplified' as type; delete from phenopolis.individual_gene where individual_id = %(id)s; insert into phenopolis.individual_gene (individual_id, gene_id) select %(id)s as individual_id, identifier from ensembl.gene where hgnc_symbol = any(%(genes)s::text[]) and assembly = %(hga)s; """, { "id": individual.id, "hpo_ids": hpo_ids, "genes": genes, "hga": HG_ASSEMBLY }, )
def test_delete_individual_for_user(_nondemo_client): # creates an individual individual = Individual() test_external_id = "for_test_Sample" individual.external_id = test_external_id individual.sex = "M" response = _nondemo_client.post("/individual", json=[individual.as_dict()], content_type="application/json") assert response.status_code == 200 # confirms existence of new individual with session_scope() as db_session: observed_individual = db_session.query(Individual).filter(Individual.external_id == test_external_id).first() assert observed_individual is not None, "Empty newly created individual" # deletes individual response = _nondemo_client.delete( f"/individual/{observed_individual.phenopolis_id}", content_type="application/json" ) assert response.status_code == 200 # confirms it does not exist observed_individual = db_session.query(Individual).filter(Individual.external_id == test_external_id).first() assert observed_individual is None, "Deletion was not successful" # try to delete non-existent individual response = _nondemo_client.delete("/individual/PH00000000", content_type="application/json") assert response.status_code == 404 # try to delete a non-authorised patient for a given user response = _nondemo_client.delete("/individual/PH00008258", content_type="application/json") assert response.status_code == 404, "PH00008258 exists but access not authorised"
def create_individual(): if is_demo_user(): return jsonify(error="Demo user not authorised"), 405 # checks individuals validity with session_scope() as db_session: try: dlist = _get_json_payload() new_individuals = [] for d in dlist: genes = [] if d.get("observed_features"): feats = d.pop("observed_features").split(",") else: feats = [] if d.get("genes") or d.get("genes") == "": genes = d.pop("genes").split(",") i = Individual(**d) _check_individual_valid(db_session, i) new_individuals.append((i, genes, feats)) except PhenopolisException as e: application.logger.error(str(e)) return jsonify(success=False, error=str(e)), e.http_status request_ok = True http_status = 200 message = "Individuals were created" ids_new_individuals = [] try: # generate a new unique id for the individual for trio in new_individuals: i, g, f = trio # insert individual db_session.add(i) # to refresh i and with new id and phenopolis_id, both lines below needed (black magic) db_session.query(Individual).count() db_session.refresh(i) # add entry to user_individual # TODO: enable access to more users than the creator db_session.add( UserIndividual(user=session[USER], internal_id=i.phenopolis_id)) if session[USER] != ADMIN_USER: db_session.add( UserIndividual(user=ADMIN_USER, internal_id=i.phenopolis_id)) db_session.commit() _insert_genes(i, g) _insert_feats(i, f) ids_new_individuals.append(i.phenopolis_id) except PhenopolisException as e: application.logger.exception(e) request_ok = False message = str(e) http_status = e.http_status return jsonify(success=request_ok, message=message, id=",".join(ids_new_individuals)), http_status
def test_create_individual_with_admin_user(_admin_client, sample, sex): individual = Individual() test_external_id = sample individual.external_id = test_external_id response = _admin_client.post("/individual", json=[individual.as_dict()], content_type="application/json") assert response.status_code == 400 assert response.json == {"error": "Null individual", "success": False}, "Sex cannot be null" individual.sex = sex individual.consanguinity = "unknown" individual.genes = "DRAM2" individual.observed_features = "HP:0000001" response = _admin_client.post("/individual", json=[Individual().as_dict()], content_type="application/json") assert response.status_code == 400 assert response.json == {"error": "Null individual", "success": False}, "Empty individual" response = _admin_client.post("/individual", json={}, content_type="application/json") assert response.status_code == 400 assert response.json == {"error": "Empty payload or wrong formatting", "success": False} response = _admin_client.post("/individual", json="not_dict_nor_list", content_type="application/json") assert response.status_code == 400 assert response.json == {"error": "Payload of unexpected type: <class 'str'>", "success": False} response = _admin_client.post("/individual", json=[individual.as_dict()], content_type="application/json") assert response.status_code == 200 with session_scope() as db_session: observed_individual = db_session.query(Individual).filter(Individual.external_id == test_external_id).first() phenopolis_id = observed_individual.phenopolis_id assert observed_individual is not None, "Empty newly created individual" assert observed_individual.external_id == test_external_id assert observed_individual.sex.name == individual.sex assert observed_individual.consanguinity == individual.consanguinity response = _admin_client.post( f"/update_patient_data/{phenopolis_id}", data="genes[]=TTLL5", content_type="application/x-www-form-urlencoded", ) assert response.status_code == 200, "Test empty features" # cleans the database _clean_test_individuals(_admin_client, db_session, test_external_id)
def _check_individual_valid(db_session: Session, new_individual: Individual): if not new_individual.as_dict() or not new_individual.sex: raise PhenopolisException("Null individual", 400) exist_internal_id = (db_session.query(Individual.phenopolis_id).filter( or_( Individual.phenopolis_id == new_individual.phenopolis_id, Individual.external_id == new_individual.external_id, )).all()) if len(exist_internal_id) > 0: raise PhenopolisException("Individual already exists.", 400)
def test_create_individual_existing_individual_fails(_admin_client): individual = Individual() test_external_id = "for_test_Sample" individual.external_id = test_external_id individual.sex = "M" individual.genes = "DRAM2,TTLL5" individual.observed_features = "HP:0000001,HP:0000618" response = _admin_client.post("/individual", json=[individual.as_dict()], content_type="application/json") assert response.status_code == 200 with session_scope() as db_session: observed_individual = db_session.query(Individual).filter(Individual.external_id == test_external_id).first() assert observed_individual is not None, "Empty newly created individual" # try to create the same individual again response = _admin_client.post("/individual", json=[individual.as_dict()], content_type="application/json") assert response.status_code == 400 # cleans the database _clean_test_individuals(_admin_client, db_session, test_external_id)
def _map_individual2output(config, individual: Individual): config[0]["metadata"]["data"][0].update(individual.as_dict()) if session[USER] == DEMO_USER: config[0]["metadata"]["data"][0]["external_id"] = "_demo_" config[0]["metadata"]["data"][0]["internal_id"] = [{ "display": individual.phenopolis_id }] config[0]["metadata"]["data"][0]["simplified_observed_features"] = [{ "display": x[1], "end_href": x[0] } for x in _get_feature_for_individual(individual)] genes = _get_genes_for_individual(individual) config[0]["metadata"]["data"][0]["genes"] = [{ "display": i[0] } for i in genes] return config
def test_create_multiple_individuals(_admin_client): individual = Individual() test_external_id = "for_test_Sample" individual.external_id = test_external_id individual.sex = "M" individual.genes = "DRAM2" individual.observed_features = "HP:0000001" individual2 = Individual() test_external_id2 = "for_test_Sample2" individual2.external_id = test_external_id2 individual2.sex = "F" response = _admin_client.post( "/individual", json=[individual.as_dict(), individual2.as_dict()], content_type="application/json" ) assert response.status_code == 200 with session_scope() as db_session: observed_individual = db_session.query(Individual).filter(Individual.external_id == test_external_id).first() assert observed_individual is not None, "Empty newly created individual" assert observed_individual.sex.name == individual.sex observed_individual2 = db_session.query(Individual).filter(Individual.external_id == test_external_id2).first() assert observed_individual2 is not None, "Empty newly created individual" assert observed_individual2.sex.name == individual2.sex # cleans the database _clean_test_individuals(_admin_client, db_session, test_external_id) _clean_test_individuals(_admin_client, db_session, test_external_id2)
def test_create_individual_with_demo_user_fails(_demo_client): individual = Individual() individual.phenopolis_id = "PH00000000" response = _demo_client.post("/individual", json=individual.as_dict(), content_type="text/json") assert response.status_code == 405