This material contains content that is copyright of SNOMED International. Implementers of these specifications must have the appropriate SNOMED CT Affiliate license - for more information contact https://www.snomed.org/get-snomed
or info@snomed.org
.
Using RxNorm codes of type SAB=RXNORM as this specification describes does not require a UMLS license. Access to the full set of RxNorm definitions, and/or additional use of other RxNorm structures and information requires a UMLS license. The use of RxNorm in this specification is pursuant to HL7's status as a licensee of the NLM UMLS. HL7's license does not convey the right to use RxNorm to any users of this specification; implementers must acquire a license to use RxNorm in their own right.
2022 CDC Clinical Practice Guideline for Prescribing Opioids Implementation Guide, published by CDC / Security Risk Solutions, Inc. (SRS). This guide is not an authorized publication; it is the continuous build for version 2022.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/security-rs/opioid-cds-r4/ and changes regularly. See the Directory of published versions ( src
)
define function ToConcept(concept FHIR.CodeableConcept):
if concept is null then
null
else
System.Concept {
codes: concept.coding C return ToCode(C),
display: concept.text.value
} ( src
)
library FHIRHelpers version '4.0.1'
using FHIR version '4.0.1'
define function ToInterval(period FHIR.Period):
if period is null then
null
else
if period."start" is null then
Interval(period."start".value, period."end".value]
else
Interval[period."start".value, period."end".value]
define function ToCalendarUnit(unit System.String):
case unit
when 'ms' then 'millisecond'
when 's' then 'second'
when 'min' then 'minute'
when 'h' then 'hour'
when 'd' then 'day'
when 'wk' then 'week'
when 'mo' then 'month'
when 'a' then 'year'
else unit
end
define function ToQuantity(quantity FHIR.Quantity):
case
when quantity is null then null
when quantity.value is null then null
when quantity.comparator is not null then
Message(null, true, 'FHIRHelpers.ToQuantity.ComparatorQuantityNotSupported', 'Error', 'FHIR Quantity value has a comparator and cannot be converted to a System.Quantity value.')
when quantity.system is null or quantity.system.value = 'http://unitsofmeasure.org'
or quantity.system.value = 'http://hl7.org/fhirpath/CodeSystem/calendar-units' then
System.Quantity { value: quantity.value.value, unit: ToCalendarUnit(Coalesce(quantity.code.value, quantity.unit.value, '1')) }
else
Message(null, true, 'FHIRHelpers.ToQuantity.InvalidFHIRQuantity', 'Error', 'Invalid FHIR Quantity code: ' & quantity.unit.value & ' (' & quantity.system.value & '|' & quantity.code.value & ')')
end
define function ToQuantityIgnoringComparator(quantity FHIR.Quantity):
case
when quantity is null then null
when quantity.value is null then null
when quantity.system is null or quantity.system.value = 'http://unitsofmeasure.org'
or quantity.system.value = 'http://hl7.org/fhirpath/CodeSystem/calendar-units' then
System.Quantity { value: quantity.value.value, unit: ToCalendarUnit(Coalesce(quantity.code.value, quantity.unit.value, '1')) }
else
Message(null, true, 'FHIRHelpers.ToQuantity.InvalidFHIRQuantity', 'Error', 'Invalid FHIR Quantity code: ' & quantity.unit.value & ' (' & quantity.system.value & '|' & quantity.code.value & ')')
end
define function ToInterval(quantity FHIR.Quantity):
if quantity is null then null else
case quantity.comparator.value
when '<' then
Interval[
null,
ToQuantityIgnoringComparator(quantity)
)
when '<=' then
Interval[
null,
ToQuantityIgnoringComparator(quantity)
]
when '>=' then
Interval[
ToQuantityIgnoringComparator(quantity),
null
]
when '>' then
Interval(
ToQuantityIgnoringComparator(quantity),
null
]
else
Interval[ToQuantity(quantity), ToQuantity(quantity)]
end
define function ToRatio(ratio FHIR.Ratio):
if ratio is null then
null
else
System.Ratio { numerator: ToQuantity(ratio.numerator), denominator: ToQuantity(ratio.denominator) }
define function ToInterval(range FHIR.Range):
if range is null then
null
else
Interval[ToQuantity(range.low), ToQuantity(range.high)]
define function ToCode(coding FHIR.Coding):
if coding is null then
null
else
System.Code {
code: coding.code.value,
system: coding.system.value,
version: coding.version.value,
display: coding.display.value
}
define function ToConcept(concept FHIR.CodeableConcept):
if concept is null then
null
else
System.Concept {
codes: concept.coding C return ToCode(C),
display: concept.text.value
}
define function ToString(value AccountStatus): value.value
define function ToString(value ActionCardinalityBehavior): value.value
define function ToString(value ActionConditionKind): value.value
define function ToString(value ActionGroupingBehavior): value.value
define function ToString(value ActionParticipantType): value.value
define function ToString(value ActionPrecheckBehavior): value.value
define function ToString(value ActionRelationshipType): value.value
define function ToString(value ActionRequiredBehavior): value.value
define function ToString(value ActionSelectionBehavior): value.value
define function ToString(value ActivityDefinitionKind): value.value
define function ToString(value ActivityParticipantType): value.value
define function ToString(value AddressType): value.value
define function ToString(value AddressUse): value.value
define function ToString(value AdministrativeGender): value.value
define function ToString(value AdverseEventActuality): value.value
define function ToString(value AggregationMode): value.value
define function ToString(value AllergyIntoleranceCategory): value.value
define function ToString(value AllergyIntoleranceCriticality): value.value
define function ToString(value AllergyIntoleranceSeverity): value.value
define function ToString(value AllergyIntoleranceType): value.value
define function ToString(value AppointmentStatus): value.value
define function ToString(value AssertionDirectionType): value.value
define function ToString(value AssertionOperatorType): value.value
define function ToString(value AssertionResponseTypes): value.value
define function ToString(value AuditEventAction): value.value
define function ToString(value AuditEventAgentNetworkType): value.value
define function ToString(value AuditEventOutcome): value.value
define function ToString(value BindingStrength): value.value
define function ToString(value BiologicallyDerivedProductCategory): value.value
define function ToString(value BiologicallyDerivedProductStatus): value.value
define function ToString(value BiologicallyDerivedProductStorageScale): value.value
define function ToString(value BundleType): value.value
define function ToString(value CapabilityStatementKind): value.value
define function ToString(value CarePlanActivityKind): value.value
define function ToString(value CarePlanActivityStatus): value.value
define function ToString(value CarePlanIntent): value.value
define function ToString(value CarePlanStatus): value.value
define function ToString(value CareTeamStatus): value.value
define function ToString(value CatalogEntryRelationType): value.value
define function ToString(value ChargeItemDefinitionPriceComponentType): value.value
define function ToString(value ChargeItemStatus): value.value
define function ToString(value ClaimResponseStatus): value.value
define function ToString(value ClaimStatus): value.value
define function ToString(value ClinicalImpressionStatus): value.value
define function ToString(value CodeSearchSupport): value.value
define function ToString(value CodeSystemContentMode): value.value
define function ToString(value CodeSystemHierarchyMeaning): value.value
define function ToString(value CommunicationPriority): value.value
define function ToString(value CommunicationRequestStatus): value.value
define function ToString(value CommunicationStatus): value.value
define function ToString(value CompartmentCode): value.value
define function ToString(value CompartmentType): value.value
define function ToString(value CompositionAttestationMode): value.value
define function ToString(value CompositionStatus): value.value
define function ToString(value ConceptMapEquivalence): value.value
define function ToString(value ConceptMapGroupUnmappedMode): value.value
define function ToString(value ConditionalDeleteStatus): value.value
define function ToString(value ConditionalReadStatus): value.value
define function ToString(value ConsentDataMeaning): value.value
define function ToString(value ConsentProvisionType): value.value
define function ToString(value ConsentState): value.value
define function ToString(value ConstraintSeverity): value.value
define function ToString(value ContactPointSystem): value.value
define function ToString(value ContactPointUse): value.value
define function ToString(value ContractPublicationStatus): value.value
define function ToString(value ContractStatus): value.value
define function ToString(value ContributorType): value.value
define function ToString(value CoverageStatus): value.value
define function ToString(value CurrencyCode): value.value
define function ToString(value DayOfWeek): value.value
define function ToString(value DaysOfWeek): value.value
define function ToString(value DetectedIssueSeverity): value.value
define function ToString(value DetectedIssueStatus): value.value
define function ToString(value DeviceMetricCalibrationState): value.value
define function ToString(value DeviceMetricCalibrationType): value.value
define function ToString(value DeviceMetricCategory): value.value
define function ToString(value DeviceMetricColor): value.value
define function ToString(value DeviceMetricOperationalStatus): value.value
define function ToString(value DeviceNameType): value.value
define function ToString(value DeviceRequestStatus): value.value
define function ToString(value DeviceUseStatementStatus): value.value
define function ToString(value DiagnosticReportStatus): value.value
define function ToString(value DiscriminatorType): value.value
define function ToString(value DocumentConfidentiality): value.value
define function ToString(value DocumentMode): value.value
define function ToString(value DocumentReferenceStatus): value.value
define function ToString(value DocumentRelationshipType): value.value
define function ToString(value EligibilityRequestPurpose): value.value
define function ToString(value EligibilityRequestStatus): value.value
define function ToString(value EligibilityResponsePurpose): value.value
define function ToString(value EligibilityResponseStatus): value.value
define function ToString(value EnableWhenBehavior): value.value
define function ToString(value EncounterLocationStatus): value.value
define function ToString(value EncounterStatus): value.value
define function ToString(value EndpointStatus): value.value
define function ToString(value EnrollmentRequestStatus): value.value
define function ToString(value EnrollmentResponseStatus): value.value
define function ToString(value EpisodeOfCareStatus): value.value
define function ToString(value EventCapabilityMode): value.value
define function ToString(value EventTiming): value.value
define function ToString(value EvidenceVariableType): value.value
define function ToString(value ExampleScenarioActorType): value.value
define function ToString(value ExplanationOfBenefitStatus): value.value
define function ToString(value ExposureState): value.value
define function ToString(value ExtensionContextType): value.value
define function ToString(value FHIRAllTypes): value.value
define function ToString(value FHIRDefinedType): value.value
define function ToString(value FHIRDeviceStatus): value.value
define function ToString(value FHIRResourceType): value.value
define function ToString(value FHIRSubstanceStatus): value.value
define function ToString(value FHIRVersion): value.value
define function ToString(value FamilyHistoryStatus): value.value
define function ToString(value FilterOperator): value.value
define function ToString(value FlagStatus): value.value
define function ToString(value GoalLifecycleStatus): value.value
define function ToString(value GraphCompartmentRule): value.value
define function ToString(value GraphCompartmentUse): value.value
define function ToString(value GroupMeasure): value.value
define function ToString(value GroupType): value.value
define function ToString(value GuidanceResponseStatus): value.value
define function ToString(value GuidePageGeneration): value.value
define function ToString(value GuideParameterCode): value.value
define function ToString(value HTTPVerb): value.value
define function ToString(value IdentifierUse): value.value
define function ToString(value IdentityAssuranceLevel): value.value
define function ToString(value ImagingStudyStatus): value.value
define function ToString(value ImmunizationEvaluationStatus): value.value
define function ToString(value ImmunizationStatus): value.value
define function ToString(value InvoicePriceComponentType): value.value
define function ToString(value InvoiceStatus): value.value
define function ToString(value IssueSeverity): value.value
define function ToString(value IssueType): value.value
define function ToString(value LinkType): value.value
define function ToString(value LinkageType): value.value
define function ToString(value ListMode): value.value
define function ToString(value ListStatus): value.value
define function ToString(value LocationMode): value.value
define function ToString(value LocationStatus): value.value
define function ToString(value MeasureReportStatus): value.value
define function ToString(value MeasureReportType): value.value
define function ToString(value MediaStatus): value.value
define function ToString(value MedicationAdministrationStatus): value.value
define function ToString(value MedicationDispenseStatus): value.value
define function ToString(value MedicationKnowledgeStatus): value.value
define function ToString(value MedicationRequestIntent): value.value
define function ToString(value MedicationRequestPriority): value.value
define function ToString(value MedicationRequestStatus): value.value
define function ToString(value MedicationStatementStatus): value.value
define function ToString(value MedicationStatus): value.value
define function ToString(value MessageSignificanceCategory): value.value
define function ToString(value Messageheader_Response_Request): value.value
define function ToString(value MimeType): value.value
define function ToString(value NameUse): value.value
define function ToString(value NamingSystemIdentifierType): value.value
define function ToString(value NamingSystemType): value.value
define function ToString(value NarrativeStatus): value.value
define function ToString(value NoteType): value.value
define function ToString(value NutritiionOrderIntent): value.value
define function ToString(value NutritionOrderStatus): value.value
define function ToString(value ObservationDataType): value.value
define function ToString(value ObservationRangeCategory): value.value
define function ToString(value ObservationStatus): value.value
define function ToString(value OperationKind): value.value
define function ToString(value OperationParameterUse): value.value
define function ToString(value OrientationType): value.value
define function ToString(value ParameterUse): value.value
define function ToString(value ParticipantRequired): value.value
define function ToString(value ParticipantStatus): value.value
define function ToString(value ParticipationStatus): value.value
define function ToString(value PaymentNoticeStatus): value.value
define function ToString(value PaymentReconciliationStatus): value.value
define function ToString(value ProcedureStatus): value.value
define function ToString(value PropertyRepresentation): value.value
define function ToString(value PropertyType): value.value
define function ToString(value ProvenanceEntityRole): value.value
define function ToString(value PublicationStatus): value.value
define function ToString(value QualityType): value.value
define function ToString(value QuantityComparator): value.value
define function ToString(value QuestionnaireItemOperator): value.value
define function ToString(value QuestionnaireItemType): value.value
define function ToString(value QuestionnaireResponseStatus): value.value
define function ToString(value ReferenceHandlingPolicy): value.value
define function ToString(value ReferenceVersionRules): value.value
define function ToString(value ReferredDocumentStatus): value.value
define function ToString(value RelatedArtifactType): value.value
define function ToString(value RemittanceOutcome): value.value
define function ToString(value RepositoryType): value.value
define function ToString(value RequestIntent): value.value
define function ToString(value RequestPriority): value.value
define function ToString(value RequestStatus): value.value
define function ToString(value ResearchElementType): value.value
define function ToString(value ResearchStudyStatus): value.value
define function ToString(value ResearchSubjectStatus): value.value
define function ToString(value ResourceType): value.value
define function ToString(value ResourceVersionPolicy): value.value
define function ToString(value ResponseType): value.value
define function ToString(value RestfulCapabilityMode): value.value
define function ToString(value RiskAssessmentStatus): value.value
define function ToString(value SPDXLicense): value.value
define function ToString(value SearchComparator): value.value
define function ToString(value SearchEntryMode): value.value
define function ToString(value SearchModifierCode): value.value
define function ToString(value SearchParamType): value.value
define function ToString(value SectionMode): value.value
define function ToString(value SequenceType): value.value
define function ToString(value ServiceRequestIntent): value.value
define function ToString(value ServiceRequestPriority): value.value
define function ToString(value ServiceRequestStatus): value.value
define function ToString(value SlicingRules): value.value
define function ToString(value SlotStatus): value.value
define function ToString(value SortDirection): value.value
define function ToString(value SpecimenContainedPreference): value.value
define function ToString(value SpecimenStatus): value.value
define function ToString(value Status): value.value
define function ToString(value StrandType): value.value
define function ToString(value StructureDefinitionKind): value.value
define function ToString(value StructureMapContextType): value.value
define function ToString(value StructureMapGroupTypeMode): value.value
define function ToString(value StructureMapInputMode): value.value
define function ToString(value StructureMapModelMode): value.value
define function ToString(value StructureMapSourceListMode): value.value
define function ToString(value StructureMapTargetListMode): value.value
define function ToString(value StructureMapTransform): value.value
define function ToString(value SubscriptionChannelType): value.value
define function ToString(value SubscriptionStatus): value.value
define function ToString(value SupplyDeliveryStatus): value.value
define function ToString(value SupplyRequestStatus): value.value
define function ToString(value SystemRestfulInteraction): value.value
define function ToString(value TaskIntent): value.value
define function ToString(value TaskPriority): value.value
define function ToString(value TaskStatus): value.value
define function ToString(value TestReportActionResult): value.value
define function ToString(value TestReportParticipantType): value.value
define function ToString(value TestReportResult): value.value
define function ToString(value TestReportStatus): value.value
define function ToString(value TestScriptRequestMethodCode): value.value
define function ToString(value TriggerType): value.value
define function ToString(value TypeDerivationRule): value.value
define function ToString(value TypeRestfulInteraction): value.value
define function ToString(value UDIEntryType): value.value
define function ToString(value UnitsOfTime): value.value
define function ToString(value Use): value.value
define function ToString(value VariableType): value.value
define function ToString(value VisionBase): value.value
define function ToString(value VisionEyes): value.value
define function ToString(value VisionStatus): value.value
define function ToString(value XPathUsageType): value.value
define function ToString(value base64Binary): value.value
define function ToBoolean(value boolean): value.value
define function ToDate(value date): value.value
define function ToDateTime(value dateTime): value.value
define function ToDecimal(value decimal): value.value
define function ToDateTime(value instant): value.value
define function ToInteger(value integer): value.value
define function ToString(value string): value.value
define function ToTime(value time): value.value
define function ToString(value uri): value.value
define function ToString(value xhtml): value.value
( src
)
library OMTKLogic version '3.0.0'
/*
This library provides functionality for calculating Morphine Milligram
Equivalents (MME) for opioid medications, as described in the 2022 CDC Clinical Practice Guideline.
The functionality in this library was developed based on the Java-based
implementation described [here](http://build.fhir.org/ig/cqframework/opioid-cds-r4/service-documentation.html#solution-component-3-core-logic-processing-java-class),
as well as the MME conversion calculation published as part of the 2022 CDC Clinical Practice Guideline.
Note that the logic in this library (and specifically the conversion factors captured here)
are based on the 2016 version of the publication available from the CDC here:
https://www.cdc.gov/drugoverdose/modules/data-files.html
National Center for Injury Prevention and Control. CDC compilation of benzodiazepines,
muscle relaxants, stimulants, zolpidem, and opioid analgesics with oral morphine milligram
equivalent conversion factors, 2018 version. Atlanta, GA: Centers for Disease Control
and Prevention; 2018. Available at https://www.cdc.gov/drugoverdose/resources/data.html
This version of the OMTKLogic library uses the OMTKData library as the
source for drug ingredient and strength information, rather than the
OMTK data source. This library has no external dependencies and so
can run in an environment that supports pure CQL.
NOTE: For performance, all terminology comparisons in this library use
direct integer comparison of the RxNorm codes.
This product uses publicly available data courtesy of the U.S. National Library of Medicine (NLM),
National Institutes of Health, Department of Health and Human Services; NLM is not responsible for
the product and does not endorse or recommend this or any other product.
Nelson SJ, Zeng K, Kilbourne J, Powell T, Moore R. Normalized names for clinical drugs: RxNorm at 6 years.
J Am Med Inform Assoc. 2011 Jul-Aug;18(4)441-8. doi: 10.1136/amiajnl-2011-000116.
Epub 2011 Apr 21. PubMed PMID: 21515544; PubMed Central PMCID: PMC3128404.
[Full text](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3128404/)
*/
include OMTKData version '3.0.0' called OMTKData
include ConversionFactors version '3.0.0' called ConversionFactors
codesystem "RXNORM": 'http://www.nlm.nih.gov/research/umls/rxnorm'
parameter ErrorLevel String default 'Warning'
define function Msg(code String, errorLevel String, message String):
{
code: code,
errorLevel: errorLevel,
message: message
}
/*
Normalizes the input units to UCUM units
The values listed here are the only ones currently present in the OMTK data
Based on the HL7 UCUM subset here:
http://download.hl7.de/documents/ucum/ucumdata.html
*/
define function ToUCUM(unit String):
case unit
when 'MG' then 'mg'
when 'MG/ACTUAT' then 'mg/{actuat}'
when 'MG/HR' then 'mg/h'
when 'MG/ML' then 'mg/mL'
else Message(null, true, 'OMTKLogic.ToUCUM.UnknownUnit', ErrorLevel, 'Unknown unit ' & unit)
end
define function ToUCUM_Msg(unit String):
unit U
let result: ToUCUM(U)
return {
result: result,
message:
if result is null then
Msg('OMTKLogic.ToUCUM.UnknownUnit', ErrorLevel, 'Unknown unit' & unit)
else
null
}
/*
Calculates daily frequency given frequency within a period
*/
define function ToDaily(frequency Integer, period Quantity):
case period.unit
when 'h' then frequency * (24.0 / period.value)
when 'min' then frequency * (24.0 / period.value) * 60
when 's' then frequency * (24.0 / period.value) * 60 * 60
when 'd' then frequency * (24.0 / period.value) / 24
when 'wk' then frequency * (24.0 / period.value) / (24 * 7)
when 'mo' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'a' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
when 'hour' then frequency * (24.0 / period.value)
when 'minute' then frequency * (24.0 / period.value) * 60
when 'second' then frequency * (24.0 / period.value) * 60 * 60
when 'day' then frequency * (24.0 / period.value) / 24
when 'week' then frequency * (24.0 / period.value) / (24 * 7)
when 'month' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'year' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
when 'hours' then frequency * (24.0 / period.value)
when 'minutes' then frequency * (24.0 / period.value) * 60
when 'seconds' then frequency * (24.0 / period.value) * 60 * 60
when 'days' then frequency * (24.0 / period.value) / 24
when 'weeks' then frequency * (24.0 / period.value) / (24 * 7)
when 'months' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'years' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
else Message(null, true, 'OMTKLogic.ToDaily.UnknownUnit', ErrorLevel, 'Unknown unit ' & period.unit)
end
define function ToDaily_Msg(frequency Integer, period Quantity):
frequency F
let result: ToDaily(frequency, period)
return {
result: result,
message:
if result is null then
Msg('OMTKLogic.ToDaily.UnknownUnit', ErrorLevel, 'Unknown unit ' & period.unit)
else
null
}
/*
Returns the opioid ingredients and their strengths that
make up the drug identified by the given rxNormCode as a list of tuples:
List<Tuple {
rxNormCode Code,
doseFormCode Code,
doseFormName String,
ingredientCode Code,
ingredientName String,
strength Quantity
}>
*/
/*
GetIngredients:
List<{
rxNormCode Code,
doseFormCode Code,
ingredientCode code,
strength Quantity
}>
*/
define function GetIngredients(rxNormCode Code):
OMTKData.DrugIngredients DI
where DI.drugCode = ToInteger(rxNormCode.code)
return {
rxNormCode: Code { code: ToString(DI.drugCode), system: 'http://www.nlm.nih.gov/research/umls/rxnorm', display: DI.drugName },
doseFormCode: Code { code: ToString(DI.doseFormCode), system: 'http://www.nlm.nih.gov/research/umls/rxnorm', display: DI.doseFormName },
ingredientCode: Code { code: ToString(DI.ingredientCode), system: 'http://www.nlm.nih.gov/research/umls/rxnorm', display: DI.ingredientName },
strength: Quantity {
value: DI.strengthValue,
unit: ToUCUM(DI.strengthUnit)
}
}
/*
Returns the first RxNorm code in the given concept that matches a drug code
specified in OMTKData.
*/
define function GetMedicationCode(concept Concept):
First(
((concept.codes) C
where C.system = 'http://www.nlm.nih.gov/research/umls/rxnorm'
return singleton from (
OMTKData.DrugIngredients DI
where DI.drugCode = ToInteger(C.code)
return Code {
code: ToString(DI.drugCode),
system: 'http://www.nlm.nih.gov/research/umls/rxnorm',
display: DI.drugName
}
)
) X
where X is not null
)
/*
Returns the display of the given concept, if present, otherwise, looks up medication
names for any RxNormCodes within the concept using the GetMedicationName function
*/
define function GetMedicationConceptName(concept Concept):
if concept.display is null then
First(
(concept.codes) C
where C.system = 'http://www.nlm.nih.gov/research/umls/rxnorm'
return GetMedicationName(C)
)
else
concept.display
/*
Returns the display of the given code, if present, otherwise looks it up from the OMTK data
*/
define function GetMedicationName(rxNormCode Code):
if rxNormCode.display is null then
singleton from (
OMTKData.DrugIngredients DI
where DI.drugCode = ToInteger(rxNormCode.code)
return DI.drugName
)
else rxNormCode.display
/*
Returns the display of the given ingredient, if present, otherwise looks it up from the OMTK data
*/
define function GetIngredientName(ingredientCode Code):
if ingredientCode.display is null then
singleton from (
OMTKData.DrugIngredients DI
where DI.ingredientCode = ToInteger(ingredientCode.code)
return DI.ingredientName
)
else ingredientCode.display
/*
Returns the display of the given dose form, if present, otherwise looks it up from the OMTK data
*/
define function GetDoseFormName(doseFormCode Code):
if doseFormCode.display is null then
singleton from (
OMTKData.DrugIngredients DI
where DI.doseFormCode = ToInteger(doseFormCode.code)
return DI.doseFormName
)
else doseFormCode.display
/*
Removes the last per argument from a unit
NOTE: Rewrote to not use LastPositionOf, since that function is not implemented in the JS engine
https://github.com/cqframework/cql-execution/issues/147
*/
define function StripPer(unit String):
unit X
let split: Split(unit, '/'),
splitCount: Count(split)
return
if splitCount > 1 then
Substring(unit, 0, Length(unit) - Length(split[splitCount - 1]) - 1)
else
unit
/*
define function StripPer(unit String):
if LastPositionOf('/', unit) >= 0
then Substring(unit, 0, LastPositionOf('/', unit))
else unit
*/
/*
Calculates daily dose for a specific ingredient based on the ingredient strength,
dose form, dose quantity, and daily frequency.
In addition, returns a textual description of the daily dose.
Tuple { result: Quantity, description: String }
*/
define function GetDailyDose(ingredientCode Code, strength Quantity, doseFormCode Code, doseQuantity Quantity, dosesPerDay Decimal):
case
when dosesPerDay is null or doseQuantity is null or strength is null or strength.value is null or strength.unit is null then
{
result: null as Quantity,
description: 'Missing doses per day, dose quantity, and/or strength'
}
/* if patch --> daily dose = dose value (e.g, number patches with doseQuantity unit = "patch") * per-hour strength */
when ToInteger(doseFormCode.code) = 316987 then
/* buprenorphine or fentanyl patch */
if ToInteger(ingredientCode.code) in { 1819, 4337 } then
(Quantity { value: dosesPerDay * doseQuantity.value * strength.value, unit: strength.unit }) dailyDose
return {
result: dailyDose,
description: GetIngredientName(ingredientCode) & ' patch: ' & ToString(doseQuantity.value) & ' * ' & ToString(dosesPerDay) & '/d * ' & ToString(strength) & ' = ' + ToString(dailyDose)
}
else
{
result: null as Quantity,
description: 'Unknown patch ingredient: ' & ingredientCode.code & ':' & ingredientCode.display
}
/* if dose unit in actual mass units (mg or ug -- when it's a single med) --> daily dose = numTimesPerDay * dose */
when doseQuantity.unit in { 'mg', 'ug' } then
(Quantity { value: dosesPerDay * doseQuantity.value, unit: doseQuantity.unit }) dailyDose
return {
result: dailyDose,
description: GetIngredientName(ingredientCode) + ' ' + GetDoseFormName(doseFormCode) + ': ' + ToString(dosesPerDay) + '/d * ' + ToString(doseQuantity) + ' = ' + ToString(dailyDose)
}
/* if doseQuantity is in actual volume units (mL) --> daily dose = numTimesPerDay * dose * strength */
when doseQuantity.unit = 'mL' and (PositionOf('/mL', strength.unit) = Length(strength.unit) - 3) then
(Quantity { value: dosesPerDay * doseQuantity.value * strength.value, unit: StripPer(strength.unit) }) dailyDose
return {
result: dailyDose,
description: GetIngredientName(ingredientCode) + ' ' + GetDoseFormName(doseFormCode) + ': ' + ToString(dosesPerDay) + '/d * ' + ToString(doseQuantity) + ' * ' & ToString(strength) & ' = ' + ToString(dailyDose)
}
/* if doseQuantity is not in actual units (e.g., 1 tab, 1 spray -- when it's a combo med with a unit of tablet, or it's mg/actuat) --> daily dose = numTimesPerDay * dose value * strength value */
else
(Quantity { value: dosesPerDay * doseQuantity.value * strength.value, unit: StripPer(strength.unit) }) dailyDose
return {
result: dailyDose,
description: GetIngredientName(ingredientCode) + ' ' + GetDoseFormName(doseFormCode) + ': ' + ToString(dosesPerDay) + '/d * ' + ToString(doseQuantity) + ' * ' + ToString(strength) + ' = ' + ToString(dailyDose)
}
end
/*
Calculates MMEs for the given input prescription information and returns it
as a list of tuples:
List<Tuple {
rxNormCode Code,
doseFormCode Code,
doseQuantity Quantity,
dosesPerDay Decimal,
ingredientCode Code,
strength Quantity,
dailyDose Quantity,
dailyDoseDescription String,
conversionFactor Decimal,
mme Quantity
}>
*/
define function CalculateMMEs(medications List<Tuple { rxNormCode Code, doseQuantity Quantity, dosesPerDay Decimal }>):
Flatten(
medications M
let Ingredients: GetIngredients(M.rxNormCode)
return
Ingredients I
let
adjustedDoseQuantity: M.doseQuantity,
dailyDose: GetDailyDose(I.ingredientCode, I.strength, I.doseFormCode, adjustedDoseQuantity, M.dosesPerDay),
factor: ConversionFactors.GetConversionFactor(I.ingredientCode, dailyDose.result, I.doseFormCode, M.dosesPerDay)
return {
rxNormCode: M.rxNormCode,
doseFormCode: I.doseFormCode,
doseQuantity: adjustedDoseQuantity,
dosesPerDay: M.dosesPerDay,
ingredientCode: I.ingredientCode,
strength: I.strength,
dailyDose: dailyDose.result,
dailyDoseDescription: dailyDose.description & (' * factor: ' + Coalesce(ToString(factor), 'No conversion factor available')),
conversionFactor: factor,
mme: Quantity(
Round(dailyDose.result.value * factor, 1),
'{MME}/d'
)
}
)
define function Quantity(value Decimal, unit String):
if value is not null then
Quantity { value: value, unit: unit }
else
null ( src
)
library OMTKLogicMK2020 version '2022.1.0'
/*
This version of the OMTKLogic library uses the FHIR MedicationKnowledge Resource
as the source for drug ingredient and strength information, rather than the
OMTK data source.
*/
using FHIR version '4.0.1'
include OMTKData2020 version '2022.1.0' called OMTKData
codesystem RxNorm: 'http://www.nlm.nih.gov/research/umls/rxnorm'
context Patient
/*
Normalizes the input units to UCUM units
Note guidance for UCUM presentation of medication units from SNOMED here:
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwjU3vLpicPTAhWFMGMKHRpOBUAQFggiMAA&url=https%3A%2F%2Fconfluence.ihtsdotools.org%2Fdownload%2Fattachments%2F17859188%2FExpressing%2520Units%2520of%2520Measure%2520for%2520Medicinal%2520Products.doc%3Fapi%3Dv2&usg=AFQjCNE5sboicqvJDUyXJ2im8VzBpgHE8A
The values listed here are the only ones currently present in the OMTK data
Based on the HL7 UCUM subset here:
http://download.hl7.de/documents/ucum/ucumdata.html
*/
define function ToUCUM(unit System.String):
case unit
when 'MG' then 'mg'
when 'MG/ACTUAT' then 'mg/{actuat}'
when 'MG/HR' then 'mg/h'
when 'MG/ML' then 'mg/mL'
else 'Error: unknown{' + unit + '}'
end
/*
Calculates daily frequency given frequency within a period
*/
define function ToDaily(frequency System.Integer, period System.Quantity):
case period.unit
when 'h' then frequency * (24.0 / period.value)
when 'min' then frequency * (24.0 / period.value) * 60
when 's' then frequency * (24.0 / period.value) * 60 * 60
when 'd' then frequency * (24.0 / period.value) / 24
when 'wk' then frequency * (24.0 / period.value) / (24 * 7)
when 'mo' then frequency * (24.0 / period.value) / (24 * 30) /* assuming 30 days in month */
when 'a' then frequency * (24.0 / period.value) / (24 * 365) /* assuming 365 days in year */
else null
end
/*
Returns true if the given dose form is a patch (transdermal system)
*/
define function IsPatch(doseFormCode System.Code):
ToInteger(doseFormCode.code) = 316987
/*
Returns the conversion factor for the given ingredient
Opioid (strength in mg except where noted) MME Conversion Factor*
Buprenorphine, transdermal patch (MCG/HR) 12.6
Buprenorphine, tablet or film 30
Buprenorphine, film (MCG) 0.03
Butorphanol 7
Codeine 0.15
Dihydrocodeine 0.25
Fentanyl, buccal/SL tabet or lozenge/troche (MCG) 0.13
Fentanyl, film or oral spray (MCG) 0.18
Fentanyl, nasal spray (MCG) 0.16
Fentanyl, transdermal patch (MCG/HR) 2.4
Hydrocodone 1
Hydromorphone 4
Levomethadyl acetate 8
Levorphanol tartrate 11
Meperidine 0.1
Methadone 3
1-20 mg/d 4
21-40 mg/d 8
41-60 mg/d 10
61-80 mg/d 12
Morphine 1
Opium 1 // NOTE: Not present as an ingredient in the RxNorm data
Oxycodone 1.5
Oxymorphone 3
Pentazocine 0.37
Tapentadol 0.4
Tramadol 0.1
*/
define function GetConversionFactor(ingredientCode System.Code, dailyDose System.Quantity, doseFormCode System.Code):
case ToInteger(ingredientCode.code)
when 161 then 0 /* Acetaminophen */
when 1191 then 0 /* Aspirin */
when 1223 then 0 /* Atropine */
when 1767 then 0 /* Brompheniramine */
when 1819 then ( /* Buprenorphine */
case
when ToInteger(doseFormCode.code) = 316987 then 12.6 /* Transdermal system */
else 30 /* Tablet or Film (or Film in MCG) */
end
)
when 1841 then 7 /* Butorphanol */
when 1886 then 0 /* Caffeine */
when 2101 then 0 /* Carisoprodol */
when 2354 then 0 /* chlorcyclizine */
when 2400 then 0 /* Chlorpheniramine */
when 2670 then 0.15 /* Codeine */
when 3423 then 4 /* Hydromorphone */
when 3498 then 0 /* Diphenhydramine */
when 4337 then ( /* Fentanyl */
case
when ToInteger(doseFormCode.code) in { 970789, 317007, 316992 } then 0.13 /* Buccal Tablet, Sublingual Tablet, Oral Lozenge */
when ToInteger(doseFormCode.code) = 858080 then 0.18 /* Buccal Film */
when ToInteger(doseFormCode.code) in { 126542, 346163 } then 0.16 /* Nasal Spray, Mucosal Spray */
when IsPatch(doseFormCode) then 2.4 /* Transdermal system */
else 1000 /* Really ought to be an error because it represents a previously unencountered dose form.... */
end
)
when 5032 then 0 /* Guaifenesin */
when 5489 then 1 /* Hydrocodone */
when 5640 then 0 /* Ibuprofen */
when 6102 then 0 /* Kaolin */
when 6378 then 11 /* Levorphanol (NOTE: Given as Levorphanol tartrate in the CDC conversion table) */
when 6754 then 0.1 /* Meperidine */
when 6813 then ( /* Methadone */
case
when dailyDose.value between 1 and 20 then 4
when dailyDose.value between 21 and 40 then 8
when dailyDose.value between 41 and 60 then 10
when dailyDose.value >= 61 then 12
else 1000 /* Really ought to be an error because it represents an unexpected dose range... */
end
)
when 7052 then 1 /* Morphine */
when 7242 then 0 /* Naloxone */
when 7243 then 0 /* Naltrexone */
when 7804 then 1.5 /* Oxycodone */
when 7814 then 3 /* Oxymorphone */
when 8001 then 0.37 /* Pentazocine */
when 8163 then 0 /* Phenylephrine */
when 8175 then 0 /* Phenylpropanolamine */
when 8745 then 0 /* Promethazine */
when 8896 then 0 /* Pseudoephedrine */
when 9009 then 0 /* Pyrilamine */
when 10689 then 0.1 /* Tramadol */
when 10849 then 0 /* Triprolidine */
when 19759 then 0 /* bromodiphenhydramine */
when 19860 then 0 /* butalbital */
when 22696 then 0 /* dexbrompheniramine */
when 22697 then 0 /* dexchlorpheniramine */
when 23088 then 0.25 /* dihydrocodeine */
when 27084 then 0 /* homatropine */
when 35780 then 0 /* ropivacaine */
when 237005 then 8 /* Levomethadyl (NOTE: given as Levomethadyl acetate in the CDC conversion table) */
when 636827 then 0 /* guaiacolsulfonate */
when 787390 then 0.4 /* tapentadol */
else 0
end
define function EnsureMicrogramQuantity(strength System.Quantity):
if strength.value < 0.1 and (PositionOf('mg', strength.unit) = 0) then
System.Quantity {
value: strength.value * 1000,
unit: 'mcg' + Substring(strength.unit, 2)
}
else
strength
/*
Returns the non-surgical opioid ingredients and their strengths that
make up the drug identified by the given rxNormCode as a list of tuples:
List<Tuple {
rxNormCode Code,
doseFormCode Code,
doseFormName String,
ingredientCode Code,
ingredientName String,
strength Quantity
}>
*/
/*
DrugIngredients:
List<{
drugCode Integer,
drugName String,
doseFormCode Integer,
doseFormName String,
ingredientCode Integer,
ingredientName String,
strength String,
strengthValue Decimal,
strengthUnit String
}>
*/
define function GetIngredients(rxNormCode System.Code):
OMTKData.DrugIngredients DI
where DI.drugCode = ToInteger(rxNormCode.code)
return {
rxNormCode: System.Code { code: ToString(DI.drugCode), system: 'http://www.nlm.nih.gov/research/umls/rxnorm', display: DI.drugName },
doseFormCode: System.Code { code: ToString(DI.doseFormCode), system: 'http://www.nlm.nih.gov/research/umls/rxnorm', display: DI.doseFormName },
doseFormName: DI.doseFormName,
ingredientCode: System.Code { code: ToString(DI.ingredientCode), system: 'http://www.nlm.nih.gov/research/umls/rxnorm', display: DI.ingredientName },
ingredientName: DI.ingredientName,
strength: EnsureMicrogramQuantity(
System.Quantity {
value: DI.strengthValue,
unit: ToUCUM(DI.strengthUnit)
}
)
}
/* define function GetIngredients(rxNormCode Code):
flatten (
[MedicationKnowledge: rxNormCode] M
return
M.ingredient I
where I.code in "Opioid Ingredients" // TODO: Need a value set of opioid ingredients
return {
rxNormCode: M.code,
doseFormCode: M.doseForm, // TODO: MedicationKnowledge specifies SNOMED-CT dose forms here, would need to profile to RXNorm
doseFormName: M.doseForm.text,
ingredientCode: I.item as CodeableConcept, // TODO: Profile to code only
ingredientName: (I.item as CodeableConcept).text,
strength: EnsureMicrogramQuantity(I.strength.denominator) // TODO: Is this correct?
}
) */
/*
Calculates daily dose for a specific ingredient based on the ingredient strength, dose form, dose quantity, and daily frequency
*/
define function GetDailyDose(ingredientCode System.Code, strength System.Quantity, doseFormCode System.Code, doseQuantity System.Quantity, dosesPerDay System.Decimal):
case
/* if patch --> daily dose = dose value (e.g, number patches with doseQuantity unit = "patch") * per-hour strength */
when IsPatch(doseFormCode) then
/* buprenorphine or fentanyl patch */
if ToInteger(ingredientCode.code) in { 1819, 4337 } then
System.Quantity {
value: dosesPerDay * doseQuantity.value * strength.value,
unit: strength.unit
}
else
null
/* if dose unit in actual mass units (mg or mcg -- when it's a single med) --> daily dose = numTimesPerDay * dose */
when doseQuantity.unit in { 'mg', 'mcg' } then
System.Quantity {
value: dosesPerDay * doseQuantity.value,
unit: doseQuantity.unit
}
/* if doseQuantity is in actual volume units (mL) --> daily dose = numTimesPerDay * dose * strength */
when doseQuantity.unit = 'mL' and (PositionOf('/mL', strength.unit) = Length(strength.unit) - 3) then
System.Quantity {
value: dosesPerDay * doseQuantity.value * strength.value,
unit: Substring(strength.unit, 0, PositionOf('/', strength.unit))
}
/* if doseQuantity is not in actual units (e.g., 1 tab, 1 spray -- when it's a combo med with a unit of tablet, or it's mg/actuat) --> daily dose = numTimesPerDay * dose value * strength value */
else
System.Quantity {
value: dosesPerDay * doseQuantity.value * strength.value,
unit: Substring(strength.unit, 0, PositionOf('/', strength.unit))
}
end
define function GetMedicationConceptName(concept Concept):
if concept.display is null then
First(
(concept.codes) C
where C.system = 'http://www.nlm.nih.gov/research/umls/rxnorm'
return GetMedicationName(C)
)
else
concept.display
define function GetMedicationName(rxNormCode System.Code):
if rxNormCode.display is null then
SingletonFrom(
OMTKData.DrugIngredients DI
where DI.drugCode = ToInteger(rxNormCode.code)
return DI.drugName
)
else rxNormCode.display
/*
Builds a description for the daily dose for an ingredient
*/
define function GetDailyDoseDescription(ingredientCode System.Code, ingredientName System.String, strength System.Quantity, doseFormCode System.Code, doseFormName System.String, doseQuantity System.Quantity, dosesPerDay System.Decimal, dailyDose System.Quantity):
case
/* if patch */
when IsPatch(doseFormCode) then
/* buprenorphine or fentanyl patch */
if ToInteger(ingredientCode.code) in { 1819, 4337 } then
ingredientName + ' patch: ' + ToString(doseQuantity.value) + ' * ' + ToString(strength.value) + ' = ' + ToString(dailyDose.value)
else
null
/* if dose unit in actual mass units (mg or mcg -- when it's a single med) */
when doseQuantity.unit in { 'mg', 'mcg' } then
ingredientName + ' ' + doseFormName + ': ' + ToString(dosesPerDay) + '/d * ' + ToString(doseQuantity.value) + ' = ' + ToString(dailyDose.value)
/* if doseQuantity in actual volume units (mL) or not in actual units (e.g. 1 tab, 1 spray) */
else
ingredientName + ' ' + doseFormName + ': ' + ToString(dosesPerDay) + '/d * ' + ToString(doseQuantity.value) + ' * ' + ToString(strength.value) + ' = ' + ToString(dailyDose.value)
end
/*
Calculates MMEs for the given input prescription information and returns it
as a list of tuples:
List<Tuple {
rxNormCode Code,
doseFormCode Code,
doseQuantity Quantity,
dosesPerDay Decimal,
ingredientCode Code,
ingredientName String,
strength Quantity,
dailyDose Quantity,
dailyDoseDescription String,
conversionFactor Decimal,
mme Quantity
}>
*/
define function CalculateMMEs(medications List<Tuple { rxNormCode System.Code, doseQuantity System.Quantity, dosesPerDay System.Decimal }>):
Flatten(
medications M
let Ingredients: GetIngredients(M.rxNormCode)
return
Ingredients I
let
adjustedDoseQuantity: EnsureMicrogramQuantity(M.doseQuantity),
dailyDose: GetDailyDose(I.ingredientCode, I.strength, I.doseFormCode, adjustedDoseQuantity, M.dosesPerDay),
factor: GetConversionFactor(I.ingredientCode, dailyDose, I.doseFormCode)
return {
rxNormCode: M.rxNormCode,
doseFormCode: I.doseFormCode,
doseQuantity: adjustedDoseQuantity,
dosesPerDay: M.dosesPerDay,
ingredientCode: I.ingredientCode,
ingredientName: I.ingredientName,
strength: I.strength,
dailyDose: dailyDose,
dailyDoseDescription: GetDailyDoseDescription(I.ingredientCode, I.ingredientName, I.strength, I.doseFormCode, I.doseFormName, adjustedDoseQuantity, M.dosesPerDay, dailyDose),
conversionFactor: factor,
mme: System.Quantity {
value: dailyDose.value * factor,
unit: dailyDose.unit + '/d'
}
}
)
/* define TestCalculateMMEs:
CalculateMMEs({ { rxNormCode: Code '388508' from RxNorm, doseQuantity: Quantity { value: 1, unit: 'patch' }, dosesPerDay: 0.33 } }) */
( src
)
library OpioidCDSCommon version '2022.1.0'
using FHIR version '4.0.1'
include FHIRHelpers version '4.0.1' called FHIRHelpers
include OMTKLogicMK2020 version '2022.1.0' called OMTKLogic
codesystem "LOINC": 'http://loinc.org'
codesystem "SNOMED": 'http://snomed.info/sct'
codesystem "Medication Request Category Codes": 'http://terminology.hl7.org/CodeSystem/medicationrequest-category'
codesystem "Medication Request Status Codes": 'http://hl7.org/fhir/medication-request-status'
codesystem "Condition Clinical Status Codes": 'http://terminology.hl7.org/CodeSystem/condition-clinical'
valueset "US Core Condition Category Codes": 'http://hl7.org/fhir/us/core/ValueSet/us-core-condition-category'
// Expression-based
valueset "Opioid analgesics with ambulatory misuse potential": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-analgesics-with-ambulatory-misuse-potential'
valueset "Extended release opioid with ambulatory misuse potential": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/extended-release-opioid-with-ambulatory-misuse-potential'
valueset "Buprenorphine and methadone medications": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/buprenorphine-and-methadone-medications'
// Enumerated-compose
valueset "Limited life expectancy conditions": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/limited-life-expectancy-conditions'
valueset "Therapies indicating end of life care": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/therapies-indicating-end-of-life-care'
valueset "Conditions likely terminal for opioid prescribing": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/conditions-likely-terminal-for-opioid-prescribing'
valueset "CDC malignant cancer conditions": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/cdc-malignant-cancer-conditions'
valueset "Oncology specialty designations (NUCC)": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/oncology-specialty-designations'
valueset "Opioid misuse disorders": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-misuse-disorders'
valueset "Substance misuse behavioral counseling": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/substance-misuse-behavioral-counseling'
valueset "Conditions documenting substance misuse": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/conditions-documenting-substance-misuse'
// Harvested from VSAC - OID: 2.16.842022.1.013883.3.464.1003.101.12.1001
// Reviewed with Terminology, 2020-02-05 - Value set name in VSAC is "Office Visit", need to verify suitability
valueset "Office Visit": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/office-visit'
valueset "Opioid counseling procedure": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-counseling-procedure'
/* Existing sets for first six recs */
valueset "Benzodiazepine medications": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/benzodiazepine-medications'
valueset "Non-opioid drug urine screening": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/non-opioid-drug-urine-screening'
valueset "Naloxone medications": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/naloxone-medications'
valueset "Opioid misuse assessment procedure": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-misuse-assessment-procedure'
valueset "Opioid drug urine screening": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-drug-urine-screening'
valueset "Hospice Disposition": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/hospice-disposition' // Harvested from VSAC - OID: 2.16.842022.1.013762.1.4.1108.15
valueset "Hospice Finding Codes": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/hospice-finding'
valueset "Hospice Procedure Codes": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/hospice-procedure'
valueset "Pain treatment plan": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/pain-treatment-plan'
valueset "Pain management procedure": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/pain-management-procedure'
valueset "PDMP review procedure": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/pdmp-review-procedure'
valueset "PDMP data reviewed finding": 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/pdmp-data-reviewed-finding'
code "Community": 'community' from "Medication Request Category Codes"
code "Active Condition": 'active' from "Condition Clinical Status Codes"
code "Active MedicationRequest": 'active' from "Medication Request Status Codes"
// TODO: code "Nonpharmacologic therapy and nonopioid pharmocologic": 'TODO' from "TODO"
context Patient
// TODO: Capture process decisions for long-term opioid use
define IsForChronicPain: true
define "Active Ambulatory Opioid Rx":
/* ("Get Active Ambulatory Medication Requests"([MedicationRequest: status in "Active MedicationRequest"])) Rx */
(
("Get Active Ambulatory Medication Requests"([MedicationRequest])) MR
where date from MR.authoredOn 2 years or less on or before Today()
and MR.medication is Reference or MR.medication in "Opioid analgesics with ambulatory misuse potential"
) Rx
let Med: [Medication: id in (Last(Split((Rx.medication as FHIR.Reference).reference, '/')))]
where not(Rx.medication is Reference) or Med.code in "Opioid analgesics with ambulatory misuse potential"
return
MedicationRequest {
id: Rx.id,
status: Rx.status,
intent: Rx.intent,
category: Rx.category,
medication: if Rx.medication is Reference then First(Med.code) else Rx.medication as CodeableConcept,
subject: Rx.subject,
recorder: Rx.recorder,
dosageInstruction: Rx.dosageInstruction,
dispenseRequest: Rx.dispenseRequest
}
define "Active Ambulatory Benzodiazepine Rx":
/* ("Get Active Ambulatory Medication Requests"([MedicationRequest: status in "Active MedicationRequest"])) Rx */
(
("Get Active Ambulatory Medication Requests"([MedicationRequest])) MR
where date from MR.authoredOn 2 years or less on or before Today()
and MR.medication is Reference or MR.medication in "Benzodiazepine medications"
) Rx
let Med: [Medication: id in (Last(Split((Rx.medication as FHIR.Reference).reference, '/')))]
where not(Rx.medication is Reference) or Med.code in "Benzodiazepine medications"
return
MedicationRequest {
id: Rx.id,
status: Rx.status,
intent: Rx.intent,
category: Rx.category,
medication: if Rx.medication is Reference then First(Med.code) else Rx.medication as CodeableConcept,
subject: Rx.subject,
recorder: Rx.recorder,
dosageInstruction: Rx.dosageInstruction,
dispenseRequest: Rx.dispenseRequest
}
define "Active Ambulatory Naloxone Rx":
/* ("Get Active Ambulatory Medication Requests"([MedicationRequest: status in "Active MedicationRequest"])) Rx */
(
("Get Active Ambulatory Medication Requests"([MedicationRequest])) MR
where date from MR.authoredOn 2 years or less on or before Today()
and MR.medication is Reference or MR.medication in "Naloxone medications"
) Rx
let Med: [Medication: id in (Last(Split((Rx.medication as FHIR.Reference).reference, '/')))]
where not(Rx.medication is Reference) or Med.code in "Naloxone medications"
return
MedicationRequest {
id: Rx.id,
status: Rx.status,
intent: Rx.intent,
category: Rx.category,
medication: if Rx.medication is Reference then First(Med.code) else Rx.medication as CodeableConcept,
subject: Rx.subject,
recorder: Rx.recorder,
dosageInstruction: Rx.dosageInstruction,
dispenseRequest: Rx.dispenseRequest
}
define function "Get Active Ambulatory Medication Requests" (value List<MedicationRequest>) returns List<MedicationRequest>:
value Rx
where Rx.status.value = 'active'
and exists (
Rx.category RxCategory
where FHIRHelpers.ToConcept(RxCategory) ~ "Community"
)
define function "Is Ambulatory Medication Request?" (value List<MedicationRequest>) returns List<MedicationRequest>:
value Rx
where exists (
Rx.category RxCategory
where FHIRHelpers.ToConcept(RxCategory) ~ "Community"
)
define function "Is Opioid Analgesic with Ambulatory Misuse Potential?"(value List<MedicationRequest>):
value Rx
let MedRef: if (Rx.medication is FHIR.Reference) then (Rx.medication as FHIR.Reference).reference else null,
Med: if MedRef is null then (Rx.medication as FHIR.CodeableConcept) else SingletonFrom([Medication: id in (Last(Split(MedRef, '/')))] Med return Med.code)
where Med in "Opioid analgesics with ambulatory misuse potential"
and exists (
Rx.category RxCategory
where FHIRHelpers.ToConcept(RxCategory) ~ "Community"
)
return
MedicationRequest {
id: Rx.id,
status: Rx.status,
intent: Rx.intent,
category: Rx.category,
medication: FHIR.CodeableConcept{ coding: Med.coding },
subject: Rx.subject,
authoredOn: Rx.authoredOn,
recorder: Rx.recorder,
dosageInstruction: Rx.dosageInstruction,
dispenseRequest: Rx.dispenseRequest
}
define function "Is Benzodiazepine?"(value List<MedicationRequest>):
value Rx
let MedRef: if (Rx.medication is FHIR.Reference) then (Rx.medication as FHIR.Reference).reference else null,
Med: if MedRef is null then (Rx.medication as FHIR.CodeableConcept) else SingletonFrom([Medication: id in (Last(Split(MedRef, '/')))] Med return Med.code)
where Med in "Benzodiazepine medications"
and exists (
Rx.category RxCategory
where FHIRHelpers.ToConcept(RxCategory) ~ "Community"
)
return
MedicationRequest {
id: Rx.id,
status: Rx.status,
intent: Rx.intent,
category: Rx.category,
medication: FHIR.CodeableConcept{ coding: Med.coding },
subject: Rx.subject,
authoredOn: Rx.authoredOn,
recorder: Rx.recorder,
dosageInstruction: Rx.dosageInstruction,
dispenseRequest: Rx.dispenseRequest
}
define "End of Life Assessment":
// 1. Conditions indicating end of life or with limited life expectancy
exists (
"Conditions Indicating End of Life or With Limited Life Expectancy"
)
// 2. Admitted/referred/discharged to hospice care
or exists (
"Admitted/Referred/Discharged to Hospice Care"
)
// 3. Medications indicating end of life
/* or exists (
"Medications Indicating End of Life"
) */
define "Conditions Indicating End of Life or With Limited Life Expectancy":
(
[Condition: category in "US Core Condition Category Codes"] C
where C.code in "Conditions likely terminal for opioid prescribing"
and exists (
C.clinicalStatus.coding Coding
where FHIRHelpers.ToCode(Coding) ~ "Active Condition"
)
)
union
(
[Condition: category in "US Core Condition Category Codes"] C
where C.code in "Limited life expectancy conditions"
and exists (
C.clinicalStatus.coding Coding
where FHIRHelpers.ToCode(Coding) ~ "Active Condition"
)
)
define "Admitted/Referred/Discharged to Hospice Care":
(
[Procedure: code in "Hospice Procedure Codes"] P
where P.status.value in { 'in-progress', 'completed' }
)
union
(
[ServiceRequest: code in "Hospice Procedure Codes"] E
where E.status.value in { 'planned', 'arrived', 'in-progress', 'finished', 'onleave' }
)
union
(
[Observation: code in "Hospice Finding Codes"] O
where not (O.status.value in { 'unknown', 'entered-in-error', 'cancelled' })
)
union
(
[Encounter] E
where
(
if E.hospitalization.dischargeDisposition.coding is null
or not exists (E.hospitalization.dischargeDisposition.coding)
then false
else E.hospitalization.dischargeDisposition in "Hospice Disposition"
)
and E.status.value in { 'planned', 'arrived', 'in-progress', 'finished', 'onleave' }
)
/*
define "Medications Indicating End of Life":
(
[MedicationAdministration: "End Of Life Opioids"] MA
where MA.status.value in { 'in-progress', 'on-hold', 'completed' }
)
union
(
[MedicationDispense: "End Of Life Opioids"] MD
where MD.status.value in { 'preparation', 'in-progress', 'on-hold', 'completed' }
)
union
(
[MedicationRequest: "End Of Life Opioids"] MR
where MR.status.value in { 'active', 'completed' }
)
union
(
[MedicationStatement: "End Of Life Opioids"] MS
where MS.status.value in { 'active', 'completed', 'intended' }
)
*/
define "Previous 10 Days Interval":
Interval[Today() - 10 days, Today()]
define "First Month":
Interval[Today() - 3 months, Today() - 2 months]
define "Second Month":
Interval[Today() - 2 months, Today() - 1 months]
define "Third Month":
Interval[Today() - 1 months, Today()]
define "Prescribed Opioids for 21 or more of 30 Days for each of the past 3 Months":
"Days on Opioids during Period"("First Month") >= 21
and "Days on Opioids during Period"("Second Month") >= 21
and "Days on Opioids during Period"("Third Month") >= 21
define function "Prescription Relevant Period"(prescription FHIR.MedicationRequest):
if (
prescription.authoredOn is not null and prescription.dispenseRequest is not null
and prescription.dispenseRequest.expectedSupplyDuration is not null
)
then Interval[
date from prescription.authoredOn,
date from prescription.authoredOn + System.Quantity{ value: GetDurationInDays(prescription.dispenseRequest.expectedSupplyDuration), unit: 'days' }
]
else null
define function "Days on Opioids during Period"(period Interval<Date>):
Sum(
(
collapse (
[MedicationRequest: "Opioid analgesics with ambulatory misuse potential"] OpioidPrescription
return "Prescription Relevant Period"( OpioidPrescription ) intersect period
)
) OpioidUseInterval
return days between start of OpioidUseInterval and end of OpioidUseInterval
)
define function Prescriptions(Orders List<MedicationRequest>):
Orders O
let
// NOTE: Assuming medication is specified as a CodeableConcept with a single RxNorm code
rxNormCode: FHIRHelpers.ToCode((O.medication as FHIR.CodeableConcept).coding[0]),
medicationName: OMTKLogic.GetMedicationName(rxNormCode),
// NOTE: Assuming a single dosage instruction element
dosageInstruction: O.dosageInstruction[0],
// NOTE: Assuming a single dose and rate element
doseAndRate: dosageInstruction.doseAndRate[0],
repeat: dosageInstruction.timing.repeat,
frequency: Coalesce(repeat.frequencyMax.value, repeat.frequency.value),
period: System.Quantity { value: repeat.period.value, unit: repeat.periodUnit.value },
doseDescription:
Coalesce(
// There should be a conversion from FHIR.SimpleQuantity to System.Quantity
if doseAndRate.dose is FHIR.Range
then ToString((doseAndRate.dose as FHIR.Range).low)
+ '-' + ToString((doseAndRate.dose as FHIR.Range).high)
+ (doseAndRate.dose as FHIR.Range).high.unit.value
else ToString(FHIRHelpers.ToQuantity(doseAndRate.dose)),
''
),
frequencyDescription:
ToString(dosageInstruction.timing.repeat.frequency.value) +
Coalesce(
'-' + ToString(dosageInstruction.timing.repeat.frequencyMax.value),
''
)
return {
rxNormCode: rxNormCode,
isDraft: O.status.value = 'draft',
// NOTE: Assuming asNeeded is expressed as a boolean
isPRN: dosageInstruction.asNeeded,
prescription:
if dosageInstruction.text is not null then
medicationName + ' ' + dosageInstruction.text.value
else
// TODO: Shouldn't need the .value here on asNeededBoolean
medicationName + ' ' + doseDescription + ' q' + frequencyDescription + (if dosageInstruction.asNeeded then ' PRN' else ''),
dose: if doseAndRate.dose is FHIR.Range
then (doseAndRate.dose as FHIR.Range).high
else FHIRHelpers.ToQuantity(doseAndRate.dose),
dosesPerDay: Coalesce(OMTKLogic.ToDaily(frequency, period), 1.0)
}
define function MME(prescriptions List<MedicationRequest>):
(Prescriptions(prescriptions)) P
let mme: SingletonFrom(OMTKLogic.CalculateMMEs({ { rxNormCode: P.rxNormCode, doseQuantity: P.dose, dosesPerDay: P.dosesPerDay } }))
return {
rxNormCode: P.rxNormCode,
isDraft: P.isDraft,
isPRN: P.isPRN,
prescription: P.prescription,
dailyDose: mme.dailyDoseDescription,
conversionFactor: mme.conversionFactor,
mme: mme.mme
}
define function TotalMME(prescriptions List<MedicationRequest>):
System.Quantity {
value: Sum((MME(prescriptions)) M return M.mme.value),
unit: 'mg/d'
}
define function GetDurationInDays(value FHIR.Duration):
if value is null then null
else
case
when value.code.value ~ 'a' then value.value.value * 365.0
when value.code.value ~ 'mo' then value.value.value * 30.0
when value.code.value ~ 'wk' then value.value.value * 7.0
when value.code.value ~ 'd' then value.value.value
when value.code.value ~ 'h' then value.value.value / 24.0
when value.code.value ~ 'min' then value.value.value / 60.0 / 24.0
when value.code.value ~ 's' then value.value.value / 60.0 / 60.0 / 24.0
when value.code.value ~ 'ms' then value.value.value / 60.0 / 60.0 / 24.0 / 1000.0
when value.code.value is null then Message(1000, true, 'Undefined', 'Error', 'Duration unit code is null')
else Message(1000, true, 'Undefined', 'Error', 'Unsupported duration unit code: ' + value.code.value)
end
define function GetIngredient(rxNormCode Code):
OMTKLogic.GetIngredients(rxNormCode).ingredientName
define function GetIngredients(rxNormCodes List<Code>):
rxNormCodes rnc return GetIngredient(rnc)
define function GetMedicationNames(medications List<MedicationRequest>):
medications M
return OMTKLogic.GetIngredients(ToRxNormCode((M.medication as FHIR.CodeableConcept).coding)).rxNormCode.display
/*
* Conversion Functions
*/
define function CodeableConceptsToString(concepts List<FHIR.CodeableConcept>):
concepts c return CodeableConceptToString(c)
define function CodingToString(coding FHIR.Coding):
if (coding is null)
then null
else
'Code {' &
'code: ' & coding.code &
'system: ' & coding.system &
'version: ' & coding.version &
'display: ' & coding.display &
'}'
define function CodeableConceptToString(concept FHIR.CodeableConcept):
if (concept is null or concept.coding is null)
then null
else
'CodeableConcept {' &
'Coding: [' &
Combine(concept.coding Coding return CodingToString(Coding), ',')
& ']'
& '}'
define function ToCodes(coding List<FHIR.Coding>):
coding c return FHIRHelpers.ToCode(c)
define function ToRxNormCode(coding List<FHIR.Coding>):
singleton from (
coding C where C.system = 'http://www.nlm.nih.gov/research/umls/rxnorm'
)
( src
)
Schadow G, McDonald CJ. The Unified Code for Units of Measure. Regenstrief Institute, Inc. and the UCUM Organization, 2017. Version 2.1, Revision 442. http://unitsofmeasure.org
Dowell D, Ragan KR, Jones CM, Baldwin GT, Chou R. CDC Clinical Practice Guideline for Prescribing Opioids for Pain — United States, 2022. MMWR Recomm Rep 2022;71(No. RR-3):1-95. DOI: http://dx.doi.org/10.15585/mmwr.rr7103a1
2022 CDC Clinical Practice Guideline for Prescribing Opioids Implementation Guide, published by CDC / Security Risk Solutions, Inc. (SRS). This guide is not an authorized publication; it is the continuous build for version 2022.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/security-rs/opioid-cds-r4/
and changes regularly. See the Directory of published versions
SUMMARY: Discuss Risks and Offer NaloxoneDETAILS:Recommend incorporating strategies to mitigate opioidtherapy risks, including offering naloxoneFor guidance regarding assessing opioid therapy risks, seeRecommendation 8 of the 2022 CDC Clinical Practice Guideline.For more information about prescribing naloxone, seehttps://prescribetoprevent.orgMME Calculator CautionsAlertOrder -Naloxone orderedDocument -Verified patient ison Naloxone an hasbeen educated on use,Snooze 3 months*Document -Naloxone discussedbut declined,Snooze 3 months*Snooze* -N/A see comment,Snooze 3 months**Snooze duration referenced in the alert response is an example and is intended to be patient specific.