@precisa-saude/fhir-ocr-utils 0.38.0 → 0.38.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/cli.js +67 -37
- package/dist/index.cjs +70 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +66 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17,6 +17,9 @@ var UNAMBIGUOUS_SHORT_NAMES = /* @__PURE__ */ new Set([
|
|
|
17
17
|
"alt",
|
|
18
18
|
"ast",
|
|
19
19
|
"bun",
|
|
20
|
+
// Creatina quinase: Fleury e a Quest imprimem só "CK", e sem a sigla o
|
|
21
|
+
// modelo ficava sem âncora e encaixava o valor em outro exame (PRE-486).
|
|
22
|
+
"ck",
|
|
20
23
|
"wbc",
|
|
21
24
|
"rbc",
|
|
22
25
|
"mcv",
|
|
@@ -119,6 +122,37 @@ var QUALITATIVE_VALUE_TERMS = /* @__PURE__ */ new Set([
|
|
|
119
122
|
"undetectable",
|
|
120
123
|
"yellow"
|
|
121
124
|
]);
|
|
125
|
+
var GENETIC_CONTEXT_PATTERNS = [
|
|
126
|
+
/\b[nx][mrpc]_\d{6,}/,
|
|
127
|
+
// RefSeq: NM_000384.2, NP_, NR_, XM_
|
|
128
|
+
/\bens[gtp]\d{6,}/,
|
|
129
|
+
// Ensembl: ENSG00000084674
|
|
130
|
+
/\bp\.[a-z]{3}\d/,
|
|
131
|
+
// HGVS proteína: p.Trp448*
|
|
132
|
+
/\bc\.\d+[acgt]?[>_+-]/,
|
|
133
|
+
// HGVS codificante: c.1234A>G, c.76_78del
|
|
134
|
+
/\brs\d{4,}\b/,
|
|
135
|
+
// dbSNP
|
|
136
|
+
/\bgenes?\b/,
|
|
137
|
+
/\bvariante?s?\b/,
|
|
138
|
+
/\bexons?\b/,
|
|
139
|
+
/\bzygosity\b/,
|
|
140
|
+
/\bzigosidade\b/,
|
|
141
|
+
/\balleles?\b/,
|
|
142
|
+
/\balelos?\b/,
|
|
143
|
+
/\bmutations?\b/,
|
|
144
|
+
/\bmutac(ao|oes)\b/,
|
|
145
|
+
/\bpathogenic/,
|
|
146
|
+
/\bpatogenic/,
|
|
147
|
+
/\bheterozyg/,
|
|
148
|
+
/\bhomozyg/,
|
|
149
|
+
/\bheterozigot/,
|
|
150
|
+
/\bhomozigot/,
|
|
151
|
+
/\bsequence change\b/
|
|
152
|
+
];
|
|
153
|
+
var SUBTYPE_AFTER = {
|
|
154
|
+
CK: /^[\s-]*mb\b/i
|
|
155
|
+
};
|
|
122
156
|
|
|
123
157
|
// src/body-region.ts
|
|
124
158
|
var WHOLE_BODY_COMPOSITION_CODES = /* @__PURE__ */ new Set([
|
|
@@ -267,19 +301,37 @@ function isSectionName(matched) {
|
|
|
267
301
|
return URINALYSIS_SECTION_NAMES.has(matched) || URINALYSIS_SECTION_NAMES.has(matched.replace(/s$/, ""));
|
|
268
302
|
}
|
|
269
303
|
var MENTIONS_URINE = /(?<![\p{L}\p{N}])urin[ae](?![\p{L}\p{N}])/u;
|
|
304
|
+
var SEDIMENT_FIELD_UNIT = /\/(?:hpf|lpf)(?![\p{L}\p{N}])/u;
|
|
305
|
+
function hasUrineCue(line) {
|
|
306
|
+
return MENTIONS_URINE.test(line) || SEDIMENT_FIELD_UNIT.test(line);
|
|
307
|
+
}
|
|
308
|
+
function kindOf(line) {
|
|
309
|
+
const text = line.text.trim();
|
|
310
|
+
if (!text) return "blank";
|
|
311
|
+
if (URINALYSIS_HEADER.test(text) && !/\d/.test(text)) return "header";
|
|
312
|
+
if (line.foreign) return "foreign";
|
|
313
|
+
if (line.urine) return "urine";
|
|
314
|
+
return line.known || line.hasValue ? "neutral" : "unknown";
|
|
315
|
+
}
|
|
270
316
|
function urinalysisLineIndexes(lines) {
|
|
317
|
+
const kinds = lines.map(kindOf);
|
|
318
|
+
const continuesAsUrine = (from) => {
|
|
319
|
+
const next = kinds.findIndex(
|
|
320
|
+
(kind, index) => index > from && (kind === "urine" || kind === "foreign" || kind === "header")
|
|
321
|
+
);
|
|
322
|
+
return next !== -1 && kinds[next] === "urine";
|
|
323
|
+
};
|
|
271
324
|
const inside = /* @__PURE__ */ new Set();
|
|
272
325
|
let open = false;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (URINALYSIS_HEADER.test(text) && !/\d/.test(text)) {
|
|
326
|
+
kinds.forEach((kind, index) => {
|
|
327
|
+
if (kind === "header") {
|
|
276
328
|
open = true;
|
|
277
329
|
return;
|
|
278
330
|
}
|
|
279
|
-
if (!open ||
|
|
331
|
+
if (!open || kind === "blank") {
|
|
280
332
|
return;
|
|
281
333
|
}
|
|
282
|
-
if (
|
|
334
|
+
if (kind === "foreign" || kind === "unknown" && !continuesAsUrine(index)) {
|
|
283
335
|
open = false;
|
|
284
336
|
return;
|
|
285
337
|
}
|
|
@@ -323,7 +375,7 @@ function applyUrinalysisSection(normalizedText, candidates, deps) {
|
|
|
323
375
|
const known = deps.patterns.some(
|
|
324
376
|
({ name, regex }) => !matchesIn(text, name, regex).next().done
|
|
325
377
|
);
|
|
326
|
-
return { foreign: false, hasValue: deps.hasValue(text), known, text };
|
|
378
|
+
return { foreign: false, hasValue: deps.hasValue(text), known, text, urine: hasUrineCue(text) };
|
|
327
379
|
});
|
|
328
380
|
for (const candidate of resolved) {
|
|
329
381
|
let index = lineStarts.length - 1;
|
|
@@ -331,7 +383,9 @@ function applyUrinalysisSection(normalizedText, candidates, deps) {
|
|
|
331
383
|
const line = lines[index];
|
|
332
384
|
line.known = true;
|
|
333
385
|
const matched = normalizedText.slice(candidate.start, candidate.end);
|
|
334
|
-
if (
|
|
386
|
+
if (candidate.entries.some((e) => deps.urineCodes.has(e.code))) {
|
|
387
|
+
line.urine = true;
|
|
388
|
+
} else if (!isSectionName(matched)) {
|
|
335
389
|
line.foreign = true;
|
|
336
390
|
}
|
|
337
391
|
}
|
|
@@ -404,40 +458,13 @@ function foldCommas(text) {
|
|
|
404
458
|
(comma, space, offset) => startsWithCatalogName(text.slice(offset + 1 + space.length)) ? comma : " "
|
|
405
459
|
);
|
|
406
460
|
}
|
|
407
|
-
var GENETIC_CONTEXT_PATTERNS = [
|
|
408
|
-
/\b[nx][mrpc]_\d{6,}/,
|
|
409
|
-
// RefSeq: NM_000384.2, NP_, NR_, XM_
|
|
410
|
-
/\bens[gtp]\d{6,}/,
|
|
411
|
-
// Ensembl: ENSG00000084674
|
|
412
|
-
/\bp\.[a-z]{3}\d/,
|
|
413
|
-
// HGVS proteína: p.Trp448*
|
|
414
|
-
/\bc\.\d+[acgt]?[>_+-]/,
|
|
415
|
-
// HGVS codificante: c.1234A>G, c.76_78del
|
|
416
|
-
/\brs\d{4,}\b/,
|
|
417
|
-
// dbSNP
|
|
418
|
-
/\bgenes?\b/,
|
|
419
|
-
/\bvariante?s?\b/,
|
|
420
|
-
/\bexons?\b/,
|
|
421
|
-
/\bzygosity\b/,
|
|
422
|
-
/\bzigosidade\b/,
|
|
423
|
-
/\balleles?\b/,
|
|
424
|
-
/\balelos?\b/,
|
|
425
|
-
/\bmutations?\b/,
|
|
426
|
-
/\bmutac(ao|oes)\b/,
|
|
427
|
-
/\bpathogenic/,
|
|
428
|
-
/\bpatogenic/,
|
|
429
|
-
/\bheterozyg/,
|
|
430
|
-
/\bhomozyg/,
|
|
431
|
-
/\bheterozigot/,
|
|
432
|
-
/\bhomozigot/,
|
|
433
|
-
/\bsequence change\b/
|
|
434
|
-
];
|
|
435
461
|
var DIGIT_PATTERN = /\d/;
|
|
436
462
|
var cachedUnitTokens = null;
|
|
437
463
|
function getUnitTokens() {
|
|
438
464
|
if (!cachedUnitTokens) {
|
|
465
|
+
const isExamName = (t) => URINALYSIS_SECTION_NAMES.has(t) || getNamePatterns().has(t);
|
|
439
466
|
cachedUnitTokens = new Set(
|
|
440
|
-
Object.keys(UNIT_TO_UCUM).map((unit) => normalize(unit).trim()).filter(
|
|
467
|
+
Object.keys(UNIT_TO_UCUM).map((unit) => normalize(unit).trim()).filter((unit) => unit && !isExamName(unit))
|
|
441
468
|
);
|
|
442
469
|
}
|
|
443
470
|
return cachedUnitTokens;
|
|
@@ -644,6 +671,9 @@ function findBiomarkersInText(ocrText) {
|
|
|
644
671
|
if (qualifiedByBodyRegion(entry.code, before) || followedByPercent(entry.code, after)) {
|
|
645
672
|
continue;
|
|
646
673
|
}
|
|
674
|
+
if (SUBTYPE_AFTER[entry.code]?.test(after)) {
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
647
677
|
if (girth && SKINFOLD_SITE_CODES.has(entry.code)) {
|
|
648
678
|
continue;
|
|
649
679
|
}
|