def sex(patient, unit, timestamp): if patient == None: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": "record not found" }) else: gender = patient.get("gender") if gender is None: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": "gender not set" }) else: return Right({ "variableValue": { "value": gender }, "certitude": 2, "how": f"FHIR resource 'Patient' field>'gender' = {gender}" })
def merge_array(a, b, err): if a is None: return Right(b) elif b is None: return Right(a) else: return Right(a + [elem for elem in b if elem not in a])
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]})
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}")
def handle_records_filtered(records_filtered): 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 = timestamp.timestamp() def key(a): return extract_key(a).rec( lambda ext_key: diff_func(strtots(ext_key) - ts), float("inf")) records_filtered_key = [(a, key(a)) for a in records_filtered] records_with_key = [ a for a in records_filtered_key if a[1] is not None ] if len(records_with_key) == 0: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": f"no record found code {from_code}" }) else: record = min(records_with_key, key=lambda a: a[1])[0] return convert_record_to_pds(record, unit, timestamp, clinical_variable, resource_name)
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}")
def func(patient, unit, timestamp): if patient == None: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": "record not found" }) else: extension = patient.get("extension") if extension is None: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": "extension not found" }) else: filtered = filter(lambda x: x["url"] == url, extension) if len(filtered) == 0: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": f"extension not found url {url}" }) else: certitude = 2 value = [] calculation = url hasValueCodeableConcept = True for a in filtered: valueCodeableConcept = a.get("valueCodeableConcept") if valueCodeableConcept is None: certitude = 1 calculation += " valueCodeableConcept not found" else: hasValueCodeableConcept = True value.append(valueCodeableConcept) if len(value) == 0: certitude = 0 elif not hasValueCodeableConcept: calculation += " on some extension" return Right({ "variableValue": { "value": value }, "certitude": certitude, "how": calculation })
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 })
def convert_record_to_pds(record, unit, timestamp, clinical_variable, resource_name): ts = extract_key(record) cert = ts.rec(const(2), 1) vq = record.get("valueQuantity") if vq is not None: v = vq["value"] from_u = vq.get("unit") 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, **({ "unit": unit } if unit is not None else { "unit": from_u } if from_u is not None else {}), }, "certitude": cert, "timestamp": maybe.to_python(ts), "how": c })
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)
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)))
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])
def sequence(l): l2 = [] for x in l: if isinstance(x, Left): return x else: l2.append(x.value) return Right(l2)
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")
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" })
def ethnicities(pat): extensions = pat.get("extension", []) return Right( list( map( lambda x: x["valueString"], filter( lambda x: x.get("url") in ethnicity_urls and "valueString" in x, extensions))))
def address(patient, unit, timestamp): if patient == None: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": "record not found" }) else: address = patient.get("address") if address is None: return Right({ "variableValue": { "value": None }, "certitude": 0, "how": "address not set" }) else: # use home type address if available, otherwise, just use the first address used_addr_dict = None for addr in address: if addr['use'] == 'home': used_addr_dict = addr break if not used_addr_dict: used_addr_dict = address[0] used_addr_str = '{line}, {city}, {state} {pc}, {country}'.format( line=','.join(used_addr_dict['line']), city=used_addr_dict['city'], state=used_addr_dict['state'], pc=used_addr_dict['postalCode'], country=used_addr_dict['country']) return Right({ "variableValue": { "value": used_addr_str }, "certitude": 2, "how": f"FHIR resource 'Patient' field>'address' = {used_addr_str}" })
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")
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")
def set_races(pat, races): extensions = pat.get("extension", []) pat["extension"] = list( filter(lambda x: x.get("url") not in race_urls, extensions)) + list( map( lambda race: { "url": race_urls[0], "extension": [{ "valueString": race }] }, races)) return Right(pat)
def set_ethnicities(pat, ethnicities): extensions = pat.get("extension", []) pat["extension"] = list( filter(lambda x: x.get("url") not in ethnicity_urls, extensions)) + list( map( lambda ethnicity: { "url": ethnicity_urls[0], "extension": [{ "valueString": ethnicity }] }, ethnicities)) return Right(pat)
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" })
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")
def set_addresses(pat, addresses): pat["address"] = list( map( lambda address: { "extension": [{ "url": None, "extension": [{ "url": "latitude", "valueDecimal": address["latitude"] }, { "url": "longitude", "valueDecimal": address["longitude"] }] }] }, addresses)) return Right(pat)
def handle_requests(requests): rescs = [] for request in requests: method = request["method"] url = request["url"] result = urlsplit(url) pcs = result.path.split("/") qcs = map(lambda x: x.split("="), result.query.split("&")) if pcs[1] == "Patient": rescs.append(_get_patient(pcs[2])) else: patient_id = None for qc in qcs: if qc[0] == "patient": patient_id = qc[1] rescs.append(_get_resource(pcs[1], patient_id)) return Right(bundle(rescs, "batch-response"))
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)
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()
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))
def cfvo_to_cfvo2(cfvo): cfvo2 = {**cfvo} return Right(cfvo2)
def set_gender(pat, gender): pat["gender"] = gender return Right(pat)