Dose to Product Translation
Overview
This page describes an important functional requirement for many system implementations using Dose Syntax. Structured Dose Syntax information must be capable of being used to support dose-based and product-based prescribing, and there is a requirement to convert between the two - e.g. to convert a dose-based prescription to an actual product for dispensing within a pharmacy.
Details of the requirements for dosage format conversion are highly use-case dependent and will be addressed as work in specific use-case areas develops.
Background
When a prescriber uses a dose-based instruction (using a VTM), it will always need to be translated into a product-based instruction (using a VMP or AMP) to be supplied or dispensed. Today, this is a highly manual process performed by a clincian. For example;
A hospital pharmacist would translate dose-based orders coming from the ward into a products that is both in-stock and suitable to meet the patients’ needs.
A GP would translate dose-based medication requests within a discharge letter into product-based repeat prescriptions.
Translation Process
It is not intended to identify a single product. A local implementation may choose to further filter the list of products on factors like local availability (stock), local formulary or cost. The order of products listed may also be locally condfigured to promote or demote products based on licensing status or local needs such as paediatric use.
The translation process requires the use of the NHS Dictionary of Medicines and Devices (dm+d) plus a mapping table for UCUM units of measure that use different terms than dm+d.
For example; gram
is a dm+d unit of measure with g
is the equivalant within UCUM, and UCUM spells liter
differently to the dm+d litre
.
Step #1: Get child products (VMPs and AMPs) of the VTM
VMPs flagged within dm+d as invalid or where actual products are not available must be ignored.
Where the VMP has a Prescribing Status
of 0004
, 0006
, 0007
, 0008
or 0009
then include the valid and available AMPs. These codes identify VMPs flagged as Never valid to prescribe as a VMP
and those flagged in various ways as VMP not recommended to prescribe
or Caution - AMP level prescribing advised
.
Where the dose-based instruction specifies a coded Route or coded Form then these are used in the query to return only VMPs for the given route and/or form.
If using dm+d data held in a relational database, the pseudo-SQL would be;
return vmp, vmp_prescribing_status where parent_vtm = {vtm_id} and vmp is valid and vmp has actual products available and vmp_form = {form_id} (if specified) and vmp_route = {route_id} (if specified)
return amp, vmp, vmp_prescribing_status where parent_vtm = {vtm_id} and vmp is valid and vmp has actual products available and vmp has vmp_prescribing_status = 0004 or 0009 and vmp_form = {form_id} (if specified) and vmp_route = {route_id} (if specified) and parent_vmp = vmp
If using the NHS England Terminology Server then a two-step approach is required. First a call to return VMP concepts for the given VTM with optional Form and Route codes. Second, for any VMPs flagged to prescribe with an AMP, those flagged with a PRES_STATCD of 0004 or 0009, make an additional call to return AMPs.
To return VMPs;
curl --location 'https://ontology.nhs.uk/staging/fhir/ValueSet/$expand' \ --header 'Authorization: Bearer } { { OAuthToken } }' \ --header 'Content-Type: application/json' \ --data '{ "resourceType": "Parameters", "parameter": [ { "name": "valueSet", "resource": { "resourceType": "ValueSet", "compose": { "include": [ { "system": "https://dmd.nhs.uk", "filter": [ { "property": "parent", "op": "=", "value": "{vtm_id}" }, { "property": "parent", "op": "=", "value": "VMP" }, { "property": "INVALID", "op": "exists", "value": "false" }, { "property": "FORMCD", "op": "in", "value": "{form1_id},{form2_id}" }, { "property": "ROUTECD", "op": "=", "value": "{route_id}" } ] } ], "exclude": [ { "system": "https://dmd.nhs.uk", "filter": [ { "property": "NON_AVAILCD", "op": "=", "value": "1" } ] } ] } } } ] }'
To return AMPs;
curl --location 'https://ontology.nhs.uk/staging/fhir/ValueSet/$expand' \ --header 'Authorization: Bearer { { OAuthToken } }' \ --header 'Content-Type: application/json' \ --data '{ "resourceType": "Parameters", "parameter": [ { "name": "valueSet", "resource": { "resourceType": "ValueSet", "compose": { "include": [ { "system": "https://dmd.nhs.uk", "filter": [ { "property": "parent", "op": "in", "value": "{vpm1_id},{vpm2_id},{vpm3_id}" }, { "property": "parent", "op": "=", "value": "AMP" }, { "property": "INVALID", "op": "exists", "value": "false" } ] } ], "exclude": [ { "system": "https://dmd.nhs.uk", "filter": [ { "property": "AVAIL_RESTRICTCD", "op": "in", "value": "9" } ] } ] } } } ] }'
Step #2: Calculate the required quantity of each VMP to fulfil the requested dose
Take the dose from the doseAndRate.doseQuantity
or doseAndRate.doseRange.low
structures. This will be a combination of a quantity and a coded unit of measure. If the unit of measure is using a UCUM unit then the SNOMED code needs to be looked-up from dm+d. This is where the addition mapping table applies.
This calculation at the VMP level will apply to all child AMPs.
Each VMP contains strength information for the active ingredients. It would not be expected to use a dose-based prescription for combination drugs (e.g. anything beginning “co-“) nor any VTM where some associated products contained multiple ingredents (e.g. Phosphate). In such cases translation from dose to products is not possible.
The strength of the ingredient may need to be converted into the same units as the requested dose for comparision purposes. For example, if the requested dose is 1gram but the VMP ingredient is expressed as 500mg then it would need to be converted into 0.5gram to calculate that the VMP is half the required strength. Whilst most dosage instructions would be expressed in terms of strength, the same conversion is required for volume (litre, millitre etc.) and length (metre, centimetre, etc.).
With all units of measure expressed in the same scaler terms, the amount of the VMP to fulfil the requested dose can be calculated as;
QUANTITY OF VMP = ( REQUESTED DOSE QUANTITY / VMP INGREDIENT STRENGTH ) / VMP UNIT DOSE FORM STRENGTH (where defined for the VMP)
Step #3 - Order the list of products in a clinically suitable order
This approach does not include where two or more products of different strengths may be used. For example a dose of 75mg requested and fulfilled by one 50mg product and one 25mg product.
Exclude VMPs flagged as Never valid to prescribe as a VMP
.
This guidance suggests ordering by least divisibility.
Whole products that can fulfil the request are listed above products that may have to be divided.
Where the quantity calculated from Step 2 is not divisible by 1, hence the product has to be divided (e.g. 1.5 tablets) then push down the list.
Where the quantity calculated from Step 2 is less than 1 (e.g. 0.5 tablets) then push lower in the list.
In either case, when a product needs to be divided and if the product has a dose form that is not typically divisable then push even lower in the list.
Products containing multiple active ingredents are pushed to the bottom of the list as the translation calculatation is not possible.
Data Requirements
dm+d
The dm+d data fields used for this process are;
VTM | VMP | VMP-VPI | VMP-FORM | VMP-ROUTE | AMP |
---|---|---|---|---|---|
VTMID | VTMID | ||||
VPID | VPID | VPID | VPID | VPID | |
NM | NM | NM | |||
INVALID | INVALID | INVALID | |||
PRES_STAT | |||||
NON_AVAILCD | |||||
UDFS | |||||
UDFS_UOMCD | |||||
UNIT_DOSE_UOMCD | |||||
STRNT_NMRTR_VAL | |||||
STRNT_NMRTR_UOMCD | |||||
STRNT_DNMTR_VAL | |||||
STRNT_DNMTR_UOMCD | |||||
FORMCD | ROUTECD | ||||
AVAIL_RESTRICTCD |
Together with the FORM, ROUTE, UNIT_OF_MEASURE and PRESCRIBING_STATUS vocabularies from the dm+d LOOKUP data.
When dm+d data is imported into a relational database, concepts marked as INVALID or VMP concepts flagged as no actual products available
may be excluded from the import.
Mapping between UCUM and SNOMED/dm+d
The following mapping table needs to be available to the implementing system. It is required to identify the units of measure within the UCUM standard that use different different codes to the dm+d.
For example g
is a UCUM code for "gram" and the equivalent within dm+d is gram|258682000
so a mapping is required to associate g
with the SNOMED code 258682000
. This mapping table may need to be extended within a local implementation depending on which UCUM units are to be expected.
SNOMED/dm+d code | UCUM unit |
---|---|
258683005 | kilogram |
258682000 | g |
258684004 | milligram |
258686002 | ng |
258685003 | ug |
258773002 | milliliter |
258770004 | liter |
258770004 | l |
Detailed Logic for Step 1 - Get relevant child products of the VTM
A suitable SQL query to return child VMPs for a VTM, with optional Route or Form constraints would be as follows. This assumes INVALID concepts and VMPs where no actual products are available has been excluded from the database.
SELECT vmp.vmpid AS vmpId , vmp.name AS vmpName , vmp.udfs_dose_uomcd AS unitDoseFormStrength , vpi.strnt_dnmtr_uomcd AS denominator FROM vtm INNER JOIN vmp ON ( vtm.vtmid = vmp.vtmid ) INNER JOIN vmpform ON ( vmp.vmpid = vmpform.vmpid ) INNER JOIN vmproute ON ( vmp.vmpid = vmproute.vmpid ) INNER JOIN vpi ON ( vmp.vmpid = vpi.vmpid ) WHERE vtm.vtmid = {insert_vtm_id} AND ( vmpform.formid = IN_form_id OR ISNULL(IN_form_id) ) AND ( vmproute.routeid = IN_route_id OR ISNULL(IN_route_id) )
Detailed Logic for Step 2 - Calculate the required quantity of each VMP to fulfil the requested dose
Conversion between scaler units of measure, e.g. gram to milligram
A function is required to convert a VTM ingredient strength into the same units as the requested dose quantity.
For example, if a required dose quantity is 12.5 milligram
, but a VMP for that drug is expressed with a strength in micrograms e.g. 500 microgram
, then that strength needs to be expressed in milligrams before the mathematical function can be executed.
Thus 500 microgram
would be converted into 0.5 milligram
.
For example;
/// // Convert 500 micrograms into milligrams // FNC_CONVERT_UNITS(vpi.strnt_nmrtr_val, vpi.strnt_nmrtr_uomcd, dose_uom_cd); /// SELECT FNC_CONVERT_UNITS(500, 258685003, 258684004); // returns `0.5`.
Within the dm+d, units of mass have the greatest range; kilogram, gram, milligram, microgram and nanogram.
Due to this range, the data type used within SQL must be a DECIMAL(30,12)
.
Conversion is required for the following units of measure.
Category | Units | SNOMED Code | Scaler Conversion |
---|---|---|---|
Mass | kilogram | 258683005 | 10^3 |
gram | 258682000 | 1 | |
milligram | 258684004 | 10^-3 | |
microgram | 258685003 | 10^-6 | |
nanogram | 258686002 | 10^-9 | |
Volume | litre | 258770004 | 1 |
millilitre | 258773002 | 10^-3 | |
microlitre | 258774008 | 10^-6 | |
nanolitre | 282113003 | 10^-9 | |
Length | metre | 258669008 | 1 |
centimetre | 258672001 | 10^-2 | |
millimetre | 258673006 | 10^-3 |
Function for quantity
A suitable SQL function to calculate the quantity of a given VMP to fulfil the requested dose quantity would be as follows.
FUNCTION FNC_CALC_QTY( doseQty DECIMAL(9,3) , numerator DECIMAL(30,12) , denominator DECIMAL(9,3) , unitDoseFormStrength DECIMAL(9,3) ) RETURNS DECIMAL(30,12) BEGIN IF denominator = 0 THEN SET denominator = 1; END IF; IF unitDoseFormStrength = 0 THEN RETURN doseQty / ( numerator / denominator ); END IF; RETURN ( doseQty / ( numerator / denominator ) ) / unitDoseFormStrength; END
A description of each variable used in FNC_CALC_QTY
is contained below.
Variable | Description |
---|---|
doseQty |
the required dose quantity - e.g. 12.5 |
numerator |
the VMP strength numerator, but has to be expressed in the same units as the requested dose, e.g. both in milligrams |
denominator |
the VMP strength denominator which may be 0 / NULL for some VMPs, so use a default value of 1 |
unitDoseFormStrength |
the VMP unit dose form strength value, which may be 0 / NULL |
Detailed Logic for Step 3 - Order the list of products in a clinically suitable order
Never valid to prescribe as a VMP
.
Function for ranking / ordering
Uses the FNC_CALC_QTY
function from above then calculates a ranking value which can be used to order the overall SQL query.
FUNCTION FNC_CALC_RANK( doseQty DECIMAL(9,3) , numerator DECIMAL(30,12) , denominator DECIMAL(9,3) , unitDoseFormStrength DECIMAL , formId BIGINT UNSIGNED ) RETURNS SMALLINT(5) UNSIGNED BEGIN DECLARE v_qty DECIMAL(30,12) UNSIGNED; DECLARE v_rank SMALLINT UNSIGNED; DECLARE v_divisable BIGINT UNSIGNED; SET v_qty = FNC_CALC_QTY(doseQty, numerator, denominator, unitDoseFormStrength); IF ( v_qty < 1 ) THEN SET v_rank = 3; ELSE IF ( ( v_qty % 1 ) != 0 ) THEN SET v_rank = 2; ELSE SET v_rank = 1; END IF; IF ( v_rank != 1 ) THEN SELECT name FROM lookup WHERE valueset = "NOTDIVISABLE" AND id = formid INTO v_divisable; IF ( NOT NULL(v_divisable) ) THEN SET v_rank = 4; END IF; END IF; RETURN v_rank; END
Where formid
is the dm+d code for the requested dose quantity unit of measure.
The rules for the ranking are best shown in a table.
Calculated Quantity | Ranking | Ranking Reason |
---|---|---|
Integer | 1 | Can be fulfilled by one or more complete doses |
Decimal greater than 1 | 2 | Requires a number of doses include part doses |
Decimal less than 1 | 3 | Requires part of a a single dose |
Decimal using a dose form typically not divisable | 4 | Unlikely to the clinically safe to use this product |
Identification of dose forms that are typically not divisable
The following dose forms are typically not divisible, however this is not always the case.
For example there are some modified-release tablets with a score along the centre to aid division, but in most cases, modified-release products should not be divided.
The same applies for products as capsules. These represent the more common dose forms used within dm+d concepts. Other non-divisible dose forms may exist but their use would be rare, but this reference table can be extended or customised as required for a local implementation.
SNOMED / dm+d code | Dose Form |
---|---|
385049006 | Capsule |
385054002 | Modified-release capsule |
385061003 | Modified-release tablet |
421720008 | Spray |
Complete Stored Procedure
PROCEDURE PRC_VTM_TO_VMP( IN IN_vtm_id BIGINT UNSIGNED , IN IN_dose_qty DECIMAL , IN IN_dose_uom_cd BIGINT UNSIGNED , IN IN_form_id BIGINT UNSIGNED , IN IN_route_id BIGINT UNSIGNED ) BEGIN SELECT DISTINCT vmp.vmpid , vmp.name , FNC_CALC_QTY( IN_dose_qty , FNC_CONVERT_UNITS( vpi.strnt_nmrtr_val , vpi.strnt_nmrtr_uomcd , IN_dose_uom_cd ) , vpi.strnt_dnmtr_val,vmp.udfs ) AS qty , vmp.udfs_dose_uomcd , vpi.strnt_dnmtr_uomcd , FNC_CALC_RANK( IN_dose_qty , FNC_CONVERT_UNITS( vpi.strnt_nmrtr_val , vpi.strnt_nmrtr_uomcd , IN_dose_uom_cd ) , vpi.strnt_dnmtr_val , vmp.udfs,vmpform.formid ) AS rnk FROM vtm INNER JOIN vmp ON ( vtm.vtmid = vmp.vtmid ) INNER JOIN vmpform ON ( vmp.vmpid = vmpform.vmpid ) INNER JOIN vmproute ON ( vmp.vmpid = vmproute.vmpid ) INNER JOIN vpi ON ( vmp.vmpid = vpi.vmpid ) INNER JOIN lookup ON ( vpi.strnt_nmrtr_uomcd = lookup.id ) WHERE vtm.vtmid = IN_vtm_id AND ( vmpform.formid = IN_form_id OR ISNULL(IN_form_id) ) AND ( vmproute.routeid = IN_route_id OR ISNULL(IN_route_id) ) ORDER BY rnk ASC, qty ASC; END
Worked Examples
Example A
VTM = Oxytetracycline | 22969001
Dose = 250 milligram
Step 1: Get child products (VMPs and AMPs) of the VTM
There are five valid and available VMPs. None are flagged in a way that require additional AMPs to be listed.
dm+d concept | Product |
---|---|
VMP | Oxytetracycline 100mg/5ml oral suspension |
VMP | Oxytetracycline 125mg/5ml oral suspension |
VMP | Oxytetracycline 250mg tablets |
VMP | Oxytetracycline 250mg/5ml oral suspension |
VMP | Oxytetracycline 500mg/5ml oral suspension |
Step 2: Calculate the required quantity of each VMP to fulfil the requested dose
dm+d concept | Product | Quantity Calculation | Unit of Measure |
---|---|---|---|
VMP | Oxytetracycline 100mg/5ml oral suspension | 250 / (20/1) = 12.5 |
ml |
VMP | Oxytetracycline 125mg/5ml oral suspension | 250 / (25/1) = 10 |
ml |
VMP | Oxytetracycline 250mg tablets | 250 / (250) = 1 |
tablet |
VMP | Oxytetracycline 250mg/5ml oral suspension | 250 / (50) = 5 |
ml |
VMP | Oxytetracycline 500mg/5ml oral suspension | 250 / (100/1) = 2.5 |
ml |
Step 3: Order the list of products in a clinically suitable order
Product | Quantity (to fulfil 250 milligrams) |
---|---|
Oxytetracycline 250mg tablets | 1 tablet |
Oxytetracycline 250mg/5ml oral suspension | 5 ml |
Oxytetracycline 125mg/5ml oral suspension | 10 ml |
Oxytetracycline 500mg/5ml oral suspension | 2.5 ml |
Oxytetracycline 100mg/5ml oral suspension | 12.5 ml |
Example B
VTM = Salbutamol | 91143003
Dose = 200 micrograms
Route = Inhalation | 18679011000001101
Step 1: Get child products (VMPs and AMPs) of the VTM
There are two valid and available VMPs, but both are flagged as Caution - AMP level prescribing advised
so we also query for valid and available AMPs.
dm+d concept | Product |
---|---|
VMP | Salbutamol 100micrograms/dose breath actuated inhaler CFC free |
-- AMP | Airomir 100micrograms/dose Autohaler (Teva UK Ltd) |
-- AMP | Salamol 100micrograms/dose Easi-Breathe inhaler (CST Pharma Ltd) |
-- AMP | Salamol 100micrograms/dose Easi-Breathe inhaler (Teva UK Ltd) |
VMP | Salbutamol 100micrograms/dose inhaler CFC free |
-- AMP | Airomir 100micrograms/dose inhaler (Teva UK Ltd) |
-- AMP | Salamol 100micrograms/dose inhaler CFC free (Teva UK Ltd) |
--AMP | Ventolin 100micrograms/dose Evohaler (GlaxoSmithKline UK Ltd) |
Step 2: Calculate the required quantity of each VMP to fulfil the requested dose
dm+d concept | Product | Quantity Calculation | Unit of Measure |
---|---|---|---|
VMP | Salbutamol 100micrograms/dose breath actuated inhaler CFC free | 200 / (100) = 2 |
dose |
-- AMP | Airomir 100micrograms/dose Autohaler (Teva UK Ltd) | 200 / (100) = 2 |
dose |
-- AMP | Salamol 100micrograms/dose Easi-Breathe inhaler (CST Pharma Ltd) | 200 / (100) = 2 |
dose |
-- AMP | Salamol 100micrograms/dose Easi-Breathe inhaler (Teva UK Ltd) | 200 / (100) = 2 |
dose |
VMP | Salbutamol 100micrograms/dose inhaler CFC free | 200 / (100) = 2 |
dose |
-- AMP | Airomir 100micrograms/dose inhaler (Teva UK Ltd) | 200 / (100) = 2 |
dose |
-- AMP | Salamol 100micrograms/dose inhaler CFC free (Teva UK Ltd) | 200 / (100) = 2 |
dose |
--AMP | Ventolin 100micrograms/dose Evohaler (GlaxoSmithKline UK Ltd) | 200 / (100) = 2 |
dose |
Step 3: Order the list of products in a clinically suitable order
As all products can be used with the same quantity, the order could be alphabetical or ordered as per any local formulary.
Product | Quantity (to fulfil 200 micrograms) |
---|---|
Salbutamol 100micrograms/dose breath actuated inhaler CFC free Note: Caution - AMP level prescribing advised |
2 dose |
Airomir 100micrograms/dose Autohaler (Teva UK Ltd) | 2 dose |
Salamol 100micrograms/dose Easi-Breathe inhaler (CST Pharma Ltd) | 2 dose |
Salamol 100micrograms/dose Easi-Breathe inhaler (Teva UK Ltd) | 2 dose |
Salbutamol 100micrograms/dose inhaler CFC free Note: Caution - AMP level prescribing advised |
2 dose |
Airomir 100micrograms/dose inhaler (Teva UK Ltd) | 2 dose |
Salamol 100micrograms/dose inhaler CFC free (Teva UK Ltd) | 2 dose |
Ventolin 100micrograms/dose Evohaler (GlaxoSmithKline UK Ltd) | 2 dose |
Known Issues
Products (VMPs) where the VPI strength is expressed as an inaccurate decimal value
The vast majority of VMPs are defined with a Virtual Product Ingredient (VPI) strength as a whole number, e.g. numerator = 5 (mg) and denominator = 1 (ml). A small percentage of VMPs are defined with a numerator expressed as an incurate decimal value.
Two examples are;
Oxybutynin 5mg/15ml bladder irrigation vials, VPI strength = 333.33 micrograms / 1 ml
Methotrexate 25mg/3ml solution for injection pre-filled syringes, VPI strength = 8.333 mg / 1 ml
This inaccuracy of values like 333.33
or 8.333
not being mathmetically the same as one third of a milligram means the mathematics used in these calculations does not result in a whole number.
For example;
- VMP =
Oxybutynin 5mg/15ml bladder irrigation vials
- Requested Dose =
10 milligram
- Calculated Quantity =
2.002 vials
and
- VMP =
Methotrexate 25mg/3ml solution for injection pre-filled syringes
- Requested Dose =
25 milligram
- Calculated Quantity =
1.041667 pre-filled disposable injection
It would be unwise to add bespoke logic to round up to the nearest whole number in such cases as this would require an assumption that this is the intention of the prescriber.
A possible solution that will be discussed with the owners of the NHS dm+d would be to express the strength in a way that uses absolute values.
For example;
- Oxybutynon 5mg/15ml bladder irrigation vials, VPI strength = 1 mg / 3 ml
- Methotrexate 25mg/3ml solution for injection pre-filled syringes, VPI strength = 25 mg / 3 ml