Checking extracted lab values against units and ranges catches misreads before they are saved: confirm the unit is one the test can carry, confirm the value sits inside wide limits only a misread could cross, and confirm the printed flag agrees with the extracted value and range. These checks test the extraction, never the patient.
Lab value checks that catch extraction errors, not clinical problems
A lab value check, in this post, is a rule that compares extracted fields with each other and with the printed page to find reading mistakes. It asks whether the data was copied correctly. It never asks whether a result is good or bad for the patient; that belongs to clinicians.
The line matters because the same comparison can serve two purposes. "Glucose is above the printed range" is a clinical observation when a clinician reads it. In an extraction pipeline, the only question is whether the extracted number, range and flag tell a consistent story. If they do, the data passes, whatever the number is. If they do not, something was misread, and a person looks at the page.
Three kinds of check cover most extraction errors in lab results:
- Unit and test pairs. Is the extracted unit one this test is reported in?
- Plausibility limits. Is the value inside limits so wide that only a misplaced decimal, a merged row or a wrong column could cross them?
- Flag agreement. Does the printed high or low flag match where the value falls against the printed range?
A fourth, simpler group checks the shape of each field: the result field holds a number or a known text result, the range field holds a range, the flag field holds a short code. Shape checks catch shifted columns and are worth running first.
Every rule here compares extracted data with the source page. The CLIA test report standard at 42 CFR 493.1291 on the eCFR requires a report to indicate the test result and, if applicable, the units of measurement or interpretation, and it says reference intervals are determined by the laboratory performing the tests. So the printed unit and range are the lab's own, and a check should compare against them rather than against a range from somewhere else.
The rule table
This table lists each rule with an example failure and the action. The values are fictional examples chosen to show the rule.
| Rule | Example failure | Action |
|---|---|---|
| Value field holds a number or known text | Result reads "mg/dL" | Reject the row and re-read the table |
| Unit is in the allowed list for the test | Hemoglobin with unit "mmol/L" from a lab whose reports always print g/dL | Send to review |
| Unit is present when the test needs one | Sodium 139 with no unit | Send to review |
| Value inside the team's plausibility limits | Glucose read as 9200 mg/dL where the page shows 92 | Send to review |
| Range parses as low-high, less-than or text | Range reads "136" | Send to review |
| Printed flag agrees with value and range | Value 4.2, range 3.5-5.1, flag H | Send to review |
| Value outside range with no printed flag | Value 104, range 70-99, no flag | Pass with a note |
| Unit spelling differs from the lab's usual form | "mg/dl" instead of "mg/dL" | Pass with a note |
Three actions are enough. Reject means the row is unusable as read and the table needs a second pass. Send to review means a person compares the field with the page. Pass with a note saves the row and records what the check saw, so a pattern can be found later.
Does the extracted unit fit the lab test?
A unit and test pair rule checks that the extracted unit is one the test is actually reported in. Each test gets a short list of allowed units, built from the reports your team receives. An extracted unit outside that list usually means the unit was read from the wrong row or column, or that OCR misread a character.
Building the allowed list is mostly a matter of collecting what you see. Take a sample of reports from each lab you receive, list each test with every unit printed beside it, and review the list with someone who knows the reports. Some tests carry one unit everywhere. Others carry different units from different labs, and both belong in the list for that test, tied to the lab that prints each one.
Unit strings need care before they are compared. The UCUM specification defines a standard way to write units "to facilitate unambiguous electronic communication of quantities together with their units". It defines case-sensitive symbols and says case-insensitive symbols are incompatible with them, and it treats text in curly braces as annotations that "do not contribute to the semantics of the unit". For a check, that means two things. Compare the printed unit after a defined clean-up, not as raw text. And keep the printed unit exactly as it appeared, so the check never hides what the lab wrote.
Mapping printed unit spellings to standard codes is its own step, covered in the guide to UCUM units in lab data. The pair rule can run on either the printed unit or the mapped code, as long as the allowed list uses the same form.
What a unit failure tells you
A unit failure is a clue about where the reading went wrong. A unit that belongs to the row above points to a row shift. A unit that is a number points to a column shift. A unit that is almost right, such as "rng/dL" for "mg/dL", points to an OCR character error. A unit that is correct for the test but new for this lab may be a real change on the lab's side, which deserves a note rather than a rejection.
Never fix a unit by converting the value. If the unit does not fit, the row goes to a person. Converting a value to make a rule pass changes the record, and the original report no longer matches the data.
Lab value plausibility limits: ranges no result can reach
A plausibility limit is a wide boundary for each test, set by your team, that only a reading error should cross. It is not a reference range and says nothing about health. It catches a dropped decimal point, two merged numbers or a value from the wrong column, which land far outside anything the source reports contain.
The safest way to set a limit is from your own data. Take the extracted values for a test from a large sample of reviewed reports and look at the spread. Then set the limit well beyond it, for example at ten times the highest value your reviewers have approved and at zero or a small fraction of the lowest. A limit set that wide does not depend on anyone's judgment about what a patient could show. It only says that a number this far outside everything the lab has sent before is more likely a misread than a result.
Limits should also follow the unit. A limit set for a test in one unit is meaningless for the same test in another, so key each limit by test and unit together. When the unit check fails, skip the limit check for that row; it would only add a second, confusing failure.
Typical misreads a limit catches
These fictional examples show the errors plausibility limits are built for:
- A value of 1.38 read as 138 because OCR missed the decimal point.
- A value of 92 read as 9299 because the next column's text ran into it.
- A value of 6.1 read as 61 because a smudge hid the decimal.
- A count printed with a thousands separator, such as 1,250, read as 1.250.
Each produces a number far outside the spread of approved values, and each is obvious when a person looks at the page. None of them is a clinical event, and the check should never be described as one.
Limits need upkeep. When a new lab or a new unit appears, the spread for that test changes, and limits based on the old spread may be too tight. Review limit failures in batches. If reviewers keep approving values the limit flagged, widen it.
Does the printed flag agree with the extracted value and range?
A flag agreement check compares the printed abnormal flag, such as H or L, with where the extracted value falls against the extracted range. When the three agree, the row passes. When they disagree, at least one of the three fields was probably misread, or the range belongs to another row, and a person checks the page.
The meaning of the common flags is set out in the HL7 v3 ObservationInterpretation code system. It defines H as a quantitative result "above the upper limit of the reference range" and L as one "below the lower limit of the reference range", with HH and LL for critical high and critical low. Labs print their own flag styles, and the guide to how abnormal flags are printed on lab reports covers the variations.
The check itself is a short comparison:
- Parse the range into a low and a high, or a single limit for less-than or greater-than ranges.
- Work out where the value falls: below the low, inside, or above the high.
- Compare with the printed flag: H with above, L with below, no flag with inside.
What a disagreement means for the extraction
A disagreement points to the field that was misread. Some common patterns, with fictional values:
- Flag H, value inside range. Value 4.2, range 3.5-5.1, flag H. The flag may belong to the row below, or the value may have lost a digit.
- Flag L, value above range. Often a decimal error in the value or a range read from another row.
- Value outside range, no flag. The flag may have been missed, especially if the lab prints it in bold or a separate narrow column. Or the lab may simply not have printed one. Your own reviewed history with that lab tells you which is likelier, and decides whether this earns a note or a review.
- Flag present, range missing. The range may have wrapped onto another line or been read as part of a comment.
The check does not decide which field is right. It says the row is not consistent and points a reviewer at it.
Ranges that cannot be compared
Some printed ranges do not reduce to a low and a high. Text ranges such as "Negative", ranges that differ by age or sex printed together, and ranges with a footnote all need care. When the range cannot be parsed into a single comparison, skip the flag check and pass with a note rather than guessing.
When a lab value check should not block entry
A lab value check should not block entry when a failure is more likely to reflect the lab's own style than a reading error, or when blocking would hold back other correct results. Those go to review or pass with a note. Only a row unusable as read, such as one with a unit in the value field, should stop.
Blocking has a cost. A lab report usually carries many results, and a rule that stops the whole report over one doubtful row delays every correct result on it. A better default is to save the rows that pass, hold the doubtful rows in review, and keep the report linked to both, so nothing is lost and nothing doubtful is saved without a person.
Some failures are worth recording but not reviewing one by one:
- a unit written in a different case or spacing from the lab's usual form,
- a value outside the printed range with no flag, where the lab is known to omit flags,
- a range that could not be parsed, where the value and unit passed every other rule.
Others always need a person:
- a unit that does not fit the test,
- a value beyond the plausibility limits,
- a flag that contradicts the value and range,
- a value that changed from an earlier report for the same test and date.
Checks like these work alongside confidence scores. A confidence score says how sure the reading step was about a field. A rule says whether the fields agree with each other. A field can have a high score and still fail a rule, and that combination is worth a person's time. The human review category covers confidence scores, thresholds and review queues in depth.
Rule failures also show where a lab's layout differs from what your rules expect. The post on lab report formats from different labs covers planning for that variety, and the tour of the parts of a lab report for data entry lists the fields these rules compare. In Schema Care, the customer sets the confidence threshold below which a field goes to review instead of into their system; the threshold demo shows that slider on a fictional sample.