Skip to main content

Data & Research

LOSPOR stores perioperative data for clinical documentation, audit, personal portfolio, and de-identified / pseudonymised research datasets. The dedicated lospor-api service owns the canonical PostgreSQL/API contract; web, mobile, and PWA clients map their payloads into the same field names and libraries before persistence.

What data does LOSPOR collect?​

Preoperative data​

  • Demographics: age, sex, height, weight, BMI, blood group, Rh factor.

  • Diagnosis: ICD-10 code with English and Bulgarian labels.

  • Planned procedure: the procedure group, and optionally the exact ICD-10-PCS operation the clinician chose within it. A procedure imported from a hospital system keeps the hospital's code (for example КСМП) and wording beside it.

  • Comorbidities: ICD-10-coded tags with English/Bulgarian labels.

  • Medication history and medication allergy rows, including Medication.kind = CURRENT or ALLERGY.

  • Risk scores: ASA, RCRI, Apfel, STOP-BANG, and their component inputs.

    The component inputs are three-valued: yes, no, and not asked. A criterion nobody put to the patient is stored as null, not as a negative, and does not count toward the score — so a score is a lower bound when some of its criteria were never asked. Analyses that treat a null as a "no" are counting something the register did not measure; the component inputs are exported precisely so that distinction is available to you.

    Scores are stored and exported as raw counts (RCRI 0–6, Apfel 0–4, STOP-BANG 0–8, POVOC, COLDS, PAED). A band is a reading of the count by one guideline, so it is added at display time and never frozen into the data. The POVOC risk percentage and the Gupta MICA risk are derived on export from their inputs and are not stored.

  • ASA suggestion: the class the suggestion rules proposed from the coded conditions and BMI, the rules that decided it and the rule-table version, stored beside the class the clinician chose.

  • Planned anaesthesia (optional): techniques, airway devices and instruments, lines, and planned ventilation after the operation.

  • Paediatric nil by mouth: one assignment per intake, in hours before surgery, with the policy it was assigned under.

  • Preop documents: each printed consent records the version and fingerprint of its text, the print layout and, for layout C, the techniques described.

  • Airway assessment: Mallampati, mouth opening, thyromental distance, neck mobility, ULBT, Cormack-Lehane, difficult-airway history, and airway features.

  • Free-text clinical notes where needed: team notes, physical exam report, difficult-airway notes. These are character-limited. On the cloud service identifying text in them is refused when it is saved. On a hospital appliance it is stored as typed, inside the hospital, and free text is cleaned of names, dates, ЕГН, long numbers and email addresses whenever it leaves: in OMOP and research exports, in Central delivery and in what is sent to the AI advisor. Coded fields (diagnoses, procedures, drug and allergy lists) leave as they are.

  • Vitals: BP, HR, SpO2, temperature, respiratory rate, including unable-to-obtain flags where available.

  • Laboratory results: canonical lab name, value, parsed numeric value, canonical unit, LOINC code, reference range, abnormal flag, source, and timestamp where available.

Preoperative questions​

Every question of the preoperative catalogue is also stored as one answer row per case (PreopAssessmentAnswer), and these rows are what research and OMOP read. That includes the baseline questions behind the standard controls, whose form fields remain as a compatibility copy.

  • A question that is switched on for the case has a row: YES, NO, UNKNOWN, NOT_APPLICABLE, or NOT_ASKED when it was on the form and left blank. A question that was off has no row, so "not on the form" and "left blank" stay distinguishable.
  • Each row records who answered it: the clinician, or an accepted suggestion from the hospital record, with the rule and the record it came from.
  • An answer given before the hospital switched the question off is kept; an answer recorded while it was off is kept and marked as such.
  • Rows of a finalized case cannot be changed.

Intraoperative data​

  • Timing: the start and end of anaesthesia as moments in time, with the case's time zone, the case month and the duration.
  • Techniques, position, airway devices/tools, ventilation modes, monitoring modalities.
  • Vascular access rows with site, size, unit, depth, lumens, and pre-existing flag.
  • Premedication rows by phase: the day before surgery, or the morning before surgery. Each row carries the drug, its WHO ATC code, dose, unit and route; there is no clock time.
  • Drug infusions record both rates: the dose rate and, where the syringe strength is known, the pump rate in mL/h with the strength. A target-controlled infusion records its model, site (Cp or Ce), the opioid switch, each target, and the pump's own total when entered. The millilitres given through infusions are stored as infusionsMl and count in the fluid balance.
  • Append-only event timeline: vitals, serum/peripheral glucose, bolus drugs, infusion starts/rate changes/stops, fluid starts/stops, inhalational agent starts/stops, fresh gas flow changes, and clinical events.
  • Fresh gas flow over time: FGF L/min, carrier gas, FiO2, calculated FiAir, and calculated FiN2O. FiO2 is clamped to 21-100%; O2-only is FiO2 100%.
  • Fluids, urine, blood products, complications, and event notes.

Postoperative data​

  • Aldrete score components and total.
  • Recovery vitals: systolic BP, diastolic BP, heart rate, SpO2, temperature.
  • Pain NRS, PONV, disposition, handover checklist, complications, and notes.

