Skip to content

Commit

Permalink
Merge pull request #1453 from CDCgov/add-mpsii-comments-mapping
Browse files Browse the repository at this point in the history
Add 99717-49 Local Code to 76030-6 LOINC mapping
  • Loading branch information
luis-pabon-tf authored Oct 24, 2024
2 parents 1ec2d91 + 4eb0e20 commit 8cc3e9c
Show file tree
Hide file tree
Showing 3 changed files with 281 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,52 +23,61 @@
public class MapLocalObservationCodes implements CustomFhirTransformation {
protected final Logger logger = ApplicationContext.getImplementation(Logger.class);

private HashMap<String, IdentifierCode> codingMap;

public MapLocalObservationCodes() {
initMap();
}

@Override
public void transform(HealthData<?> resource, Map<String, Object> args) {
var codingMap = getMapFromArgs(args);

var bundle = (Bundle) resource.getUnderlyingData();
var msh41Identifier =
HapiHelper.getMSH4_1Identifier(bundle) != null
? HapiHelper.getMSH4_1Identifier(bundle).getValue()
: null;
var messageId = HapiHelper.getMessageControlId(bundle);
var observations = HapiHelper.resourcesInBundle(bundle, Observation.class);

for (Observation obv : observations.toList()) {
var codingList = obv.getCode().getCoding();

if (codingList.size() != 1) {
continue;
}

var coding = codingList.get(0);
if (!HapiHelper.hasDefinedCoding(
coding, HapiHelper.EXTENSION_ALT_CODING, HapiHelper.LOCAL_CODE)) {
continue;
}
observations
.filter(this::hasValidCoding)
.forEach(
observation ->
processCoding(observation, codingMap, msh41Identifier, messageId));
}

var identifier = codingMap.get(coding.getCode());
if (identifier == null) {
logUnmappedLocalCode(bundle, coding);
continue;
}
private boolean hasValidCoding(Observation observation) {
var codingList = observation.getCode().getCoding();
return codingList.size() == 1 && isLocalCode(codingList.get(0));
}

var mappedCoding = getMappedCoding(identifier);
private boolean isLocalCode(Coding coding) {
return HapiHelper.hasDefinedCoding(
coding, HapiHelper.EXTENSION_ALT_CODING, HapiHelper.LOCAL_CODE);
}

// Add the mapped code as the first in the list, ahead of the existing alternate code
codingList.add(0, mappedCoding);
private void processCoding(
Observation observation,
Map<String, IdentifierCode> codingMap,
String msh41Identifier,
String messageId) {
var originalCoding = observation.getCode().getCoding().get(0);
IdentifierCode identifier = codingMap.get(originalCoding.getCode());

if (identifier == null) {
logger.logWarning(
"Unmapped local code detected: '{}', from sender: '{}', message Id: '{}'",
originalCoding.getCode(),
msh41Identifier,
messageId);
return;
}
}

private void logUnmappedLocalCode(Bundle bundle, Coding coding) {
var msh41Identifier = HapiHelper.getMSH4_1Identifier(bundle);
var msh41Value = msh41Identifier != null ? msh41Identifier.getValue() : null;
var mappedCoding = getMappedCoding(identifier);
observation.getCode().getCoding().add(0, mappedCoding);
}

logger.logWarning(
"Unmapped local code detected: '{}', from sender: '{}', message Id: '{}'",
coding.getCode(),
msh41Value,
HapiHelper.getMessageControlId(bundle));
private String validateField(String field, String fieldName) {
if (field == null || field.isBlank()) {
throw new IllegalArgumentException("missing or empty required field " + fieldName);
}
return field;
}

private Coding getMappedCoding(IdentifierCode identifierCode) {
Expand All @@ -85,92 +94,30 @@ private Coding getMappedCoding(IdentifierCode identifierCode) {
return mappedCoding;
}

/**
* Initializes the local-to-LOINC/PLT hash map, customized for CDPH and UCSD. Currently, the
* mapping is hardcoded for simplicity. If expanded to support additional entities, the
* implementation may be updated to allow dynamic configuration via
* transformation_definitions.json or a database-driven mapping.
*/
private void initMap() {
this.codingMap = new HashMap<>();
// ALD
codingMap.put(
"99717-32",
new IdentifierCode(
"85269-9",
"X-linked Adrenoleukodystrophy (X- ALD) newborn screen interpretation",
HapiHelper.LOINC_CODE));
codingMap.put(
"99717-33",
new IdentifierCode(
"85268-1",
"X-linked Adrenoleukodystrophy (X- ALD) newborn screening comment-discussion",
HapiHelper.LOINC_CODE));
codingMap.put(
"99717-34",
new IdentifierCode(
"PLT325",
"ABCD1 gene mutation found [Identifier] in DBS by Sequencing",
HapiHelper.PLT_CODE));
// CAH
codingMap.put(
"99717-6",
new IdentifierCode(
"53340-6",
"17-Hydroxyprogesterone [Moles/volume] in DBS",
HapiHelper.LOINC_CODE));
// CF
codingMap.put(
"99717-35",
new IdentifierCode(
"PLT3289",
"CFTR gene mutation found [Interpretation] in DBS by Sequencing",
HapiHelper.PLT_CODE));
codingMap.put(
"99717-36",
new IdentifierCode(
"PLT3290",
"CFTR gene variant found [Identifier] in DBS by Sequencing comments/discussion",
HapiHelper.PLT_CODE));
// MPS I
codingMap.put(
"99717-48",
new IdentifierCode(
"PLT3258",
"IDUA gene mutations found [Identifier] in DBS by Sequencing",
HapiHelper.PLT_CODE));
codingMap.put(
"99717-44",
new IdentifierCode(
"PLT3291",
"IDUA gene variant analysis in DBS by Sequencing comments/discussion",
HapiHelper.PLT_CODE));
// MPS II
codingMap.put(
"99717-50",
new IdentifierCode(
"PLT3294",
"IDS gene mutations found [Identifier] in Dried Bloodspot by Molecular genetics method",
HapiHelper.PLT_CODE));
// Pompe
codingMap.put(
"99717-47",
new IdentifierCode(
"PLT3252",
"GAA gene mutation found [Identifier] in DBS by Sequencing",
HapiHelper.PLT_CODE));
codingMap.put(
"99717-46",
new IdentifierCode(
"PLT3292",
"GAA gene variant analysis in DBS by Sequencing comments/discussion",
HapiHelper.PLT_CODE));
// SMA
codingMap.put(
"99717-60",
new IdentifierCode(
"PLT3293",
"SMN1 exon 7 deletion analysis in DBS by Sequencing",
HapiHelper.PLT_CODE));
private Map<String, IdentifierCode> getMapFromArgs(Map<String, Object> args) {
var codingMap = new HashMap<String, IdentifierCode>();

// Suppressing the unchecked cast warning. The assignment below will throw a
// ClassCastException if it fails.
@SuppressWarnings("unchecked")
var argsCodingMap = (Map<String, Map<String, String>>) args.get("codingMap");

for (Map.Entry<String, Map<String, String>> entry : argsCodingMap.entrySet()) {
var localCode = entry.getKey();
var mappedCode = getIdentifierCode(entry);

codingMap.put(localCode, mappedCode);
}

return codingMap;
}

private IdentifierCode getIdentifierCode(Map.Entry<String, Map<String, String>> entry) {
var value = entry.getValue();
var code = validateField(value.get("code"), "code");
var display = validateField(value.get("display"), "display");
var codingSystem = validateField(value.get("codingSystem"), "codingSystem");

return new IdentifierCode(code, display, codingSystem);
}
}
70 changes: 69 additions & 1 deletion etor/src/main/resources/transformation_definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,75 @@
"rules": [
{
"name": "MapLocalObservationCodes",
"args": {}
"args": {
"codingMap" : {
"99717-6": {
"code": "53340-6",
"display": "17-Hydroxyprogesterone [Moles/volume] in DBS",
"codingSystem": "LN"
},
"99717-32": {
"code": "85269-9",
"display": "X-linked Adrenoleukodystrophy (X- ALD) newborn screen interpretation",
"codingSystem": "LN"
},
"99717-33": {
"code": "85268-1",
"display": "X-linked Adrenoleukodystrophy (X- ALD) newborn screening comment-discussion",
"codingSystem": "LN"
},
"99717-34": {
"code": "PLT325",
"display": "ABCD1 gene mutation found [Identifier] in DBS by Sequencing",
"codingSystem": "PLT"
},
"99717-35": {
"code": "PLT3289",
"display": "CFTR gene mutation found [Interpretation] in DBS by Sequencing",
"codingSystem": "PLT"
},
"99717-36": {
"code": "PLT3290",
"display": "CFTR gene variant found [Identifier] in DBS by Sequencing comments/discussion",
"codingSystem": "PLT"
},
"99717-44": {
"code": "PLT3291",
"display": "IDUA gene variant analysis in DBS by Sequencing comments/discussion",
"codingSystem": "PLT"
},
"99717-46": {
"code": "PLT3292",
"display": "GAA gene variant analysis in DBS by Sequencing comments/discussion",
"codingSystem": "PLT"
},
"99717-47": {
"code": "PLT3252",
"display": "GAA gene mutation found [Identifier] in DBS by Sequencing",
"codingSystem": "PLT"
},
"99717-48": {
"code": "PLT3258",
"display": "IDUA gene mutations found [Identifier] in DBS by Sequencing",
"codingSystem": "PLT"
},
"99717-49": {
"code": "76030-6",
"display": "IDS gene full mutation analysis in Blood or Tissue by Sequencing",
"codingSystem": "LN"
},
"99717-50": {
"code": "PLT3294",
"display": "IDS gene mutations found [Identifier] in Dried Bloodspot by Molecular genetics method",
"codingSystem": "PLT"
},
"99717-60": {
"code": "PLT3293",
"display": "SMN1 exon 7 deletion analysis in DBS by Sequencing",
"codingSystem": "PLT"
}
}
}
}
]
},
Expand Down
Loading

0 comments on commit 8cc3e9c

Please sign in to comment.