예제 #1
0
def filter_records(records, codes, resource_name):
    records_filtered = []
    for record in records:
        logger.info(f"filtering record: {record}")
        for c in codes:
            system = c["system"]
            code = c["code"]
            is_regex = c["is_regex"]

            if resource_name == "MedicationRequest":
                code2 = record.get("medication",
                                   {}).get("medicationCodeableConcept")
            else:
                code2 = record.get("code")

            if code2 is None:
                return Left({
                    "error": f"malformated record: no code",
                    "record": record
                })
            coding2 = code2.get("coding")
            if coding2 is None:
                return Left({
                    "error": f"malformated record: no coding under code",
                    "record": record
                })
            for c2 in coding2:
                if c2["system"] == system:
                    if (is_regex and re.search(code, "^" + c2["code"] +
                                               "$")) or c2["code"] == code:
                        records_filtered.append(record)
    return Right(records_filtered)
예제 #2
0
def address(pat):
    extensions = pat.get("extension", [])
    lat = list(
        map(
            lambda x: x["valueDecimal"],
            filter(lambda x: x.get("url", "").lower() == "latitude",
                   extensions)))
    lon = list(
        map(
            lambda x: x["valueDecimal"],
            filter(lambda x: x.get("url", "").lower() == "longitude",
                   extensions)))
    if len(lat) > 1:
        return Left("more than one latitudes")
    if len(lon) > 1:
        return Left("more than one longitudes")
    if len(lat) == 0:
        if len(lon) == 0:
            return Right(None)
        else:
            return Left("a longitude without a latitude")
    elif len(lon) == 0:
        return Left("a latitude without a longitude")
    else:
        return Right({"latitude": lat[0], "longitude": lon[0]})
예제 #3
0
def query_feature(table, feature):
    feature_def = features_dict[table][feature]
    ty = feature_def["type"]
    if ty == "string":
        if "enum" not in feature_def:
            return Left("node has type string but has no enum")
        else:
            return Right({
                "feature_name":
                feature,
                "feature_qualifiers": [{
                    "operator": "=",
                    "value": v
                } for v in feature_def["enum"]]
            })
    elif ty == "integer":
        if "maximum" not in feature_def or "minimum" not in feature_def:
            return Left(
                "node has type integer but has no maximum or has no minimum")
        else:
            return Right({
                "feature_name":
                feature,
                "feature_qualifiers": [{
                    "operator": "=",
                    "value": v
                } for v in range(feature_def["minimum"],
                                 feature_def["maximum"] + 1)]
            })
    else:
        return Left(f"unsupported node type {ty}")
예제 #4
0
def calculate_age2(born, timestamp):
    try:
        today = strtodate(timestamp)
    except Exception as e:
        return Left({"error": str(e)})
    return Right(today.year - born.year -
                 ((today.month, today.day) < (born.month, born.day)))
예제 #5
0
def get_features_by_identifier(table, identifier):
    if table in input_dict:
        identifier_dict = input_dict[table]
    else:
        raise Left(f"Cannot find table {table}, available {input_dict}")

    return Right([feature for feature, identifiers in identifier_dict.items() if identifier in identifiers])
예제 #6
0
def update_key(d, ok, nk):
    curr_keys = list(d.keys())
    if ok in curr_keys:
        i = curr_keys.index(ok)
        d.insert(i, nk, d.pop(ok))
        return Right(())
    else:
        return Left(f"variable {ok} no longer exists")
예제 #7
0
def merge(a, b, err):
    if a is None:
        return Right(b)
    elif b is None:
        return Right(a)
    elif a == b:
        return Right(a)
    else:
        return Left(f"err={err} a={a} b={b}")