What is not stored?​

The following are intentionally never uploaded or stored:

  • Patient name.
  • Patient national ID / EGN.
  • Hospital file number or patient ID number.
  • Date of birth; the age at the procedure is stored instead. (The date and time of the anaesthesia are stored, because the chart is a timeline.)
  • Surgeon, anaesthesiologist, or nurse names as structured fields.
  • On the cloud service, free text that triggers the server-side PII detector.

The printable protocol leaves patient identity fields blank. Clinicians fill those fields by hand after printing if needed for the local paper record.

Canonical libraries​

LOSPOR uses shared backend libraries rather than app-specific hardcoded lists.

LibrarySource of truthUsed for
ICD-10Icd10Code, Icd10Synonymdiagnoses and comorbidities
Labs/LOINCLabLoinc and canonical lab codeAI scan, manual labs, export
Drugs/ATC/INNAtc, Drug, option-library drug rowsmedication history, allergies, intraop drugs/infusions
App optionsOptionLibrarytechniques, airway, ventilation, monitoring, position, fluids, events, disposition, handover, numeric ranges
Athena/OMOP vocabularyOmopConcept, OmopVocabulary, relationships, ancestors, synonymslocal standard concept resolution
Concept mapConceptMapsource code/label preservation, mapping method/confidence, review state, and OMOP concept IDs where known

ICD-10 English and Bulgarian labels are metadata for the same ICD code. They are not duplicate clinical concepts.

Research data layers​

LOSPOR keeps compatibility JSON/cache data for the apps, but research queries should use normalized rows where available.

Clinical dataSQL tableResearch columns
DiagnosesPreopDiagnosisICD code, labels, source vocabulary/code, OMOP concept ID if mapped
ProceduresPreopProcedurecode, group, domain, source mapping
ComorbiditiesComorbidityICD-10 code, labels, source mapping
LabsLabResultvalueNum, unitCanon, LOINC, ranges, abnormal flag, source mapping
Medications/allergiesMedicationkind, drugId, INN, ATC, dose, route, source mapping
Vascular accessVascularAccesssite, size, unit, depth, lumens, pre-existing flag
PremedicationPremedicationAdministrationphase, raw name, INN, ATC, dose, route
ComplicationsCaseComplicationsection, label, note, timestamp, source mapping
SelectionsCaseSelectionsection, category, value, source mapping
Intraop timelineCaseEventevent type, timestamp, typed vitals/gas/drug/fluid/agent columns, provenance
MissingnessClinicalFieldStatusfieldKey, presence, source, sourceVersion

CaseEvent is append-only. Edits supersede older rows and deletes tombstone rows, so the current chart can be projected from active rows while preserving history for audit.

Missingness and provenance​

Research exports must distinguish blank data from negative data. ClinicalFieldStatus records whether key fields are:

  • PRESENT
  • ABSENT
  • UNKNOWN
  • NOT_APPLICABLE
  • NOT_DOCUMENTED

Normalized rows also carry source/provenance metadata such as user input, web/mobile source, AI scan, backfill, migration, or relational sync where available. Field-status coverage is intentionally broad so normalized rows can serve as the research/export authority while UI JSON remains a compatibility cache.

OMOP export​

The OMOP export is an OMOP CDM v5.4-oriented research export. It now reads normalized rows and active event rows instead of raw legacy blobs.

