diff --git a/schema/fhir_json.csv b/schema/fhir_json.csv deleted file mode 100644 index 6a2cc113..00000000 --- a/schema/fhir_json.csv +++ /dev/null @@ -1,169 +0,0 @@ -spec:SSSOM,spec:R4,spec:R5 -MappingSet.comment,extension,extension -MappingSet.creator_id,identifier.assigner.reference,identifier.assigner.reference -MappingSet.creator_label,identifier.assigner.display,identifier.assigner.display -MappingSet.creator_label,publisher,publisher -MappingSet.creator_label,contact.name,contact.name -MappingSet.license,copyright,copyright -MappingSet.mapping_date,date,date -MappingSet.mapping_date,identifier.period.start,identifier.period.start -MappingSet.mapping_date,.,approvalDate -MappingSet.mapping_date,.,lastReviewDate -MappingSet.mapping_date,.,effectivePeriod.start -.,.,effectivePeriod.end -MappingSet.mapping_provider,extension,extension -MappingSet.mapping_set_description,description,description -MappingSet.mapping_set_id,url,url -MappingSet.mapping_set_id,title,title -MappingSet.mapping_set_id,name,name -MappingSet.mapping_set_id,identifier.value,identifier.value -MappingSet.mapping_set_source,extension,extension -MappingSet.mapping_set_version,version,version -MappingSet.mapping_tool,extension,extension -MappingSet.mappings,.,. -MappingSet.object_match_field,extension,extension -MappingSet.object_preprocessing,extension,extension -MappingSet.object_source,targetCanonical,targetScopeCanonical -MappingSet.object_source,targetUri,targetScopeUri -MappingSet.object_source,group.target,group.target -MappingSet.object_source_version,group.targetVersion,extension -MappingSet.object_type,extension,extension -MappingSet.other,extension,extension -MappingSet.see_also,extension,extension -MappingSet.subject_match_field,extension,extension -MappingSet.subject_preprocessing,extension,extension -MappingSet.subject_source,sourceCanonical,sourceScopeCanonical -MappingSet.subject_source,sourceUri,sourceScopeUri -MappingSet.subject_source,group.source,group.source -MappingSet.subject_source_version,group.sourceVersion,extension -Mapping.subject_type,group.element.target.extension,group.element.target.extension -Mapping.author_id,group.element.target.extension,group.element.target.extension -Mapping.author_label,group.element.target.extension,group.element.target.extension -Mapping.comment,group.element.target.comment,group.element.target.comment -Mapping.confidence,group.element.target.extension,group.element.target.extension -Mapping.creator_id,group.element.target.extension,group.element.target.extension -Mapping.creator_label,group.element.target.extension,group.element.target.extension -Mapping.license,group.element.target.extension,group.element.target.extension -Mapping.mapping_cardinality,group.element.target.extension,group.element.target.extension -Mapping.mapping_date,group.element.target.extension,group.element.target.extension -Mapping.mapping_justification,group.element.target.extension,group.element.target.extension -Mapping.mapping_provider,group.element.target.extension,group.element.target.extension -Mapping.mapping_tool,group.element.target.extension,group.element.target.extension -Mapping.mapping_tool_version,group.element.target.extension,group.element.target.extension -Mapping.match_string,group.element.target.extension,group.element.target.extension -Mapping.object_category,group.element.target.extension,group.element.target.extension -Mapping.object_id,group.element.target.code,group.element.target.code -Mapping.object_label,group.element.target.display,group.element.target.display -Mapping.object_match_field,group.element.target.extension,group.element.target.extension -Mapping.object_preprocessing,group.element.target.extension,group.element.target.extension -Mapping.object_source,group.element.target.extension,group.element.target.extension -Mapping.object_source_version,group.element.target.extension,group.element.target.extension -Mapping.object_type,group.element.target.extension,group.element.target.extension -Mapping.other,group.element.target.extension,group.element.target.extension -Mapping.predicate_id,group.element.target.equivalence,group.element.target.relationship -.,.,group.element.target.valueSet -Mapping.predicate_id,group.element.target.dependsOn.value,group.element.target.dependsOn.valueCode -Mapping.predicate_id,group.element.target.dependsOn.property,group.element.target.dependsOn.property -.,.,group.element.target.dependsOn.valueSet -Mapping.predicate_id,group.element.target.dependsOn.system,. -.,group.element.target.product,group.element.target.product -Mapping.predicate_label,group.element.target.dependsOn.display,group.element.target.dependsOn.valueString -Mapping.predicate_modifier,.,. -Mapping.reviewer_id,group.element.target.extension,group.element.target.extension -Mapping.reviewer_label,group.element.target.extension,group.element.target.extension -Mapping.see_also,group.element.target.extension,group.element.target.extension -Mapping.semantic_similarity_measure,group.element.target.extension,group.element.target.extension -Mapping.semantic_similarity_score,group.element.target.extension,group.element.target.extension -Mapping.subject_category,group.element.target.extension,group.element.target.extension -Mapping.subject_id,group.element.code,group.element.code -Mapping.subject_label,group.element.display,group.element.display -Mapping.subject_match_field,group.element.target.extension,group.element.target.extension -Mapping.subject_preprocessing,group.element.target.extension,group.element.target.extension -Mapping.subject_source,group.element.target.extension,group.element.target.extension -Mapping.subject_source_version,group.element.target.extension,group.element.target.extension -Mapping.subject_type,group.element.target.extension,group.element.target.extension -.,identifier.period.end,identifier.period.end -MappingSet.mapping_set_id,identifier.system,identifier.system -.,identifier.use,identifier.use -?,identifier.type.text,identifier.type.text -?,identifier.type.coding.system,identifier.type.coding.system -?,identifier.type.coding.version,identifier.type.coding.version -?,identifier.type.coding.code,identifier.type.coding.code -?,identifier.type.coding.display,identifier.type.coding.display -.,identifier.type.coding.userSelected,identifier.type.coding.userSelected -.,identifier.assigner.type,identifier.assigner.type -.,identifier.assigner.identifier,identifier.assigner.reference.identifier -.,status,status -.,experimental,experimental -.,contact.telecom.system,contact.telecom.system -.,contact.telecom.value,contact.telecom.value -.,contact.telecom.use,contact.telecom.use -.,contact.telecom.rank,contact.telecom.rank -.,contact.telecom.period.start,contact.telecom.period.start -.,contact.telecom.period.end,contact.telecom.period.end -.,purpose,purpose -.,.,topic -?,.,author.name -.,.,author.contact.telecom.system -.,.,author.contact.telecom.value -.,.,author.contact.telecom.use -.,.,author.contact.telecom.rank -.,.,author.contact.telecom.period.start -.,.,author.contact.telecom.period.end -?,.,editor.name -.,.,editor.contact.telecom.system -.,.,editor.contact.telecom.value -.,.,editor.contact.telecom.use -.,.,editor.contact.telecom.rank -.,.,editor.contact.telecom.period.start -.,.,editor.contact.telecom.period.end -?,.,reviewer.name -.,.,reviewer.contact.telecom.system -.,.,reviewer.contact.telecom.value -.,.,reviewer.contact.telecom.use -.,.,reviewer.contact.telecom.rank -.,.,reviewer.contact.telecom.period.start -.,.,reviewer.contact.telecom.period.end -?,.,endorser.name -.,.,endorser.contact.telecom.system -.,.,endorser.contact.telecom.value -.,.,endorser.contact.telecom.use -.,.,endorser.contact.telecom.rank -.,.,endorser.contact.telecom.period.start -.,.,endorser.contact.telecom.period.end -?,.,releasedArtifact.type -.,.,releasedArtifact.label -MappingSet.mapping_set_description,.,releasedArtifact.display -?,.,releasedArtifact.citation -.,.,releasedArtifact.classifier.code -.,.,releasedArtifact.classifier.display -.,.,releasedArtifact.classifier.definition -.,.,releasedArtifact.document.contentType -.,.,releasedArtifact.document.language -.,.,releasedArtifact.document.data -MappingSet.mapping_set_id,.,releasedArtifact.document.url -.,.,releasedArtifact.document.size -.,.,releasedArtifact.document.hash -MappingSet.mapping_set_id,.,releasedArtifact.document.title -.,.,releasedArtifact.document.creation -.,.,releasedArtifact.document.height -.,.,releasedArtifact.document.width -.,.,releasedArtifact.document.frames -.,.,releasedArtifact.document.duration -.,.,releasedArtifact.document.pages -.,.,releasedArtifact.resource -.,.,releasedArtifact.resourceReference.reference -.,.,releasedArtifact.resourceReference.type -MappingSet.mapping_set_id,.,releasedArtifact.resourceReference.display -.,.,releasedArtifact.resourceReference.identifier -.,group.element.noMap,. -.,group.element.valueSet,. -.,group.element.target.unmapped.mode,group.element.target.unmapped.mode -Mapping.subject_id,group.element.target.unmapped.code,group.element.target.unmapped.code -Mapping.subject_label,group.element.target.unmapped.display,group.element.target.unmapped.display -.,.,group.element.target.unmapped.valueSet -Mapping.predicate_id,.,group.element.target.unmapped.relationship -.,group.element.target.unmapped.url,group.element.target.unmapped.otherMap -.,useContext.code,useContext.code -.,useContext.valueCodeableConcept,useContext.valueCodeableConcept -.,jurisdiction,jurisdiction \ No newline at end of file diff --git a/src/sssom/writers.py b/src/sssom/writers.py index 65553ed2..f215d170 100644 --- a/src/sssom/writers.py +++ b/src/sssom/writers.py @@ -308,6 +308,8 @@ def to_rdf_graph(msdf: MappingSetDataFrame) -> Graph: # TODO: add to CLI & to these functions: r4 vs r5 param +# TODO: What if the msdf doesn't have everything we need? (i) metadata, e.g. yml, (ii) what if we need to override? +# - todo: later: allow any nested aribtrary override: (get in kwargs, else metadata.get(key, None)) def to_fhir_json(msdf: MappingSetDataFrame) -> Dict: """Convert a mapping set dataframe to a JSON object. @@ -322,14 +324,18 @@ def to_fhir_json(msdf: MappingSetDataFrame) -> Dict: TODO: Add additional fields from both specs - ConceptMap spec fields: https://www.hl7.org/fhir/r4/conceptmap.html - Joe: Can also utilize: /Users/joeflack4/projects/hapi-fhir-jpaserver-starter/_archive/issues/sssom/example_json/minimal.json - - SSSOM https://mapping-commons.github.io/sssom/Mapping/ + + Common issues + #1: If there is any variation for any records in a MappingSet, this may need to be a group.element.target.extension + + - SSSOM: Mapping https://mapping-commons.github.io/sssom/Mapping/ author_id,? author_label,? comment,group.element.target.comment confidence,? creator_id,?,?,See: #1 creator_label,?,?,See: #1 - license,copyright~,?,#1: If there is any variation for any records in a MappingSet, this may need to be a group.element.target.extension + license,copyright~,See: #1 mapping_cardinality,? mapping_date,date~,?,See: #1 mapping_justification,?,group.element.target.extension @@ -362,7 +368,8 @@ def to_fhir_json(msdf: MappingSetDataFrame) -> Dict: subject_source,sourceUri;group.source~,?,See: #1 subject_source_version,?,?,See: #1 subject_type,?,?,See: #1 - - SSSOM https://mapping-commons.github.io/sssom/MappingSet/ + + - SSSOM: MappingSet https://mapping-commons.github.io/sssom/MappingSet/ comment,? creator_id,? creator_label,? @@ -394,9 +401,6 @@ def to_fhir_json(msdf: MappingSetDataFrame) -> Dict: mapping_set_id = metadata.get("mapping_set_id", "") name: str = mapping_set_id.split("/")[-1].replace(".sssom.tsv", "") # Construct JSON - # TODO: Fix: sssom/writers.py:293: error: Item "None" of "Optional[Dict[str, Any]]" has no attribute "get" - # ...a. Maybe remove the typing? b. remove the get? c. do outside of dict and add after?, d. Add "None"? maybe cant be done here - # ...e. Probably assign metadata to new object and use that instead. so won't read as None json_obj = { "resourceType": "ConceptMap", "url": mapping_set_id, @@ -439,98 +443,101 @@ def to_fhir_json(msdf: MappingSetDataFrame) -> Dict: "targetUri": metadata.get("object_source", ""), # TODO: Might want to make each "group" first, if there is more than 1 set of ontology1::ontology2 # ...within a given MappingSet / set of SSSOM TSV rows. - "group": [{ - "source": metadata.get("subject_source", ""), - "target": metadata.get("object_source", ""), - "element": [ - { - "code": row["subject_id"], - "display": row.get("subject_label", ""), - "target": [ - { - "code": row["object_id"], - "display": row.get("object_label", ""), - # TODO: R4 (try this first) - # relatedto | equivalent | equal | wider | subsumes | narrower | specializes | inexact | unmatched | disjoint - # https://www.hl7.org/fhir/r4/conceptmap.html - # todo: r4: if not found, eventually needs to be `null` or something. check docs to see if nullable, else ask on Zulip - # TODO: R5 Needs to be one of: - # related-to | equivalent | source-is-narrower-than-target | source-is-broader-than-target | not-related-to - # https://www.hl7.org/fhir/r4/valueset-concept-map-equivalence.html - # ill update that next time. i can map SSSOM SKOS/etc mappings to FHIR ones - # and then add the original SSSOM mapping CURIE fields somewhere else - # https://www.hl7.org/fhir/valueset-concept-map-equivalence.html - # https://github.com/mapping-commons/sssom-py/issues/258 - "equivalence": { - # relateedto: The concepts are related to each other, and have at least some overlap - # in meaning, but the exact relationship is not known. - "skos:related": "relatedto", - "skos:relatedMatch": "relatedto", # canonical - # equivalent: The definitions of the concepts mean the same thing (including when - # structural implications of meaning are considered) (i.e. extensionally identical). - "skos:exactMatch": "equivalent", - # equal: The definitions of the concepts are exactly the same (i.e. only grammatical - # differences) and structural implications of meaning are identical or irrelevant - # (i.e. intentionally identical). - "equal": "equal", # todo what's difference between this and above? which to use? - # wider: The target mapping is wider in meaning than the source concept. - "skos:broader": "wider", - "skos:broadMatch": "wider", # canonical - # subsumes: The target mapping subsumes the meaning of the source concept (e.g. the - # source is-a target). - "rdfs:subClassOf": "subsumes", - "owl:subClassOf": "subsumes", - # narrower: The target mapping is narrower in meaning than the source concept. The - # sense in which the mapping is narrower SHALL be described in the comments in this - # case, and applications should be careful when attempting to use these mappings - # operationally. - "skos:narrower": "narrower", - "skos:narrowMatch": "narrower", # canonical - # specializes: The target mapping specializes the meaning of the source concept - # (e.g. the target is-a source). - "sssom:superClassOf": "specializes", - # inexact: The target mapping overlaps with the source concept, but both source and - # target cover additional meaning, or the definitions are imprecise and it is - # uncertain whether they have the same boundaries to their meaning. The sense in - # which the mapping is inexact SHALL be described in the comments in this case, and - # applications should be careful when attempting to use these mappings operationally - "skos:closeMatch": "inexact", - # unmatched: There is no match for this concept in the target code system. - # todo: unmatched: this is more complicated. This will be a combination of - # predicate_id and predicate_modifier (if present). See: - # https://github.com/mapping-commons/sssom/issues/185 - "unmatched": "unmatched", - # disjoint: This is an explicit assertion that there is no mapping between the - # source and target concept. - "owl:disjointWith": "disjoint", - }.get( - row["predicate_id"], row["predicate_id"] - ), # r4 - # "relationship": row['predicate_id'], # r5 - # "comment": '', - "extension": [ - { - # todo: `mapping_justification` consider changing `ValueString` -> `ValueCoding` - # ...that is, if I happen to know the categories/codes for this categorical variable - # ...if i do that, do i also need to upload that coding as a (i) `ValueSet` resource? (or (ii) codeable concept? prolly (i)) - "url": "http://example.org/fhir/StructureDefinition/mapping_justification", - "ValueString": row.get( - "mapping_justification", - row.get("mapping_justification", ""), - ), - } - ], - } - ], - } - for i, row in df.iterrows() - ], - # "unmapped": { # todo: conceptmap - # "mode": "fixed", - # "code": "temp", - # "display": "temp" - # } - }], + "group": [ + { + # TODO: Override? but how? + "source": metadata.get("subject_source", ""), + "target": metadata.get("object_source", ""), + "element": [ + { + "code": row["subject_id"], + "display": row.get("subject_label", ""), + "target": [ + { + "code": row["object_id"], + "display": row.get("object_label", ""), + # TODO: R4 (try this first) + # relatedto | equivalent | equal | wider | subsumes | narrower | specializes | inexact | unmatched | disjoint + # https://www.hl7.org/fhir/r4/conceptmap.html + # todo: r4: if not found, eventually needs to be `null` or something. check docs to see if nullable, else ask on Zulip + # TODO: R5 Needs to be one of: + # related-to | equivalent | source-is-narrower-than-target | source-is-broader-than-target | not-related-to + # https://www.hl7.org/fhir/r4/valueset-concept-map-equivalence.html + # ill update that next time. i can map SSSOM SKOS/etc mappings to FHIR ones + # and then add the original SSSOM mapping CURIE fields somewhere else + # https://www.hl7.org/fhir/valueset-concept-map-equivalence.html + # https://github.com/mapping-commons/sssom-py/issues/258 + "equivalence": { + # relateedto: The concepts are related to each other, and have at least some overlap + # in meaning, but the exact relationship is not known. + "skos:related": "relatedto", + "skos:relatedMatch": "relatedto", # canonical + # equivalent: The definitions of the concepts mean the same thing (including when + # structural implications of meaning are considered) (i.e. extensionally identical). + "skos:exactMatch": "equivalent", + # equal: The definitions of the concepts are exactly the same (i.e. only grammatical + # differences) and structural implications of meaning are identical or irrelevant + # (i.e. intentionally identical). + "equal": "equal", # todo what's difference between this and above? which to use? + # wider: The target mapping is wider in meaning than the source concept. + "skos:broader": "wider", + "skos:broadMatch": "wider", # canonical + # subsumes: The target mapping subsumes the meaning of the source concept (e.g. the + # source is-a target). + "rdfs:subClassOf": "subsumes", + "owl:subClassOf": "subsumes", + # narrower: The target mapping is narrower in meaning than the source concept. The + # sense in which the mapping is narrower SHALL be described in the comments in this + # case, and applications should be careful when attempting to use these mappings + # operationally. + "skos:narrower": "narrower", + "skos:narrowMatch": "narrower", # canonical + # specializes: The target mapping specializes the meaning of the source concept + # (e.g. the target is-a source). + "sssom:superClassOf": "specializes", + # inexact: The target mapping overlaps with the source concept, but both source and + # target cover additional meaning, or the definitions are imprecise and it is + # uncertain whether they have the same boundaries to their meaning. The sense in + # which the mapping is inexact SHALL be described in the comments in this case, and + # applications should be careful when attempting to use these mappings operationally + "skos:closeMatch": "inexact", + # unmatched: There is no match for this concept in the target code system. + # todo: unmatched: this is more complicated. This will be a combination of + # predicate_id and predicate_modifier (if present). See: + # https://github.com/mapping-commons/sssom/issues/185 + "unmatched": "unmatched", + # disjoint: This is an explicit assertion that there is no mapping between the + # source and target concept. + "owl:disjointWith": "disjoint", + }.get( + row["predicate_id"], row["predicate_id"] + ), # r4 + # "relationship": row['predicate_id'], # r5 + # "comment": '', + "extension": [ + { + # todo: `mapping_justification` consider changing `ValueString` -> `ValueCoding` + # ...that is, if I happen to know the categories/codes for this categorical variable + # ...if i do that, do i also need to upload that coding as a (i) `ValueSet` resource? (or (ii) codeable concept? prolly (i)) + "url": "http://example.org/fhir/StructureDefinition/mapping_justification", + "ValueString": row.get( + "mapping_justification", + row.get("mapping_justification", ""), + ), + } + ], + } + ], + } + for i, row in df.iterrows() + ], + # "unmapped": { # todo: conceptmap + # "mode": "fixed", + # "code": "temp", + # "display": "temp" + # } + } + ], } # Delete empty fields