예제 #8
0
def validateTable(ctx, tablename, tfname, kvp):
    with open(tfname, "r", newline="", encoding="utf-8") as tfi:
        reader = csv.reader(tfi)
        header = next(reader)
        n = len(header)
        i = 0
        for row in reader:
            n2 = len(row)
            if n2 != n:
                return Left(f"row {i} number of items, expected {n}, encountered {n2}")
            i += 1
        seen = set()
        dups = []
        for x in header:
            if x in seen:
                dups.append(x)
            else:
                seen.add(x)
        if len(dups) > 0:
            return Left(f"duplicate header(s) in upload {dups}")
        header2 = list(kvp.keys())
        i2 = [a for a in header if a in header2]
        if len(i2) > 0:
            return Left(f"duplicate header(s) in input {i2}")
        conn = connect(user=ctx["dbuser"], password=ctx["dbpass"], host=ctx["dbhost"], dbname=ctx["dbname"])
        cursor = conn.cursor()
        try:
            cursor.execute('''
select column_name, data_type
from information_schema.columns
where table_schema NOT IN ('information_schema', 'pg_catalog') and table_name=%s
order by table_schema, table_name
''', (tablename,))
            rows = cursor.fetchall()
            header3 = list(map(lambda r:r[0], rows))
            d2 = [a for a in header + header2 if a not in header3]
            if len(d2) > 0:
                return Left(f"undefined header(s) in input {d2} available {header3}")
            return Right(())
        finally:
            cursor.close()
            conn.close()
예제 #9
0
def one(xs):
    if len(xs) == 1:
        return Right(xs[0])
    elif len(xs) == 0:
        return Right(None)
    else:
        return Left({
            "variableValue": {
                "value": None
            },
            "how": "more than one record found",
            "certitude": 0
        })
예제 #10
0
def lookupClinicalFromRecord(patient_id, data, v, timestamp):
    clinical = v["id"]
    unit = v.get("units")
    filter_data, feature, unit2 = mapping.get(clinical)
    if unit is None:
        unit = unit2
    if feature is None:
        return Left((f"cannot find mapping for {clinical}", 400))
    else:
        return filter_data(
            patient_id,
            data).bind(lambda records: feature(records, unit, timestamp)).map(
                add_variable(clinical))
예제 #11
0
파일: __init__.py 프로젝트: RENCI/pds
    def handle_clinical_feature_variables(config):
        if len(config) > 0:
            if len(config) > 1:
                log(syslog.LOG_ERR, f"more than one configs for plugin {piid}",
                    "pds")
            clinical_feature_variable_objects = config[0]["settingsDefaults"][
                "patientVariables"]

            def cfvo_to_cfvo2(cfvo):
                cfvo2 = {**cfvo}
                return Right(cfvo2)

            return list_traversable_either_applicative.sequence(
                list(map(cfvo_to_cfvo2, clinical_feature_variable_objects)))
        else:
            return Left(f"no configs for plugin {piid}")
예제 #12
0
def age(patient, unit, timestamp):
    if unit is not None and unit != "year":
        return Left((f"unsupported unit {unit}", 400))

    if patient == None:
        return Right({
            "variableValue": {
                "value": None
            },
            "certitude": 0,
            "how": "record not found"
        })
    else:
        if "birthDate" in patient:
            birth_date = patient["birthDate"]
            date_of_birth = strtodate2(birth_date)
            today = timestamp.strftime("%Y-%m-%d")
            mage = calculate_age2(date_of_birth, timestamp)
            return mage.map(
                lambda age: {
                    "variableValue": {
                        "value": age,
                        "unit": "year"
                    },
                    "certitude": 2,
                    "how": {
                        "request_timestamp": today,
                        "computed_from": ["request_timestamp", "birthDate"],
                        "birthDate": {
                            "computed_from": {
                                "resourceType": "Patient",
                                "field": "birthDate"
                            },
                            "value": birth_date
                        }
                    }
                })
        else:
            return Right({
                "variableValue": {
                    "value": None
                },
                "certitude": 0,
                "how": "birthDate not set"
            })
예제 #13
0
 def handle_src_and_tgt_features(src_features, tgt_features):
     edge_property_value = []
     for src_feature in src_features:
         for tgt_feature in tgt_features:
             edge = co_occurrence_feature_edge(conn, table, year,
                                               cohort_features, src_feature,
                                               tgt_feature)
             if isinstance(edge, Right):
                 edge_property_value.append({
                     "src_feature": src_feature,
                     "tgt_feature": tgt_feature,
                     "p_value": edge.value
                 })
             else:
                 return edge
     if len(edge_property_value) == 0:
         return Left("no edge found")
     else:
         return Right(edge_property_value)