The export includes:

  • care site as its own table, referenced by visit occurrence through care_site_id
  • person and observation period, the CDM root tables
  • visit occurrence
  • condition occurrence from diagnoses and comorbidities. An ICD-10 code that OMOP splits into several concepts (E11.2: type 2 diabetes, and a kidney disorder due to it) exports one row per concept with the same source value
  • procedure occurrence from every planned procedure, the anaesthesia technique, vascular access, the act of placing an instrumented airway, and each blood unit's transfusion. A planned procedure carries its standard concept only when the clinician chose the exact ICD-10-PCS operation; a group alone exports concept 0 with the group in the source value
  • observation rows for each answered preoperative question, from its answer row: the question's concept from the catalogue (0 with the LOSPOR:PREOP_<question> source value where no standard concept says what the question asks), and the answer as value_as_concept_id Yes 4188539 or No 4188540. NOT_ASKED exports nothing. Unintentional weight loss exports as a condition, and the planned urgency as a procedure modifier
  • measurement rows for preop/postop vitals, labs, intraop vitals, glucose, and gas settings, carrying value_source_value for results the laboratory reported as text and range_low / range_high for the reference range the result was judged against
  • drug exposure rows for medications, bolus drugs, premedication, agents, infusions and IV fluids, with drug_exposure_end_date paired from stop events for continuous administrations. A fluid is coded as the clinical drug at the strength given, from a hand-checked table, because fluids share ATC codes (saline, Hartmann's and Plasma-Lyte are all B05BB01). Premedication is dated the day before (D-1) or the day of the operation
  • device exposure rows for instrumented airway devices and for each blood unit, the unit carrying its product concept and its volume as quantity in mL (unit_concept_id 8587). Cell salvage has no product concept and exports as the autotransfusion procedure, with its volume as an observation
  • observations for ASA, scores, selections, complications, handover, disposition, the preoperative history and airway examination, airway devices and ventilation, drug allergies, and other app-local concepts

Clinical yes/no questions are exported for a recorded "no" as well as a "yes". No row means the question was never asked, which is a different claim about a patient than a negative finding.

An allergy is exported as an observation, never as a drug exposure. A substance a patient reacts to is not one they were given.

Dates and times are the theatre's clock.

  • Dates: every *_date is the local calendar date in the case's time zone.
  • Times: every *_datetime is the local time with its UTC offset, for example 2026-06-02T01:30:00+03:00 for a case begun at 01:30 in Sofia. It is the same moment as the UTC instant, readable as the clock in theatre.
  • No zone: a case that never recorded its zone is in UTC.

A target-controlled infusion exports as one drug exposure:

  • Dose: the amount given, which is the pump's own total when entered and otherwise the model's calculation.
  • Beside it, observations: the model (LOSPOR:TCI_MODEL), the site, the opioid switch, every target (LOSPOR:TCI_TARGET), and both the calculated and the pump total.
  • mL without a syringe: a pump total in mL with no syringe strength cannot become an amount, and is kept as LOSPOR:TCI_TOTAL_PUMP_ML.

Infusion volume. The drug-infusion millilitres export as LOSPOR:DRUG_INFUSIONS_ML, with each infusion's pump rate and strength.

Known OMOP concept IDs are stored/exported where confidently mapped. The concept is fixed when the case is saved, so exporting a case twice gives the same file, and a finalized case is never rewritten when vocabularies change.

The research numbers LOSPOR needs ship with every release, so a site exports standard concepts without importing any terminology: the ICD-10-PCS operations, the OMOP concept ids of LOSPOR's ICD-10 codes, the LOINC codes of its laboratory tests, and the RxNorm targets of its catalogue drugs' ATC codes. For SNOMED CT only the OMOP concept numbers are bundled, never SNOMED codes or descriptions. The Bulgarian national ICD-10 extensions have no concept of their own and export as source codes; they do not borrow their parent code's concept. A filtered Athena CSV import can still enrich mappings through local OMOP vocabulary tables, and wins where it resolves a code. Otherwise LOSPOR exports source vocabulary, source code, and source labels with an explicit source-only/unmapped status. Fake OMOP IDs are not used.

Each export includes a manifest with app/schema version, concept-map version, row counts, mapping summary, de-identification notes, and quality warnings. Governed export manifest v2 also freezes the parent clinical/event/relational revisions and every section revision for each finalized case. App exports warn rather than block when source-only mappings, missing field-status rows, exact timestamps, or institution linkage are present. Downloadable research artifacts are retained for 30 days by default; their checksum, row count, source version, and audit history remain after the file expires.

An OMOP request that matches more than 5000 cases is rejected with HTTP 422 and reports the matching count, limit, and complete: false. LOSPOR never returns the first 5000 cases as if they were the full research dataset. Narrow the export or use the future resumable institution-to-datacentre export workflow for larger cohorts.

De-identification / pseudonymisation​

Each case receives a generated case code such as 2026-0001. This is the visible case-level pseudonym used in the UI and exports.

Internally, LOSPOR stores operational linkage needed for access control, audit, governance, and research quality: user ID, institution ID, timestamps, role/audit information, and finalisation snapshots. These are not patient identifiers, but they mean LOSPOR data should be described as de-identified / pseudonymised, not fully anonymised.

Data quality tools​

The backend includes tooling for release and research checks:

  • scripts/seed-vocabularies.ts seeds ICD-10, ICD-10CM synonyms, ATC, and Drug rows.
  • scripts/seed-athena-vocabularies.ts --filtered-lospor imports only LOSPOR-needed local Athena/OMOP rows for vocabulary-backed mapping.
  • scripts/seed-lab-loinc.ts seeds the canonical lab/LOINC catalogue.
  • scripts/seed-option-library.ts seeds shared app option libraries.
  • scripts/seed-concept-maps.ts seeds local bilingual concept maps and enriches them from Athena when available.
  • scripts/backfill-relational.ts rebuilds normalized rows and typed event columns from existing cases.
  • scripts/data-quality-report.ts reports relational drift, unmapped/source-only concepts, invalid ranges, impossible timestamps, and missing key research fields.
  • scripts/wipe-dev-clinical-data.ts can wipe dev clinical data while preserving accounts, institutions, vocabularies, option libraries, and configuration.

Research access​

The standalone LOSPOR Database Research Browser provides governed cohort queries, comparisons, pseudonymous case inspection, data-quality review, benchmarks, saved cohorts, and complete audited exports. It uses read-only /v1/research/* API projections and never connects to operational tables directly. See Research Browser.

Citing LOSPOR​

If you use LOSPOR data in a publication, cite:

LOSPOR - Large Open Source Perioperative Register. Available at https://lospor.org. Licensed under AGPL-3.0.