@precisa-saude/fhir 0.33.0 → 0.34.0
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 +2 -0
- package/dist/{chunk-ZCIZUBMR.cjs → chunk-376KM7IL.cjs} +10 -3
- package/dist/chunk-376KM7IL.cjs.map +1 -0
- package/dist/{chunk-KS2YZBAS.js → chunk-K3VZ3F5Z.js} +8 -2
- package/dist/chunk-K3VZ3F5Z.js.map +1 -0
- package/dist/{chunk-X5WVIJGG.js → chunk-NJM45WAH.js} +8 -1
- package/dist/chunk-NJM45WAH.js.map +1 -0
- package/dist/{chunk-FGZXQWSR.cjs → chunk-NKDUVSDK.cjs} +8 -2
- package/dist/chunk-NKDUVSDK.cjs.map +1 -0
- package/dist/{chunk-WXCX5TJJ.js → chunk-P4G534AQ.js} +444 -60
- package/dist/chunk-P4G534AQ.js.map +1 -0
- package/dist/{chunk-LXKFVJF4.cjs → chunk-VKLWTTUO.cjs} +445 -61
- package/dist/chunk-VKLWTTUO.cjs.map +1 -0
- package/dist/cli.js +1237 -847
- package/dist/{converter-DZH9x52r.d.cts → converter-DP8VkkO3.d.cts} +9 -1
- package/dist/{converter-D1Q84Oc9.d.ts → converter-UygMzWlL.d.ts} +9 -1
- package/dist/converter.cjs +3 -2
- package/dist/converter.cjs.map +1 -1
- package/dist/converter.d.cts +3 -2
- package/dist/converter.d.ts +3 -2
- package/dist/converter.js +2 -1
- package/dist/{fhir-types-B1KQmlRb.d.ts → fhir-types-Cn5WFbOI.d.cts} +5 -0
- package/dist/{fhir-types-B1KQmlRb.d.cts → fhir-types-Cn5WFbOI.d.ts} +5 -0
- package/dist/importer.cjs +2 -2
- package/dist/importer.d.cts +3 -1
- package/dist/importer.d.ts +3 -1
- package/dist/importer.js +1 -1
- package/dist/index.cjs +11 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/reference-ranges.cjs +6 -2
- package/dist/reference-ranges.cjs.map +1 -1
- package/dist/reference-ranges.d.cts +83 -1
- package/dist/reference-ranges.d.ts +83 -1
- package/dist/reference-ranges.js +7 -3
- package/dist/validators.d.cts +1 -1
- package/dist/validators.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-FGZXQWSR.cjs.map +0 -1
- package/dist/chunk-KS2YZBAS.js.map +0 -1
- package/dist/chunk-LXKFVJF4.cjs.map +0 -1
- package/dist/chunk-WXCX5TJJ.js.map +0 -1
- package/dist/chunk-X5WVIJGG.js.map +0 -1
- package/dist/chunk-ZCIZUBMR.cjs.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -4412,628 +4412,89 @@ function resolveUcum(unit, biomarkerCode) {
|
|
|
4412
4412
|
return isUcumCode(unit) ? unit : void 0;
|
|
4413
4413
|
}
|
|
4414
4414
|
|
|
4415
|
-
// src/
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
case "L":
|
|
4422
|
-
return "L";
|
|
4423
|
-
// Low
|
|
4424
|
-
default:
|
|
4425
|
-
return "N";
|
|
4426
|
-
}
|
|
4427
|
-
}
|
|
4428
|
-
function interpretationDisplay(flag) {
|
|
4429
|
-
switch (flag) {
|
|
4430
|
-
case "H":
|
|
4431
|
-
return "High";
|
|
4432
|
-
case "L":
|
|
4433
|
-
return "Low";
|
|
4434
|
-
default:
|
|
4435
|
-
return "Normal";
|
|
4436
|
-
}
|
|
4437
|
-
}
|
|
4438
|
-
var SEX_CODING = {
|
|
4439
|
-
female: {
|
|
4440
|
-
code: "female",
|
|
4441
|
-
display: "Female",
|
|
4442
|
-
system: "http://hl7.org/fhir/administrative-gender"
|
|
4415
|
+
// src/reference-ranges.ts
|
|
4416
|
+
var biomarkerRangeDefinitions = {
|
|
4417
|
+
Albumin_Creatinine_Ratio: {
|
|
4418
|
+
default: { max: 30, min: 0, optimalMax: 20, optimalMin: 0, unit: "mg/g" },
|
|
4419
|
+
kind: "decision-threshold",
|
|
4420
|
+
source: "tietz-7ed-2015"
|
|
4443
4421
|
},
|
|
4444
|
-
|
|
4445
|
-
}
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4422
|
+
Adiponectin: {
|
|
4423
|
+
default: { max: 26, min: 4, optimalMax: 20, optimalMin: 8, unit: "mcg/mL" },
|
|
4424
|
+
kind: "reference-interval",
|
|
4425
|
+
source: "tietz-7ed-2015"
|
|
4426
|
+
},
|
|
4427
|
+
ADMA: {
|
|
4428
|
+
default: { max: 0.7, min: 0.3, optimalMax: 0.55, optimalMin: 0.3, unit: "umol/L" },
|
|
4429
|
+
kind: "reference-interval",
|
|
4430
|
+
source: "nemeth-adma-2017"
|
|
4431
|
+
},
|
|
4432
|
+
AFP: {
|
|
4433
|
+
default: { max: 10, min: 0, optimalMax: 8, optimalMin: 0, unit: "ng/mL" },
|
|
4434
|
+
kind: "reference-interval",
|
|
4435
|
+
source: "sturgeon-nacb-2008"
|
|
4436
|
+
},
|
|
4437
|
+
Albumin_Globulin_Ratio: {
|
|
4438
|
+
default: { max: 2.5, min: 1, optimalMax: 2.2, optimalMin: 1.2, unit: "" },
|
|
4439
|
+
kind: "reference-interval",
|
|
4440
|
+
source: "tietz-7ed-2015"
|
|
4441
|
+
},
|
|
4442
|
+
Albumin: {
|
|
4443
|
+
default: { max: 5, min: 3.5, optimalMax: 4.8, optimalMin: 4, unit: "g/dL" },
|
|
4444
|
+
kind: "reference-interval",
|
|
4445
|
+
source: "pns-bioquimica-2019"
|
|
4446
|
+
},
|
|
4447
|
+
AlkalinePhosphatase: {
|
|
4448
|
+
default: { max: 147, min: 44, optimalMax: 120, optimalMin: 50, unit: "U/L" },
|
|
4449
|
+
kind: "reference-interval",
|
|
4450
|
+
source: "tietz-7ed-2015",
|
|
4451
|
+
variants: [
|
|
4450
4452
|
{
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
}
|
|
4455
|
-
];
|
|
4456
|
-
};
|
|
4457
|
-
if (observation.referenceRanges && observation.referenceRanges.length > 0) {
|
|
4458
|
-
return observation.referenceRanges.flatMap((r) => toRanges(r.low, r.high, r.appliesTo));
|
|
4459
|
-
}
|
|
4460
|
-
return toRanges(observation.referenceMin, observation.referenceMax);
|
|
4461
|
-
};
|
|
4462
|
-
function labObservationToFHIR(observation, patientId, laboratoryName) {
|
|
4463
|
-
const loincCode = codeToLoinc(observation.biomarkerCode);
|
|
4464
|
-
const sourceUnit = observation.unit || getDefaultUnit(observation.biomarkerCode) || observation.unit;
|
|
4465
|
-
const ucumUnit = resolveUcum(sourceUnit, observation.biomarkerCode);
|
|
4466
|
-
const quantity = (value) => ({
|
|
4467
|
-
...ucumUnit ? { code: ucumUnit, system: "http://unitsofmeasure.org" } : {},
|
|
4468
|
-
...sourceUnit ? { unit: sourceUnit } : {},
|
|
4469
|
-
value
|
|
4470
|
-
});
|
|
4471
|
-
const isQualitative = observation.isQualitative || typeof observation.value === "string";
|
|
4472
|
-
const fhirObs = {
|
|
4473
|
-
category: [
|
|
4453
|
+
ageMin: 18,
|
|
4454
|
+
range: { max: 147, min: 44, optimalMax: 120, optimalMin: 50, unit: "U/L" },
|
|
4455
|
+
sex: "M"
|
|
4456
|
+
},
|
|
4474
4457
|
{
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
display: "Laboratory",
|
|
4479
|
-
system: "http://terminology.hl7.org/CodeSystem/observation-category"
|
|
4480
|
-
}
|
|
4481
|
-
]
|
|
4458
|
+
ageMin: 18,
|
|
4459
|
+
range: { max: 104, min: 35, optimalMax: 90, optimalMin: 40, unit: "U/L" },
|
|
4460
|
+
sex: "F"
|
|
4482
4461
|
}
|
|
4483
|
-
]
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
coding: [
|
|
4491
|
-
...loincCode ? [
|
|
4492
|
-
{
|
|
4493
|
-
code: loincCode,
|
|
4494
|
-
display: observation.biomarkerName,
|
|
4495
|
-
system: LOINC_SYSTEM
|
|
4496
|
-
}
|
|
4497
|
-
] : [],
|
|
4498
|
-
{
|
|
4499
|
-
code: observation.biomarkerCode,
|
|
4500
|
-
display: observation.biomarkerName,
|
|
4501
|
-
system: BIOMARKER_CODE_SYSTEM
|
|
4502
|
-
}
|
|
4503
|
-
],
|
|
4504
|
-
text: observation.biomarkerName
|
|
4505
|
-
},
|
|
4506
|
-
effectiveDateTime: observation.collectionDate,
|
|
4507
|
-
id: `${observation.reportId}-${observation.biomarkerCode}`,
|
|
4508
|
-
interpretation: [
|
|
4462
|
+
]
|
|
4463
|
+
},
|
|
4464
|
+
ALT: {
|
|
4465
|
+
default: { max: 35, min: 0, optimalMax: 25, optimalMin: 0, unit: "U/L" },
|
|
4466
|
+
kind: "reference-interval",
|
|
4467
|
+
source: "tietz-7ed-2015",
|
|
4468
|
+
variants: [
|
|
4509
4469
|
{
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
system: "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"
|
|
4515
|
-
}
|
|
4516
|
-
]
|
|
4517
|
-
}
|
|
4518
|
-
],
|
|
4519
|
-
performer: laboratoryName ? [{ display: laboratoryName }] : void 0,
|
|
4520
|
-
resourceType: "Observation",
|
|
4521
|
-
status: "final",
|
|
4522
|
-
subject: {
|
|
4523
|
-
reference: `Patient/${patientId}`
|
|
4524
|
-
}
|
|
4525
|
-
};
|
|
4526
|
-
if (isQualitative) {
|
|
4527
|
-
fhirObs.valueString = String(observation.value);
|
|
4528
|
-
} else {
|
|
4529
|
-
fhirObs.valueQuantity = quantity(observation.value);
|
|
4530
|
-
const referenceRange = buildReferenceRanges(observation, quantity);
|
|
4531
|
-
if (referenceRange.length > 0) fhirObs.referenceRange = referenceRange;
|
|
4532
|
-
}
|
|
4533
|
-
return fhirObs;
|
|
4534
|
-
}
|
|
4535
|
-
function labReportToFHIR(report, patientId, observationIds) {
|
|
4536
|
-
let status;
|
|
4537
|
-
switch (report.processingStatus) {
|
|
4538
|
-
case "complete":
|
|
4539
|
-
status = "final";
|
|
4540
|
-
break;
|
|
4541
|
-
case "partial":
|
|
4542
|
-
status = "partial";
|
|
4543
|
-
break;
|
|
4544
|
-
case "pending_review":
|
|
4545
|
-
status = "preliminary";
|
|
4546
|
-
break;
|
|
4547
|
-
default:
|
|
4548
|
-
status = "final";
|
|
4549
|
-
}
|
|
4550
|
-
return {
|
|
4551
|
-
category: [
|
|
4470
|
+
ageMin: 18,
|
|
4471
|
+
range: { max: 56, min: 7, optimalMax: 35, optimalMin: 10, unit: "U/L" },
|
|
4472
|
+
sex: "M"
|
|
4473
|
+
},
|
|
4552
4474
|
{
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
display: "Laboratory",
|
|
4557
|
-
system: "http://terminology.hl7.org/CodeSystem/v2-0074"
|
|
4558
|
-
}
|
|
4559
|
-
]
|
|
4475
|
+
ageMin: 18,
|
|
4476
|
+
range: { max: 45, min: 7, optimalMax: 30, optimalMin: 10, unit: "U/L" },
|
|
4477
|
+
sex: "F"
|
|
4560
4478
|
}
|
|
4561
|
-
]
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
conclusionCode: report.overallStatus === "ANORMAL" ? [
|
|
4479
|
+
]
|
|
4480
|
+
},
|
|
4481
|
+
// AMH — fortemente dependente de idade e sexo. As variantes femininas por
|
|
4482
|
+
// faixa etária são a referência clínica; o `default` foi ajustado para
|
|
4483
|
+
// refletir uma faixa adulta conservadora (~18-40 anos, mulheres em idade
|
|
4484
|
+
// reprodutiva geral). optimalMax anterior (6.9 ng/mL) sobrepunha-se a
|
|
4485
|
+
// valores sugestivos de SOP ou risco de OHSS; clinicamente, valores acima
|
|
4486
|
+
// de ~4 ng/mL já merecem investigação.
|
|
4487
|
+
AMH: {
|
|
4488
|
+
default: { max: 6, min: 1, optimalMax: 4, optimalMin: 1.5, unit: "ng/mL" },
|
|
4489
|
+
kind: "reference-interval",
|
|
4490
|
+
source: "tietz-7ed-2015",
|
|
4491
|
+
variants: [
|
|
4575
4492
|
{
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
}
|
|
4582
|
-
]
|
|
4583
|
-
}
|
|
4584
|
-
] : void 0,
|
|
4585
|
-
effectiveDateTime: report.collectionDate,
|
|
4586
|
-
id: report.reportId,
|
|
4587
|
-
issued: report.createdAt,
|
|
4588
|
-
performer: report.laboratoryName ? [{ display: report.laboratoryName }] : void 0,
|
|
4589
|
-
resourceType: "DiagnosticReport",
|
|
4590
|
-
result: observationIds.map((id) => ({ reference: `Observation/${id}` })),
|
|
4591
|
-
status,
|
|
4592
|
-
subject: {
|
|
4593
|
-
reference: `Patient/${patientId}`
|
|
4594
|
-
}
|
|
4595
|
-
};
|
|
4596
|
-
}
|
|
4597
|
-
function userProfileToFHIR(profile) {
|
|
4598
|
-
const nameParts = profile.name.split(" ");
|
|
4599
|
-
const given = nameParts.slice(0, -1);
|
|
4600
|
-
const family = nameParts[nameParts.length - 1] || "";
|
|
4601
|
-
return {
|
|
4602
|
-
address: profile.address ? [
|
|
4603
|
-
{
|
|
4604
|
-
city: profile.address.city,
|
|
4605
|
-
country: profile.address.country || "BR",
|
|
4606
|
-
line: [
|
|
4607
|
-
profile.address.street && profile.address.number ? `${profile.address.street}, ${profile.address.number}` : profile.address.street,
|
|
4608
|
-
profile.address.complement
|
|
4609
|
-
].filter(Boolean),
|
|
4610
|
-
postalCode: profile.address.postalCode,
|
|
4611
|
-
state: profile.address.state
|
|
4612
|
-
}
|
|
4613
|
-
] : void 0,
|
|
4614
|
-
birthDate: profile.birthDate,
|
|
4615
|
-
gender: profile.gender,
|
|
4616
|
-
id: profile.userId,
|
|
4617
|
-
name: [
|
|
4618
|
-
{
|
|
4619
|
-
family,
|
|
4620
|
-
given: given.length > 0 ? given : void 0,
|
|
4621
|
-
text: profile.name
|
|
4622
|
-
}
|
|
4623
|
-
],
|
|
4624
|
-
resourceType: "Patient",
|
|
4625
|
-
telecom: [
|
|
4626
|
-
...profile.email ? [{ system: "email", value: profile.email }] : [],
|
|
4627
|
-
...profile.phone ? [{ system: "phone", value: profile.phone }] : []
|
|
4628
|
-
].length > 0 ? [
|
|
4629
|
-
...profile.email ? [{ system: "email", value: profile.email }] : [],
|
|
4630
|
-
...profile.phone ? [{ system: "phone", value: profile.phone }] : []
|
|
4631
|
-
] : void 0
|
|
4632
|
-
};
|
|
4633
|
-
}
|
|
4634
|
-
function labResultToFHIRBundle(report, observations, userProfile) {
|
|
4635
|
-
const patientId = userProfile.userId;
|
|
4636
|
-
const fhirObservations = observations.map((obs) => {
|
|
4637
|
-
const resource = labObservationToFHIR(
|
|
4638
|
-
{ ...obs, collectionDate: report.collectionDate },
|
|
4639
|
-
patientId,
|
|
4640
|
-
report.laboratoryName
|
|
4641
|
-
);
|
|
4642
|
-
return { fullUrl: entryFullUrl(resource), resource };
|
|
4643
|
-
});
|
|
4644
|
-
const observationIds = fhirObservations.map((entry) => entry.resource.id);
|
|
4645
|
-
const diagnosticReport = labReportToFHIR(report, patientId, observationIds);
|
|
4646
|
-
const fhirPatient = userProfileToFHIR(userProfile);
|
|
4647
|
-
return {
|
|
4648
|
-
entry: [
|
|
4649
|
-
{ fullUrl: entryFullUrl(fhirPatient), resource: fhirPatient },
|
|
4650
|
-
{ fullUrl: entryFullUrl(diagnosticReport), resource: diagnosticReport },
|
|
4651
|
-
...fhirObservations
|
|
4652
|
-
],
|
|
4653
|
-
resourceType: "Bundle",
|
|
4654
|
-
type: "collection"
|
|
4655
|
-
};
|
|
4656
|
-
}
|
|
4657
|
-
|
|
4658
|
-
// src/cli/commands/convert.ts
|
|
4659
|
-
async function convert(args, json) {
|
|
4660
|
-
const raw = await getInput(args[0]);
|
|
4661
|
-
const data = parseJson(
|
|
4662
|
-
raw,
|
|
4663
|
-
"JSON inv\xE1lido. Forne\xE7a um objeto com { report, observations, profile }."
|
|
4664
|
-
);
|
|
4665
|
-
if (!data.report || !data.observations || !data.profile) {
|
|
4666
|
-
exitWithError(
|
|
4667
|
-
'Formato esperado: { "report": LabReportData, "observations": LabObservationData[], "profile": UserProfileData }'
|
|
4668
|
-
);
|
|
4669
|
-
}
|
|
4670
|
-
const bundle = labResultToFHIRBundle(data.report, data.observations, data.profile);
|
|
4671
|
-
if (json) {
|
|
4672
|
-
outputJson(bundle);
|
|
4673
|
-
} else {
|
|
4674
|
-
outputText(JSON.stringify(bundle, null, 2));
|
|
4675
|
-
}
|
|
4676
|
-
}
|
|
4677
|
-
|
|
4678
|
-
// src/validators.ts
|
|
4679
|
-
function validateFHIRImportBundle(data) {
|
|
4680
|
-
const errors = [];
|
|
4681
|
-
if (!data || typeof data !== "object") {
|
|
4682
|
-
errors.push({ details: "Input must be a JSON object", field: "root" });
|
|
4683
|
-
return errors;
|
|
4684
|
-
}
|
|
4685
|
-
const bundle = data;
|
|
4686
|
-
if (bundle.resourceType !== "Bundle") {
|
|
4687
|
-
errors.push({
|
|
4688
|
-
details: `Expected resourceType "Bundle", got "${String(bundle.resourceType)}"`,
|
|
4689
|
-
field: "resourceType"
|
|
4690
|
-
});
|
|
4691
|
-
}
|
|
4692
|
-
if (!Array.isArray(bundle.entry)) {
|
|
4693
|
-
errors.push({ details: 'Bundle must contain an "entry" array', field: "entry" });
|
|
4694
|
-
} else if (bundle.entry.length === 0) {
|
|
4695
|
-
errors.push({ details: "Bundle entry array is empty", field: "entry" });
|
|
4696
|
-
}
|
|
4697
|
-
return errors;
|
|
4698
|
-
}
|
|
4699
|
-
|
|
4700
|
-
// src/importer.ts
|
|
4701
|
-
var MAX_OBSERVATIONS = 5e3;
|
|
4702
|
-
var MAX_FILE_SIZE = 15 * 1024 * 1024;
|
|
4703
|
-
function resolveBiomarkerCode(observation) {
|
|
4704
|
-
const coding = observation.code?.coding ?? [];
|
|
4705
|
-
const loincCode = coding.find((c) => c.system === LOINC_SYSTEM)?.code;
|
|
4706
|
-
const declaredCode = coding.find((c) => c.system === BIOMARKER_CODE_SYSTEM)?.code;
|
|
4707
|
-
const seenCodes = [
|
|
4708
|
-
...loincCode ? [`LOINC ${loincCode}`] : [],
|
|
4709
|
-
...declaredCode ? [`biomarker code ${declaredCode}`] : []
|
|
4710
|
-
];
|
|
4711
|
-
let reason;
|
|
4712
|
-
if (seenCodes.length > 0) {
|
|
4713
|
-
reason = `Unknown code: ${seenCodes.join(", ")}`;
|
|
4714
|
-
} else if (coding.length > 0) {
|
|
4715
|
-
const systems = [...new Set(coding.map((c) => c.system ?? "(sem system)"))];
|
|
4716
|
-
reason = `No code in a supported system (found: ${systems.join(", ")})`;
|
|
4717
|
-
} else {
|
|
4718
|
-
reason = "No code found in observation coding";
|
|
4719
|
-
}
|
|
4720
|
-
const fromLoinc = loincCode ? loincToCode(loincCode) : void 0;
|
|
4721
|
-
if (fromLoinc) return { internalCode: fromLoinc, loincCode, reason };
|
|
4722
|
-
if (declaredCode && isValidCode(declaredCode)) {
|
|
4723
|
-
const canonical = normalizeCode(declaredCode);
|
|
4724
|
-
return { internalCode: canonical, loincCode: codeToLoinc(canonical), reason };
|
|
4725
|
-
}
|
|
4726
|
-
return { loincCode, reason };
|
|
4727
|
-
}
|
|
4728
|
-
function extractFlag(observation) {
|
|
4729
|
-
const code = observation.interpretation?.[0]?.coding?.[0]?.code;
|
|
4730
|
-
if (code === "H" || code === "HH") return "H";
|
|
4731
|
-
if (code === "L" || code === "LL") return "L";
|
|
4732
|
-
return "";
|
|
4733
|
-
}
|
|
4734
|
-
function extractObservationsFromBundle(bundle) {
|
|
4735
|
-
const observations = [];
|
|
4736
|
-
const skipped = [];
|
|
4737
|
-
for (let i = 0; i < bundle.entry.length; i++) {
|
|
4738
|
-
const entry = bundle.entry[i];
|
|
4739
|
-
if (!entry.resource) {
|
|
4740
|
-
skipped.push({ index: i, reason: "Entry has no resource" });
|
|
4741
|
-
continue;
|
|
4742
|
-
}
|
|
4743
|
-
if (entry.resource.resourceType !== "Observation") {
|
|
4744
|
-
continue;
|
|
4745
|
-
}
|
|
4746
|
-
if (observations.length >= MAX_OBSERVATIONS) {
|
|
4747
|
-
skipped.push({ index: i, reason: `Maximum of ${MAX_OBSERVATIONS} observations exceeded` });
|
|
4748
|
-
continue;
|
|
4749
|
-
}
|
|
4750
|
-
observations.push(entry.resource);
|
|
4751
|
-
}
|
|
4752
|
-
return { observations, skipped };
|
|
4753
|
-
}
|
|
4754
|
-
function mapFHIRObservationToInternal(observation, index) {
|
|
4755
|
-
const { internalCode, loincCode, reason } = resolveBiomarkerCode(observation);
|
|
4756
|
-
if (!internalCode) {
|
|
4757
|
-
return {
|
|
4758
|
-
skipped: { index, loincCode, reason, resourceType: "Observation" }
|
|
4759
|
-
};
|
|
4760
|
-
}
|
|
4761
|
-
const definition = getDefinitionByCode(internalCode);
|
|
4762
|
-
let value;
|
|
4763
|
-
let unit = "";
|
|
4764
|
-
let isQualitative = false;
|
|
4765
|
-
if (observation.valueQuantity?.value !== void 0) {
|
|
4766
|
-
value = observation.valueQuantity.value;
|
|
4767
|
-
unit = observation.valueQuantity.unit || observation.valueQuantity.code || "";
|
|
4768
|
-
} else if (observation.valueString) {
|
|
4769
|
-
value = observation.valueString;
|
|
4770
|
-
isQualitative = true;
|
|
4771
|
-
} else {
|
|
4772
|
-
return {
|
|
4773
|
-
skipped: {
|
|
4774
|
-
index,
|
|
4775
|
-
loincCode,
|
|
4776
|
-
reason: "Observation has no value (valueQuantity or valueString)",
|
|
4777
|
-
resourceType: "Observation"
|
|
4778
|
-
}
|
|
4779
|
-
};
|
|
4780
|
-
}
|
|
4781
|
-
const collectionDate = observation.effectiveDateTime || observation.effectivePeriod?.start || "";
|
|
4782
|
-
if (!collectionDate) {
|
|
4783
|
-
return {
|
|
4784
|
-
skipped: {
|
|
4785
|
-
index,
|
|
4786
|
-
loincCode,
|
|
4787
|
-
reason: "Observation has no effectiveDateTime or effectivePeriod.start",
|
|
4788
|
-
resourceType: "Observation"
|
|
4789
|
-
}
|
|
4790
|
-
};
|
|
4791
|
-
}
|
|
4792
|
-
let referenceMin;
|
|
4793
|
-
let referenceMax;
|
|
4794
|
-
if (observation.referenceRange?.[0]) {
|
|
4795
|
-
referenceMin = observation.referenceRange[0].low?.value;
|
|
4796
|
-
referenceMax = observation.referenceRange[0].high?.value;
|
|
4797
|
-
}
|
|
4798
|
-
const imported = {
|
|
4799
|
-
biomarkerCode: internalCode,
|
|
4800
|
-
biomarkerName: definition?.names.pt[0] || definition?.names.en[0] || observation.code.text || internalCode,
|
|
4801
|
-
collectionDate,
|
|
4802
|
-
flag: extractFlag(observation),
|
|
4803
|
-
isQualitative,
|
|
4804
|
-
loincCode,
|
|
4805
|
-
referenceMax,
|
|
4806
|
-
referenceMin,
|
|
4807
|
-
unit: unit || definition?.unit || "",
|
|
4808
|
-
value
|
|
4809
|
-
};
|
|
4810
|
-
return { observation: imported };
|
|
4811
|
-
}
|
|
4812
|
-
function processImportBundle(data) {
|
|
4813
|
-
const validationErrors = validateFHIRImportBundle(data);
|
|
4814
|
-
if (validationErrors.length > 0) {
|
|
4815
|
-
return {
|
|
4816
|
-
errors: validationErrors,
|
|
4817
|
-
imported: [],
|
|
4818
|
-
skipped: [],
|
|
4819
|
-
totalProcessed: 0
|
|
4820
|
-
};
|
|
4821
|
-
}
|
|
4822
|
-
const bundle = data;
|
|
4823
|
-
const { observations, skipped } = extractObservationsFromBundle(bundle);
|
|
4824
|
-
const imported = [];
|
|
4825
|
-
const allSkipped = [...skipped];
|
|
4826
|
-
for (let i = 0; i < observations.length; i++) {
|
|
4827
|
-
const result = mapFHIRObservationToInternal(observations[i], i);
|
|
4828
|
-
if ("observation" in result) {
|
|
4829
|
-
imported.push(result.observation);
|
|
4830
|
-
} else {
|
|
4831
|
-
allSkipped.push(result.skipped);
|
|
4832
|
-
}
|
|
4833
|
-
}
|
|
4834
|
-
return {
|
|
4835
|
-
errors: [],
|
|
4836
|
-
imported,
|
|
4837
|
-
skipped: allSkipped,
|
|
4838
|
-
totalProcessed: observations.length
|
|
4839
|
-
};
|
|
4840
|
-
}
|
|
4841
|
-
|
|
4842
|
-
// src/cli/commands/import.ts
|
|
4843
|
-
async function importBundle(args, json) {
|
|
4844
|
-
const raw = await getInput(args[0]);
|
|
4845
|
-
const bundle = parseJson(raw, "JSON inv\xE1lido.");
|
|
4846
|
-
const result = processImportBundle(bundle);
|
|
4847
|
-
if (json) {
|
|
4848
|
-
outputJson(result);
|
|
4849
|
-
return;
|
|
4850
|
-
}
|
|
4851
|
-
outputText(`Processados: ${result.totalProcessed}`);
|
|
4852
|
-
outputText(`Importados: ${result.imported.length}`);
|
|
4853
|
-
outputText(`Ignorados: ${result.skipped.length}`);
|
|
4854
|
-
outputText(`Erros: ${result.errors.length}`);
|
|
4855
|
-
if (result.imported.length > 0) {
|
|
4856
|
-
outputText("\nObserva\xE7\xF5es importadas:");
|
|
4857
|
-
for (const obs of result.imported) {
|
|
4858
|
-
outputText(` ${obs.biomarkerCode} (${obs.loincCode}): ${obs.value} ${obs.unit}`);
|
|
4859
|
-
}
|
|
4860
|
-
}
|
|
4861
|
-
if (result.errors.length > 0) {
|
|
4862
|
-
outputText("\nErros:");
|
|
4863
|
-
for (const err of result.errors) {
|
|
4864
|
-
outputText(` ${err.field}: ${err.details}`);
|
|
4865
|
-
}
|
|
4866
|
-
}
|
|
4867
|
-
}
|
|
4868
|
-
|
|
4869
|
-
// src/cli/commands/list.ts
|
|
4870
|
-
import { parseArgs } from "util";
|
|
4871
|
-
async function list(args, json) {
|
|
4872
|
-
const { values } = parseArgs({
|
|
4873
|
-
args,
|
|
4874
|
-
options: {
|
|
4875
|
-
category: { type: "string" },
|
|
4876
|
-
visible: { default: false, type: "boolean" }
|
|
4877
|
-
},
|
|
4878
|
-
strict: false
|
|
4879
|
-
});
|
|
4880
|
-
let defs;
|
|
4881
|
-
if (values.category) {
|
|
4882
|
-
defs = getBiomarkersByCategory(values.category);
|
|
4883
|
-
if (defs.length === 0) {
|
|
4884
|
-
exitWithError(`Categoria n\xE3o encontrada ou vazia: ${values.category}`);
|
|
4885
|
-
}
|
|
4886
|
-
} else if (values.visible) {
|
|
4887
|
-
defs = getVisibleDefinitions();
|
|
4888
|
-
} else {
|
|
4889
|
-
defs = getAllDefinitions();
|
|
4890
|
-
}
|
|
4891
|
-
if (json) {
|
|
4892
|
-
outputJson(defs);
|
|
4893
|
-
return;
|
|
4894
|
-
}
|
|
4895
|
-
const rows = defs.map((d) => [
|
|
4896
|
-
d.code,
|
|
4897
|
-
d.loinc ?? "\u2014",
|
|
4898
|
-
d.names.pt[0] ?? "",
|
|
4899
|
-
d.unit ?? "\u2014",
|
|
4900
|
-
Array.isArray(d.category) ? d.category.join(", ") : d.category
|
|
4901
|
-
]);
|
|
4902
|
-
outputText(formatTable(["C\xF3digo", "LOINC", "Nome (pt)", "Unidade", "Categoria"], rows));
|
|
4903
|
-
outputText(`
|
|
4904
|
-
Total: ${defs.length} biomarcadores`);
|
|
4905
|
-
}
|
|
4906
|
-
|
|
4907
|
-
// src/cli/commands/loinc-map.ts
|
|
4908
|
-
async function loincMap(_args, json) {
|
|
4909
|
-
const defs = getAllDefinitions().filter((d) => d.loinc);
|
|
4910
|
-
if (json) {
|
|
4911
|
-
const map = Object.fromEntries(defs.map((d) => [d.loinc, d.code]));
|
|
4912
|
-
outputJson(map);
|
|
4913
|
-
return;
|
|
4914
|
-
}
|
|
4915
|
-
const rows = defs.map((d) => [d.loinc, d.code, d.names.pt[0] ?? d.names.en[0] ?? ""]);
|
|
4916
|
-
outputText(formatTable(["LOINC", "C\xF3digo", "Nome (pt)"], rows));
|
|
4917
|
-
outputText(`
|
|
4918
|
-
Total: ${rows.length} mapeamentos`);
|
|
4919
|
-
}
|
|
4920
|
-
|
|
4921
|
-
// src/cli/commands/lookup.ts
|
|
4922
|
-
function displayDefinition(def) {
|
|
4923
|
-
const cat = Array.isArray(def.category) ? def.category.join(", ") : def.category;
|
|
4924
|
-
outputText(
|
|
4925
|
-
[
|
|
4926
|
-
`Biomarcador: ${def.code}`,
|
|
4927
|
-
` LOINC: ${def.loinc ?? "\u2014"}`,
|
|
4928
|
-
` Nomes (pt): ${def.names.pt.join(", ")}`,
|
|
4929
|
-
` Nomes (en): ${def.names.en.join(", ")}`,
|
|
4930
|
-
` Categoria: ${cat}`,
|
|
4931
|
-
` Unidade: ${def.unit ?? "\u2014"}`,
|
|
4932
|
-
` Sexo: ${def.sex ?? "ambos"}`,
|
|
4933
|
-
` Vis\xEDvel: ${def.hidden ? "n\xE3o" : "sim"}`
|
|
4934
|
-
].join("\n")
|
|
4935
|
-
);
|
|
4936
|
-
}
|
|
4937
|
-
async function lookup(args, json) {
|
|
4938
|
-
const code = args[0];
|
|
4939
|
-
if (!code) exitWithError("Uso: fhir-bio lookup <c\xF3digo>");
|
|
4940
|
-
const def = getDefinitionByCode(code);
|
|
4941
|
-
if (!def) exitWithError(`Biomarcador n\xE3o encontrado: ${code}`);
|
|
4942
|
-
if (json) {
|
|
4943
|
-
outputJson(def);
|
|
4944
|
-
} else {
|
|
4945
|
-
displayDefinition(def);
|
|
4946
|
-
}
|
|
4947
|
-
}
|
|
4948
|
-
async function lookupLoinc(args, json) {
|
|
4949
|
-
const loinc = args[0];
|
|
4950
|
-
if (!loinc) exitWithError("Uso: fhir-bio lookup-loinc <loinc>");
|
|
4951
|
-
const def = getDefinitionByLoinc(loinc);
|
|
4952
|
-
if (!def) exitWithError(`Biomarcador n\xE3o encontrado para LOINC: ${loinc}`);
|
|
4953
|
-
if (json) {
|
|
4954
|
-
outputJson(def);
|
|
4955
|
-
} else {
|
|
4956
|
-
displayDefinition(def);
|
|
4957
|
-
}
|
|
4958
|
-
}
|
|
4959
|
-
|
|
4960
|
-
// src/cli/commands/range.ts
|
|
4961
|
-
import { parseArgs as parseArgs2 } from "util";
|
|
4962
|
-
|
|
4963
|
-
// src/reference-ranges.ts
|
|
4964
|
-
var biomarkerRangeDefinitions = {
|
|
4965
|
-
Albumin_Creatinine_Ratio: {
|
|
4966
|
-
default: { max: 30, min: 0, optimalMax: 20, optimalMin: 0, unit: "mg/g" },
|
|
4967
|
-
source: "tietz-7ed-2015"
|
|
4968
|
-
},
|
|
4969
|
-
Adiponectin: {
|
|
4970
|
-
default: { max: 26, min: 4, optimalMax: 20, optimalMin: 8, unit: "mcg/mL" },
|
|
4971
|
-
source: "tietz-7ed-2015"
|
|
4972
|
-
},
|
|
4973
|
-
ADMA: {
|
|
4974
|
-
default: { max: 0.7, min: 0.3, optimalMax: 0.55, optimalMin: 0.3, unit: "umol/L" },
|
|
4975
|
-
source: "nemeth-adma-2017"
|
|
4976
|
-
},
|
|
4977
|
-
AFP: {
|
|
4978
|
-
default: { max: 10, min: 0, optimalMax: 8, optimalMin: 0, unit: "ng/mL" },
|
|
4979
|
-
source: "sturgeon-nacb-2008"
|
|
4980
|
-
},
|
|
4981
|
-
Albumin_Globulin_Ratio: {
|
|
4982
|
-
default: { max: 2.5, min: 1, optimalMax: 2.2, optimalMin: 1.2, unit: "" },
|
|
4983
|
-
source: "tietz-7ed-2015"
|
|
4984
|
-
},
|
|
4985
|
-
Albumin: {
|
|
4986
|
-
default: { max: 5, min: 3.5, optimalMax: 4.8, optimalMin: 4, unit: "g/dL" },
|
|
4987
|
-
source: "pns-bioquimica-2019"
|
|
4988
|
-
},
|
|
4989
|
-
AlkalinePhosphatase: {
|
|
4990
|
-
default: { max: 147, min: 44, optimalMax: 120, optimalMin: 50, unit: "U/L" },
|
|
4991
|
-
source: "tietz-7ed-2015",
|
|
4992
|
-
variants: [
|
|
4993
|
-
{
|
|
4994
|
-
ageMin: 18,
|
|
4995
|
-
range: { max: 147, min: 44, optimalMax: 120, optimalMin: 50, unit: "U/L" },
|
|
4996
|
-
sex: "M"
|
|
4997
|
-
},
|
|
4998
|
-
{
|
|
4999
|
-
ageMin: 18,
|
|
5000
|
-
range: { max: 104, min: 35, optimalMax: 90, optimalMin: 40, unit: "U/L" },
|
|
5001
|
-
sex: "F"
|
|
5002
|
-
}
|
|
5003
|
-
]
|
|
5004
|
-
},
|
|
5005
|
-
ALT: {
|
|
5006
|
-
default: { max: 35, min: 0, optimalMax: 25, optimalMin: 0, unit: "U/L" },
|
|
5007
|
-
source: "tietz-7ed-2015",
|
|
5008
|
-
variants: [
|
|
5009
|
-
{
|
|
5010
|
-
ageMin: 18,
|
|
5011
|
-
range: { max: 56, min: 7, optimalMax: 35, optimalMin: 10, unit: "U/L" },
|
|
5012
|
-
sex: "M"
|
|
5013
|
-
},
|
|
5014
|
-
{
|
|
5015
|
-
ageMin: 18,
|
|
5016
|
-
range: { max: 45, min: 7, optimalMax: 30, optimalMin: 10, unit: "U/L" },
|
|
5017
|
-
sex: "F"
|
|
5018
|
-
}
|
|
5019
|
-
]
|
|
5020
|
-
},
|
|
5021
|
-
// AMH — fortemente dependente de idade e sexo. As variantes femininas por
|
|
5022
|
-
// faixa etária são a referência clínica; o `default` foi ajustado para
|
|
5023
|
-
// refletir uma faixa adulta conservadora (~18-40 anos, mulheres em idade
|
|
5024
|
-
// reprodutiva geral). optimalMax anterior (6.9 ng/mL) sobrepunha-se a
|
|
5025
|
-
// valores sugestivos de SOP ou risco de OHSS; clinicamente, valores acima
|
|
5026
|
-
// de ~4 ng/mL já merecem investigação.
|
|
5027
|
-
AMH: {
|
|
5028
|
-
default: { max: 6, min: 1, optimalMax: 4, optimalMin: 1.5, unit: "ng/mL" },
|
|
5029
|
-
source: "tietz-7ed-2015",
|
|
5030
|
-
variants: [
|
|
5031
|
-
{
|
|
5032
|
-
ageMax: 24,
|
|
5033
|
-
ageMin: 18,
|
|
5034
|
-
range: { max: 13, min: 1.5, optimalMax: 10, optimalMin: 3, unit: "ng/mL" },
|
|
5035
|
-
sex: "F"
|
|
5036
|
-
},
|
|
4493
|
+
ageMax: 24,
|
|
4494
|
+
ageMin: 18,
|
|
4495
|
+
range: { max: 13, min: 1.5, optimalMax: 10, optimalMin: 3, unit: "ng/mL" },
|
|
4496
|
+
sex: "F"
|
|
4497
|
+
},
|
|
5037
4498
|
{
|
|
5038
4499
|
ageMax: 30,
|
|
5039
4500
|
ageMin: 25,
|
|
@@ -5061,14 +4522,17 @@ var biomarkerRangeDefinitions = {
|
|
|
5061
4522
|
},
|
|
5062
4523
|
Ammonia: {
|
|
5063
4524
|
default: { max: 45, min: 15, optimalMax: 40, optimalMin: 20, unit: "umol/L" },
|
|
4525
|
+
kind: "reference-interval",
|
|
5064
4526
|
source: "tietz-7ed-2015"
|
|
5065
4527
|
},
|
|
5066
4528
|
AntiThyroglobulin: {
|
|
5067
4529
|
default: { max: 115, min: 0, optimalMax: 40, optimalMin: 0, unit: "IU/mL" },
|
|
4530
|
+
kind: "reference-interval",
|
|
5068
4531
|
source: "tietz-7ed-2015"
|
|
5069
4532
|
},
|
|
5070
4533
|
AntiTPO: {
|
|
5071
4534
|
default: { max: 34, min: 0, optimalMax: 9, optimalMin: 0, unit: "IU/mL" },
|
|
4535
|
+
kind: "reference-interval",
|
|
5072
4536
|
source: "tietz-7ed-2015"
|
|
5073
4537
|
},
|
|
5074
4538
|
// Aortic valve calcium — no standardized clinical threshold; use mild cutoff
|
|
@@ -5076,23 +4540,28 @@ var biomarkerRangeDefinitions = {
|
|
|
5076
4540
|
AorticValveCalcium: {
|
|
5077
4541
|
default: { max: 99, min: 0, optimalMax: 0, optimalMin: 0, unit: "AU" },
|
|
5078
4542
|
direction: "lower-better",
|
|
4543
|
+
kind: "decision-threshold",
|
|
5079
4544
|
source: "rumberger-cac-1999"
|
|
5080
4545
|
},
|
|
5081
4546
|
ApoA1: {
|
|
5082
4547
|
default: { max: 200, min: 100, optimalMax: 180, optimalMin: 120, unit: "mg/dL" },
|
|
4548
|
+
kind: "reference-interval",
|
|
5083
4549
|
source: "contois-apoa1-1996"
|
|
5084
4550
|
},
|
|
5085
4551
|
ApoB: {
|
|
5086
4552
|
default: { max: 90, min: 0, optimalMax: 70, optimalMin: 0, unit: "mg/dL" },
|
|
5087
4553
|
direction: "lower-better",
|
|
4554
|
+
kind: "decision-threshold",
|
|
5088
4555
|
source: "sbc-lipids-2025"
|
|
5089
4556
|
},
|
|
5090
4557
|
ApoCIII: {
|
|
5091
4558
|
default: { max: 10, min: 0, optimalMax: 7, optimalMin: 0, unit: "mg/dL" },
|
|
4559
|
+
kind: "decision-threshold",
|
|
5092
4560
|
source: "khetarpal-apociii-2016"
|
|
5093
4561
|
},
|
|
5094
4562
|
Omega6_AA: {
|
|
5095
4563
|
default: { max: 15, min: 5, optimalMax: 12, optimalMin: 7, unit: "%" },
|
|
4564
|
+
kind: "decision-threshold",
|
|
5096
4565
|
source: "simopoulos-omega-ratio-2002"
|
|
5097
4566
|
},
|
|
5098
4567
|
// Razão Ácido Araquidônico/EPA (sangue total) — `lower-better`: razão menor =
|
|
@@ -5105,16 +4574,19 @@ var biomarkerRangeDefinitions = {
|
|
|
5105
4574
|
// dentro do intervalo. Sem `optimal*`: não há corte ótimo de AA/EPA com fonte.
|
|
5106
4575
|
// Em telas de relatório único, prefira o intervalo impresso pelo laboratório.
|
|
5107
4576
|
AA_EPA_Ratio: {
|
|
5108
|
-
default: { max: 40.7, min: 3.7, unit: "" },
|
|
4577
|
+
default: { max: 40.7, min: 3.7, minKind: "display", unit: "" },
|
|
5109
4578
|
direction: "lower-better",
|
|
4579
|
+
kind: "population",
|
|
5110
4580
|
source: "torrissen-omega3-dbs-2025"
|
|
5111
4581
|
},
|
|
5112
4582
|
Arsenic: {
|
|
5113
4583
|
default: { max: 35, min: 0, optimalMax: 20, optimalMin: 0, unit: "mcg/L" },
|
|
4584
|
+
kind: "decision-threshold",
|
|
5114
4585
|
source: "nr7-pcmso-2020"
|
|
5115
4586
|
},
|
|
5116
4587
|
AST: {
|
|
5117
4588
|
default: { max: 35, min: 0, optimalMax: 25, optimalMin: 0, unit: "U/L" },
|
|
4589
|
+
kind: "reference-interval",
|
|
5118
4590
|
source: "tietz-7ed-2015",
|
|
5119
4591
|
variants: [
|
|
5120
4592
|
{
|
|
@@ -5133,6 +4605,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5133
4605
|
// Tabela 2 da PNS 2019. Ver o comentário em `Neutrophils_Abs`.
|
|
5134
4606
|
Basophils_Abs: {
|
|
5135
4607
|
default: { max: 0.072, min: 0, unit: "K/uL" },
|
|
4608
|
+
kind: "reference-interval",
|
|
5136
4609
|
source: "pns-hemograma-2019",
|
|
5137
4610
|
variants: [
|
|
5138
4611
|
{ ageMin: 18, range: { max: 0.062, min: 0, unit: "K/uL" }, sex: "M" },
|
|
@@ -5141,6 +4614,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5141
4614
|
},
|
|
5142
4615
|
Bicarbonate: {
|
|
5143
4616
|
default: { max: 29, min: 23, optimalMax: 28, optimalMin: 24, unit: "mEq/L" },
|
|
4617
|
+
kind: "reference-interval",
|
|
5144
4618
|
source: "tietz-7ed-2015"
|
|
5145
4619
|
},
|
|
5146
4620
|
// β-Hidroxibutirato (BHB) sérico — corpos cetônicos. Faixa derivada de
|
|
@@ -5150,23 +4624,28 @@ var biomarkerRangeDefinitions = {
|
|
|
5150
4624
|
// superior aqui reflete estado pós-prandial habitual, não jejum.
|
|
5151
4625
|
BetaHydroxybutyrate: {
|
|
5152
4626
|
default: { max: 0.28, min: 0.02, optimalMax: 0.28, optimalMin: 0.02, unit: "mmol/L" },
|
|
4627
|
+
kind: "reference-interval",
|
|
5153
4628
|
source: "klee-bhb-2020"
|
|
5154
4629
|
},
|
|
5155
4630
|
BilirubinDirect: {
|
|
5156
4631
|
default: { max: 0.3, min: 0, optimalMax: 0.2, optimalMin: 0, unit: "mg/dL" },
|
|
4632
|
+
kind: "reference-interval",
|
|
5157
4633
|
source: "tietz-7ed-2015"
|
|
5158
4634
|
},
|
|
5159
4635
|
BilirubinIndirect: {
|
|
5160
4636
|
default: { max: 0.8, min: 0, optimalMax: 0.6, optimalMin: 0, unit: "mg/dL" },
|
|
4637
|
+
kind: "reference-interval",
|
|
5161
4638
|
source: "tietz-7ed-2015"
|
|
5162
4639
|
},
|
|
5163
4640
|
BilirubinTotal: {
|
|
5164
4641
|
default: { max: 1.2, min: 0.1, optimalMax: 0.9, optimalMin: 0.2, unit: "mg/dL" },
|
|
4642
|
+
kind: "reference-interval",
|
|
5165
4643
|
source: "tietz-7ed-2015"
|
|
5166
4644
|
},
|
|
5167
4645
|
// BNP: 35 pg/mL = corte não-agudo para triagem de IC (SBC IC 2018)
|
|
5168
4646
|
BNP: {
|
|
5169
4647
|
default: { max: 35, min: 0, optimalMax: 20, optimalMin: 0, unit: "pg/mL" },
|
|
4648
|
+
kind: "decision-threshold",
|
|
5170
4649
|
source: "sbc-ic-2018"
|
|
5171
4650
|
},
|
|
5172
4651
|
// Razão BUN/Creatinina — faixa 10-20 aplica-se ao Nitrogênio Ureico (BUN).
|
|
@@ -5177,14 +4656,17 @@ var biomarkerRangeDefinitions = {
|
|
|
5177
4656
|
// distinta. Ver issue #41 para alinhamento de nomenclatura/LOINC.
|
|
5178
4657
|
BUN_Creatinine_Ratio: {
|
|
5179
4658
|
default: { max: 20, min: 10, optimalMax: 18, optimalMin: 12, unit: "" },
|
|
4659
|
+
kind: "reference-interval",
|
|
5180
4660
|
source: "tietz-7ed-2015"
|
|
5181
4661
|
},
|
|
5182
4662
|
CA125: {
|
|
5183
4663
|
default: { max: 35, min: 0, optimalMax: 25, optimalMin: 0, unit: "U/mL" },
|
|
4664
|
+
kind: "reference-interval",
|
|
5184
4665
|
source: "sturgeon-nacb-2008"
|
|
5185
4666
|
},
|
|
5186
4667
|
CA199: {
|
|
5187
4668
|
default: { max: 37, min: 0, optimalMax: 30, optimalMin: 0, unit: "U/mL" },
|
|
4669
|
+
kind: "reference-interval",
|
|
5188
4670
|
source: "sturgeon-nacb-2008"
|
|
5189
4671
|
},
|
|
5190
4672
|
// CAC: Agatston classification — 0=none, 1-99=mild, 100-399=moderate, 400+=severe
|
|
@@ -5192,44 +4674,53 @@ var biomarkerRangeDefinitions = {
|
|
|
5192
4674
|
CAC: {
|
|
5193
4675
|
default: { max: 99, min: 0, optimalMax: 0, optimalMin: 0, unit: "AU" },
|
|
5194
4676
|
direction: "lower-better",
|
|
4677
|
+
kind: "decision-threshold",
|
|
5195
4678
|
source: "rumberger-cac-1999"
|
|
5196
4679
|
},
|
|
5197
4680
|
// Per-vessel scores — same Agatston classification applied per vessel
|
|
5198
4681
|
CAC_LAD: {
|
|
5199
4682
|
default: { max: 99, min: 0, optimalMax: 0, optimalMin: 0, unit: "AU" },
|
|
5200
4683
|
direction: "lower-better",
|
|
4684
|
+
kind: "decision-threshold",
|
|
5201
4685
|
source: "rumberger-cac-1999"
|
|
5202
4686
|
},
|
|
5203
4687
|
CAC_LCX: {
|
|
5204
4688
|
default: { max: 99, min: 0, optimalMax: 0, optimalMin: 0, unit: "AU" },
|
|
5205
4689
|
direction: "lower-better",
|
|
4690
|
+
kind: "decision-threshold",
|
|
5206
4691
|
source: "rumberger-cac-1999"
|
|
5207
4692
|
},
|
|
5208
4693
|
CAC_LMA: {
|
|
5209
4694
|
default: { max: 99, min: 0, optimalMax: 0, optimalMin: 0, unit: "AU" },
|
|
5210
4695
|
direction: "lower-better",
|
|
4696
|
+
kind: "decision-threshold",
|
|
5211
4697
|
source: "rumberger-cac-1999"
|
|
5212
4698
|
},
|
|
5213
4699
|
CAC_Percentile: {
|
|
5214
4700
|
default: { max: 50, min: 0, optimalMax: 25, optimalMin: 0, unit: "%", warningMax: 75 },
|
|
5215
4701
|
direction: "lower-better",
|
|
4702
|
+
kind: "decision-threshold",
|
|
5216
4703
|
source: "rumberger-cac-1999"
|
|
5217
4704
|
},
|
|
5218
4705
|
CAC_RCA: {
|
|
5219
4706
|
default: { max: 99, min: 0, optimalMax: 0, optimalMin: 0, unit: "AU" },
|
|
5220
4707
|
direction: "lower-better",
|
|
4708
|
+
kind: "decision-threshold",
|
|
5221
4709
|
source: "rumberger-cac-1999"
|
|
5222
4710
|
},
|
|
5223
4711
|
Cadmium: {
|
|
5224
4712
|
default: { max: 1.2, min: 0, optimalMax: 0.5, optimalMin: 0, unit: "mcg/L" },
|
|
4713
|
+
kind: "decision-threshold",
|
|
5225
4714
|
source: "nr7-pcmso-2020"
|
|
5226
4715
|
},
|
|
5227
4716
|
Calcium: {
|
|
5228
4717
|
default: { max: 10.5, min: 8.5, optimalMax: 10, optimalMin: 9, unit: "mg/dL" },
|
|
4718
|
+
kind: "reference-interval",
|
|
5229
4719
|
source: "tietz-7ed-2015"
|
|
5230
4720
|
},
|
|
5231
4721
|
CEA: {
|
|
5232
4722
|
default: { max: 3, min: 0, optimalMax: 2.5, optimalMin: 0, unit: "ng/mL" },
|
|
4723
|
+
kind: "reference-interval",
|
|
5233
4724
|
source: "sturgeon-nacb-2008"
|
|
5234
4725
|
},
|
|
5235
4726
|
// CK: valores conservadores baseados em faixas laboratoriais típicas
|
|
@@ -5254,6 +4745,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5254
4745
|
// autodeclaração de raça/Cor". Ver a issue #3 para a decisão registrada.
|
|
5255
4746
|
CK: {
|
|
5256
4747
|
default: { max: 314, min: 30, optimalMax: 170, optimalMin: 40, unit: "U/L" },
|
|
4748
|
+
kind: "reference-interval",
|
|
5257
4749
|
source: "kalaria-ck-ri-2026",
|
|
5258
4750
|
variants: [
|
|
5259
4751
|
{ sex: "F", range: { max: 170, min: 30, optimalMax: 150, optimalMin: 40, unit: "U/L" } }
|
|
@@ -5261,6 +4753,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5261
4753
|
},
|
|
5262
4754
|
Chloride: {
|
|
5263
4755
|
default: { max: 106, min: 98, optimalMax: 105, optimalMin: 100, unit: "mEq/L" },
|
|
4756
|
+
kind: "reference-interval",
|
|
5264
4757
|
source: "tietz-7ed-2015"
|
|
5265
4758
|
},
|
|
5266
4759
|
// Colesterol total — SBC 2017/2025: valor desejável < 190 mg/dL para adultos,
|
|
@@ -5268,6 +4761,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5268
4761
|
// (NCEP, 2002), superada pelas atualizações brasileiras.
|
|
5269
4762
|
Cholesterol: {
|
|
5270
4763
|
default: { max: 190, min: 0, optimalMax: 170, optimalMin: 0, unit: "mg/dL" },
|
|
4764
|
+
kind: "decision-threshold",
|
|
5271
4765
|
source: "sbc-lipids-2025"
|
|
5272
4766
|
},
|
|
5273
4767
|
// Índice de Castelli I (CT/HDL-c)
|
|
@@ -5275,6 +4769,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5275
4769
|
// Índice de Castelli I — SBC 2017: M <4.9, F <4.3
|
|
5276
4770
|
default: { max: 4.9, min: 0, optimalMax: 3.5, optimalMin: 0, unit: "" },
|
|
5277
4771
|
direction: "lower-better",
|
|
4772
|
+
kind: "decision-threshold",
|
|
5278
4773
|
source: "castelli-ratio-1992",
|
|
5279
4774
|
variants: [
|
|
5280
4775
|
{
|
|
@@ -5291,22 +4786,27 @@ var biomarkerRangeDefinitions = {
|
|
|
5291
4786
|
},
|
|
5292
4787
|
CO2: {
|
|
5293
4788
|
default: { max: 29, min: 23, optimalMax: 28, optimalMin: 24, unit: "mEq/L" },
|
|
4789
|
+
kind: "reference-interval",
|
|
5294
4790
|
source: "tietz-7ed-2015"
|
|
5295
4791
|
},
|
|
5296
4792
|
Copper: {
|
|
5297
4793
|
default: { max: 175, min: 70, optimalMax: 150, optimalMin: 85, unit: "mcg/dL" },
|
|
4794
|
+
kind: "reference-interval",
|
|
5298
4795
|
source: "tietz-7ed-2015"
|
|
5299
4796
|
},
|
|
5300
4797
|
CoQ10: {
|
|
5301
4798
|
default: { max: 1.5, min: 0.5, optimalMax: 1.3, optimalMin: 0.7, unit: "mg/L" },
|
|
4799
|
+
kind: "reference-interval",
|
|
5302
4800
|
source: "tietz-7ed-2015"
|
|
5303
4801
|
},
|
|
5304
4802
|
Cortisol: {
|
|
5305
4803
|
default: { max: 25, min: 5, optimalMax: 20, optimalMin: 10, unit: "mcg/dL" },
|
|
4804
|
+
kind: "reference-interval",
|
|
5306
4805
|
source: "tietz-7ed-2015"
|
|
5307
4806
|
},
|
|
5308
4807
|
CortisolFree: {
|
|
5309
4808
|
default: { max: 2.5, min: 0.5, optimalMax: 2, optimalMin: 0.8, unit: "mcg/dL" },
|
|
4809
|
+
kind: "reference-interval",
|
|
5310
4810
|
source: "tietz-7ed-2015"
|
|
5311
4811
|
},
|
|
5312
4812
|
CPeptide: {
|
|
@@ -5318,10 +4818,12 @@ var biomarkerRangeDefinitions = {
|
|
|
5318
4818
|
optimalMin: 1,
|
|
5319
4819
|
unit: "ng/mL"
|
|
5320
4820
|
},
|
|
4821
|
+
kind: "reference-interval",
|
|
5321
4822
|
source: "tietz-7ed-2015"
|
|
5322
4823
|
},
|
|
5323
4824
|
Creatinine: {
|
|
5324
4825
|
default: { max: 1.2, min: 0.6, optimalMax: 1, optimalMin: 0.7, unit: "mg/dL" },
|
|
4826
|
+
kind: "reference-interval",
|
|
5325
4827
|
source: "pns-bioquimica-2019",
|
|
5326
4828
|
variants: [
|
|
5327
4829
|
// Gestação: hiperfiltração glomerular (↑ 40–50% GFR) reduz a creatinina
|
|
@@ -5347,10 +4849,12 @@ var biomarkerRangeDefinitions = {
|
|
|
5347
4849
|
CRP: {
|
|
5348
4850
|
default: { max: 3, min: 0, optimalMax: 1, optimalMin: 0, unit: "mg/L" },
|
|
5349
4851
|
direction: "lower-better",
|
|
4852
|
+
kind: "decision-threshold",
|
|
5350
4853
|
source: "tietz-7ed-2015"
|
|
5351
4854
|
},
|
|
5352
4855
|
CystatinC: {
|
|
5353
4856
|
default: { max: 1, min: 0.5, optimalMax: 0.9, optimalMin: 0.6, unit: "mg/L" },
|
|
4857
|
+
kind: "reference-interval",
|
|
5354
4858
|
source: "tietz-7ed-2015"
|
|
5355
4859
|
},
|
|
5356
4860
|
// D-Dímero — exame de exclusão de TEV (tromboembolismo venoso) com
|
|
@@ -5364,6 +4868,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5364
4868
|
DDimer: {
|
|
5365
4869
|
default: { max: 500, min: 0, unit: "ng/mL" },
|
|
5366
4870
|
direction: "lower-better",
|
|
4871
|
+
kind: "decision-threshold",
|
|
5367
4872
|
source: "wells-ddimer-2003",
|
|
5368
4873
|
variants: [
|
|
5369
4874
|
// Corte ajustado por idade — ESC 2019 (Konstantinides et al.) e
|
|
@@ -5377,10 +4882,12 @@ var biomarkerRangeDefinitions = {
|
|
|
5377
4882
|
},
|
|
5378
4883
|
Omega3_DHA: {
|
|
5379
4884
|
default: { max: 8, min: 2, optimalMax: 6.5, optimalMin: 3.5, unit: "%" },
|
|
4885
|
+
kind: "decision-threshold",
|
|
5380
4886
|
source: "harris-omega3-2004"
|
|
5381
4887
|
},
|
|
5382
4888
|
DHEAS: {
|
|
5383
4889
|
default: { max: 500, min: 100, optimalMax: 400, optimalMin: 150, unit: "mcg/dL" },
|
|
4890
|
+
kind: "reference-interval",
|
|
5384
4891
|
source: "tietz-7ed-2015",
|
|
5385
4892
|
variants: [
|
|
5386
4893
|
{
|
|
@@ -5421,20 +4928,30 @@ var biomarkerRangeDefinitions = {
|
|
|
5421
4928
|
},
|
|
5422
4929
|
Omega3_DPA: {
|
|
5423
4930
|
default: { max: 2, min: 0.3, optimalMax: 1.5, optimalMin: 0.5, unit: "%" },
|
|
4931
|
+
kind: "decision-threshold",
|
|
5424
4932
|
source: "harris-omega3-2004"
|
|
5425
4933
|
},
|
|
5426
4934
|
eGFR: {
|
|
5427
|
-
default: {
|
|
4935
|
+
default: {
|
|
4936
|
+
max: 120,
|
|
4937
|
+
maxKind: "display",
|
|
4938
|
+
min: 60,
|
|
4939
|
+
optimalMax: 120,
|
|
4940
|
+
optimalMin: 90,
|
|
4941
|
+
unit: "mL/min/1.73m\xB2"
|
|
4942
|
+
},
|
|
5428
4943
|
// KDIGO 2024: TFG 60-89 (G2) sem marcador de lesão renal não é DRC, em
|
|
5429
4944
|
// nenhuma faixa etária. A variante por idade que existia aqui rebaixava o
|
|
5430
4945
|
// piso só para 60+ e ainda limitava o teto a 90, o que sinalizava como
|
|
5431
4946
|
// alterado qualquer idoso com função preservada.
|
|
4947
|
+
kind: "decision-threshold",
|
|
5432
4948
|
source: "kdigo-ckd-2024"
|
|
5433
4949
|
},
|
|
5434
4950
|
// `Eosinophils` (%) fica sem faixa de propósito e `Eosinophils_Abs` usa os limites da
|
|
5435
4951
|
// Tabela 2 da PNS 2019. Ver o comentário em `Neutrophils_Abs`.
|
|
5436
4952
|
Eosinophils_Abs: {
|
|
5437
4953
|
default: { max: 0.66, min: 0, unit: "K/uL" },
|
|
4954
|
+
kind: "reference-interval",
|
|
5438
4955
|
source: "pns-hemograma-2019",
|
|
5439
4956
|
variants: [
|
|
5440
4957
|
{ ageMin: 18, range: { max: 0.66, min: 0, unit: "K/uL" }, sex: "M" },
|
|
@@ -5443,18 +4960,22 @@ var biomarkerRangeDefinitions = {
|
|
|
5443
4960
|
},
|
|
5444
4961
|
Omega3_EPA: {
|
|
5445
4962
|
default: { max: 3.5, min: 0.5, optimalMax: 2.5, optimalMin: 1, unit: "%" },
|
|
4963
|
+
kind: "decision-threshold",
|
|
5446
4964
|
source: "harris-omega3-2004"
|
|
5447
4965
|
},
|
|
5448
4966
|
EPADPADHA: {
|
|
5449
4967
|
default: { max: 10, min: 3, optimalMax: 9, optimalMin: 5, unit: "%" },
|
|
4968
|
+
kind: "decision-threshold",
|
|
5450
4969
|
source: "harris-omega3-2004"
|
|
5451
4970
|
},
|
|
5452
4971
|
ESR: {
|
|
5453
4972
|
default: { max: 20, min: 0, optimalMax: 10, optimalMin: 0, unit: "mm/hr" },
|
|
4973
|
+
kind: "reference-interval",
|
|
5454
4974
|
source: "tietz-7ed-2015"
|
|
5455
4975
|
},
|
|
5456
4976
|
Estradiol: {
|
|
5457
4977
|
default: { max: 40, min: 10, optimalMax: 35, optimalMin: 15, unit: "pg/mL" },
|
|
4978
|
+
kind: "reference-interval",
|
|
5458
4979
|
source: "tietz-7ed-2015",
|
|
5459
4980
|
variants: [
|
|
5460
4981
|
{
|
|
@@ -5477,6 +4998,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5477
4998
|
},
|
|
5478
4999
|
F2Isoprostanes: {
|
|
5479
5000
|
default: { max: 86, min: 0, optimalMax: 60, optimalMin: 0, unit: "pg/mL" },
|
|
5001
|
+
kind: "reference-interval",
|
|
5480
5002
|
source: "tietz-7ed-2015"
|
|
5481
5003
|
},
|
|
5482
5004
|
// Ferritina — WHO 2020 é o documento de referência específico para avaliação
|
|
@@ -5486,6 +5008,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5486
5008
|
// tipo de faixa, mas documentado aqui para consumidores).
|
|
5487
5009
|
Ferritin: {
|
|
5488
5010
|
default: { max: 150, min: 12, optimalMax: 120, optimalMin: 30, unit: "ng/mL" },
|
|
5011
|
+
kind: "decision-threshold",
|
|
5489
5012
|
source: "who-iron-2020",
|
|
5490
5013
|
variants: [
|
|
5491
5014
|
// Gestação: ferritina cai fisiologicamente no 2º/3º trimestre pela expansão
|
|
@@ -5518,14 +5041,17 @@ var biomarkerRangeDefinitions = {
|
|
|
5518
5041
|
// Fibrinogênio: 200-400 mg/dL — faixa de referência padrão (método de Clauss)
|
|
5519
5042
|
Fibrinogen: {
|
|
5520
5043
|
default: { max: 400, min: 200, optimalMax: 350, optimalMin: 250, unit: "mg/dL" },
|
|
5044
|
+
kind: "reference-interval",
|
|
5521
5045
|
source: "tietz-7ed-2015"
|
|
5522
5046
|
},
|
|
5523
5047
|
FolicAcid: {
|
|
5524
5048
|
default: { max: 20, min: 3, optimalMax: 15, optimalMin: 5, unit: "ng/mL" },
|
|
5049
|
+
kind: "reference-interval",
|
|
5525
5050
|
source: "tietz-7ed-2015"
|
|
5526
5051
|
},
|
|
5527
5052
|
FSH: {
|
|
5528
5053
|
default: { max: 12.4, min: 1.5, optimalMax: 10, optimalMin: 3, unit: "mIU/mL" },
|
|
5054
|
+
kind: "reference-interval",
|
|
5529
5055
|
source: "tietz-7ed-2015",
|
|
5530
5056
|
variants: [
|
|
5531
5057
|
{
|
|
@@ -5549,26 +5075,29 @@ var biomarkerRangeDefinitions = {
|
|
|
5549
5075
|
GGT: {
|
|
5550
5076
|
default: { max: 55, min: 0, optimalMax: 30, optimalMin: 0, unit: "U/L" },
|
|
5551
5077
|
direction: "lower-better",
|
|
5078
|
+
kind: "reference-interval",
|
|
5552
5079
|
source: "tietz-7ed-2015",
|
|
5553
5080
|
variants: [
|
|
5554
5081
|
{
|
|
5555
5082
|
ageMin: 18,
|
|
5556
|
-
range: { max: 61, min: 8, optimalMax: 40, optimalMin: 10, unit: "U/L" },
|
|
5083
|
+
range: { max: 61, min: 8, minKind: "display", optimalMax: 40, optimalMin: 10, unit: "U/L" },
|
|
5557
5084
|
sex: "M"
|
|
5558
5085
|
},
|
|
5559
5086
|
{
|
|
5560
5087
|
ageMin: 18,
|
|
5561
|
-
range: { max: 36, min: 5, optimalMax: 25, optimalMin: 8, unit: "U/L" },
|
|
5088
|
+
range: { max: 36, min: 5, minKind: "display", optimalMax: 25, optimalMin: 8, unit: "U/L" },
|
|
5562
5089
|
sex: "F"
|
|
5563
5090
|
}
|
|
5564
5091
|
]
|
|
5565
5092
|
},
|
|
5566
5093
|
Ghrelin: {
|
|
5567
5094
|
default: { max: 1e3, min: 300, optimalMax: 800, optimalMin: 400, unit: "pg/mL" },
|
|
5095
|
+
kind: "reference-interval",
|
|
5568
5096
|
source: "tietz-7ed-2015"
|
|
5569
5097
|
},
|
|
5570
5098
|
Globulin: {
|
|
5571
5099
|
default: { max: 3.5, min: 2, optimalMax: 3.2, optimalMin: 2.3, unit: "g/dL" },
|
|
5100
|
+
kind: "reference-interval",
|
|
5572
5101
|
source: "tietz-7ed-2015"
|
|
5573
5102
|
},
|
|
5574
5103
|
// A faixa é de jejum, então mora na definição que afirma jejum. Glicose
|
|
@@ -5591,6 +5120,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5591
5120
|
optimalMin: 70,
|
|
5592
5121
|
unit: "mg/dL"
|
|
5593
5122
|
},
|
|
5123
|
+
kind: "decision-threshold",
|
|
5594
5124
|
source: "sbd-diabetes-2024",
|
|
5595
5125
|
variants: [
|
|
5596
5126
|
// Gestação: DMG (IADPSG/SBD 2024) usa cortes mais restritivos na glicemia
|
|
@@ -5612,10 +5142,12 @@ var biomarkerRangeDefinitions = {
|
|
|
5612
5142
|
},
|
|
5613
5143
|
GlycoMark: {
|
|
5614
5144
|
default: { max: 40, min: 10, optimalMax: 35, optimalMin: 15, unit: "mcg/mL" },
|
|
5145
|
+
kind: "reference-interval",
|
|
5615
5146
|
source: "tietz-7ed-2015"
|
|
5616
5147
|
},
|
|
5617
5148
|
GrowthHormone: {
|
|
5618
5149
|
default: { max: 5, min: 0, optimalMax: 3, optimalMin: 0, unit: "ng/mL" },
|
|
5150
|
+
kind: "reference-interval",
|
|
5619
5151
|
source: "tietz-7ed-2015"
|
|
5620
5152
|
},
|
|
5621
5153
|
// HbA1c — SBD 2024 não estabelece piso de referência clinicamente acionável.
|
|
@@ -5625,11 +5157,13 @@ var biomarkerRangeDefinitions = {
|
|
|
5625
5157
|
// criar flag clínico em valores fisiologicamente baixos. optimalMin preserva
|
|
5626
5158
|
// o alvo fisiológico da fração glicada.
|
|
5627
5159
|
HbA1c: {
|
|
5628
|
-
default: { max: 5.7, min: 2, optimalMax: 5.3, optimalMin: 4.5, unit: "%" },
|
|
5160
|
+
default: { max: 5.7, min: 2, minKind: "display", optimalMax: 5.3, optimalMin: 4.5, unit: "%" },
|
|
5161
|
+
kind: "decision-threshold",
|
|
5629
5162
|
source: "sbd-diabetes-2024"
|
|
5630
5163
|
},
|
|
5631
5164
|
Hct: {
|
|
5632
5165
|
default: { max: 50, min: 36, optimalMax: 48, optimalMin: 40, unit: "%" },
|
|
5166
|
+
kind: "reference-interval",
|
|
5633
5167
|
source: "pns-hemograma-2019",
|
|
5634
5168
|
variants: [
|
|
5635
5169
|
{
|
|
@@ -5651,18 +5185,40 @@ var biomarkerRangeDefinitions = {
|
|
|
5651
5185
|
// não como ponto de corte clínico; consumidores devem tratar `direction:
|
|
5652
5186
|
// higher-better` como sinal autoritativo.
|
|
5653
5187
|
HDL: {
|
|
5654
|
-
default: {
|
|
5188
|
+
default: {
|
|
5189
|
+
max: 100,
|
|
5190
|
+
maxKind: "display",
|
|
5191
|
+
min: 40,
|
|
5192
|
+
optimalMax: 100,
|
|
5193
|
+
optimalMin: 50,
|
|
5194
|
+
unit: "mg/dL"
|
|
5195
|
+
},
|
|
5655
5196
|
direction: "higher-better",
|
|
5197
|
+
kind: "decision-threshold",
|
|
5656
5198
|
source: "sbc-lipids-2025",
|
|
5657
5199
|
variants: [
|
|
5658
5200
|
{
|
|
5659
5201
|
ageMin: 18,
|
|
5660
|
-
range: {
|
|
5202
|
+
range: {
|
|
5203
|
+
max: 100,
|
|
5204
|
+
maxKind: "display",
|
|
5205
|
+
min: 40,
|
|
5206
|
+
optimalMax: 100,
|
|
5207
|
+
optimalMin: 45,
|
|
5208
|
+
unit: "mg/dL"
|
|
5209
|
+
},
|
|
5661
5210
|
sex: "M"
|
|
5662
5211
|
},
|
|
5663
5212
|
{
|
|
5664
5213
|
ageMin: 18,
|
|
5665
|
-
range: {
|
|
5214
|
+
range: {
|
|
5215
|
+
max: 100,
|
|
5216
|
+
maxKind: "display",
|
|
5217
|
+
min: 50,
|
|
5218
|
+
optimalMax: 100,
|
|
5219
|
+
optimalMin: 55,
|
|
5220
|
+
unit: "mg/dL"
|
|
5221
|
+
},
|
|
5666
5222
|
sex: "F"
|
|
5667
5223
|
}
|
|
5668
5224
|
]
|
|
@@ -5670,12 +5226,21 @@ var biomarkerRangeDefinitions = {
|
|
|
5670
5226
|
HDL_Large: {
|
|
5671
5227
|
// HDL Large: higher is better
|
|
5672
5228
|
// Quest Ion Mobility reference: Male 4334-10815, Female 5038-17886 nmol/L, optimal >6729
|
|
5673
|
-
default: {
|
|
5229
|
+
default: {
|
|
5230
|
+
max: 17886,
|
|
5231
|
+
maxKind: "display",
|
|
5232
|
+
min: 4334,
|
|
5233
|
+
optimalMax: 17886,
|
|
5234
|
+
optimalMin: 6729,
|
|
5235
|
+
unit: "nmol/L"
|
|
5236
|
+
},
|
|
5674
5237
|
direction: "higher-better",
|
|
5238
|
+
kind: "reference-interval",
|
|
5675
5239
|
source: "caulfield-ionmobility-2008"
|
|
5676
5240
|
},
|
|
5677
5241
|
Hgb: {
|
|
5678
5242
|
default: { max: 17.5, min: 12, optimalMax: 16, optimalMin: 13.5, unit: "g/dL" },
|
|
5243
|
+
kind: "reference-interval",
|
|
5679
5244
|
source: "pns-hemograma-2019",
|
|
5680
5245
|
variants: [
|
|
5681
5246
|
// Gestação: hemodiluição fisiológica reduz o piso aceitável.
|
|
@@ -5731,19 +5296,23 @@ var biomarkerRangeDefinitions = {
|
|
|
5731
5296
|
warningMax: 2.71
|
|
5732
5297
|
},
|
|
5733
5298
|
direction: "lower-better",
|
|
5299
|
+
kind: "decision-threshold",
|
|
5734
5300
|
source: "geloneze-brams-2009"
|
|
5735
5301
|
},
|
|
5736
5302
|
Homocysteine: {
|
|
5737
|
-
default: { max: 15, min: 4, optimalMax: 10, optimalMin: 5, unit: "umol/L" },
|
|
5303
|
+
default: { max: 15, min: 4, minKind: "display", optimalMax: 10, optimalMin: 5, unit: "umol/L" },
|
|
5738
5304
|
direction: "lower-better",
|
|
5305
|
+
kind: "reference-interval",
|
|
5739
5306
|
source: "selhub-homocysteine-1999"
|
|
5740
5307
|
},
|
|
5741
5308
|
IGF1: {
|
|
5742
5309
|
default: { max: 350, min: 100, optimalMax: 300, optimalMin: 150, unit: "ng/mL" },
|
|
5310
|
+
kind: "reference-interval",
|
|
5743
5311
|
source: "tietz-7ed-2015"
|
|
5744
5312
|
},
|
|
5745
5313
|
ImmatureGranulocytes: {
|
|
5746
5314
|
default: { max: 1, min: 0, optimalMax: 0.5, optimalMin: 0, unit: "%" },
|
|
5315
|
+
kind: "reference-interval",
|
|
5747
5316
|
source: "tietz-7ed-2015"
|
|
5748
5317
|
},
|
|
5749
5318
|
Insulin: {
|
|
@@ -5755,10 +5324,12 @@ var biomarkerRangeDefinitions = {
|
|
|
5755
5324
|
optimalMin: 3,
|
|
5756
5325
|
unit: "uIU/mL"
|
|
5757
5326
|
},
|
|
5327
|
+
kind: "reference-interval",
|
|
5758
5328
|
source: "tietz-7ed-2015"
|
|
5759
5329
|
},
|
|
5760
5330
|
Iron: {
|
|
5761
5331
|
default: { max: 170, min: 60, optimalMax: 140, optimalMin: 80, unit: "mcg/dL" },
|
|
5332
|
+
kind: "reference-interval",
|
|
5762
5333
|
source: "sbpc-ml-2021",
|
|
5763
5334
|
variants: [
|
|
5764
5335
|
{
|
|
@@ -5775,6 +5346,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5775
5346
|
},
|
|
5776
5347
|
Lactate: {
|
|
5777
5348
|
default: { max: 2.2, min: 0.5, optimalMax: 1.8, optimalMin: 0.7, unit: "mmol/L" },
|
|
5349
|
+
kind: "reference-interval",
|
|
5778
5350
|
source: "tietz-7ed-2015"
|
|
5779
5351
|
},
|
|
5780
5352
|
// DHL/LDH — método IFCC a 37 °C (padrão atual na maioria dos laboratórios
|
|
@@ -5786,6 +5358,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5786
5358
|
LDH: {
|
|
5787
5359
|
default: { max: 248, min: 0, optimalMax: 248, optimalMin: 0, unit: "U/L" },
|
|
5788
5360
|
direction: "lower-better",
|
|
5361
|
+
kind: "reference-interval",
|
|
5789
5362
|
source: "schumann-ifcc-ldh-2002",
|
|
5790
5363
|
variants: [
|
|
5791
5364
|
{
|
|
@@ -5803,59 +5376,109 @@ var biomarkerRangeDefinitions = {
|
|
|
5803
5376
|
LDL: {
|
|
5804
5377
|
default: { max: 100, min: 0, optimalMax: 70, optimalMin: 0, unit: "mg/dL" },
|
|
5805
5378
|
direction: "lower-better",
|
|
5379
|
+
kind: "decision-threshold",
|
|
5806
5380
|
source: "sbc-lipids-2025"
|
|
5807
5381
|
},
|
|
5808
5382
|
LDL_Medium: {
|
|
5809
5383
|
// LDL Medium (LDL Média): lower is better
|
|
5810
5384
|
// Quest Ion Mobility reference: Male 167-485, Female 121-397 nmol/L, optimal <215
|
|
5811
|
-
default: {
|
|
5385
|
+
default: {
|
|
5386
|
+
max: 485,
|
|
5387
|
+
min: 121,
|
|
5388
|
+
minKind: "display",
|
|
5389
|
+
optimalMax: 215,
|
|
5390
|
+
optimalMin: 121,
|
|
5391
|
+
unit: "nmol/L"
|
|
5392
|
+
},
|
|
5812
5393
|
direction: "lower-better",
|
|
5394
|
+
kind: "reference-interval",
|
|
5813
5395
|
source: "caulfield-ionmobility-2008"
|
|
5814
5396
|
},
|
|
5815
5397
|
LDL_ParticleNumber: {
|
|
5816
5398
|
// LDL Particle Number: lower is better
|
|
5817
5399
|
// Quest Ion Mobility reference: 1016-2185 nmol/L, optimal <1138
|
|
5818
|
-
default: {
|
|
5400
|
+
default: {
|
|
5401
|
+
max: 2185,
|
|
5402
|
+
min: 1016,
|
|
5403
|
+
minKind: "display",
|
|
5404
|
+
optimalMax: 1138,
|
|
5405
|
+
optimalMin: 1016,
|
|
5406
|
+
unit: "nmol/L"
|
|
5407
|
+
},
|
|
5819
5408
|
direction: "lower-better",
|
|
5409
|
+
kind: "reference-interval",
|
|
5820
5410
|
source: "caulfield-ionmobility-2008"
|
|
5821
5411
|
},
|
|
5822
5412
|
LDL_Peak_Size: {
|
|
5823
5413
|
// LDL Peak Size: higher is better (larger particles less atherogenic)
|
|
5824
5414
|
// Quest Ion Mobility reference: optimal >222.9 Å (22.29 nm)
|
|
5825
|
-
default: {
|
|
5415
|
+
default: {
|
|
5416
|
+
max: 250,
|
|
5417
|
+
maxKind: "display",
|
|
5418
|
+
min: 217.4,
|
|
5419
|
+
optimalMax: 250,
|
|
5420
|
+
optimalMin: 222.9,
|
|
5421
|
+
unit: "Angstrom"
|
|
5422
|
+
},
|
|
5826
5423
|
direction: "higher-better",
|
|
5424
|
+
kind: "reference-interval",
|
|
5827
5425
|
source: "caulfield-ionmobility-2008"
|
|
5828
5426
|
},
|
|
5829
5427
|
LDL_Small: {
|
|
5830
5428
|
// LDL Small (LDL Pequena): lower is better (small dense LDL is most atherogenic)
|
|
5831
5429
|
// Quest Ion Mobility reference: Male 123-441, Female 126-382 nmol/L, optimal <142
|
|
5832
|
-
default: {
|
|
5430
|
+
default: {
|
|
5431
|
+
max: 441,
|
|
5432
|
+
min: 123,
|
|
5433
|
+
minKind: "display",
|
|
5434
|
+
optimalMax: 142,
|
|
5435
|
+
optimalMin: 123,
|
|
5436
|
+
unit: "nmol/L"
|
|
5437
|
+
},
|
|
5833
5438
|
direction: "lower-better",
|
|
5439
|
+
kind: "reference-interval",
|
|
5834
5440
|
source: "caulfield-ionmobility-2008"
|
|
5835
5441
|
},
|
|
5836
5442
|
Lead: {
|
|
5837
5443
|
default: { max: 5, min: 0, optimalMax: 2, optimalMin: 0, unit: "mcg/dL" },
|
|
5444
|
+
kind: "decision-threshold",
|
|
5838
5445
|
source: "nr7-pcmso-2020"
|
|
5839
5446
|
},
|
|
5840
5447
|
Leptin: {
|
|
5841
|
-
default: { max: 15, min: 2, optimalMax: 12, optimalMin: 3, unit: "ng/mL" },
|
|
5448
|
+
default: { max: 15, min: 2, minKind: "clinical", optimalMax: 12, optimalMin: 3, unit: "ng/mL" },
|
|
5842
5449
|
direction: "lower-better",
|
|
5450
|
+
kind: "reference-interval",
|
|
5843
5451
|
source: "tietz-7ed-2015",
|
|
5844
5452
|
variants: [
|
|
5845
5453
|
{
|
|
5846
5454
|
ageMin: 18,
|
|
5847
|
-
range: {
|
|
5455
|
+
range: {
|
|
5456
|
+
max: 10,
|
|
5457
|
+
min: 1,
|
|
5458
|
+
minKind: "clinical",
|
|
5459
|
+
optimalMax: 8,
|
|
5460
|
+
optimalMin: 2,
|
|
5461
|
+
unit: "ng/mL"
|
|
5462
|
+
},
|
|
5848
5463
|
sex: "M"
|
|
5849
5464
|
},
|
|
5850
5465
|
{
|
|
5851
5466
|
ageMin: 18,
|
|
5852
|
-
range: {
|
|
5467
|
+
range: {
|
|
5468
|
+
max: 25,
|
|
5469
|
+
min: 4,
|
|
5470
|
+
minKind: "clinical",
|
|
5471
|
+
optimalMax: 18,
|
|
5472
|
+
optimalMin: 5,
|
|
5473
|
+
unit: "ng/mL"
|
|
5474
|
+
},
|
|
5853
5475
|
sex: "F"
|
|
5854
5476
|
}
|
|
5855
5477
|
]
|
|
5856
5478
|
},
|
|
5857
5479
|
LH: {
|
|
5858
5480
|
default: { max: 8.6, min: 1.7, optimalMax: 8, optimalMin: 2, unit: "mIU/mL" },
|
|
5481
|
+
kind: "reference-interval",
|
|
5859
5482
|
source: "tietz-7ed-2015",
|
|
5860
5483
|
variants: [
|
|
5861
5484
|
{
|
|
@@ -5878,6 +5501,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5878
5501
|
},
|
|
5879
5502
|
Omega6_LA: {
|
|
5880
5503
|
default: { max: 35, min: 15, optimalMax: 28, optimalMin: 18, unit: "%" },
|
|
5504
|
+
kind: "decision-threshold",
|
|
5881
5505
|
source: "simopoulos-omega-ratio-2002"
|
|
5882
5506
|
},
|
|
5883
5507
|
// Lp(a) — SBC 2025 (seção 3.1.1.2.7): níveis ≥ 50 mg/dL ou ≥ 125 nmol/L são
|
|
@@ -5889,12 +5513,14 @@ var biomarkerRangeDefinitions = {
|
|
|
5889
5513
|
Lipoprotein_a: {
|
|
5890
5514
|
default: { max: 125, min: 0, optimalMax: 75, optimalMin: 0, unit: "nmol/L" },
|
|
5891
5515
|
direction: "lower-better",
|
|
5516
|
+
kind: "decision-threshold",
|
|
5892
5517
|
source: "sbc-lipids-2025"
|
|
5893
5518
|
},
|
|
5894
5519
|
// `Lymphocytes` (%) fica sem faixa de propósito e `Lymphocytes_Abs` usa os limites da
|
|
5895
5520
|
// Tabela 2 da PNS 2019. Ver o comentário em `Neutrophils_Abs`.
|
|
5896
5521
|
Lymphocytes_Abs: {
|
|
5897
5522
|
default: { max: 3.414, min: 0.72, unit: "K/uL" },
|
|
5523
|
+
kind: "reference-interval",
|
|
5898
5524
|
source: "pns-hemograma-2019",
|
|
5899
5525
|
variants: [
|
|
5900
5526
|
{ ageMin: 18, range: { max: 3.37, min: 0.72, unit: "K/uL" }, sex: "M" },
|
|
@@ -5903,40 +5529,49 @@ var biomarkerRangeDefinitions = {
|
|
|
5903
5529
|
},
|
|
5904
5530
|
Magnesium: {
|
|
5905
5531
|
default: { max: 2.2, min: 1.7, optimalMax: 2.1, optimalMin: 1.9, unit: "mg/dL" },
|
|
5532
|
+
kind: "reference-interval",
|
|
5906
5533
|
source: "tietz-7ed-2015"
|
|
5907
5534
|
},
|
|
5908
5535
|
Magnesium_RBC: {
|
|
5909
5536
|
default: { max: 6.8, min: 4, optimalMax: 6, optimalMin: 4.5, unit: "mg/dL" },
|
|
5537
|
+
kind: "reference-interval",
|
|
5910
5538
|
source: "tietz-7ed-2015"
|
|
5911
5539
|
},
|
|
5912
5540
|
MCH: {
|
|
5913
5541
|
default: { max: 33, min: 27, optimalMax: 32, optimalMin: 28, unit: "pg" },
|
|
5542
|
+
kind: "reference-interval",
|
|
5914
5543
|
source: "pns-hemograma-2019"
|
|
5915
5544
|
},
|
|
5916
5545
|
MCHC: {
|
|
5917
5546
|
default: { max: 36, min: 32, optimalMax: 35, optimalMin: 33, unit: "g/dL" },
|
|
5547
|
+
kind: "reference-interval",
|
|
5918
5548
|
source: "pns-hemograma-2019"
|
|
5919
5549
|
},
|
|
5920
5550
|
MCV: {
|
|
5921
5551
|
default: { max: 100, min: 80, optimalMax: 98, optimalMin: 82, unit: "fL" },
|
|
5552
|
+
kind: "reference-interval",
|
|
5922
5553
|
source: "pns-hemograma-2019"
|
|
5923
5554
|
},
|
|
5924
5555
|
Mercury: {
|
|
5925
5556
|
default: { max: 10, min: 0, optimalMax: 5, optimalMin: 0, unit: "mcg/L" },
|
|
5557
|
+
kind: "decision-threshold",
|
|
5926
5558
|
source: "nr7-pcmso-2020"
|
|
5927
5559
|
},
|
|
5928
5560
|
Microalbumin: {
|
|
5929
5561
|
default: { max: 30, min: 0, optimalMax: 20, optimalMin: 0, unit: "mg/L" },
|
|
5562
|
+
kind: "decision-threshold",
|
|
5930
5563
|
source: "kdigo-ckd-2024"
|
|
5931
5564
|
},
|
|
5932
5565
|
MMA: {
|
|
5933
5566
|
default: { max: 378, min: 0, optimalMax: 270, optimalMin: 0, unit: "nmol/L" },
|
|
5567
|
+
kind: "reference-interval",
|
|
5934
5568
|
source: "tietz-7ed-2015"
|
|
5935
5569
|
},
|
|
5936
5570
|
// `Monocytes` (%) fica sem faixa de propósito e `Monocytes_Abs` usa os limites da
|
|
5937
5571
|
// Tabela 2 da PNS 2019. Ver o comentário em `Neutrophils_Abs`.
|
|
5938
5572
|
Monocytes_Abs: {
|
|
5939
5573
|
default: { max: 0.812, min: 0.011, unit: "K/uL" },
|
|
5574
|
+
kind: "reference-interval",
|
|
5940
5575
|
source: "pns-hemograma-2019",
|
|
5941
5576
|
variants: [
|
|
5942
5577
|
{ ageMin: 18, range: { max: 0.812, min: 0.011, unit: "K/uL" }, sex: "M" },
|
|
@@ -5945,11 +5580,13 @@ var biomarkerRangeDefinitions = {
|
|
|
5945
5580
|
},
|
|
5946
5581
|
MPV: {
|
|
5947
5582
|
default: { max: 11.5, min: 7.5, optimalMax: 10.5, optimalMin: 8, unit: "fL" },
|
|
5583
|
+
kind: "reference-interval",
|
|
5948
5584
|
source: "pns-hemograma-2019"
|
|
5949
5585
|
},
|
|
5950
5586
|
// MPO: Meuwese 2007 (EPIC-Norfolk) — risco CV elevado >322 pmol/L
|
|
5951
5587
|
Myeloperoxidase: {
|
|
5952
5588
|
default: { max: 470, min: 0, optimalMax: 322, optimalMin: 0, unit: "pmol/L" },
|
|
5589
|
+
kind: "decision-threshold",
|
|
5953
5590
|
source: "meuwese-mpo-2007"
|
|
5954
5591
|
},
|
|
5955
5592
|
// Leucograma diferencial em percentual (`Neutrophils`, `Lymphocytes`,
|
|
@@ -5973,6 +5610,7 @@ var biomarkerRangeDefinitions = {
|
|
|
5973
5610
|
// (menor mínimo e maior máximo entre homens e mulheres).
|
|
5974
5611
|
Neutrophils_Abs: {
|
|
5975
5612
|
default: { max: 6.474, min: 0.576, unit: "K/uL" },
|
|
5613
|
+
kind: "reference-interval",
|
|
5976
5614
|
source: "pns-hemograma-2019",
|
|
5977
5615
|
variants: [
|
|
5978
5616
|
{ ageMin: 18, range: { max: 5.971, min: 0.576, unit: "K/uL" }, sex: "M" },
|
|
@@ -5982,22 +5620,27 @@ var biomarkerRangeDefinitions = {
|
|
|
5982
5620
|
NonHDL_Cholesterol: {
|
|
5983
5621
|
default: { max: 130, min: 0, optimalMax: 100, optimalMin: 0, unit: "mg/dL" },
|
|
5984
5622
|
direction: "lower-better",
|
|
5623
|
+
kind: "decision-threshold",
|
|
5985
5624
|
source: "sbc-lipids-2025"
|
|
5986
5625
|
},
|
|
5987
5626
|
NRBC: {
|
|
5988
5627
|
default: { max: 0, min: 0, optimalMax: 0, optimalMin: 0, unit: "/100WBC" },
|
|
5628
|
+
kind: "reference-interval",
|
|
5989
5629
|
source: "tietz-7ed-2015"
|
|
5990
5630
|
},
|
|
5991
5631
|
NTproBNP: {
|
|
5992
5632
|
default: { max: 125, min: 0, optimalMax: 75, optimalMin: 0, unit: "pg/mL" },
|
|
5633
|
+
kind: "decision-threshold",
|
|
5993
5634
|
source: "sbc-ic-2018"
|
|
5994
5635
|
},
|
|
5995
5636
|
Oleic_Acid: {
|
|
5996
5637
|
default: { max: 25, min: 15, optimalMax: 22, optimalMin: 18, unit: "%" },
|
|
5638
|
+
kind: "reference-interval",
|
|
5997
5639
|
source: "tietz-7ed-2015"
|
|
5998
5640
|
},
|
|
5999
5641
|
Omega3_Index: {
|
|
6000
5642
|
default: { max: 8, min: 4, optimalMax: 8, optimalMin: 5.5, unit: "%" },
|
|
5643
|
+
kind: "decision-threshold",
|
|
6001
5644
|
source: "harris-omega3-2004"
|
|
6002
5645
|
},
|
|
6003
5646
|
// Ômega-3 Total (% de ácidos graxos eritrocitários) — Harris & von Schacky
|
|
@@ -6007,39 +5650,55 @@ var biomarkerRangeDefinitions = {
|
|
|
6007
5650
|
// a literatura e o próprio texto educacional do `platform`.
|
|
6008
5651
|
Omega3_Total: {
|
|
6009
5652
|
default: { max: 12, min: 3, optimalMax: 10, optimalMin: 8, unit: "%" },
|
|
5653
|
+
kind: "decision-threshold",
|
|
6010
5654
|
source: "harris-omega3-2004"
|
|
6011
5655
|
},
|
|
6012
5656
|
Omega6_Total: {
|
|
6013
5657
|
default: { max: 40, min: 20, optimalMax: 35, optimalMin: 25, unit: "%" },
|
|
5658
|
+
kind: "decision-threshold",
|
|
6014
5659
|
source: "simopoulos-omega-ratio-2002"
|
|
6015
5660
|
},
|
|
6016
5661
|
Omega6_Omega3_Ratio: {
|
|
6017
|
-
default: {
|
|
5662
|
+
default: {
|
|
5663
|
+
max: 10,
|
|
5664
|
+
min: 1,
|
|
5665
|
+
minKind: "display",
|
|
5666
|
+
optimalMax: 4,
|
|
5667
|
+
optimalMin: 1,
|
|
5668
|
+
unit: ""
|
|
5669
|
+
},
|
|
6018
5670
|
direction: "lower-better",
|
|
5671
|
+
kind: "decision-threshold",
|
|
6019
5672
|
source: "simopoulos-omega-ratio-2002"
|
|
6020
5673
|
},
|
|
6021
5674
|
OmegaCheck: {
|
|
6022
5675
|
default: { max: 8, min: 4, optimalMax: 8, optimalMin: 5.5, unit: "%" },
|
|
5676
|
+
kind: "decision-threshold",
|
|
6023
5677
|
source: "harris-omega3-2004"
|
|
6024
5678
|
},
|
|
6025
5679
|
Palmitic_Acid: {
|
|
6026
5680
|
default: { max: 30, min: 20, optimalMax: 27, optimalMin: 22, unit: "%" },
|
|
5681
|
+
kind: "reference-interval",
|
|
6027
5682
|
source: "tietz-7ed-2015"
|
|
6028
5683
|
},
|
|
6029
5684
|
Phosphorus: {
|
|
6030
5685
|
default: { max: 4.5, min: 2.5, optimalMax: 4, optimalMin: 3, unit: "mg/dL" },
|
|
5686
|
+
kind: "reference-interval",
|
|
6031
5687
|
source: "tietz-7ed-2015"
|
|
6032
5688
|
},
|
|
6033
5689
|
Platelets: {
|
|
6034
5690
|
default: { max: 400, min: 150, optimalMax: 350, optimalMin: 180, unit: "K/uL" },
|
|
5691
|
+
kind: "reference-interval",
|
|
6035
5692
|
source: "pns-hemograma-2019"
|
|
6036
5693
|
},
|
|
6037
5694
|
Potassium: {
|
|
6038
5695
|
default: { max: 5, min: 3.5, optimalMax: 4.6, optimalMin: 3.8, unit: "mEq/L" },
|
|
5696
|
+
kind: "reference-interval",
|
|
6039
5697
|
source: "tietz-7ed-2015"
|
|
6040
5698
|
},
|
|
6041
5699
|
Prealbumin: {
|
|
6042
5700
|
default: { max: 38, min: 18, optimalMax: 35, optimalMin: 20, unit: "mg/dL" },
|
|
5701
|
+
kind: "reference-interval",
|
|
6043
5702
|
source: "tietz-7ed-2015"
|
|
6044
5703
|
},
|
|
6045
5704
|
// Progesterona — varia drasticamente com a fase do ciclo menstrual.
|
|
@@ -6050,6 +5709,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6050
5709
|
// ciclo, indisponível neste contexto.
|
|
6051
5710
|
Progesterone: {
|
|
6052
5711
|
default: { max: 0.9, min: 0.1, optimalMax: 0.7, optimalMin: 0.2, unit: "ng/mL" },
|
|
5712
|
+
kind: "reference-interval",
|
|
6053
5713
|
source: "tietz-7ed-2015",
|
|
6054
5714
|
variants: [
|
|
6055
5715
|
{
|
|
@@ -6076,6 +5736,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6076
5736
|
},
|
|
6077
5737
|
Prolactin: {
|
|
6078
5738
|
default: { max: 18, min: 2, optimalMax: 15, optimalMin: 4, unit: "ng/mL" },
|
|
5739
|
+
kind: "reference-interval",
|
|
6079
5740
|
source: "tietz-7ed-2015",
|
|
6080
5741
|
variants: [
|
|
6081
5742
|
{
|
|
@@ -6092,6 +5753,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6092
5753
|
},
|
|
6093
5754
|
PSA: {
|
|
6094
5755
|
default: { max: 4, min: 0, optimalMax: 2.5, optimalMin: 0, unit: "ng/mL" },
|
|
5756
|
+
kind: "reference-interval",
|
|
6095
5757
|
source: "sturgeon-nacb-2008",
|
|
6096
5758
|
variants: [
|
|
6097
5759
|
{
|
|
@@ -6121,6 +5783,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6121
5783
|
},
|
|
6122
5784
|
RBC: {
|
|
6123
5785
|
default: { max: 5.5, min: 4, optimalMax: 5.2, optimalMin: 4.3, unit: "M/uL" },
|
|
5786
|
+
kind: "reference-interval",
|
|
6124
5787
|
source: "pns-hemograma-2019",
|
|
6125
5788
|
variants: [
|
|
6126
5789
|
{
|
|
@@ -6137,22 +5800,27 @@ var biomarkerRangeDefinitions = {
|
|
|
6137
5800
|
},
|
|
6138
5801
|
RDW: {
|
|
6139
5802
|
default: { max: 14.5, min: 11.5, optimalMax: 14, optimalMin: 12, unit: "%" },
|
|
5803
|
+
kind: "reference-interval",
|
|
6140
5804
|
source: "pns-hemograma-2019"
|
|
6141
5805
|
},
|
|
6142
5806
|
Reticulocytes: {
|
|
6143
5807
|
default: { max: 2.5, min: 0.5, optimalMax: 2, optimalMin: 0.8, unit: "%" },
|
|
5808
|
+
kind: "reference-interval",
|
|
6144
5809
|
source: "pns-hemograma-2019"
|
|
6145
5810
|
},
|
|
6146
5811
|
SDMA: {
|
|
6147
5812
|
default: { max: 0.6, min: 0.3, optimalMax: 0.5, optimalMin: 0.3, unit: "umol/L" },
|
|
5813
|
+
kind: "reference-interval",
|
|
6148
5814
|
source: "schwedhelm-sdma-2011"
|
|
6149
5815
|
},
|
|
6150
5816
|
Selenium: {
|
|
6151
5817
|
default: { max: 150, min: 70, optimalMax: 125, optimalMin: 85, unit: "\xB5g/L" },
|
|
5818
|
+
kind: "reference-interval",
|
|
6152
5819
|
source: "tietz-7ed-2015"
|
|
6153
5820
|
},
|
|
6154
5821
|
SHBG: {
|
|
6155
5822
|
default: { max: 54, min: 18, optimalMax: 50, optimalMin: 20, unit: "nmol/L" },
|
|
5823
|
+
kind: "reference-interval",
|
|
6156
5824
|
source: "tietz-7ed-2015",
|
|
6157
5825
|
variants: [
|
|
6158
5826
|
{
|
|
@@ -6169,34 +5837,42 @@ var biomarkerRangeDefinitions = {
|
|
|
6169
5837
|
},
|
|
6170
5838
|
Sodium: {
|
|
6171
5839
|
default: { max: 145, min: 136, optimalMax: 143, optimalMin: 138, unit: "mEq/L" },
|
|
5840
|
+
kind: "reference-interval",
|
|
6172
5841
|
source: "tietz-7ed-2015"
|
|
6173
5842
|
},
|
|
6174
5843
|
SpecificGravity_Urine: {
|
|
6175
5844
|
default: { max: 1.03, min: 1.005, optimalMax: 1.025, optimalMin: 1.01, unit: "SG" },
|
|
5845
|
+
kind: "reference-interval",
|
|
6176
5846
|
source: "tietz-7ed-2015"
|
|
6177
5847
|
},
|
|
6178
5848
|
Stearic_Acid: {
|
|
6179
5849
|
default: { max: 14, min: 8, optimalMax: 12, optimalMin: 10, unit: "%" },
|
|
5850
|
+
kind: "reference-interval",
|
|
6180
5851
|
source: "tietz-7ed-2015"
|
|
6181
5852
|
},
|
|
6182
5853
|
T3Free: {
|
|
6183
5854
|
default: { max: 4.2, min: 2.3, optimalMax: 3.8, optimalMin: 2.8, unit: "pg/mL" },
|
|
5855
|
+
kind: "reference-interval",
|
|
6184
5856
|
source: "tietz-7ed-2015"
|
|
6185
5857
|
},
|
|
6186
5858
|
T3Reverse: {
|
|
6187
5859
|
default: { max: 24, min: 10, optimalMax: 20, optimalMin: 12, unit: "ng/dL" },
|
|
5860
|
+
kind: "reference-interval",
|
|
6188
5861
|
source: "tietz-7ed-2015"
|
|
6189
5862
|
},
|
|
6190
5863
|
T4Free: {
|
|
6191
5864
|
default: { max: 1.8, min: 0.8, optimalMax: 1.5, optimalMin: 1, unit: "ng/dL" },
|
|
5865
|
+
kind: "reference-interval",
|
|
6192
5866
|
source: "tietz-7ed-2015"
|
|
6193
5867
|
},
|
|
6194
5868
|
T4Total: {
|
|
6195
5869
|
default: { max: 12, min: 4.5, optimalMax: 10, optimalMin: 6, unit: "ug/dL" },
|
|
5870
|
+
kind: "reference-interval",
|
|
6196
5871
|
source: "tietz-7ed-2015"
|
|
6197
5872
|
},
|
|
6198
5873
|
Testosterone: {
|
|
6199
5874
|
default: { max: 1e3, min: 300, optimalMax: 800, optimalMin: 500, unit: "ng/dL" },
|
|
5875
|
+
kind: "reference-interval",
|
|
6200
5876
|
source: "tietz-7ed-2015",
|
|
6201
5877
|
variants: [
|
|
6202
5878
|
{
|
|
@@ -6219,12 +5895,14 @@ var biomarkerRangeDefinitions = {
|
|
|
6219
5895
|
},
|
|
6220
5896
|
TestosteroneBioavailable: {
|
|
6221
5897
|
default: { max: 200, min: 50, optimalMax: 150, optimalMin: 80, unit: "ng/dL" },
|
|
5898
|
+
kind: "reference-interval",
|
|
6222
5899
|
source: "tietz-7ed-2015"
|
|
6223
5900
|
},
|
|
6224
5901
|
// TestosteroneFree - using direct immunoassay ranges (Quest/LabCorp standard)
|
|
6225
5902
|
// Previous values (9.3-26.5 pg/mL) were based on equilibrium dialysis method
|
|
6226
5903
|
TestosteroneFree: {
|
|
6227
5904
|
default: { max: 155, min: 35, optimalMax: 120, optimalMin: 50, unit: "pg/mL" },
|
|
5905
|
+
kind: "reference-interval",
|
|
6228
5906
|
source: "tietz-7ed-2015",
|
|
6229
5907
|
variants: [
|
|
6230
5908
|
{
|
|
@@ -6247,22 +5925,27 @@ var biomarkerRangeDefinitions = {
|
|
|
6247
5925
|
},
|
|
6248
5926
|
TIBC: {
|
|
6249
5927
|
default: { max: 370, min: 250, optimalMax: 350, optimalMin: 280, unit: "mcg/dL" },
|
|
5928
|
+
kind: "reference-interval",
|
|
6250
5929
|
source: "tietz-7ed-2015"
|
|
6251
5930
|
},
|
|
6252
5931
|
TotalProtein: {
|
|
6253
5932
|
default: { max: 8.3, min: 6, optimalMax: 7.8, optimalMin: 6.5, unit: "g/dL" },
|
|
5933
|
+
kind: "reference-interval",
|
|
6254
5934
|
source: "tietz-7ed-2015"
|
|
6255
5935
|
},
|
|
6256
5936
|
Trans_Fat_Index: {
|
|
6257
5937
|
default: { max: 1, min: 0, optimalMax: 0.5, optimalMin: 0, unit: "%" },
|
|
5938
|
+
kind: "reference-interval",
|
|
6258
5939
|
source: "tietz-7ed-2015"
|
|
6259
5940
|
},
|
|
6260
5941
|
Transferrin: {
|
|
6261
5942
|
default: { max: 360, min: 200, optimalMax: 340, optimalMin: 220, unit: "mg/dL" },
|
|
5943
|
+
kind: "reference-interval",
|
|
6262
5944
|
source: "tietz-7ed-2015"
|
|
6263
5945
|
},
|
|
6264
5946
|
TransferrinSaturation: {
|
|
6265
5947
|
default: { max: 50, min: 20, optimalMax: 45, optimalMin: 25, unit: "%" },
|
|
5948
|
+
kind: "reference-interval",
|
|
6266
5949
|
source: "tietz-7ed-2015",
|
|
6267
5950
|
variants: [
|
|
6268
5951
|
{
|
|
@@ -6290,16 +5973,19 @@ var biomarkerRangeDefinitions = {
|
|
|
6290
5973
|
unit: "mg/dL"
|
|
6291
5974
|
},
|
|
6292
5975
|
direction: "lower-better",
|
|
5976
|
+
kind: "decision-threshold",
|
|
6293
5977
|
source: "sbc-lipids-2025"
|
|
6294
5978
|
},
|
|
6295
5979
|
// TroponinI: 0.04 ng/mL = percentil 99 (ensaio Siemens TnI-Ultra)
|
|
6296
5980
|
TroponinI: {
|
|
6297
5981
|
default: { max: 0.04, min: 0, optimalMax: 0.02, optimalMin: 0, unit: "ng/mL" },
|
|
5982
|
+
kind: "reference-interval",
|
|
6298
5983
|
source: "keller-tni-2013"
|
|
6299
5984
|
},
|
|
6300
5985
|
// TroponinT: 14 ng/L = percentil 99 hs-cTnT (ensaio Roche Elecsys 5ª geração)
|
|
6301
5986
|
TroponinT: {
|
|
6302
5987
|
default: { max: 14, min: 0, optimalMax: 10, optimalMin: 0, unit: "ng/L" },
|
|
5988
|
+
kind: "reference-interval",
|
|
6303
5989
|
source: "giannitsis-hstnt-2010"
|
|
6304
5990
|
},
|
|
6305
5991
|
// TSH — 0.4–4.0 é a faixa de referência adulta geral. O alvo 2.5 µIU/mL é
|
|
@@ -6309,6 +5995,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6309
5995
|
// expandido (tolerância fisiológica do eixo em idosos, SBEM 2013).
|
|
6310
5996
|
TSH: {
|
|
6311
5997
|
default: { max: 4, min: 0.4, optimalMax: 3, optimalMin: 1, unit: "uIU/mL" },
|
|
5998
|
+
kind: "reference-interval",
|
|
6312
5999
|
source: "sbem-thyroid-2013",
|
|
6313
6000
|
variants: [
|
|
6314
6001
|
// Variantes gestacionais (ATA 2017 / SBEM): supressão fisiológica por hCG
|
|
@@ -6357,10 +6044,12 @@ var biomarkerRangeDefinitions = {
|
|
|
6357
6044
|
// deve ser revisto em biomarkers.ts — ver issue #41.
|
|
6358
6045
|
Urea: {
|
|
6359
6046
|
default: { max: 50, min: 15, optimalMax: 40, optimalMin: 20, unit: "mg/dL" },
|
|
6047
|
+
kind: "reference-interval",
|
|
6360
6048
|
source: "tietz-7ed-2015"
|
|
6361
6049
|
},
|
|
6362
6050
|
UricAcid: {
|
|
6363
6051
|
default: { max: 7, min: 2.5, optimalMax: 5.5, optimalMin: 3, unit: "mg/dL" },
|
|
6052
|
+
kind: "reference-interval",
|
|
6364
6053
|
source: "tietz-7ed-2015",
|
|
6365
6054
|
variants: [
|
|
6366
6055
|
{
|
|
@@ -6377,50 +6066,62 @@ var biomarkerRangeDefinitions = {
|
|
|
6377
6066
|
},
|
|
6378
6067
|
Urobilinogen_Urine: {
|
|
6379
6068
|
default: { max: 1, min: 0.1, optimalMax: 1, optimalMin: 0.1, unit: "mg/dL" },
|
|
6069
|
+
kind: "reference-interval",
|
|
6380
6070
|
source: "tietz-7ed-2015"
|
|
6381
6071
|
},
|
|
6382
6072
|
pH_Urine: {
|
|
6383
6073
|
default: { max: 8, min: 4.5, optimalMax: 7, optimalMin: 5.5, unit: "pH" },
|
|
6074
|
+
kind: "reference-interval",
|
|
6384
6075
|
source: "tietz-7ed-2015"
|
|
6385
6076
|
},
|
|
6386
6077
|
HyalineCasts_Urine: {
|
|
6387
6078
|
default: { max: 2, min: 0, optimalMax: 1, optimalMin: 0, unit: "/LPF" },
|
|
6079
|
+
kind: "reference-interval",
|
|
6388
6080
|
source: "tietz-7ed-2015"
|
|
6389
6081
|
},
|
|
6390
6082
|
RBC_Urine: {
|
|
6391
6083
|
default: { max: 3, min: 0, optimalMax: 1, optimalMin: 0, unit: "/HPF" },
|
|
6084
|
+
kind: "reference-interval",
|
|
6392
6085
|
source: "tietz-7ed-2015"
|
|
6393
6086
|
},
|
|
6394
6087
|
SquamousEpithelial_Urine: {
|
|
6395
6088
|
default: { max: 15, min: 0, optimalMax: 5, optimalMin: 0, unit: "/HPF" },
|
|
6089
|
+
kind: "reference-interval",
|
|
6396
6090
|
source: "tietz-7ed-2015"
|
|
6397
6091
|
},
|
|
6398
6092
|
Leukocytes_Urine: {
|
|
6399
6093
|
default: { max: 5, min: 0, optimalMax: 2, optimalMin: 0, unit: "/HPF" },
|
|
6094
|
+
kind: "reference-interval",
|
|
6400
6095
|
source: "tietz-7ed-2015"
|
|
6401
6096
|
},
|
|
6402
6097
|
Folate: {
|
|
6403
6098
|
default: { max: 20, min: 3.9, optimalMax: 17, optimalMin: 5, unit: "ng/mL" },
|
|
6099
|
+
kind: "reference-interval",
|
|
6404
6100
|
source: "tietz-7ed-2015"
|
|
6405
6101
|
},
|
|
6406
6102
|
VitaminA: {
|
|
6407
6103
|
default: { max: 100, min: 20, optimalMax: 80, optimalMin: 30, unit: "mcg/dL" },
|
|
6104
|
+
kind: "reference-interval",
|
|
6408
6105
|
source: "tietz-7ed-2015"
|
|
6409
6106
|
},
|
|
6410
6107
|
VitaminB1: {
|
|
6411
6108
|
default: { max: 180, min: 70, optimalMax: 150, optimalMin: 80, unit: "nmol/L" },
|
|
6109
|
+
kind: "reference-interval",
|
|
6412
6110
|
source: "tietz-7ed-2015"
|
|
6413
6111
|
},
|
|
6414
6112
|
VitaminB12: {
|
|
6415
6113
|
default: { max: 900, min: 200, optimalMax: 800, optimalMin: 400, unit: "pg/mL" },
|
|
6114
|
+
kind: "reference-interval",
|
|
6416
6115
|
source: "tietz-7ed-2015"
|
|
6417
6116
|
},
|
|
6418
6117
|
VitaminB6: {
|
|
6419
6118
|
default: { max: 50, min: 5, optimalMax: 40, optimalMin: 10, unit: "ng/mL" },
|
|
6119
|
+
kind: "reference-interval",
|
|
6420
6120
|
source: "tietz-7ed-2015"
|
|
6421
6121
|
},
|
|
6422
6122
|
VitaminC: {
|
|
6423
6123
|
default: { max: 2, min: 0.4, optimalMax: 1.5, optimalMin: 0.6, unit: "mg/dL" },
|
|
6124
|
+
kind: "reference-interval",
|
|
6424
6125
|
source: "tietz-7ed-2015"
|
|
6425
6126
|
},
|
|
6426
6127
|
// Vitamina D — posicionamento conjunto SBEM/SBPC-ML 2017:
|
|
@@ -6437,6 +6138,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6437
6138
|
// quando a modelagem de comorbidades chegar ao schema.
|
|
6438
6139
|
VitaminD: {
|
|
6439
6140
|
default: { max: 100, min: 20, optimalMax: 70, optimalMin: 40, unit: "ng/mL" },
|
|
6141
|
+
kind: "decision-threshold",
|
|
6440
6142
|
source: "ferreira-vitd-2017",
|
|
6441
6143
|
variants: [
|
|
6442
6144
|
{
|
|
@@ -6448,10 +6150,12 @@ var biomarkerRangeDefinitions = {
|
|
|
6448
6150
|
},
|
|
6449
6151
|
VitaminD_1_25: {
|
|
6450
6152
|
default: { max: 72, min: 18, optimalMax: 60, optimalMin: 25, unit: "pg/mL" },
|
|
6153
|
+
kind: "reference-interval",
|
|
6451
6154
|
source: "tietz-7ed-2015"
|
|
6452
6155
|
},
|
|
6453
6156
|
VitaminE: {
|
|
6454
6157
|
default: { max: 17, min: 5.5, optimalMax: 14, optimalMin: 7, unit: "mg/L" },
|
|
6158
|
+
kind: "reference-interval",
|
|
6455
6159
|
source: "tietz-7ed-2015"
|
|
6456
6160
|
},
|
|
6457
6161
|
// VLDL — estimado clinicamente via TG/5 (método Friedewald). O corte de
|
|
@@ -6460,30 +6164,34 @@ var biomarkerRangeDefinitions = {
|
|
|
6460
6164
|
// método de cálculo, mas a faixa de referência tem respaldo na diretriz
|
|
6461
6165
|
// SBC 2025.
|
|
6462
6166
|
VLDL: {
|
|
6463
|
-
default: { max: 30, min: 2, optimalMax: 20, optimalMin: 5, unit: "mg/dL" },
|
|
6167
|
+
default: { max: 30, min: 2, minKind: "display", optimalMax: 20, optimalMin: 5, unit: "mg/dL" },
|
|
6168
|
+
kind: "decision-threshold",
|
|
6464
6169
|
source: "sbc-lipids-2025"
|
|
6465
6170
|
},
|
|
6466
6171
|
WBC: {
|
|
6467
6172
|
default: { max: 11, min: 4, optimalMax: 8, optimalMin: 5, unit: "K/uL" },
|
|
6173
|
+
kind: "reference-interval",
|
|
6468
6174
|
source: "pns-hemograma-2019"
|
|
6469
6175
|
},
|
|
6470
6176
|
Zinc: {
|
|
6471
6177
|
default: { max: 120, min: 60, optimalMax: 100, optimalMin: 70, unit: "mcg/dL" },
|
|
6178
|
+
kind: "reference-interval",
|
|
6472
6179
|
source: "tietz-7ed-2015"
|
|
6473
6180
|
},
|
|
6474
6181
|
AndroidFatPct: {
|
|
6475
|
-
default: { max: 35, min: 10, optimalMax: 25, optimalMin: 15, unit: "%" },
|
|
6182
|
+
default: { max: 35, min: 10, minKind: "display", optimalMax: 25, optimalMin: 15, unit: "%" },
|
|
6476
6183
|
direction: "lower-better",
|
|
6184
|
+
kind: "population",
|
|
6477
6185
|
source: "kelly-dxa-2009",
|
|
6478
6186
|
variants: [
|
|
6479
6187
|
{
|
|
6480
6188
|
ageMin: 18,
|
|
6481
|
-
range: { max: 30, min: 10, optimalMax: 22, optimalMin: 12, unit: "%" },
|
|
6189
|
+
range: { max: 30, min: 10, minKind: "display", optimalMax: 22, optimalMin: 12, unit: "%" },
|
|
6482
6190
|
sex: "M"
|
|
6483
6191
|
},
|
|
6484
6192
|
{
|
|
6485
6193
|
ageMin: 18,
|
|
6486
|
-
range: { max: 42, min: 15, optimalMax: 32, optimalMin: 20, unit: "%" },
|
|
6194
|
+
range: { max: 42, min: 15, minKind: "display", optimalMax: 32, optimalMin: 20, unit: "%" },
|
|
6487
6195
|
sex: "F"
|
|
6488
6196
|
}
|
|
6489
6197
|
]
|
|
@@ -6534,6 +6242,7 @@ var biomarkerRangeDefinitions = {
|
|
|
6534
6242
|
CalfCircumference: {
|
|
6535
6243
|
default: { unit: "cm" },
|
|
6536
6244
|
direction: "higher-better",
|
|
6245
|
+
kind: "decision-threshold",
|
|
6537
6246
|
source: "ewgsop2-2019",
|
|
6538
6247
|
// O corte não é específico por sexo na fonte; as duas variantes existem
|
|
6539
6248
|
// porque `RangeVariant` exige o campo, e carregam o mesmo número.
|
|
@@ -6545,38 +6254,76 @@ var biomarkerRangeDefinitions = {
|
|
|
6545
6254
|
WaistToHeightRatio: {
|
|
6546
6255
|
default: { max: 0.5, unit: "" },
|
|
6547
6256
|
direction: "lower-better",
|
|
6257
|
+
kind: "decision-threshold",
|
|
6548
6258
|
source: "browning-ashwell-2010"
|
|
6549
6259
|
},
|
|
6550
6260
|
AndroidGynoidRatio: {
|
|
6551
|
-
default: { max: 1.2, min: 0.5, optimalMax: 1, optimalMin: 0.6, unit: "" },
|
|
6261
|
+
default: { max: 1.2, min: 0.5, minKind: "display", optimalMax: 1, optimalMin: 0.6, unit: "" },
|
|
6552
6262
|
direction: "lower-better",
|
|
6263
|
+
kind: "population",
|
|
6553
6264
|
source: "kelly-dxa-2009",
|
|
6554
6265
|
variants: [
|
|
6555
6266
|
{
|
|
6556
6267
|
ageMin: 18,
|
|
6557
|
-
range: {
|
|
6268
|
+
range: {
|
|
6269
|
+
max: 1.2,
|
|
6270
|
+
min: 0.6,
|
|
6271
|
+
minKind: "display",
|
|
6272
|
+
optimalMax: 1,
|
|
6273
|
+
optimalMin: 0.7,
|
|
6274
|
+
unit: ""
|
|
6275
|
+
},
|
|
6558
6276
|
sex: "M"
|
|
6559
6277
|
},
|
|
6560
6278
|
{
|
|
6561
6279
|
ageMin: 18,
|
|
6562
|
-
range: {
|
|
6280
|
+
range: {
|
|
6281
|
+
max: 1,
|
|
6282
|
+
min: 0.4,
|
|
6283
|
+
minKind: "display",
|
|
6284
|
+
optimalMax: 0.8,
|
|
6285
|
+
optimalMin: 0.5,
|
|
6286
|
+
unit: ""
|
|
6287
|
+
},
|
|
6563
6288
|
sex: "F"
|
|
6564
6289
|
}
|
|
6565
6290
|
]
|
|
6566
6291
|
},
|
|
6567
6292
|
BMC: {
|
|
6568
|
-
default: {
|
|
6293
|
+
default: {
|
|
6294
|
+
max: 3.5,
|
|
6295
|
+
maxKind: "display",
|
|
6296
|
+
min: 2,
|
|
6297
|
+
optimalMax: 3.2,
|
|
6298
|
+
optimalMin: 2.3,
|
|
6299
|
+
unit: "kg"
|
|
6300
|
+
},
|
|
6569
6301
|
direction: "higher-better",
|
|
6302
|
+
kind: "population",
|
|
6570
6303
|
source: "kelly-dxa-2009",
|
|
6571
6304
|
variants: [
|
|
6572
6305
|
{
|
|
6573
6306
|
ageMin: 18,
|
|
6574
|
-
range: {
|
|
6307
|
+
range: {
|
|
6308
|
+
max: 4,
|
|
6309
|
+
maxKind: "display",
|
|
6310
|
+
min: 2.5,
|
|
6311
|
+
optimalMax: 3.5,
|
|
6312
|
+
optimalMin: 2.8,
|
|
6313
|
+
unit: "kg"
|
|
6314
|
+
},
|
|
6575
6315
|
sex: "M"
|
|
6576
6316
|
},
|
|
6577
6317
|
{
|
|
6578
6318
|
ageMin: 18,
|
|
6579
|
-
range: {
|
|
6319
|
+
range: {
|
|
6320
|
+
max: 3,
|
|
6321
|
+
maxKind: "display",
|
|
6322
|
+
min: 1.8,
|
|
6323
|
+
optimalMax: 2.7,
|
|
6324
|
+
optimalMin: 2,
|
|
6325
|
+
unit: "kg"
|
|
6326
|
+
},
|
|
6580
6327
|
sex: "F"
|
|
6581
6328
|
}
|
|
6582
6329
|
]
|
|
@@ -6584,142 +6331,148 @@ var biomarkerRangeDefinitions = {
|
|
|
6584
6331
|
// BodyFatPct — Age-bracketed ranges from Gallagher et al. Am J Clin Nutr 2000;72:694-701
|
|
6585
6332
|
// (PMID: 10966886) and ACSM Guidelines for Exercise Testing, 11th Ed (2021)
|
|
6586
6333
|
BodyFatPct: {
|
|
6587
|
-
default: { max: 30, min: 10, optimalMax: 25, optimalMin: 15, unit: "%" },
|
|
6334
|
+
default: { max: 30, min: 10, minKind: "clinical", optimalMax: 25, optimalMin: 15, unit: "%" },
|
|
6588
6335
|
direction: "lower-better",
|
|
6336
|
+
kind: "decision-threshold",
|
|
6589
6337
|
source: "gallagher-bodyfat-2000",
|
|
6590
6338
|
variants: [
|
|
6591
6339
|
// Men — age brackets
|
|
6592
6340
|
{
|
|
6593
6341
|
ageMax: 25,
|
|
6594
6342
|
ageMin: 18,
|
|
6595
|
-
range: { max: 25, min: 5, optimalMax: 20, optimalMin: 10, unit: "%" },
|
|
6343
|
+
range: { max: 25, min: 5, minKind: "clinical", optimalMax: 20, optimalMin: 10, unit: "%" },
|
|
6596
6344
|
sex: "M"
|
|
6597
6345
|
},
|
|
6598
6346
|
{
|
|
6599
6347
|
ageMax: 35,
|
|
6600
6348
|
ageMin: 26,
|
|
6601
|
-
range: { max: 26, min: 5, optimalMax: 21, optimalMin: 11, unit: "%" },
|
|
6349
|
+
range: { max: 26, min: 5, minKind: "clinical", optimalMax: 21, optimalMin: 11, unit: "%" },
|
|
6602
6350
|
sex: "M"
|
|
6603
6351
|
},
|
|
6604
6352
|
{
|
|
6605
6353
|
ageMax: 45,
|
|
6606
6354
|
ageMin: 36,
|
|
6607
|
-
range: { max: 27, min: 5, optimalMax: 22, optimalMin: 12, unit: "%" },
|
|
6355
|
+
range: { max: 27, min: 5, minKind: "clinical", optimalMax: 22, optimalMin: 12, unit: "%" },
|
|
6608
6356
|
sex: "M"
|
|
6609
6357
|
},
|
|
6610
6358
|
{
|
|
6611
6359
|
ageMax: 55,
|
|
6612
6360
|
ageMin: 46,
|
|
6613
|
-
range: { max: 28, min: 5, optimalMax: 23, optimalMin: 13, unit: "%" },
|
|
6361
|
+
range: { max: 28, min: 5, minKind: "clinical", optimalMax: 23, optimalMin: 13, unit: "%" },
|
|
6614
6362
|
sex: "M"
|
|
6615
6363
|
},
|
|
6616
6364
|
{
|
|
6617
6365
|
ageMin: 56,
|
|
6618
|
-
range: { max: 29, min: 5, optimalMax: 24, optimalMin: 14, unit: "%" },
|
|
6366
|
+
range: { max: 29, min: 5, minKind: "clinical", optimalMax: 24, optimalMin: 14, unit: "%" },
|
|
6619
6367
|
sex: "M"
|
|
6620
6368
|
},
|
|
6621
6369
|
// Women — age brackets
|
|
6622
6370
|
{
|
|
6623
6371
|
ageMax: 25,
|
|
6624
6372
|
ageMin: 18,
|
|
6625
|
-
range: { max: 32, min: 13, optimalMax: 28, optimalMin: 18, unit: "%" },
|
|
6373
|
+
range: { max: 32, min: 13, minKind: "clinical", optimalMax: 28, optimalMin: 18, unit: "%" },
|
|
6626
6374
|
sex: "F"
|
|
6627
6375
|
},
|
|
6628
6376
|
{
|
|
6629
6377
|
ageMax: 35,
|
|
6630
6378
|
ageMin: 26,
|
|
6631
|
-
range: { max: 33, min: 13, optimalMax: 29, optimalMin: 18, unit: "%" },
|
|
6379
|
+
range: { max: 33, min: 13, minKind: "clinical", optimalMax: 29, optimalMin: 18, unit: "%" },
|
|
6632
6380
|
sex: "F"
|
|
6633
6381
|
},
|
|
6634
6382
|
{
|
|
6635
6383
|
ageMax: 45,
|
|
6636
6384
|
ageMin: 36,
|
|
6637
|
-
range: { max: 34, min: 13, optimalMax: 30, optimalMin: 19, unit: "%" },
|
|
6385
|
+
range: { max: 34, min: 13, minKind: "clinical", optimalMax: 30, optimalMin: 19, unit: "%" },
|
|
6638
6386
|
sex: "F"
|
|
6639
6387
|
},
|
|
6640
6388
|
{
|
|
6641
6389
|
ageMax: 55,
|
|
6642
6390
|
ageMin: 46,
|
|
6643
|
-
range: { max: 35, min: 13, optimalMax: 31, optimalMin: 20, unit: "%" },
|
|
6391
|
+
range: { max: 35, min: 13, minKind: "clinical", optimalMax: 31, optimalMin: 20, unit: "%" },
|
|
6644
6392
|
sex: "F"
|
|
6645
6393
|
},
|
|
6646
6394
|
{
|
|
6647
6395
|
ageMin: 56,
|
|
6648
|
-
range: { max: 36, min: 13, optimalMax: 32, optimalMin: 20, unit: "%" },
|
|
6396
|
+
range: { max: 36, min: 13, minKind: "clinical", optimalMax: 32, optimalMin: 20, unit: "%" },
|
|
6649
6397
|
sex: "F"
|
|
6650
6398
|
}
|
|
6651
6399
|
]
|
|
6652
6400
|
},
|
|
6653
6401
|
FatFreeMass: {
|
|
6654
|
-
default: { max: 80, min: 40, optimalMax: 70, optimalMin: 45, unit: "kg" },
|
|
6402
|
+
default: { max: 80, maxKind: "display", min: 40, optimalMax: 70, optimalMin: 45, unit: "kg" },
|
|
6655
6403
|
direction: "higher-better",
|
|
6404
|
+
kind: "population",
|
|
6656
6405
|
source: "kelly-dxa-2009",
|
|
6657
6406
|
variants: [
|
|
6658
6407
|
{
|
|
6659
6408
|
ageMin: 18,
|
|
6660
|
-
range: { max: 90, min: 50, optimalMax: 80, optimalMin: 55, unit: "kg" },
|
|
6409
|
+
range: { max: 90, maxKind: "display", min: 50, optimalMax: 80, optimalMin: 55, unit: "kg" },
|
|
6661
6410
|
sex: "M"
|
|
6662
6411
|
},
|
|
6663
6412
|
{
|
|
6664
6413
|
ageMin: 18,
|
|
6665
|
-
range: { max: 60, min: 35, optimalMax: 52, optimalMin: 38, unit: "kg" },
|
|
6414
|
+
range: { max: 60, maxKind: "display", min: 35, optimalMax: 52, optimalMin: 38, unit: "kg" },
|
|
6666
6415
|
sex: "F"
|
|
6667
6416
|
}
|
|
6668
6417
|
]
|
|
6669
6418
|
},
|
|
6670
6419
|
FatMass: {
|
|
6671
|
-
default: { max: 30, min: 5, optimalMax: 20, optimalMin: 8, unit: "kg" },
|
|
6420
|
+
default: { max: 30, min: 5, minKind: "clinical", optimalMax: 20, optimalMin: 8, unit: "kg" },
|
|
6672
6421
|
direction: "lower-better",
|
|
6422
|
+
kind: "population",
|
|
6673
6423
|
source: "kelly-dxa-2009",
|
|
6674
6424
|
variants: [
|
|
6675
6425
|
{
|
|
6676
6426
|
ageMin: 18,
|
|
6677
|
-
range: { max: 25, min: 5, optimalMax: 18, optimalMin: 7, unit: "kg" },
|
|
6427
|
+
range: { max: 25, min: 5, minKind: "clinical", optimalMax: 18, optimalMin: 7, unit: "kg" },
|
|
6678
6428
|
sex: "M"
|
|
6679
6429
|
},
|
|
6680
6430
|
{
|
|
6681
6431
|
ageMin: 18,
|
|
6682
|
-
range: { max: 30, min: 8, optimalMax: 22, optimalMin: 10, unit: "kg" },
|
|
6432
|
+
range: { max: 30, min: 8, minKind: "clinical", optimalMax: 22, optimalMin: 10, unit: "kg" },
|
|
6683
6433
|
sex: "F"
|
|
6684
6434
|
}
|
|
6685
6435
|
]
|
|
6686
6436
|
},
|
|
6687
6437
|
GynoidFatPct: {
|
|
6688
|
-
default: { max: 45, min: 15, optimalMax: 35, optimalMin: 20, unit: "%" },
|
|
6438
|
+
default: { max: 45, min: 15, minKind: "display", optimalMax: 35, optimalMin: 20, unit: "%" },
|
|
6689
6439
|
direction: "lower-better",
|
|
6440
|
+
kind: "population",
|
|
6690
6441
|
source: "kelly-dxa-2009",
|
|
6691
6442
|
variants: [
|
|
6692
6443
|
{
|
|
6693
6444
|
ageMin: 18,
|
|
6694
|
-
range: { max: 35, min: 12, optimalMax: 28, optimalMin: 15, unit: "%" },
|
|
6445
|
+
range: { max: 35, min: 12, minKind: "display", optimalMax: 28, optimalMin: 15, unit: "%" },
|
|
6695
6446
|
sex: "M"
|
|
6696
6447
|
},
|
|
6697
6448
|
{
|
|
6698
6449
|
ageMin: 18,
|
|
6699
|
-
range: { max: 50, min: 20, optimalMax: 40, optimalMin: 25, unit: "%" },
|
|
6450
|
+
range: { max: 50, min: 20, minKind: "display", optimalMax: 40, optimalMin: 25, unit: "%" },
|
|
6700
6451
|
sex: "F"
|
|
6701
6452
|
}
|
|
6702
6453
|
]
|
|
6703
6454
|
},
|
|
6704
6455
|
LeanMass: {
|
|
6705
|
-
default: { max: 75, min: 35, optimalMax: 65, optimalMin: 40, unit: "kg" },
|
|
6456
|
+
default: { max: 75, maxKind: "display", min: 35, optimalMax: 65, optimalMin: 40, unit: "kg" },
|
|
6706
6457
|
direction: "higher-better",
|
|
6458
|
+
kind: "population",
|
|
6707
6459
|
source: "kelly-dxa-2009",
|
|
6708
6460
|
variants: [
|
|
6709
6461
|
{
|
|
6710
6462
|
ageMin: 18,
|
|
6711
|
-
range: { max: 85, min: 45, optimalMax: 75, optimalMin: 50, unit: "kg" },
|
|
6463
|
+
range: { max: 85, maxKind: "display", min: 45, optimalMax: 75, optimalMin: 50, unit: "kg" },
|
|
6712
6464
|
sex: "M"
|
|
6713
6465
|
},
|
|
6714
6466
|
{
|
|
6715
6467
|
ageMin: 18,
|
|
6716
|
-
range: { max: 55, min: 30, optimalMax: 48, optimalMin: 35, unit: "kg" },
|
|
6468
|
+
range: { max: 55, maxKind: "display", min: 30, optimalMax: 48, optimalMin: 35, unit: "kg" },
|
|
6717
6469
|
sex: "F"
|
|
6718
6470
|
}
|
|
6719
6471
|
]
|
|
6720
6472
|
},
|
|
6721
6473
|
TotalMass: {
|
|
6722
6474
|
default: { max: 100, min: 50, optimalMax: 85, optimalMin: 55, unit: "kg" },
|
|
6475
|
+
kind: "population",
|
|
6723
6476
|
source: "kelly-dxa-2009",
|
|
6724
6477
|
variants: [
|
|
6725
6478
|
{
|
|
@@ -6737,223 +6490,853 @@ var biomarkerRangeDefinitions = {
|
|
|
6737
6490
|
VATMass: {
|
|
6738
6491
|
default: { max: 1.5, min: 0, optimalMax: 0.8, optimalMin: 0, unit: "kg" },
|
|
6739
6492
|
direction: "lower-better",
|
|
6493
|
+
kind: "population",
|
|
6740
6494
|
source: "ofenheimer-vat-2020",
|
|
6741
6495
|
variants: [
|
|
6742
6496
|
{
|
|
6743
6497
|
ageMin: 18,
|
|
6744
|
-
range: { max: 1.5, min: 0, optimalMax: 1, optimalMin: 0, unit: "kg" },
|
|
6498
|
+
range: { max: 1.5, min: 0, optimalMax: 1, optimalMin: 0, unit: "kg" },
|
|
6499
|
+
sex: "M"
|
|
6500
|
+
},
|
|
6501
|
+
{
|
|
6502
|
+
ageMin: 18,
|
|
6503
|
+
range: { max: 1, min: 0, optimalMax: 0.5, optimalMin: 0, unit: "kg" },
|
|
6504
|
+
sex: "F"
|
|
6505
|
+
}
|
|
6506
|
+
]
|
|
6507
|
+
},
|
|
6508
|
+
VATVolume: {
|
|
6509
|
+
default: {
|
|
6510
|
+
max: 852,
|
|
6511
|
+
min: 0,
|
|
6512
|
+
optimalMax: 600,
|
|
6513
|
+
optimalMin: 0,
|
|
6514
|
+
unit: "cm\xB3",
|
|
6515
|
+
warningMax: 1837
|
|
6516
|
+
},
|
|
6517
|
+
direction: "lower-better",
|
|
6518
|
+
kind: "decision-threshold",
|
|
6519
|
+
source: "ge-corescan"
|
|
6520
|
+
},
|
|
6521
|
+
BMD_Total: {
|
|
6522
|
+
default: {
|
|
6523
|
+
max: 1.4,
|
|
6524
|
+
maxKind: "display",
|
|
6525
|
+
min: 0.9,
|
|
6526
|
+
optimalMax: 1.3,
|
|
6527
|
+
optimalMin: 1,
|
|
6528
|
+
unit: "g/cm\xB2"
|
|
6529
|
+
},
|
|
6530
|
+
direction: "higher-better",
|
|
6531
|
+
kind: "decision-threshold",
|
|
6532
|
+
source: "who-osteoporosis-1994"
|
|
6533
|
+
},
|
|
6534
|
+
TScore_Total: {
|
|
6535
|
+
default: {
|
|
6536
|
+
max: 4,
|
|
6537
|
+
maxKind: "display",
|
|
6538
|
+
min: -1,
|
|
6539
|
+
optimalMax: 2,
|
|
6540
|
+
optimalMin: -0.5,
|
|
6541
|
+
unit: ""
|
|
6542
|
+
},
|
|
6543
|
+
direction: "higher-better",
|
|
6544
|
+
kind: "decision-threshold",
|
|
6545
|
+
source: "who-osteoporosis-1994"
|
|
6546
|
+
},
|
|
6547
|
+
ZScore_Total: {
|
|
6548
|
+
default: {
|
|
6549
|
+
max: 2,
|
|
6550
|
+
maxKind: "display",
|
|
6551
|
+
min: -2,
|
|
6552
|
+
optimalMax: 1,
|
|
6553
|
+
optimalMin: -1,
|
|
6554
|
+
unit: ""
|
|
6555
|
+
},
|
|
6556
|
+
direction: "higher-better",
|
|
6557
|
+
kind: "decision-threshold",
|
|
6558
|
+
source: "who-osteoporosis-1994"
|
|
6559
|
+
},
|
|
6560
|
+
Amylase: {
|
|
6561
|
+
default: { max: 100, min: 28, optimalMax: 90, optimalMin: 35, unit: "U/L" },
|
|
6562
|
+
kind: "reference-interval",
|
|
6563
|
+
source: "tietz-7ed-2015"
|
|
6564
|
+
},
|
|
6565
|
+
Creatinine_Urine: {
|
|
6566
|
+
default: { max: 300, min: 20, optimalMax: 250, optimalMin: 40, unit: "mg/dL" },
|
|
6567
|
+
kind: "reference-interval",
|
|
6568
|
+
source: "tietz-7ed-2015",
|
|
6569
|
+
variants: [
|
|
6570
|
+
{
|
|
6571
|
+
ageMin: 18,
|
|
6572
|
+
range: { max: 300, min: 40, optimalMax: 260, optimalMin: 60, unit: "mg/dL" },
|
|
6573
|
+
sex: "M"
|
|
6574
|
+
},
|
|
6575
|
+
{
|
|
6576
|
+
ageMin: 18,
|
|
6577
|
+
range: { max: 220, min: 20, optimalMax: 180, optimalMin: 40, unit: "mg/dL" },
|
|
6578
|
+
sex: "F"
|
|
6579
|
+
}
|
|
6580
|
+
]
|
|
6581
|
+
},
|
|
6582
|
+
IgA: {
|
|
6583
|
+
default: { max: 400, min: 70, optimalMax: 350, optimalMin: 100, unit: "mg/dL" },
|
|
6584
|
+
kind: "reference-interval",
|
|
6585
|
+
source: "tietz-7ed-2015"
|
|
6586
|
+
},
|
|
6587
|
+
Lipase: {
|
|
6588
|
+
default: { max: 60, min: 0, optimalMax: 50, optimalMin: 10, unit: "U/L" },
|
|
6589
|
+
kind: "reference-interval",
|
|
6590
|
+
source: "tietz-7ed-2015"
|
|
6591
|
+
},
|
|
6592
|
+
Microalbumin_Urine: {
|
|
6593
|
+
default: { max: 30, min: 0, optimalMax: 20, optimalMin: 0, unit: "mg/L" },
|
|
6594
|
+
kind: "decision-threshold",
|
|
6595
|
+
source: "kdigo-ckd-2024"
|
|
6596
|
+
},
|
|
6597
|
+
PSA_Free: {
|
|
6598
|
+
default: { max: 1.5, min: 0, optimalMax: 1, optimalMin: 0, unit: "ng/mL" },
|
|
6599
|
+
kind: "reference-interval",
|
|
6600
|
+
source: "sturgeon-nacb-2008"
|
|
6601
|
+
},
|
|
6602
|
+
// Relação PSA livre/total — `higher-better`: razão maior = menor risco de
|
|
6603
|
+
// câncer de próstata, logo não há limite superior "ruim" (acima do normal é
|
|
6604
|
+
// verde). Faixas alinhadas à tabela clínica: ≥25% baixo risco (verde),
|
|
6605
|
+
// 10–25% atenção — intermediário/moderado (âmbar), <10% alto risco >50%
|
|
6606
|
+
// (vermelho). Limites: `min` (25) é o piso do verde e `warningMin` (10) o
|
|
6607
|
+
// piso do âmbar — o vermelho é estritamente abaixo de 10% (< 10%); 10%
|
|
6608
|
+
// pertence ao âmbar, conforme a faixa "10–15% moderado" da tabela.
|
|
6609
|
+
PSA_FreeRatio: {
|
|
6610
|
+
default: {
|
|
6611
|
+
max: 100,
|
|
6612
|
+
maxKind: "display",
|
|
6613
|
+
min: 25,
|
|
6614
|
+
optimalMax: 100,
|
|
6615
|
+
optimalMin: 30,
|
|
6616
|
+
unit: "%",
|
|
6617
|
+
warningMin: 10
|
|
6618
|
+
},
|
|
6619
|
+
direction: "higher-better",
|
|
6620
|
+
kind: "decision-threshold",
|
|
6621
|
+
source: "sturgeon-nacb-2008"
|
|
6622
|
+
},
|
|
6623
|
+
// BMI - WHO classification: 18.5–24.9 normal, 25–29.9 overweight, ≥30 obese
|
|
6624
|
+
BMI: {
|
|
6625
|
+
default: { max: 30, min: 18.5, optimalMax: 24.9, optimalMin: 18.5, unit: "kg/m2" },
|
|
6626
|
+
kind: "decision-threshold",
|
|
6627
|
+
source: "who-obesity-2000"
|
|
6628
|
+
},
|
|
6629
|
+
// eAG — Estimated Average Glucose, derivada da HbA1c pela fórmula ADAG:
|
|
6630
|
+
// eAG (mg/dL) = 28,7 × HbA1c(%) − 46,7 (NATHAN, D. M. et al. Translating the
|
|
6631
|
+
// A1C assay into estimated average glucose values. Diabetes Care, v. 31, n. 8,
|
|
6632
|
+
// p. 1473-1478, 2008. DOI: 10.2337/dc08-0545).
|
|
6633
|
+
//
|
|
6634
|
+
// As faixas espelham os cortes diagnósticos de HbA1c da SBD (ver entrada
|
|
6635
|
+
// `HbA1c`) convertidos por essa fórmula, mantendo a eAG coerente com o
|
|
6636
|
+
// marcador de origem:
|
|
6637
|
+
// optimalMax 105 ← HbA1c 5,3 % (teto do controle ótimo)
|
|
6638
|
+
// max 117 ← HbA1c 5,7 % (teto do não diabético → início do pré-diabetes)
|
|
6639
|
+
// warningMax 137 ← HbA1c 6,4 % (teto do pré-diabetes → acima disso, diabetes)
|
|
6640
|
+
// optimalMin 82 ← HbA1c 4,5 % (piso do alvo fisiológico da entrada HbA1c)
|
|
6641
|
+
// min 11 ← HbA1c 2,0 % (mesmo piso de sanidade da entrada HbA1c)
|
|
6642
|
+
//
|
|
6643
|
+
// O piso era 70 nos dois campos, e não vinha desta conversão: 70 é o limite
|
|
6644
|
+
// inferior clássico da glicemia **de jejum**, transplantado para uma média
|
|
6645
|
+
// estimada de ~3 meses. Pela fórmula, 70 equivale a HbA1c 4,07 % — ou seja,
|
|
6646
|
+
// marcava como alterado exatamente quem a entrada `HbA1c` documenta que não
|
|
6647
|
+
// deve ser sinalizado, já que HbA1c baixa reflete hemólise, perda sanguínea
|
|
6648
|
+
// ou hemoglobinopatia, e não doença do metabolismo glicêmico. Espelhar o piso
|
|
6649
|
+
// do HbA1c mantém as duas entradas coerentes, que é o que o comentário sempre
|
|
6650
|
+
// afirmou fazer.
|
|
6651
|
+
//
|
|
6652
|
+
// Substitui a faixa anterior (optimalMax 126 = corte de glicemia de jejum;
|
|
6653
|
+
// max 154 = meta terapêutica do diabético, HbA1c 7 %), que classificava como
|
|
6654
|
+
// "Normal" valores já pré-diabéticos e diabéticos.
|
|
6655
|
+
eAG: {
|
|
6656
|
+
default: {
|
|
6657
|
+
max: 117,
|
|
6658
|
+
min: 11,
|
|
6659
|
+
minKind: "display",
|
|
6660
|
+
optimalMax: 105,
|
|
6661
|
+
optimalMin: 82,
|
|
6662
|
+
unit: "mg/dL",
|
|
6663
|
+
warningMax: 137
|
|
6664
|
+
},
|
|
6665
|
+
kind: "decision-threshold",
|
|
6666
|
+
source: "sbd-diabetes-2024"
|
|
6667
|
+
},
|
|
6668
|
+
// INR - International Normalized Ratio (non-anticoagulated patients)
|
|
6669
|
+
INR: {
|
|
6670
|
+
default: { max: 1.2, min: 0.8, optimalMax: 1.1, optimalMin: 0.9, unit: "ratio" },
|
|
6671
|
+
kind: "reference-interval",
|
|
6672
|
+
source: "tietz-7ed-2015"
|
|
6673
|
+
},
|
|
6674
|
+
// Prothrombin Time
|
|
6675
|
+
ProthrombinTime: {
|
|
6676
|
+
default: { max: 13.5, min: 11, optimalMax: 13, optimalMin: 11, unit: "seconds" },
|
|
6677
|
+
kind: "reference-interval",
|
|
6678
|
+
source: "tietz-7ed-2015"
|
|
6679
|
+
},
|
|
6680
|
+
// DHT - Dihydrotestosterone (adult male reference; female values are much lower)
|
|
6681
|
+
DHT: {
|
|
6682
|
+
default: { max: 85, min: 30, optimalMax: 85, optimalMin: 30, unit: "ng/dL" },
|
|
6683
|
+
kind: "reference-interval",
|
|
6684
|
+
source: "tietz-7ed-2015",
|
|
6685
|
+
variants: [
|
|
6686
|
+
{
|
|
6687
|
+
ageMin: 18,
|
|
6688
|
+
range: { max: 85, min: 30, optimalMax: 85, optimalMin: 30, unit: "ng/dL" },
|
|
6745
6689
|
sex: "M"
|
|
6746
6690
|
},
|
|
6747
6691
|
{
|
|
6748
6692
|
ageMin: 18,
|
|
6749
|
-
range: { max:
|
|
6693
|
+
range: { max: 22, min: 4, optimalMax: 22, optimalMin: 4, unit: "ng/dL" },
|
|
6750
6694
|
sex: "F"
|
|
6751
6695
|
}
|
|
6752
6696
|
]
|
|
6753
6697
|
},
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
min: 0,
|
|
6758
|
-
optimalMax: 600,
|
|
6759
|
-
optimalMin: 0,
|
|
6760
|
-
unit: "cm\xB3",
|
|
6761
|
-
warningMax: 1837
|
|
6762
|
-
},
|
|
6698
|
+
// Total IgE - higher values suggest atopy/allergic sensitization
|
|
6699
|
+
IgE_Total: {
|
|
6700
|
+
default: { max: 100, min: 0, optimalMax: 100, optimalMin: 0, unit: "IU/mL" },
|
|
6763
6701
|
direction: "lower-better",
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
BMD_Total: {
|
|
6767
|
-
default: { max: 1.4, min: 0.9, optimalMax: 1.3, optimalMin: 1, unit: "g/cm\xB2" },
|
|
6768
|
-
direction: "higher-better",
|
|
6769
|
-
source: "who-osteoporosis-1994"
|
|
6702
|
+
kind: "reference-interval",
|
|
6703
|
+
source: "tietz-7ed-2015"
|
|
6770
6704
|
},
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6705
|
+
// IgG - Immunoglobulin G
|
|
6706
|
+
IgG: {
|
|
6707
|
+
default: { max: 1600, min: 700, optimalMax: 1600, optimalMin: 700, unit: "mg/dL" },
|
|
6708
|
+
kind: "reference-interval",
|
|
6709
|
+
source: "tietz-7ed-2015"
|
|
6775
6710
|
},
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6711
|
+
// IgE E1 Cat Dander - Class 0 (≤0.35 kU/L) = negative
|
|
6712
|
+
IgE_E1_CatDander: {
|
|
6713
|
+
default: { max: 0.35, min: 0, optimalMax: 0.35, optimalMin: 0, unit: "kU/L" },
|
|
6714
|
+
direction: "lower-better",
|
|
6715
|
+
kind: "decision-threshold",
|
|
6716
|
+
source: "tietz-7ed-2015"
|
|
6780
6717
|
},
|
|
6781
|
-
|
|
6782
|
-
|
|
6718
|
+
// IgE GX1 Grasses - Class 0 (≤0.35 kU/L) = negative
|
|
6719
|
+
IgE_GX1_Grasses: {
|
|
6720
|
+
default: { max: 0.35, min: 0, optimalMax: 0.35, optimalMin: 0, unit: "kU/L" },
|
|
6721
|
+
direction: "lower-better",
|
|
6722
|
+
kind: "decision-threshold",
|
|
6783
6723
|
source: "tietz-7ed-2015"
|
|
6724
|
+
}
|
|
6725
|
+
};
|
|
6726
|
+
var defaultReferenceRanges = Object.fromEntries(
|
|
6727
|
+
Object.entries(biomarkerRangeDefinitions).map(([code, def]) => [
|
|
6728
|
+
code,
|
|
6729
|
+
{
|
|
6730
|
+
...def.default,
|
|
6731
|
+
...def.kind && { kind: def.kind },
|
|
6732
|
+
...def.source && { source: def.source }
|
|
6733
|
+
}
|
|
6734
|
+
])
|
|
6735
|
+
);
|
|
6736
|
+
function getReferenceRange(testCode, context) {
|
|
6737
|
+
const definition = biomarkerRangeDefinitions[testCode];
|
|
6738
|
+
if (!definition) return void 0;
|
|
6739
|
+
const withSource = (range2, kind = definition.kind) => ({
|
|
6740
|
+
...range2,
|
|
6741
|
+
...kind && { kind },
|
|
6742
|
+
...definition.source && { source: definition.source }
|
|
6743
|
+
});
|
|
6744
|
+
if (!context || !definition.variants || definition.variants.length === 0) {
|
|
6745
|
+
return withSource(definition.default);
|
|
6746
|
+
}
|
|
6747
|
+
const { age, biologicalSex, pregnancyTrimester, pregnant } = context;
|
|
6748
|
+
const hasPregnancyVariant = definition.variants.some((v) => v.pregnant === true);
|
|
6749
|
+
for (const variant of definition.variants) {
|
|
6750
|
+
if (variant.pregnant === true) {
|
|
6751
|
+
if (!pregnant) continue;
|
|
6752
|
+
if (variant.pregnancyTrimester !== void 0 && variant.pregnancyTrimester !== pregnancyTrimester) {
|
|
6753
|
+
continue;
|
|
6754
|
+
}
|
|
6755
|
+
} else if (pregnant && hasPregnancyVariant) {
|
|
6756
|
+
continue;
|
|
6757
|
+
}
|
|
6758
|
+
if (variant.sex !== "all" && variant.sex !== biologicalSex) {
|
|
6759
|
+
continue;
|
|
6760
|
+
}
|
|
6761
|
+
if (variant.ageMin !== void 0 && (age === void 0 || age < variant.ageMin)) {
|
|
6762
|
+
continue;
|
|
6763
|
+
}
|
|
6764
|
+
if (variant.ageMax !== void 0 && (age === void 0 || age > variant.ageMax)) {
|
|
6765
|
+
continue;
|
|
6766
|
+
}
|
|
6767
|
+
return withSource(variant.range, variant.kind ?? definition.kind);
|
|
6768
|
+
}
|
|
6769
|
+
return withSource(definition.default);
|
|
6770
|
+
}
|
|
6771
|
+
function getRangeDirection(testCode) {
|
|
6772
|
+
return biomarkerRangeDefinitions[testCode]?.direction ?? "range";
|
|
6773
|
+
}
|
|
6774
|
+
function referenceRangeMeaning(kind) {
|
|
6775
|
+
const system = "http://terminology.hl7.org/CodeSystem/referencerange-meaning";
|
|
6776
|
+
if (kind === "reference-interval") return { code: "normal", display: "Normal Range", system };
|
|
6777
|
+
if (kind === "decision-threshold") {
|
|
6778
|
+
return { code: "recommended", display: "Recommended Range", system };
|
|
6779
|
+
}
|
|
6780
|
+
return void 0;
|
|
6781
|
+
}
|
|
6782
|
+
|
|
6783
|
+
// src/converter.ts
|
|
6784
|
+
function interpretationCode(flag) {
|
|
6785
|
+
switch (flag) {
|
|
6786
|
+
case "H":
|
|
6787
|
+
return "H";
|
|
6788
|
+
// High
|
|
6789
|
+
case "L":
|
|
6790
|
+
return "L";
|
|
6791
|
+
// Low
|
|
6792
|
+
default:
|
|
6793
|
+
return "N";
|
|
6794
|
+
}
|
|
6795
|
+
}
|
|
6796
|
+
function interpretationDisplay(flag) {
|
|
6797
|
+
switch (flag) {
|
|
6798
|
+
case "H":
|
|
6799
|
+
return "High";
|
|
6800
|
+
case "L":
|
|
6801
|
+
return "Low";
|
|
6802
|
+
default:
|
|
6803
|
+
return "Normal";
|
|
6804
|
+
}
|
|
6805
|
+
}
|
|
6806
|
+
var SEX_CODING = {
|
|
6807
|
+
female: {
|
|
6808
|
+
code: "female",
|
|
6809
|
+
display: "Female",
|
|
6810
|
+
system: "http://hl7.org/fhir/administrative-gender"
|
|
6784
6811
|
},
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6812
|
+
male: { code: "male", display: "Male", system: "http://hl7.org/fhir/administrative-gender" }
|
|
6813
|
+
};
|
|
6814
|
+
var buildReferenceRanges = (observation, quantity) => {
|
|
6815
|
+
const toRanges = (low, high, sex) => {
|
|
6816
|
+
if (low === void 0 && high === void 0) return [];
|
|
6817
|
+
return [
|
|
6789
6818
|
{
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
}
|
|
6819
|
+
...sex === void 0 ? {} : { appliesTo: [{ coding: [SEX_CODING[sex]] }] },
|
|
6820
|
+
...high === void 0 ? {} : { high: quantity(high) },
|
|
6821
|
+
...low === void 0 ? {} : { low: quantity(low) }
|
|
6822
|
+
}
|
|
6823
|
+
];
|
|
6824
|
+
};
|
|
6825
|
+
if (observation.referenceRanges && observation.referenceRanges.length > 0) {
|
|
6826
|
+
return observation.referenceRanges.flatMap((r) => toRanges(r.low, r.high, r.appliesTo));
|
|
6827
|
+
}
|
|
6828
|
+
const meaning = observation.referenceKind && referenceRangeMeaning(observation.referenceKind);
|
|
6829
|
+
return toRanges(observation.referenceMin, observation.referenceMax).map(
|
|
6830
|
+
(range2) => meaning ? { ...range2, type: { coding: [meaning] } } : range2
|
|
6831
|
+
);
|
|
6832
|
+
};
|
|
6833
|
+
function labObservationToFHIR(observation, patientId, laboratoryName) {
|
|
6834
|
+
const loincCode = codeToLoinc(observation.biomarkerCode);
|
|
6835
|
+
const sourceUnit = observation.unit || getDefaultUnit(observation.biomarkerCode) || observation.unit;
|
|
6836
|
+
const ucumUnit = resolveUcum(sourceUnit, observation.biomarkerCode);
|
|
6837
|
+
const quantity = (value) => ({
|
|
6838
|
+
...ucumUnit ? { code: ucumUnit, system: "http://unitsofmeasure.org" } : {},
|
|
6839
|
+
...sourceUnit ? { unit: sourceUnit } : {},
|
|
6840
|
+
value
|
|
6841
|
+
});
|
|
6842
|
+
const isQualitative = observation.isQualitative || typeof observation.value === "string";
|
|
6843
|
+
const fhirObs = {
|
|
6844
|
+
category: [
|
|
6845
|
+
{
|
|
6846
|
+
coding: [
|
|
6847
|
+
{
|
|
6848
|
+
code: "laboratory",
|
|
6849
|
+
display: "Laboratory",
|
|
6850
|
+
system: "http://terminology.hl7.org/CodeSystem/observation-category"
|
|
6851
|
+
}
|
|
6852
|
+
]
|
|
6853
|
+
}
|
|
6854
|
+
],
|
|
6855
|
+
code: {
|
|
6856
|
+
// Sem LOINC, o coding LOINC simplesmente não sai. Antes ia `99999-9`,
|
|
6857
|
+
// que não é código LOINC nenhum: publicava sob `http://loinc.org` uma
|
|
6858
|
+
// afirmação falsa, e quem consumisse o bundle confiando no system
|
|
6859
|
+
// trataria aquilo como código de verdade. Composição corporal, densidade
|
|
6860
|
+
// óssea e escore de cálcio não têm LOINC, e o certo é a lacuna explícita.
|
|
6861
|
+
coding: [
|
|
6862
|
+
...loincCode ? [
|
|
6863
|
+
{
|
|
6864
|
+
code: loincCode,
|
|
6865
|
+
display: observation.biomarkerName,
|
|
6866
|
+
system: LOINC_SYSTEM
|
|
6867
|
+
}
|
|
6868
|
+
] : [],
|
|
6869
|
+
{
|
|
6870
|
+
code: observation.biomarkerCode,
|
|
6871
|
+
display: observation.biomarkerName,
|
|
6872
|
+
system: BIOMARKER_CODE_SYSTEM
|
|
6873
|
+
}
|
|
6874
|
+
],
|
|
6875
|
+
text: observation.biomarkerName
|
|
6876
|
+
},
|
|
6877
|
+
effectiveDateTime: observation.collectionDate,
|
|
6878
|
+
id: `${observation.reportId}-${observation.biomarkerCode}`,
|
|
6879
|
+
interpretation: [
|
|
6880
|
+
{
|
|
6881
|
+
coding: [
|
|
6882
|
+
{
|
|
6883
|
+
code: interpretationCode(observation.flag),
|
|
6884
|
+
display: interpretationDisplay(observation.flag),
|
|
6885
|
+
system: "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"
|
|
6886
|
+
}
|
|
6887
|
+
]
|
|
6888
|
+
}
|
|
6889
|
+
],
|
|
6890
|
+
performer: laboratoryName ? [{ display: laboratoryName }] : void 0,
|
|
6891
|
+
resourceType: "Observation",
|
|
6892
|
+
status: "final",
|
|
6893
|
+
subject: {
|
|
6894
|
+
reference: `Patient/${patientId}`
|
|
6895
|
+
}
|
|
6896
|
+
};
|
|
6897
|
+
if (isQualitative) {
|
|
6898
|
+
fhirObs.valueString = String(observation.value);
|
|
6899
|
+
} else {
|
|
6900
|
+
fhirObs.valueQuantity = quantity(observation.value);
|
|
6901
|
+
const referenceRange = buildReferenceRanges(observation, quantity);
|
|
6902
|
+
if (referenceRange.length > 0) fhirObs.referenceRange = referenceRange;
|
|
6903
|
+
}
|
|
6904
|
+
return fhirObs;
|
|
6905
|
+
}
|
|
6906
|
+
function labReportToFHIR(report, patientId, observationIds) {
|
|
6907
|
+
let status;
|
|
6908
|
+
switch (report.processingStatus) {
|
|
6909
|
+
case "complete":
|
|
6910
|
+
status = "final";
|
|
6911
|
+
break;
|
|
6912
|
+
case "partial":
|
|
6913
|
+
status = "partial";
|
|
6914
|
+
break;
|
|
6915
|
+
case "pending_review":
|
|
6916
|
+
status = "preliminary";
|
|
6917
|
+
break;
|
|
6918
|
+
default:
|
|
6919
|
+
status = "final";
|
|
6920
|
+
}
|
|
6921
|
+
return {
|
|
6922
|
+
category: [
|
|
6923
|
+
{
|
|
6924
|
+
coding: [
|
|
6925
|
+
{
|
|
6926
|
+
code: "LAB",
|
|
6927
|
+
display: "Laboratory",
|
|
6928
|
+
system: "http://terminology.hl7.org/CodeSystem/v2-0074"
|
|
6929
|
+
}
|
|
6930
|
+
]
|
|
6931
|
+
}
|
|
6932
|
+
],
|
|
6933
|
+
code: {
|
|
6934
|
+
coding: [
|
|
6935
|
+
{
|
|
6936
|
+
code: "11502-2",
|
|
6937
|
+
// Laboratory report
|
|
6938
|
+
display: "Laboratory report",
|
|
6939
|
+
system: "http://loinc.org"
|
|
6940
|
+
}
|
|
6941
|
+
],
|
|
6942
|
+
text: "Laboratory Results"
|
|
6943
|
+
},
|
|
6944
|
+
conclusion: report.overallStatus === "NORMAL" ? "All results within normal limits" : "One or more abnormal results detected",
|
|
6945
|
+
conclusionCode: report.overallStatus === "ANORMAL" ? [
|
|
6794
6946
|
{
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6947
|
+
coding: [
|
|
6948
|
+
{
|
|
6949
|
+
code: "A",
|
|
6950
|
+
display: "Abnormal",
|
|
6951
|
+
system: "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"
|
|
6952
|
+
}
|
|
6953
|
+
]
|
|
6798
6954
|
}
|
|
6799
|
-
]
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
// câncer de próstata, logo não há limite superior "ruim" (acima do normal é
|
|
6819
|
-
// verde). Faixas alinhadas à tabela clínica: ≥25% baixo risco (verde),
|
|
6820
|
-
// 10–25% atenção — intermediário/moderado (âmbar), <10% alto risco >50%
|
|
6821
|
-
// (vermelho). Limites: `min` (25) é o piso do verde e `warningMin` (10) o
|
|
6822
|
-
// piso do âmbar — o vermelho é estritamente abaixo de 10% (< 10%); 10%
|
|
6823
|
-
// pertence ao âmbar, conforme a faixa "10–15% moderado" da tabela.
|
|
6824
|
-
PSA_FreeRatio: {
|
|
6825
|
-
default: { max: 100, min: 25, optimalMax: 100, optimalMin: 30, unit: "%", warningMin: 10 },
|
|
6826
|
-
direction: "higher-better",
|
|
6827
|
-
source: "sturgeon-nacb-2008"
|
|
6828
|
-
},
|
|
6829
|
-
// BMI - WHO classification: 18.5–24.9 normal, 25–29.9 overweight, ≥30 obese
|
|
6830
|
-
BMI: {
|
|
6831
|
-
default: { max: 30, min: 18.5, optimalMax: 24.9, optimalMin: 18.5, unit: "kg/m2" },
|
|
6832
|
-
source: "who-obesity-2000"
|
|
6833
|
-
},
|
|
6834
|
-
// eAG — Estimated Average Glucose, derivada da HbA1c pela fórmula ADAG:
|
|
6835
|
-
// eAG (mg/dL) = 28,7 × HbA1c(%) − 46,7 (NATHAN, D. M. et al. Translating the
|
|
6836
|
-
// A1C assay into estimated average glucose values. Diabetes Care, v. 31, n. 8,
|
|
6837
|
-
// p. 1473-1478, 2008. DOI: 10.2337/dc08-0545).
|
|
6838
|
-
//
|
|
6839
|
-
// As faixas espelham os cortes diagnósticos de HbA1c da SBD (ver entrada
|
|
6840
|
-
// `HbA1c`) convertidos por essa fórmula, mantendo a eAG coerente com o
|
|
6841
|
-
// marcador de origem:
|
|
6842
|
-
// optimalMax 105 ← HbA1c 5,3 % (teto do controle ótimo)
|
|
6843
|
-
// max 117 ← HbA1c 5,7 % (teto do não diabético → início do pré-diabetes)
|
|
6844
|
-
// warningMax 137 ← HbA1c 6,4 % (teto do pré-diabetes → acima disso, diabetes)
|
|
6845
|
-
// optimalMin 82 ← HbA1c 4,5 % (piso do alvo fisiológico da entrada HbA1c)
|
|
6846
|
-
// min 11 ← HbA1c 2,0 % (mesmo piso de sanidade da entrada HbA1c)
|
|
6847
|
-
//
|
|
6848
|
-
// O piso era 70 nos dois campos, e não vinha desta conversão: 70 é o limite
|
|
6849
|
-
// inferior clássico da glicemia **de jejum**, transplantado para uma média
|
|
6850
|
-
// estimada de ~3 meses. Pela fórmula, 70 equivale a HbA1c 4,07 % — ou seja,
|
|
6851
|
-
// marcava como alterado exatamente quem a entrada `HbA1c` documenta que não
|
|
6852
|
-
// deve ser sinalizado, já que HbA1c baixa reflete hemólise, perda sanguínea
|
|
6853
|
-
// ou hemoglobinopatia, e não doença do metabolismo glicêmico. Espelhar o piso
|
|
6854
|
-
// do HbA1c mantém as duas entradas coerentes, que é o que o comentário sempre
|
|
6855
|
-
// afirmou fazer.
|
|
6856
|
-
//
|
|
6857
|
-
// Substitui a faixa anterior (optimalMax 126 = corte de glicemia de jejum;
|
|
6858
|
-
// max 154 = meta terapêutica do diabético, HbA1c 7 %), que classificava como
|
|
6859
|
-
// "Normal" valores já pré-diabéticos e diabéticos.
|
|
6860
|
-
eAG: {
|
|
6861
|
-
default: { max: 117, min: 11, optimalMax: 105, optimalMin: 82, unit: "mg/dL", warningMax: 137 },
|
|
6862
|
-
source: "sbd-diabetes-2024"
|
|
6863
|
-
},
|
|
6864
|
-
// INR - International Normalized Ratio (non-anticoagulated patients)
|
|
6865
|
-
INR: {
|
|
6866
|
-
default: { max: 1.2, min: 0.8, optimalMax: 1.1, optimalMin: 0.9, unit: "ratio" },
|
|
6867
|
-
source: "tietz-7ed-2015"
|
|
6868
|
-
},
|
|
6869
|
-
// Prothrombin Time
|
|
6870
|
-
ProthrombinTime: {
|
|
6871
|
-
default: { max: 13.5, min: 11, optimalMax: 13, optimalMin: 11, unit: "seconds" },
|
|
6872
|
-
source: "tietz-7ed-2015"
|
|
6873
|
-
},
|
|
6874
|
-
// DHT - Dihydrotestosterone (adult male reference; female values are much lower)
|
|
6875
|
-
DHT: {
|
|
6876
|
-
default: { max: 85, min: 30, optimalMax: 85, optimalMin: 30, unit: "ng/dL" },
|
|
6877
|
-
source: "tietz-7ed-2015",
|
|
6878
|
-
variants: [
|
|
6955
|
+
] : void 0,
|
|
6956
|
+
effectiveDateTime: report.collectionDate,
|
|
6957
|
+
id: report.reportId,
|
|
6958
|
+
issued: report.createdAt,
|
|
6959
|
+
performer: report.laboratoryName ? [{ display: report.laboratoryName }] : void 0,
|
|
6960
|
+
resourceType: "DiagnosticReport",
|
|
6961
|
+
result: observationIds.map((id) => ({ reference: `Observation/${id}` })),
|
|
6962
|
+
status,
|
|
6963
|
+
subject: {
|
|
6964
|
+
reference: `Patient/${patientId}`
|
|
6965
|
+
}
|
|
6966
|
+
};
|
|
6967
|
+
}
|
|
6968
|
+
function userProfileToFHIR(profile) {
|
|
6969
|
+
const nameParts = profile.name.split(" ");
|
|
6970
|
+
const given = nameParts.slice(0, -1);
|
|
6971
|
+
const family = nameParts[nameParts.length - 1] || "";
|
|
6972
|
+
return {
|
|
6973
|
+
address: profile.address ? [
|
|
6879
6974
|
{
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6975
|
+
city: profile.address.city,
|
|
6976
|
+
country: profile.address.country || "BR",
|
|
6977
|
+
line: [
|
|
6978
|
+
profile.address.street && profile.address.number ? `${profile.address.street}, ${profile.address.number}` : profile.address.street,
|
|
6979
|
+
profile.address.complement
|
|
6980
|
+
].filter(Boolean),
|
|
6981
|
+
postalCode: profile.address.postalCode,
|
|
6982
|
+
state: profile.address.state
|
|
6983
|
+
}
|
|
6984
|
+
] : void 0,
|
|
6985
|
+
birthDate: profile.birthDate,
|
|
6986
|
+
gender: profile.gender,
|
|
6987
|
+
id: profile.userId,
|
|
6988
|
+
name: [
|
|
6884
6989
|
{
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6990
|
+
family,
|
|
6991
|
+
given: given.length > 0 ? given : void 0,
|
|
6992
|
+
text: profile.name
|
|
6888
6993
|
}
|
|
6889
|
-
]
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6994
|
+
],
|
|
6995
|
+
resourceType: "Patient",
|
|
6996
|
+
telecom: [
|
|
6997
|
+
...profile.email ? [{ system: "email", value: profile.email }] : [],
|
|
6998
|
+
...profile.phone ? [{ system: "phone", value: profile.phone }] : []
|
|
6999
|
+
].length > 0 ? [
|
|
7000
|
+
...profile.email ? [{ system: "email", value: profile.email }] : [],
|
|
7001
|
+
...profile.phone ? [{ system: "phone", value: profile.phone }] : []
|
|
7002
|
+
] : void 0
|
|
7003
|
+
};
|
|
7004
|
+
}
|
|
7005
|
+
function labResultToFHIRBundle(report, observations, userProfile) {
|
|
7006
|
+
const patientId = userProfile.userId;
|
|
7007
|
+
const fhirObservations = observations.map((obs) => {
|
|
7008
|
+
const resource = labObservationToFHIR(
|
|
7009
|
+
{ ...obs, collectionDate: report.collectionDate },
|
|
7010
|
+
patientId,
|
|
7011
|
+
report.laboratoryName
|
|
7012
|
+
);
|
|
7013
|
+
return { fullUrl: entryFullUrl(resource), resource };
|
|
7014
|
+
});
|
|
7015
|
+
const observationIds = fhirObservations.map((entry) => entry.resource.id);
|
|
7016
|
+
const diagnosticReport = labReportToFHIR(report, patientId, observationIds);
|
|
7017
|
+
const fhirPatient = userProfileToFHIR(userProfile);
|
|
7018
|
+
return {
|
|
7019
|
+
entry: [
|
|
7020
|
+
{ fullUrl: entryFullUrl(fhirPatient), resource: fhirPatient },
|
|
7021
|
+
{ fullUrl: entryFullUrl(diagnosticReport), resource: diagnosticReport },
|
|
7022
|
+
...fhirObservations
|
|
7023
|
+
],
|
|
7024
|
+
resourceType: "Bundle",
|
|
7025
|
+
type: "collection"
|
|
7026
|
+
};
|
|
7027
|
+
}
|
|
7028
|
+
|
|
7029
|
+
// src/cli/commands/convert.ts
|
|
7030
|
+
async function convert(args, json) {
|
|
7031
|
+
const raw = await getInput(args[0]);
|
|
7032
|
+
const data = parseJson(
|
|
7033
|
+
raw,
|
|
7034
|
+
"JSON inv\xE1lido. Forne\xE7a um objeto com { report, observations, profile }."
|
|
7035
|
+
);
|
|
7036
|
+
if (!data.report || !data.observations || !data.profile) {
|
|
7037
|
+
exitWithError(
|
|
7038
|
+
'Formato esperado: { "report": LabReportData, "observations": LabObservationData[], "profile": UserProfileData }'
|
|
7039
|
+
);
|
|
6913
7040
|
}
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
const
|
|
6925
|
-
if (!
|
|
6926
|
-
|
|
7041
|
+
const bundle = labResultToFHIRBundle(data.report, data.observations, data.profile);
|
|
7042
|
+
if (json) {
|
|
7043
|
+
outputJson(bundle);
|
|
7044
|
+
} else {
|
|
7045
|
+
outputText(JSON.stringify(bundle, null, 2));
|
|
7046
|
+
}
|
|
7047
|
+
}
|
|
7048
|
+
|
|
7049
|
+
// src/validators.ts
|
|
7050
|
+
function validateFHIRImportBundle(data) {
|
|
7051
|
+
const errors = [];
|
|
7052
|
+
if (!data || typeof data !== "object") {
|
|
7053
|
+
errors.push({ details: "Input must be a JSON object", field: "root" });
|
|
7054
|
+
return errors;
|
|
7055
|
+
}
|
|
7056
|
+
const bundle = data;
|
|
7057
|
+
if (bundle.resourceType !== "Bundle") {
|
|
7058
|
+
errors.push({
|
|
7059
|
+
details: `Expected resourceType "Bundle", got "${String(bundle.resourceType)}"`,
|
|
7060
|
+
field: "resourceType"
|
|
7061
|
+
});
|
|
7062
|
+
}
|
|
7063
|
+
if (!Array.isArray(bundle.entry)) {
|
|
7064
|
+
errors.push({ details: 'Bundle must contain an "entry" array', field: "entry" });
|
|
7065
|
+
} else if (bundle.entry.length === 0) {
|
|
7066
|
+
errors.push({ details: "Bundle entry array is empty", field: "entry" });
|
|
7067
|
+
}
|
|
7068
|
+
return errors;
|
|
7069
|
+
}
|
|
7070
|
+
|
|
7071
|
+
// src/importer.ts
|
|
7072
|
+
var MAX_OBSERVATIONS = 5e3;
|
|
7073
|
+
var MAX_FILE_SIZE = 15 * 1024 * 1024;
|
|
7074
|
+
function resolveBiomarkerCode(observation) {
|
|
7075
|
+
const coding = observation.code?.coding ?? [];
|
|
7076
|
+
const loincCode = coding.find((c) => c.system === LOINC_SYSTEM)?.code;
|
|
7077
|
+
const declaredCode = coding.find((c) => c.system === BIOMARKER_CODE_SYSTEM)?.code;
|
|
7078
|
+
const seenCodes = [
|
|
7079
|
+
...loincCode ? [`LOINC ${loincCode}`] : [],
|
|
7080
|
+
...declaredCode ? [`biomarker code ${declaredCode}`] : []
|
|
7081
|
+
];
|
|
7082
|
+
let reason;
|
|
7083
|
+
if (seenCodes.length > 0) {
|
|
7084
|
+
reason = `Unknown code: ${seenCodes.join(", ")}`;
|
|
7085
|
+
} else if (coding.length > 0) {
|
|
7086
|
+
const systems = [...new Set(coding.map((c) => c.system ?? "(sem system)"))];
|
|
7087
|
+
reason = `No code in a supported system (found: ${systems.join(", ")})`;
|
|
7088
|
+
} else {
|
|
7089
|
+
reason = "No code found in observation coding";
|
|
6927
7090
|
}
|
|
6928
|
-
const
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
7091
|
+
const fromLoinc = loincCode ? loincToCode(loincCode) : void 0;
|
|
7092
|
+
if (fromLoinc) return { internalCode: fromLoinc, loincCode, reason };
|
|
7093
|
+
if (declaredCode && isValidCode(declaredCode)) {
|
|
7094
|
+
const canonical = normalizeCode(declaredCode);
|
|
7095
|
+
return { internalCode: canonical, loincCode: codeToLoinc(canonical), reason };
|
|
7096
|
+
}
|
|
7097
|
+
return { loincCode, reason };
|
|
7098
|
+
}
|
|
7099
|
+
function extractFlag(observation) {
|
|
7100
|
+
const code = observation.interpretation?.[0]?.coding?.[0]?.code;
|
|
7101
|
+
if (code === "H" || code === "HH") return "H";
|
|
7102
|
+
if (code === "L" || code === "LL") return "L";
|
|
7103
|
+
return "";
|
|
7104
|
+
}
|
|
7105
|
+
function extractObservationsFromBundle(bundle) {
|
|
7106
|
+
const observations = [];
|
|
7107
|
+
const skipped = [];
|
|
7108
|
+
for (let i = 0; i < bundle.entry.length; i++) {
|
|
7109
|
+
const entry = bundle.entry[i];
|
|
7110
|
+
if (!entry.resource) {
|
|
7111
|
+
skipped.push({ index: i, reason: "Entry has no resource" });
|
|
6937
7112
|
continue;
|
|
6938
7113
|
}
|
|
6939
|
-
if (
|
|
7114
|
+
if (entry.resource.resourceType !== "Observation") {
|
|
6940
7115
|
continue;
|
|
6941
7116
|
}
|
|
6942
|
-
if (
|
|
7117
|
+
if (observations.length >= MAX_OBSERVATIONS) {
|
|
7118
|
+
skipped.push({ index: i, reason: `Maximum of ${MAX_OBSERVATIONS} observations exceeded` });
|
|
6943
7119
|
continue;
|
|
6944
7120
|
}
|
|
6945
|
-
|
|
6946
|
-
|
|
7121
|
+
observations.push(entry.resource);
|
|
7122
|
+
}
|
|
7123
|
+
return { observations, skipped };
|
|
7124
|
+
}
|
|
7125
|
+
function mapFHIRObservationToInternal(observation, index) {
|
|
7126
|
+
const { internalCode, loincCode, reason } = resolveBiomarkerCode(observation);
|
|
7127
|
+
if (!internalCode) {
|
|
7128
|
+
return {
|
|
7129
|
+
skipped: { index, loincCode, reason, resourceType: "Observation" }
|
|
7130
|
+
};
|
|
7131
|
+
}
|
|
7132
|
+
const definition = getDefinitionByCode(internalCode);
|
|
7133
|
+
let value;
|
|
7134
|
+
let unit = "";
|
|
7135
|
+
let isQualitative = false;
|
|
7136
|
+
if (observation.valueQuantity?.value !== void 0) {
|
|
7137
|
+
value = observation.valueQuantity.value;
|
|
7138
|
+
unit = observation.valueQuantity.unit || observation.valueQuantity.code || "";
|
|
7139
|
+
} else if (observation.valueString) {
|
|
7140
|
+
value = observation.valueString;
|
|
7141
|
+
isQualitative = true;
|
|
7142
|
+
} else {
|
|
7143
|
+
return {
|
|
7144
|
+
skipped: {
|
|
7145
|
+
index,
|
|
7146
|
+
loincCode,
|
|
7147
|
+
reason: "Observation has no value (valueQuantity or valueString)",
|
|
7148
|
+
resourceType: "Observation"
|
|
7149
|
+
}
|
|
7150
|
+
};
|
|
7151
|
+
}
|
|
7152
|
+
const collectionDate = observation.effectiveDateTime || observation.effectivePeriod?.start || "";
|
|
7153
|
+
if (!collectionDate) {
|
|
7154
|
+
return {
|
|
7155
|
+
skipped: {
|
|
7156
|
+
index,
|
|
7157
|
+
loincCode,
|
|
7158
|
+
reason: "Observation has no effectiveDateTime or effectivePeriod.start",
|
|
7159
|
+
resourceType: "Observation"
|
|
7160
|
+
}
|
|
7161
|
+
};
|
|
7162
|
+
}
|
|
7163
|
+
let referenceMin;
|
|
7164
|
+
let referenceMax;
|
|
7165
|
+
let referenceKind;
|
|
7166
|
+
if (observation.referenceRange?.[0]) {
|
|
7167
|
+
referenceMin = observation.referenceRange[0].low?.value;
|
|
7168
|
+
referenceMax = observation.referenceRange[0].high?.value;
|
|
7169
|
+
const meaning = observation.referenceRange[0].type?.coding?.find(
|
|
7170
|
+
(c) => c.system === "http://terminology.hl7.org/CodeSystem/referencerange-meaning"
|
|
7171
|
+
)?.code;
|
|
7172
|
+
if (meaning === "normal") referenceKind = "reference-interval";
|
|
7173
|
+
else if (meaning === "recommended") referenceKind = "decision-threshold";
|
|
7174
|
+
}
|
|
7175
|
+
const imported = {
|
|
7176
|
+
biomarkerCode: internalCode,
|
|
7177
|
+
biomarkerName: definition?.names.pt[0] || definition?.names.en[0] || observation.code.text || internalCode,
|
|
7178
|
+
collectionDate,
|
|
7179
|
+
flag: extractFlag(observation),
|
|
7180
|
+
isQualitative,
|
|
7181
|
+
loincCode,
|
|
7182
|
+
...referenceKind && { referenceKind },
|
|
7183
|
+
referenceMax,
|
|
7184
|
+
referenceMin,
|
|
7185
|
+
unit: unit || definition?.unit || "",
|
|
7186
|
+
value
|
|
7187
|
+
};
|
|
7188
|
+
return { observation: imported };
|
|
7189
|
+
}
|
|
7190
|
+
function processImportBundle(data) {
|
|
7191
|
+
const validationErrors = validateFHIRImportBundle(data);
|
|
7192
|
+
if (validationErrors.length > 0) {
|
|
7193
|
+
return {
|
|
7194
|
+
errors: validationErrors,
|
|
7195
|
+
imported: [],
|
|
7196
|
+
skipped: [],
|
|
7197
|
+
totalProcessed: 0
|
|
7198
|
+
};
|
|
7199
|
+
}
|
|
7200
|
+
const bundle = data;
|
|
7201
|
+
const { observations, skipped } = extractObservationsFromBundle(bundle);
|
|
7202
|
+
const imported = [];
|
|
7203
|
+
const allSkipped = [...skipped];
|
|
7204
|
+
for (let i = 0; i < observations.length; i++) {
|
|
7205
|
+
const result = mapFHIRObservationToInternal(observations[i], i);
|
|
7206
|
+
if ("observation" in result) {
|
|
7207
|
+
imported.push(result.observation);
|
|
7208
|
+
} else {
|
|
7209
|
+
allSkipped.push(result.skipped);
|
|
6947
7210
|
}
|
|
6948
|
-
return withSource(variant.range);
|
|
6949
7211
|
}
|
|
6950
|
-
return
|
|
7212
|
+
return {
|
|
7213
|
+
errors: [],
|
|
7214
|
+
imported,
|
|
7215
|
+
skipped: allSkipped,
|
|
7216
|
+
totalProcessed: observations.length
|
|
7217
|
+
};
|
|
6951
7218
|
}
|
|
6952
|
-
|
|
6953
|
-
|
|
7219
|
+
|
|
7220
|
+
// src/cli/commands/import.ts
|
|
7221
|
+
async function importBundle(args, json) {
|
|
7222
|
+
const raw = await getInput(args[0]);
|
|
7223
|
+
const bundle = parseJson(raw, "JSON inv\xE1lido.");
|
|
7224
|
+
const result = processImportBundle(bundle);
|
|
7225
|
+
if (json) {
|
|
7226
|
+
outputJson(result);
|
|
7227
|
+
return;
|
|
7228
|
+
}
|
|
7229
|
+
outputText(`Processados: ${result.totalProcessed}`);
|
|
7230
|
+
outputText(`Importados: ${result.imported.length}`);
|
|
7231
|
+
outputText(`Ignorados: ${result.skipped.length}`);
|
|
7232
|
+
outputText(`Erros: ${result.errors.length}`);
|
|
7233
|
+
if (result.imported.length > 0) {
|
|
7234
|
+
outputText("\nObserva\xE7\xF5es importadas:");
|
|
7235
|
+
for (const obs of result.imported) {
|
|
7236
|
+
outputText(` ${obs.biomarkerCode} (${obs.loincCode}): ${obs.value} ${obs.unit}`);
|
|
7237
|
+
}
|
|
7238
|
+
}
|
|
7239
|
+
if (result.errors.length > 0) {
|
|
7240
|
+
outputText("\nErros:");
|
|
7241
|
+
for (const err of result.errors) {
|
|
7242
|
+
outputText(` ${err.field}: ${err.details}`);
|
|
7243
|
+
}
|
|
7244
|
+
}
|
|
7245
|
+
}
|
|
7246
|
+
|
|
7247
|
+
// src/cli/commands/list.ts
|
|
7248
|
+
import { parseArgs } from "util";
|
|
7249
|
+
async function list(args, json) {
|
|
7250
|
+
const { values } = parseArgs({
|
|
7251
|
+
args,
|
|
7252
|
+
options: {
|
|
7253
|
+
category: { type: "string" },
|
|
7254
|
+
visible: { default: false, type: "boolean" }
|
|
7255
|
+
},
|
|
7256
|
+
strict: false
|
|
7257
|
+
});
|
|
7258
|
+
let defs;
|
|
7259
|
+
if (values.category) {
|
|
7260
|
+
defs = getBiomarkersByCategory(values.category);
|
|
7261
|
+
if (defs.length === 0) {
|
|
7262
|
+
exitWithError(`Categoria n\xE3o encontrada ou vazia: ${values.category}`);
|
|
7263
|
+
}
|
|
7264
|
+
} else if (values.visible) {
|
|
7265
|
+
defs = getVisibleDefinitions();
|
|
7266
|
+
} else {
|
|
7267
|
+
defs = getAllDefinitions();
|
|
7268
|
+
}
|
|
7269
|
+
if (json) {
|
|
7270
|
+
outputJson(defs);
|
|
7271
|
+
return;
|
|
7272
|
+
}
|
|
7273
|
+
const rows = defs.map((d) => [
|
|
7274
|
+
d.code,
|
|
7275
|
+
d.loinc ?? "\u2014",
|
|
7276
|
+
d.names.pt[0] ?? "",
|
|
7277
|
+
d.unit ?? "\u2014",
|
|
7278
|
+
Array.isArray(d.category) ? d.category.join(", ") : d.category
|
|
7279
|
+
]);
|
|
7280
|
+
outputText(formatTable(["C\xF3digo", "LOINC", "Nome (pt)", "Unidade", "Categoria"], rows));
|
|
7281
|
+
outputText(`
|
|
7282
|
+
Total: ${defs.length} biomarcadores`);
|
|
7283
|
+
}
|
|
7284
|
+
|
|
7285
|
+
// src/cli/commands/loinc-map.ts
|
|
7286
|
+
async function loincMap(_args, json) {
|
|
7287
|
+
const defs = getAllDefinitions().filter((d) => d.loinc);
|
|
7288
|
+
if (json) {
|
|
7289
|
+
const map = Object.fromEntries(defs.map((d) => [d.loinc, d.code]));
|
|
7290
|
+
outputJson(map);
|
|
7291
|
+
return;
|
|
7292
|
+
}
|
|
7293
|
+
const rows = defs.map((d) => [d.loinc, d.code, d.names.pt[0] ?? d.names.en[0] ?? ""]);
|
|
7294
|
+
outputText(formatTable(["LOINC", "C\xF3digo", "Nome (pt)"], rows));
|
|
7295
|
+
outputText(`
|
|
7296
|
+
Total: ${rows.length} mapeamentos`);
|
|
7297
|
+
}
|
|
7298
|
+
|
|
7299
|
+
// src/cli/commands/lookup.ts
|
|
7300
|
+
function displayDefinition(def) {
|
|
7301
|
+
const cat = Array.isArray(def.category) ? def.category.join(", ") : def.category;
|
|
7302
|
+
outputText(
|
|
7303
|
+
[
|
|
7304
|
+
`Biomarcador: ${def.code}`,
|
|
7305
|
+
` LOINC: ${def.loinc ?? "\u2014"}`,
|
|
7306
|
+
` Nomes (pt): ${def.names.pt.join(", ")}`,
|
|
7307
|
+
` Nomes (en): ${def.names.en.join(", ")}`,
|
|
7308
|
+
` Categoria: ${cat}`,
|
|
7309
|
+
` Unidade: ${def.unit ?? "\u2014"}`,
|
|
7310
|
+
` Sexo: ${def.sex ?? "ambos"}`,
|
|
7311
|
+
` Vis\xEDvel: ${def.hidden ? "n\xE3o" : "sim"}`
|
|
7312
|
+
].join("\n")
|
|
7313
|
+
);
|
|
7314
|
+
}
|
|
7315
|
+
async function lookup(args, json) {
|
|
7316
|
+
const code = args[0];
|
|
7317
|
+
if (!code) exitWithError("Uso: fhir-bio lookup <c\xF3digo>");
|
|
7318
|
+
const def = getDefinitionByCode(code);
|
|
7319
|
+
if (!def) exitWithError(`Biomarcador n\xE3o encontrado: ${code}`);
|
|
7320
|
+
if (json) {
|
|
7321
|
+
outputJson(def);
|
|
7322
|
+
} else {
|
|
7323
|
+
displayDefinition(def);
|
|
7324
|
+
}
|
|
7325
|
+
}
|
|
7326
|
+
async function lookupLoinc(args, json) {
|
|
7327
|
+
const loinc = args[0];
|
|
7328
|
+
if (!loinc) exitWithError("Uso: fhir-bio lookup-loinc <loinc>");
|
|
7329
|
+
const def = getDefinitionByLoinc(loinc);
|
|
7330
|
+
if (!def) exitWithError(`Biomarcador n\xE3o encontrado para LOINC: ${loinc}`);
|
|
7331
|
+
if (json) {
|
|
7332
|
+
outputJson(def);
|
|
7333
|
+
} else {
|
|
7334
|
+
displayDefinition(def);
|
|
7335
|
+
}
|
|
6954
7336
|
}
|
|
6955
7337
|
|
|
6956
7338
|
// src/cli/commands/range.ts
|
|
7339
|
+
import { parseArgs as parseArgs2 } from "util";
|
|
6957
7340
|
async function range(args, json) {
|
|
6958
7341
|
const { positionals, values } = parseArgs2({
|
|
6959
7342
|
allowPositionals: true,
|
|
@@ -6990,11 +7373,18 @@ async function range(args, json) {
|
|
|
6990
7373
|
const sexLabel = ctx.biologicalSex === "M" ? "Homem" : ctx.biologicalSex === "F" ? "Mulher" : "Geral";
|
|
6991
7374
|
const ageLabel = ctx.age !== void 0 ? `, ${ctx.age} anos` : "";
|
|
6992
7375
|
const fmt = (v) => v !== void 0 ? String(v) : "\u2014";
|
|
7376
|
+
const desenho = (kind) => kind === "display" ? " (desenho, n\xE3o \xE9 corte)" : "";
|
|
7377
|
+
const tipos = {
|
|
7378
|
+
"decision-threshold": "limiar de decis\xE3o",
|
|
7379
|
+
population: "distribui\xE7\xE3o populacional",
|
|
7380
|
+
"reference-interval": "intervalo de refer\xEAncia"
|
|
7381
|
+
};
|
|
6993
7382
|
outputText(
|
|
6994
7383
|
[
|
|
6995
7384
|
`Faixa de Refer\xEAncia: ${code} (${sexLabel}${ageLabel})`,
|
|
6996
|
-
`
|
|
6997
|
-
` M\
|
|
7385
|
+
` Tipo: ${ref.kind ? tipos[ref.kind] : "\u2014"}`,
|
|
7386
|
+
` M\xEDnimo: ${fmt(ref.min)} ${ref.unit}${desenho(ref.minKind)}`,
|
|
7387
|
+
` M\xE1ximo: ${fmt(ref.max)} ${ref.unit}${desenho(ref.maxKind)}`,
|
|
6998
7388
|
` \xD3timo (m\xEDn): ${fmt(ref.optimalMin)} ${ref.unit}`,
|
|
6999
7389
|
` \xD3timo (m\xE1x): ${fmt(ref.optimalMax)} ${ref.unit}`,
|
|
7000
7390
|
` Alerta (m\xE1x): ${fmt(ref.warningMax)} ${ref.unit}`,
|
|
@@ -7487,7 +7877,7 @@ var COMMANDS = {
|
|
|
7487
7877
|
async function main() {
|
|
7488
7878
|
const { command, help, json, resto, version } = dividirArgv(process.argv.slice(2));
|
|
7489
7879
|
if (version) {
|
|
7490
|
-
process.stdout.write(`${"0.
|
|
7880
|
+
process.stdout.write(`${"0.34.0"}
|
|
7491
7881
|
`);
|
|
7492
7882
|
return;
|
|
7493
7883
|
}
|