예제 #1
0
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
                },
            )
예제 #2
0
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"
예제 #3
0
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
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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)
예제 #7
0
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
예제 #8
0
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)
예제 #9
0
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