Document ontology done
This commit is contained in:
parent
a5a7d75e58
commit
b9802d0101
|
@ -47,6 +47,10 @@ RSNA Playbook
|
||||||
equivalent (or would they be wider/narrower). They look equivalent to me.
|
equivalent (or would they be wider/narrower). They look equivalent to me.
|
||||||
|
|
||||||
Document Ontology
|
Document Ontology
|
||||||
|
- Per the SOW, "A value set containing terms in the LOINC Document Ontology
|
||||||
|
will be created". Just to confirm, entries in this ValueSet are therefore
|
||||||
|
LOINC terms (such as "11488-4 / Consultation Note") as opposed to part
|
||||||
|
codes?
|
||||||
- Need to define a URI for the document ontology ValueSet. Currently I am
|
- Need to define a URI for the document ontology ValueSet. Currently I am
|
||||||
using "http://loinc.org/document-ontology-codes"
|
using "http://loinc.org/document-ontology-codes"
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,11 @@ import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
||||||
import ca.uhn.fhir.jpa.term.IRecordHandler;
|
import ca.uhn.fhir.jpa.term.IRecordHandler;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import org.apache.commons.csv.CSVRecord;
|
import org.apache.commons.csv.CSVRecord;
|
||||||
import org.hl7.fhir.r4.model.CanonicalType;
|
|
||||||
import org.hl7.fhir.r4.model.ConceptMap;
|
|
||||||
import org.hl7.fhir.r4.model.Enumerations;
|
import org.hl7.fhir.r4.model.Enumerations;
|
||||||
import org.hl7.fhir.r4.model.ValueSet;
|
import org.hl7.fhir.r4.model.ValueSet;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
import static org.apache.commons.lang3.StringUtils.trim;
|
import static org.apache.commons.lang3.StringUtils.trim;
|
||||||
|
|
||||||
public class LoincDocumentOntologyHandler implements IRecordHandler {
|
public class LoincDocumentOntologyHandler implements IRecordHandler {
|
||||||
|
@ -26,7 +23,7 @@ public class LoincDocumentOntologyHandler implements IRecordHandler {
|
||||||
private final Set<String> myPropertyNames;
|
private final Set<String> myPropertyNames;
|
||||||
private final List<ValueSet> myValueSets;
|
private final List<ValueSet> myValueSets;
|
||||||
private final Map<String, ValueSet> myIdToValueSet = new HashMap<>();
|
private final Map<String, ValueSet> myIdToValueSet = new HashMap<>();
|
||||||
private final Set<String> myCodesInRsnaPlaybookValueSet = new HashSet<>();
|
private final Set<String> myCodesInDocumentOntologyValueSet = new HashSet<>();
|
||||||
|
|
||||||
public LoincDocumentOntologyHandler(TermCodeSystemVersion theCodeSystemVersion, Map<String, TermConcept> theCode2concept, Set<String> thePropertyNames, List<ValueSet> theValueSets) {
|
public LoincDocumentOntologyHandler(TermCodeSystemVersion theCodeSystemVersion, Map<String, TermConcept> theCode2concept, Set<String> thePropertyNames, List<ValueSet> theValueSets) {
|
||||||
myCodeSystemVersion = theCodeSystemVersion;
|
myCodeSystemVersion = theCodeSystemVersion;
|
||||||
|
@ -46,39 +43,50 @@ public class LoincDocumentOntologyHandler implements IRecordHandler {
|
||||||
|
|
||||||
// RSNA Codes VS
|
// RSNA Codes VS
|
||||||
ValueSet vs;
|
ValueSet vs;
|
||||||
if (!myIdToValueSet.containsKey(RSNA_CODES_VS_ID)) {
|
if (!myIdToValueSet.containsKey(DOCUMENT_ONTOLOGY_CODES_VS_ID)) {
|
||||||
vs = new ValueSet();
|
vs = new ValueSet();
|
||||||
vs.setUrl(RSNA_CODES_VS_URI);
|
vs.setUrl(DOCUMENT_ONTOLOGY_CODES_VS_URI);
|
||||||
vs.setId(RSNA_CODES_VS_ID);
|
vs.setId(DOCUMENT_ONTOLOGY_CODES_VS_ID);
|
||||||
vs.setName(RSNA_CODES_VS_NAME);
|
vs.setName(DOCUMENT_ONTOLOGY_CODES_VS_NAME);
|
||||||
vs.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
vs.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||||
myIdToValueSet.put(RSNA_CODES_VS_ID, vs);
|
myIdToValueSet.put(DOCUMENT_ONTOLOGY_CODES_VS_ID, vs);
|
||||||
myValueSets.add(vs);
|
myValueSets.add(vs);
|
||||||
} else {
|
} else {
|
||||||
vs = myIdToValueSet.get(RSNA_CODES_VS_ID);
|
vs = myIdToValueSet.get(DOCUMENT_ONTOLOGY_CODES_VS_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!myCodesInRsnaPlaybookValueSet.contains(loincNumber)) {
|
if (!myCodesInDocumentOntologyValueSet.contains(loincNumber)) {
|
||||||
|
String loincDisplayName= null;
|
||||||
|
if (myCode2Concept.containsKey(loincNumber)) {
|
||||||
|
loincDisplayName = myCode2Concept.get(loincNumber).getDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
vs
|
vs
|
||||||
.getCompose()
|
.getCompose()
|
||||||
.getIncludeFirstRep()
|
.getIncludeFirstRep()
|
||||||
.setSystem(IHapiTerminologyLoaderSvc.LOINC_URL)
|
.setSystem(IHapiTerminologyLoaderSvc.LOINC_URL)
|
||||||
.addConcept()
|
.addConcept()
|
||||||
.setCode(loincNumber)
|
.setCode(loincNumber)
|
||||||
.setDisplay(longCommonName);
|
.setDisplay(loincDisplayName);
|
||||||
myCodesInRsnaPlaybookValueSet.add(loincNumber);
|
myCodesInDocumentOntologyValueSet.add(loincNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
String loincCodePropName;
|
String loincCodePropName;
|
||||||
switch (partTypeName) {
|
switch (partTypeName) {
|
||||||
case "Rad.Anatomic Location.Region Imaged":
|
case "Document.Kind":
|
||||||
loincCodePropName = "rad-anatomic-location-region-imaged";
|
loincCodePropName = "document-kind";
|
||||||
break;
|
break;
|
||||||
case "Rad.Anatomic Location.Imaging Focus":
|
case "Document.Role":
|
||||||
loincCodePropName = "rad-anatomic-location-imaging-focus";
|
loincCodePropName = "document-role";
|
||||||
break;
|
break;
|
||||||
case "Rad.Modality.Modality type":
|
case "Document.Setting":
|
||||||
loincCodePropName = "rad-modality-modality-type";
|
loincCodePropName = "document-setting";
|
||||||
|
break;
|
||||||
|
case "Document.SubjectMatterDomain":
|
||||||
|
loincCodePropName = "document-subject-matter-domain";
|
||||||
|
break;
|
||||||
|
case "Document.TypeOfService":
|
||||||
|
loincCodePropName = "document-type-of-service";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InternalErrorException("Unknown PartTypeName: " + partTypeName);
|
throw new InternalErrorException("Unknown PartTypeName: " + partTypeName);
|
||||||
|
@ -89,7 +97,6 @@ public class LoincDocumentOntologyHandler implements IRecordHandler {
|
||||||
code.addPropertyCoding(loincCodePropName, IHapiTerminologyLoaderSvc.LOINC_URL, partNumber, partName);
|
code.addPropertyCoding(loincCodePropName, IHapiTerminologyLoaderSvc.LOINC_URL, partNumber, partName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.term;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
|
import ca.uhn.fhir.jpa.term.loinc.LoincDocumentOntologyHandler;
|
||||||
import ca.uhn.fhir.jpa.term.loinc.LoincPartHandler;
|
import ca.uhn.fhir.jpa.term.loinc.LoincPartHandler;
|
||||||
import ca.uhn.fhir.jpa.term.loinc.LoincPartRelatedCodeMappingHandler;
|
import ca.uhn.fhir.jpa.term.loinc.LoincPartRelatedCodeMappingHandler;
|
||||||
import ca.uhn.fhir.jpa.term.loinc.LoincRsnaPlaybookHandler;
|
import ca.uhn.fhir.jpa.term.loinc.LoincRsnaPlaybookHandler;
|
||||||
|
@ -158,8 +159,22 @@ public class TerminologyLoaderSvcLoincTest {
|
||||||
assertEquals("420710006", group.getElement().get(0).getTarget().get(0).getCode());
|
assertEquals("420710006", group.getElement().get(0).getTarget().get(0).getCode());
|
||||||
assertEquals("Interferon beta (substance)", group.getElement().get(0).getTarget().get(0).getDisplay());
|
assertEquals("Interferon beta (substance)", group.getElement().get(0).getTarget().get(0).getDisplay());
|
||||||
|
|
||||||
// Document Ontology Parts
|
// Document Ontology ValueSet
|
||||||
|
vs = valueSets.get(LoincDocumentOntologyHandler.DOCUMENT_ONTOLOGY_CODES_VS_ID);
|
||||||
|
assertEquals(LoincDocumentOntologyHandler.DOCUMENT_ONTOLOGY_CODES_VS_NAME, vs.getName());
|
||||||
|
assertEquals(LoincDocumentOntologyHandler.DOCUMENT_ONTOLOGY_CODES_VS_URI, vs.getUrl());
|
||||||
|
assertEquals(1, vs.getCompose().getInclude().size());
|
||||||
|
assertEquals(IHapiTerminologyLoaderSvc.LOINC_URL, vs.getCompose().getInclude().get(0).getSystem());
|
||||||
|
assertEquals(3, vs.getCompose().getInclude().get(0).getConcept().size());
|
||||||
|
assertEquals("11488-4", vs.getCompose().getInclude().get(0).getConcept().get(0).getCode());
|
||||||
|
assertEquals("Consult note", vs.getCompose().getInclude().get(0).getConcept().get(0).getDisplay());
|
||||||
|
|
||||||
|
// Document ontology parts
|
||||||
|
code = concepts.get("11488-4");
|
||||||
|
assertEquals(1, code.getCodingProperties("document-kind").size());
|
||||||
|
assertEquals(IHapiTerminologyLoaderSvc.LOINC_URL, code.getCodingProperties("document-kind").get(0).getSystem());
|
||||||
|
assertEquals("LP173418-7", code.getCodingProperties("document-kind").get(0).getCode());
|
||||||
|
assertEquals("Note", code.getCodingProperties("document-kind").get(0).getDisplay());
|
||||||
|
|
||||||
// RSNA Playbook ValueSet
|
// RSNA Playbook ValueSet
|
||||||
vs = valueSets.get(LoincRsnaPlaybookHandler.RSNA_CODES_VS_ID);
|
vs = valueSets.get(LoincRsnaPlaybookHandler.RSNA_CODES_VS_ID);
|
||||||
|
|
|
@ -13,3 +13,4 @@
|
||||||
"17787-3" ,"Study report" ,"Find" ,"Pt" ,"Neck>Thyroid gland","Doc" ,"NM" ,"RAD" ,"2.61" ,"MIN" , ,"ACTIVE", ,2 , , , , , , , ,"Document; Finding; Findings; Imaging; Point in time; Radiology; Random; Study report; Thy" ,"NM Thyroid Study report" ,"Both" , , , , ,"NM Thyroid gland Study report" , , , , , , ,"Changed System from ""Thyroid"" for conformance with the LOINC/RadLex unified model.; Method of ""Radnuc"" was changed to ""NM"". The LOINC/RadLex Committee agreed to use a subset of the two-letter DICOM modality codes as the primary modality identifier." ,0 ,0 ,0 ,"IG exists" , , , ,"81220-6;72230-6" ,"1.0l" ,
|
"17787-3" ,"Study report" ,"Find" ,"Pt" ,"Neck>Thyroid gland","Doc" ,"NM" ,"RAD" ,"2.61" ,"MIN" , ,"ACTIVE", ,2 , , , , , , , ,"Document; Finding; Findings; Imaging; Point in time; Radiology; Random; Study report; Thy" ,"NM Thyroid Study report" ,"Both" , , , , ,"NM Thyroid gland Study report" , , , , , , ,"Changed System from ""Thyroid"" for conformance with the LOINC/RadLex unified model.; Method of ""Radnuc"" was changed to ""NM"". The LOINC/RadLex Committee agreed to use a subset of the two-letter DICOM modality codes as the primary modality identifier." ,0 ,0 ,0 ,"IG exists" , , , ,"81220-6;72230-6" ,"1.0l" ,
|
||||||
"17788-1" ,"Large unstained cells/100 leukocytes" ,"NFr" ,"Pt" ,"Bld" ,"Qn" ,"Automated count","HEM/BC" ,"2.50" ,"MIN" ,"Part of auto diff output of Bayer H*3S; peroxidase negative cells too large to be classified as lymph or basophil","ACTIVE", ,1 , , , , , ,"Y" ,"%" ,"100WBC; Auto; Automated detection; Blood; Cell; Cellularity; Elec; Elect; Electr; HEMATOLOGY/CELL COUNTS; Leuc; Leuk; Leukocyte; Lkcs; LUC; Number Fraction; Percent; Point in time; QNT; Quan; Quant; Quantitative; Random; WB; WBC; WBCs; White blood cell; White blood cells; Whole blood","LUC/leuk NFr Bld Auto" ,"Observation", , , ,"%" ,"Large unstained cells/100 leukocytes in Blood by Automated count" , , ,"%" , , , , ,1894 ,0 ,1894 , , , , , ,"1.0l" ,
|
"17788-1" ,"Large unstained cells/100 leukocytes" ,"NFr" ,"Pt" ,"Bld" ,"Qn" ,"Automated count","HEM/BC" ,"2.50" ,"MIN" ,"Part of auto diff output of Bayer H*3S; peroxidase negative cells too large to be classified as lymph or basophil","ACTIVE", ,1 , , , , , ,"Y" ,"%" ,"100WBC; Auto; Automated detection; Blood; Cell; Cellularity; Elec; Elect; Electr; HEMATOLOGY/CELL COUNTS; Leuc; Leuk; Leukocyte; Lkcs; LUC; Number Fraction; Percent; Point in time; QNT; Quan; Quant; Quantitative; Random; WB; WBC; WBCs; White blood cell; White blood cells; Whole blood","LUC/leuk NFr Bld Auto" ,"Observation", , , ,"%" ,"Large unstained cells/100 leukocytes in Blood by Automated count" , , ,"%" , , , , ,1894 ,0 ,1894 , , , , , ,"1.0l" ,
|
||||||
"11488-4" ,"Consultation note" ,"Find" ,"Pt" ,"{Setting}" ,"Doc" ,"{Role}" ,"DOC.ONTOLOGY","2.63" ,"MIN" , ,"ACTIVE", ,2 , , , , , , , ,"Consult note; DOC.ONT; Document; Encounter; Evaluation and management; Evaluation and management note; Finding; Findings; notes; Point in time; Random; Visit note" ,"Consult note" ,"Both" , , , , ,"Consult note" , , , , , , ,"Edit made because this term is conformant to the Document Ontology axis values and therefore are being placed in this class.; Based on Clinical LOINC Committee decision during the September 2014 meeting, {Provider} was changed to {Author Type} to emphasize a greater breadth of potential document authors. At the September 2015 Clinical LOINC Committee meeting, the Committee decided to change {Author Type} to {Role} to align with the 'Role' axis name in the LOINC Document Ontology.; Because it is too difficult to maintain and because the distinction between documents and sections is not clear-cut nor necessary in most cases, the DOCUMENT_SECTION field has been deemed to have little value. The field has been set to null in the December 2017 release in preparation for removal in the December 2018 release. These changes were approved by the Clinical LOINC Committee.",0 ,0 ,0 ,"IG exists" , , , ,"81222-2;72231-4;81243-8","1.0j-a" ,"Y"
|
"11488-4" ,"Consultation note" ,"Find" ,"Pt" ,"{Setting}" ,"Doc" ,"{Role}" ,"DOC.ONTOLOGY","2.63" ,"MIN" , ,"ACTIVE", ,2 , , , , , , , ,"Consult note; DOC.ONT; Document; Encounter; Evaluation and management; Evaluation and management note; Finding; Findings; notes; Point in time; Random; Visit note" ,"Consult note" ,"Both" , , , , ,"Consult note" , , , , , , ,"Edit made because this term is conformant to the Document Ontology axis values and therefore are being placed in this class.; Based on Clinical LOINC Committee decision during the September 2014 meeting, {Provider} was changed to {Author Type} to emphasize a greater breadth of potential document authors. At the September 2015 Clinical LOINC Committee meeting, the Committee decided to change {Author Type} to {Role} to align with the 'Role' axis name in the LOINC Document Ontology.; Because it is too difficult to maintain and because the distinction between documents and sections is not clear-cut nor necessary in most cases, the DOCUMENT_SECTION field has been deemed to have little value. The field has been set to null in the December 2017 release in preparation for removal in the December 2018 release. These changes were approved by the Clinical LOINC Committee.",0 ,0 ,0 ,"IG exists" , , , ,"81222-2;72231-4;81243-8","1.0j-a" ,"Y"
|
||||||
|
|
||||||
|
|
Can't render this file because it contains an unexpected character in line 1 and column 23.
|
Loading…
Reference in New Issue