예제 #14
0
    def get(self, table, key):
        FHIR, GEOID, NearestRoad, NearestPoint, Visit = self.get_sub_objects()
        FHIR_keys, GEOID_keys, NearestRoad_keys, NearestPoint_keys, Visit_keys = self.get_sub_keys(
            FHIR, GEOID, NearestRoad, NearestPoint, Visit)
        if key in FHIR_keys:
            return Right(self.obj["FHIR"][key])

        for name, keys in GEOID_keys.items():
            if key in keys:
                return Right(GEOID[name])

        for name, keys in NearestRoad_keys.items():
            if old_key in keys:
                return Right(NearestRoad[name])

        for name, keys in NearestPoint_keys.items():
            if old_key in keys:
                return Right(NearestPoint[name])

        return Left(f"variable {old_key} no longer exists")
예제 #15
0
    def update_key(self, table, old_key, new_key):
        FHIR, GEOID, NearestRoad, NearestPoint, Visit = self.get_sub_objects()
        FHIR_keys, GEOID_keys, NearestRoad_keys, NearestPoint_keys, Visit_keys = self.get_sub_keys(
            FHIR, GEOID, NearestRoad, NearestPoint, Visit)
        if old_key in FHIR_keys:
            update_key(self.obj["FHIR"], old_key, new_key)
            return Right(())

        for name, keys in GEOID_keys.items():
            if old_key in keys:
                columns = GEOID[name]["columns"]
                for column_name, var_name in columns.items():
                    if var_name == old_key:
                        columns[column_name] = new_key
                        return Right(())

        for name, keys in NearestRoad_keys.items():
            if old_key in keys:
                nearest_road = NearestRoad[name]
                if old_key == nearest_road["distance_feature_name"]:
                    nearest_road["distance_feature_name"] = new_key
                else:
                    for attribute_name, feature in nearest_road[
                            "attributes_to_features_map"].items():
                        if feature["feature_name"] == old_key:
                            feature["feature_name"] = new_key
                            return Right(())

        for name, keys in NearestPoint_keys.items():
            if old_key in keys:
                nearest_point = NearestPoint[name]
                if old_key == nearest_point["distance_feature_name"]:
                    nearest_point["distance_feature_name"] = new_key
                else:
                    for attribute_name, feature in nearest_point[
                            "attributes_to_features_map"].items():
                        if feature["feature_name"] == old_key:
                            feature["feature_name"] = new_key
                            return Right(())

        return Left(f"variable {old_key} no longer exists")
예제 #16
0
def age(patient, unit, timestamp):
    if unit is not None and unit != "year":
        return Left((f"unsupported unit {unit}", 400))

    if patient == None:
        return Right({
            "variableValue": {
                "value": None
            },
            "certitude": 0,
            "how": "record not found"
        })
    else:
        if "birthDate" in patient:
            birth_date = patient["birthDate"]
            date_of_birth = strtodate(birth_date)
            today = strtodate(timestamp).strftime("%Y-%m-%d")
            mage = calculate_age2(date_of_birth, timestamp)
            return mage.map(
                lambda age: {
                    "variableValue": {
                        "value": age,
                        "units": "year"
                    },
                    "certitude":
                    2,
                    "how":
                    f"Current date '{today}' minus patient's birthdate (FHIR resource 'Patient' field>'birthDate' = '{birth_date}')"
                })
        else:
            return Right({
                "variableValue": {
                    "value": None
                },
                "certitude": 0,
                "how": "birthDate not set"
            })
예제 #17
0
    def update_value(self, table, key, new_value):
        FHIR, GEOID, NearestRoad, NearestPoint, Visit = self.get_sub_objects()
        FHIR_keys, GEOID_keys, NearestRoad_keys, NearestPoint_keys, Visit_keys = self.get_sub_keys(
            FHIR, GEOID, NearestRoad, NearestPoint, Visit)
        if key in FHIR_keys:
            self.obj["FHIR"][key] = new_value
            return Right(())

        for name, keys in GEOID_keys.items():
            if key in keys:
                GEOID[name] = new_value
                return Right(())

        for name, keys in NearestRoad_keys.items():
            if key in keys:
                NearestRoad[name] = new_value
                return Right(())

        for name, keys in NearestPoint_keys.items():
            if key in keys:
                NearestPoint[name] = new_value
                return Right(())

        return Left(f"variable {key} no longer exists")
