/* * Copyright (c) 1995, 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "y.tab.h" #include "results.h" #include "LOINC.h" #include "Unit.h" #include "exception.h" #define NUMBER_OF(x) (x ## _END - x ## _ORG - 1) #define INDEX_INTO(x, v) (v - x ## _ORG - 1) const char *specimen_tab[NUMBER_OF(SPECIMEN)] = { "", // BLANK_SPEC "BLDC", // CAPILLARY_SPEC "BLDA", // ARTERIAL_SPEC "BLDV", // VENOUS_SPEC "GAS", // GAS_SPEC // the following is for quality check specimens and not covered by LOINC "UNKNOWN", "S2030", "S2040", "S2050", "S2060", // the following are implicit specimen "IHG", // inhaled gas "PAT", // patient "BLD", // simply blood where artherial/venous is meaningless (e.g. E'lytes) }; const char *measurements_tab[NUMBER_OF(MEASUREMENTS)] = { "BASE EXCESS", // ABE "BAROMETRIC PRESSURE", // BARO (Gas sample) "CALCIUM.FREE", // CA "CALCIUM.FREE^^PH ADJUSTED TO 7.4", // CA_S "CARBON DIOXIDE", // CO2 "CARBON DIOXIDE", // FCO2 (Gas sample) "OXYGEN", // FO2 (Gas sample) "HYDROGEN ION", // H "HEMOGLOBIN", // HB "CARBON MONOXIDE.HEMOGLOBIN", // HBCO "OXYHEMOGLOBIN.TOTAL", // HBO2 "BICARBONATE", // HCO3 "POTASSIUM", // K "METHEMOGLOBIN", // METHB "SODIUM", // NA "OXYGEN", // O2 "OXYGEN.TOTAL", // O2CT "OXYGEN^^SATURATION ADJUSTED TO 0.5", // P50E "OXYGEN^^SATURATION ADJUSTED TO 0.5", // P50C "CARBON DIOXIDE", // PCO2 "PH", // PH "OXYGEN", // PO2 "OXYGEN SATURATION", // SAT "BICARBONATE^^STANDARD", // SBC "BASE EXCESS^^STANDARD", // SBE "CARBON DIOXIDE.TOTAL", // TCO2 "OXYGEN INHALED", // FIO2 "BODY TEMPERATURE", // TEMP }; const char *units_tab[NUMBER_OF(UNITS)] = { "CEL", // C_UN "DEGF", // F_UN "MM(HG)", // MMHG_UN "KPAL", // KPA_UN "PAL", // PA_UN "%", // PC_UN "%", // GPC_UN "%", // VOLPC_UN "NMOL/L", // NMPL_UN "MMOL/L", // MMPL_UN "1", // ONE_UN }; const char *properties_tab[NUMBER_OF(UNITS)] = { "TEMP", // C_UN "TEMP", // F_UN "PRES", // MMHG_UN "PRES", // KPA_UN "PRES", // PA_UN "NFR", // PC_UN "MCNC", // GPC_UN "VCNT", // VOLPC_UN "SCNC", // NMPL_UN "SCNC", // MMPL_UN "NUM", // ONE_UN }; const char *analyzers_tab[NUMBER_OF(ANALYZERS)] = { "ENTERED", // PRE_ANA /* pre observations: FIO2 and TEMP */ "ABL", // DEF_ANA /* default analyzer */ "OSM", // OSM_ANA /* Hemoximeter */ "ICA", // ICA_ANA /* Calcium */ "KNA", // KNA_ANA /* Sodium, Potassium */ }; const char *specimen(int x) { return specimen_tab[INDEX_INTO(SPECIMEN, x)]; } const char *measurement(int x) { return measurements_tab[INDEX_INTO(MEASUREMENTS, x)]; } const char *unit(int x) { return units_tab[INDEX_INTO(UNITS, x)]; } const char *property(int x) { return properties_tab[INDEX_INTO(UNITS, x)]; } const char *analyzer(int x) { return analyzers_tab[INDEX_INTO(ANALYZERS, x)]; } /* The following function maps the internal representation of * * * measurement * * unit * * specimen * * observation value * * into LOINC code / ISO+ unit representation, where the observation value * is converted if the unit is to be changed. */ void toLOINC(int iMs, int iUn, int iSp, NMtyp &val, Loinc &loinc, Unit &iso_unit) { loinc.unset(); /* there must be a value for anything here to make sense */ if(!val.ispresent() || val.isnull()) return; double rval = (double)val; u_int prec = val.getPrecision(); switch(iMs) { case FIO2: if(iUn == ONE_UN) { iUn = PC_UN; rval = convert(rval, "1", "%"); } loinc.setMeasure(measurement(iMs)); loinc.setSpecimen(specimen(iSp)); loinc.setProperty("NFR"); iso_unit = unit(iUn); break; case PH: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen(specimen(iSp)); loinc.setProperty("SCNC"); iso_unit = "PH"; break; case SAT: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen(specimen(iSp)); loinc.setProperty("SFR"); iso_unit = unit(iUn); break; case O2CT: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen(specimen(iSp)); loinc.setProperty("SCNC"); if(iUn == VOLPC_UN) { rval = convert(rval / 22.41, "%/l.mol", "mmol/l"); iUn = MMPL_UN; } iso_unit = unit(iUn); break; /* these are inert to arterial/venous difference */ case CA: case CA_S: case K: case NA: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen("BLD"); loinc.setProperty(property(iUn)); iso_unit = unit(iUn); break; case HB: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen("BLD"); if(iUn == GPC_UN) { rval = convert(rval/16113.439, "g/dl/g.mol", "mmol/l"); iUn = MMPL_UN; loinc.setProperty("ACNC"); } if(iUn == MMPL_UN) loinc.setProperty("ACNC"); iso_unit = unit(iUn); break; /* GAS sample measures */ case O2: case CO2: case FO2: case FCO2: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen(specimen(iSp)); loinc.setProperty("NFR"); if(iUn == ONE_UN) { rval = convert(rval, "1", "%"); iUn = PC_UN; } iso_unit = unit(iUn); break; default: loinc.setMeasure(measurement(iMs)); loinc.setSpecimen(specimen(iSp)); loinc.setProperty(property(iUn)); iso_unit = unit(iUn); } if(! loinc.lookup()) { ERROR("unable to find a LOINC code for:\n" " MEASURE = %s(%d)\n" " SPECIMEN = %s(%d)\n" " PROPERTY = %s(%d)\n", measurement(iMs), iMs, specimen(iSp), iSp, property(iUn), iUn); } val = NMtyp(rval, prec + 1); }