예제 #18
0
 def get(self, table, key):
     if key in self.obj[table]:
         val = self.obj[table][key]
         return Right(val)
     else:
         return Left(f"variable {key} does not exist")
예제 #19
0
def test_eq_on_Left():
    assert Left(1) == Left(1)
예제 #20
0
def test_sequence():
    either = list_traversable(either_monad)
    assert either.sequence([Right(1), Right(2), Right(3)]) == Right([1,2,3])
    assert either.sequence([Left(1), Right(2), Right(3)]) == Left(1)
예제 #21
0
def test_ne_on_Right():
    assert Right(1) != Right(2)
    assert Right(1) != Left(1)
예제 #22
0
 def get(self, table, key):
     val = self.obj[table].get(key)
     if val is None:
         return Left(f"variable {key} no longer exists")
     else:
         return Right(val)
예제 #23
0
def test_rec():
    assert Left(1).rec(lambda x: x, lambda x: x + 1) == 1
    assert Right(2).rec(lambda x: x + 1, lambda x: x) == 2
예제 #24
0
파일: __init__.py 프로젝트: RENCI/pds
def error_code(result):
    return result.rec(
        lambda err: Left(("not found", 404)
                         if err[0]["status_code"] == 404 else err),
        lambda config: Right(config))
예제 #25
0
def test_bind_on_Left():
    assert Left(1).bind(lambda x: Right(2)) == Left(1)
예제 #26
0
def test_pickle_Left():
    pickle.dumps(Left(1))
예제 #27
0
def test_map_on_Left():
    assert Left(1).map(lambda x: 2) == Left(1)
예제 #28
0
def update_value(d, k, nv):
    if k in d:
        d[k] = nv
        return Right(())
    else:
        return Left(f"variable {k} does not exist")
예제 #29
0
def query_records(records, codes, unit, timestamp, clinical_variable,
                  resource_name):
    if records == None:
        return Right({"value": None, "certitude": 0, "how": "no record found"})

    records_filtered = []
    for record in records:
        for c in codes:
            system = c["system"]
            code = c["code"]
            is_regex = c["is_regex"]

            code2 = record.get("code")
            if code2 is None:
                return Left({
                    "error": f"malformated record: no code",
                    "record": record
                })
            coding2 = code2.get("coding")
            if coding2 is None:
                return Left({
                    "error": f"malformated record: no coding under code",
                    "record": record
                })
            for c2 in coding2:
                if c2["system"] == system:
                    if (is_regex and re.search(code, "^" + c2["code"] +
                                               "$")) or c2["code"] == code:
                        records_filtered.append(record)
    if len(records_filtered) == 0:
        from_code = calculation(codes)
        return Right({
            "variableValue": {
                "value": None
            },
            "certitude": 0,
            "how": f"no record found code {from_code}"
        })
    else:
        ts = strtots(timestamp)

        def key(a):
            ext_key = extract_key(a)
            if ext_key is None:
                return float("inf")
            else:
                return abs(strtots(ext_key) - ts)

        record = min(records_filtered, key=key)
        keyr = extract_key(record)
        if keyr is None:
            ts = None
            cert = 1
        else:
            ts = extract_key(record)
            cert = 2
        vq = record.get("valueQuantity")
        if vq is not None:
            v = vq["value"]
            from_u = vq.get("units")
            if from_u is None:
                from_u = vq.get("code")
            mv = convert(v, from_u, unit)
            if isinstance(mv, Left):
                return mv
            else:
                v = mv.value
        else:
            v = True
            from_u = None
        c = calculation_template(clinical_variable, resource_name, timestamp,
                                 record, unit)
        return Right({
            "variableValue": {
                "value":
                v,
                **({
                    "units": unit
                } if unit is not None else {
                       "units": from_u
                   } if from_u is not None else {}),
            },
            "certitude": cert,
            "timestamp": ts,
            "how": c
        })
예제 #30
0
def feature_names(table, node_curie):
    return (maybe.from_python(node_curie).rec(
        Right, Left("no curie specified at node")).bind(
            partial(get_features_by_identifier, table)))