Summary
Medical terminologies (ICD-10, SNOMED CT, LOINC, RxNorm…) all live together in OMOP inside a single dictionary called CONCEPT, where every code gets a stable internal identifier: the concept_id. Two other tables drive the system: CONCEPT_RELATIONSHIP connects codes together — this is where the mappings that turn a source code into a standard concept live — and CONCEPT_ANCESTOR stores the hierarchies, so a single query can reach all the descendants of a concept. These three tables are the engine that makes OMOP queries comparable from one database to another.
What you already know
In the Understanding health data warehouses section, the article Speaking the same language: medical terminologies introduced medical terminologies in general: ICD-10, SNOMED CT, LOINC, ATC, RxNorm, and their respective uses.
If these names don’t ring a bell, read that article first: we assume here that you know what a standardized terminology is and why one is needed.
The previous article, The OMOP CDM model, also detailed the source/standard duality in the event tables (condition_concept_id vs condition_source_value vs condition_source_concept_id). This article exposes the machinery that makes that duality possible.
The problem OMOP solves
Every country, hospital, and software vendor uses its own codes. OMOP therefore needs to do two things:
- Gather all these vocabularies into a single dictionary that can be queried in SQL.
- Map local codes to standard concepts so international comparison becomes possible.
The result: a system where every medical code exists in a unified form, identified by a concept_id, and where links between codes (equivalences, hierarchies, mappings) are themselves queryable data.
Three levels to keep apart
This is probably the least obvious point in the whole OMOP system, and the one worth nailing down before going further. When you look at a clinical event row — say a diagnosis in CONDITION_OCCURRENCE — you don’t see two representations in parallel (source and standard), as you might initially think, but three distinct levels.
1. Raw local code
The string as it existed in the hospital system. Stored in _source_value. No concept_id, just text.
2. Source concept
The OMOP identifier for the source code if one exists. Stored in _source_concept_id. May come from an integrated vocabulary (ICD-10, CCAM…) or be created locally.
3. Standard concept
The reference concept designated by OHDSI for that domain (SNOMED CT for diagnoses, RxNorm for drugs, LOINC for labs…). Stored in _concept_id. Marked standard_concept = ‘S’.
The distinction that surprises most people sits between cases 1 and 2 (below): being part of the OHDSI Vocabularies doesn’t mean being standard. ICD-10 is integrated, every code has an official concept_id, but those concepts are non-standard — SNOMED CT was chosen as the standard vocabulary for diagnoses. ICD-10 therefore plays the role of source concept, not standard concept.
Three typical cases make the relationship between these levels concrete. We present them from least to most demanding for the ETL.
Case 1 — The source code is already a standard concept
This is the easiest situation: the source already uses the vocabulary that OHDSI designated as the standard for the domain (LOINC for labs, RxNorm for drugs, SNOMED CT for diagnoses when the EHR supports it). The ETL looks the concept up in CONCEPT and places it in both _source_concept_id and _concept_id — both fields carry the same value, without any real mapping work.
Example — a LOINC-coded lab, as in MIMIC or modern EHRs
Raw local code
”8867-4”
LOINC code Heart rate as it comes out of the EHR — already standard.
Source concept
3027018
LOINC concept Heart rate. Because LOINC is the standard for labs, this concept is already marked standard_concept = ‘S’.
Standard concept
3027018
Identical to the source concept. When the source is already standard, both fields carry the same value.
Case 2 — The source code is in an OHDSI vocabulary but non-standard
This is the most common case in European databases: the source uses a vocabulary integrated into the OHDSI Vocabularies — ICD-10, ICD-10-CM, CCAM, ATC, NABM… — that isn’t standard for the domain. The ETL finds the official concept_id for the code, then follows the mapping already pre-built in CONCEPT_RELATIONSHIP to reach the standard concept.
Example — an ICD-10-coded diagnosis
Raw local code
”E11.9”
Entered by the physician through the hospital’s ICD-10 picker.
Source concept
45561952
Official OHDSI concept for ICD-10 code E11.9. Non-standard (standard_concept = NULL).
Standard concept
201826
SNOMED CT concept Type 2 diabetes mellitus. Standard (‘S’). Reached via the Maps to provided by OHDSI.
Case 3 — The source code is not in the OHDSI Vocabularies
This is the most demanding case: the source code has no equivalent in the vocabularies the OHDSI community maintains (in-house institution thesaurus, proprietary vendor code, short monitor label…). The ETL then has two options.
Option A — Create a custom concept (“2-billionaires”). When the code deserves to be properly tracked, it gets a concept_id above 2,000,000,000. OMOP reserves this range for local concepts to avoid clashes with official identifiers — hence the nickname “2B+” or “2-billionaires”. The concept is added to a vocabulary_id specific to the institution, and the ETL has to draw the Maps to link to a standard concept itself.
Example — an in-house diagnosis thesaurus in a Dutch hospital
Raw local code
”DHD-12345”
Internal code from the DHD Diagnose Thesaurus meaning type 1 diabetes, a diagnosis vocabulary owned by a Dutch hospital network.
Source concept (custom)
2,000,000,001
Concept created by the local ETL in a dedicated vocabulary_id (“DHD Diagnose Thesaurus”). Always non-standard.
Standard concept
201254
SNOMED CT concept Type 1 diabetes mellitus, reached via a Maps to added manually by the ETL.
Option B — Leave the source concept at 0. When the source code isn’t worth tracking (ephemeral label, unreliable data, no business need), the ETL doesn’t create a custom concept. The _source_value is kept as is, but _source_concept_id is set to 0 (“No matching concept”). The standard concept can still be filled in if the ETL manages to interpret the label.
Example — a heart rate value recorded by an ICU monitor
Raw local code
”HR bpm”
In-house monitor label, no structured code.
Source concept
0
No custom concept created: OMOP uses the “No matching concept” placeholder.
Standard concept
3027018
LOINC concept Heart rate. Standard (‘S’). Decided by the ETL during mapping.
Rules to follow for custom concepts (≥ 2 billion)
The official OMOP documentation sets several constraints for local concepts:
- They must belong to a new
vocabulary_idspecific to the institution, never to an existing OHDSI vocabulary. - Their
standard_conceptmust stayNULL: they are never standard. - They can only appear in
_source_concept_idfields, never in_concept_id. - They must not be attached to the hierarchies of OHDSI vocabularies. If hospital A declares its custom concept as a subtype of a SNOMED concept, a query for “all descendants of that SNOMED concept” will return different results in hospital A and hospital B — the hierarchy would no longer be the same across instances.
- They must carry a
Maps tolink to a standard concept, otherwise the data cannot be used for network research.
Who decides what’s standard?
This “standard / non-standard” designation is not an intrinsic property of a vocabulary: it’s a decision made by OHDSI, vocabulary by vocabulary, domain by domain. ICD-10 and SNOMED CT are both mature, widely used diagnosis vocabularies, but OHDSI chose SNOMED CT as the standard. ICD-10 therefore stays in the OHDSI Vocabularies, fully integrated, but confined to the role of source vocabulary.
One concept representing the meaning of each clinical event is designated the Standard. (…) Only these Standard Concepts are used to record data in the CDM fields ending in
_CONCEPT_ID.
The Book of OHDSI spells out the criteria: the choice is made “for each domain separately at the vocabulary level”, based on concept quality, available hierarchy, and the declared purpose of the vocabulary. The OHDSI Vocabulary Working Group maintains these decisions, integrates new vocabularies, and publishes updates through ATHENA.
Standards and sources: who plays which role
Not all terminologies play the same role. For each domain, OMOP designates one standard vocabulary and accepts the others as source vocabularies to be mapped onto the standard.
| Domain | Standard vocabulary | Common source vocabularies |
|---|---|---|
| Diagnoses | SNOMED CT | ICD-10, ICD-10-CM, Read codes |
| Medications | RxNorm + RxNorm Extension | ATC (classification), local codes |
| Labs / measurements | LOINC | Local codes, NABM (France) |
| Procedures | SNOMED CT, CPT4, HCPCS, ICD10PCS | CCAM (France), local codes |
| Demographics (gender) | Gender (OMOP vocabulary) | ISO codes, local codes |
ATC: a role of its own
ATC plays a particular role in OMOP: it’s neither a standard vocabulary (that role is reserved for RxNorm for drugs), nor a plain source vocabulary. OHDSI marks it as a classification (standard_concept = ‘C’): its concepts can’t be used to record a drug, but they take part in the hierarchy. In practice, a drug is recorded through its RxNorm concept, and you can then climb to its ATC class via CONCEPT_ANCESTOR — useful for analyses by therapeutic class.
The three tables at the heart of the vocabularies
OMOP fits its entire vocabulary system into three tables, each complementing the others:
CONCEPT— the dictionary: a unique identifier for every code in every vocabulary.CONCEPT_RELATIONSHIP— the links between concepts: equivalences, mappings, semantic relationships.CONCEPT_ANCESTOR— the pre-computed hierarchies, so a single query can reach a concept and all its descendants.
We cover them in that order.
CONCEPT — the universal dictionary
- Role:
- Unified dictionary of every medical code integrated into OMOP.
- One row per:
- Concept (one code in one vocabulary = one row).
- Connected to:
- Every
_concept_idcolumn in the event tables, and to itself viaCONCEPT_RELATIONSHIPandCONCEPT_ANCESTOR.
CONCEPT is the central table of the system. Every medical code in every integrated vocabulary appears there as a unique row, with a stable internal identifier: the concept_id.
| Column | Content |
|---|---|
concept_id | Unique OMOP identifier for the concept (use this in all queries) |
concept_name | Concept label (in English) |
domain_id | Domain (Condition, Drug, Measurement, Observation…) |
vocabulary_id | Source vocabulary (SNOMED, ICD10, LOINC, RxNorm…) |
concept_class_id | Class inside the vocabulary (e.g. “Clinical Finding” in SNOMED) |
standard_concept | ’S’ = standard, ‘C’ = classification, NULL = non-standard source |
concept_code | Code in the original vocabulary |
valid_start_date, valid_end_date | Validity period |
All vocabularies coexist within the same table: a query like WHERE concept_name LIKE '%diabetes%' can return SNOMED CT results, ICD-10 codes, British Read codes, or concepts from other national vocabularies.
Table preview
Three rows for the same clinical idea — type 2 diabetes — viewed from three angles. The first one (201826) is the standard SNOMED CT concept (standard_concept = ‘S’); this is what you’ll find in condition_concept_id. The second one (45561952) is the ICD-10 source concept corresponding to code E11.9 — non-standard, but recognized by OMOP. The third one (21600712) is an ATC entry — neither a raw source code nor a standard concept, but a classification participating in the hierarchy.
| concept_id | concept_name | domain_id | vocabulary_id | standard_concept | concept_code |
|---|---|---|---|---|---|
| 201826 | Type 2 diabetes mellitus | Condition | SNOMED | S | 44054006 |
| 45561952 | Type 2 diabetes mellitus, without complications | Condition | ICD10 | NULL | E11.9 |
| 21600712 | DRUGS USED IN DIABETES | Drug | ATC | C | A10 |
standard_concept = 'S': the column to watch
When writing a query, you almost always want to filter on standard_concept = ‘S’. This ensures you’re using the reference concept rather than an equivalent source code that might not be recognized by tools or by other databases in the OHDSI network.
domain_id: where the event lands
The domain_id column tells you which event table a record using this concept should be stored in. A concept with domain_id = ‘Measurement’ goes into MEASUREMENT, a domain_id = ‘Drug’ into DRUG_EXPOSURE, and so on for Condition → CONDITION_OCCURRENCE, Procedure → PROCEDURE_OCCURRENCE, Observation → OBSERVATION. When you look up a concept in ATHENA and aren’t sure where it will live in the database, this column settles it.
CONCEPT_RELATIONSHIP — the links between concepts
- Role:
- Defines directed relationships between two concepts, whether standard or not: mappings to standards, hierarchical relationships, question/answer links…
- One row per:
- Directed relationship between two concepts, qualified by a
relationship_id. - Connected to:
CONCEPTviaconcept_id_1andconcept_id_2.
Once the dictionary is in place, concepts need to be linked together. That’s the role of CONCEPT_RELATIONSHIP. Each row defines a directed relationship:
concept_id_1 → [relationship_id] → concept_id_2
A few of the most important relationships:
| Relationship | Meaning |
|---|---|
Maps to | concept_id_1 (source) is mapped to concept_id_2 (standard) |
Mapped from | Inverse of Maps to |
Is a | The concept is a subtype of… (hierarchy) |
Subsumes | Inverse of Is a (the concept encompasses…) |
Maps to value | Maps a pre-coordinated concept to a separate value |
Has answer | Links a question (e.g. LOINC) to its possible answers |
"Maps to", the pivot of the system
This is probably the relationship you’ll encounter most often. It indicates that one source concept should be treated as equivalent to a standard concept: an ICD-10 code to its SNOMED CT equivalent, a local lab code to LOINC, and so on.
Standard Concepts are mapped to themselves, non-standard concepts to Standard Concepts. Most non-standard and all Standard Concepts have this relationship to a Standard Concept.
Concretely, if you have an ICD-10 source code E11.9 (type 2 diabetes mellitus without complications) in condition_source_value, its condition_source_concept_id will point to the OMOP concept 45561952 that represents that code. That concept is non-standard, but it has a Maps to relationship pointing to the standard SNOMED CT concept 201826 — which is what you’ll find in condition_concept_id.
Table preview
Three relationships around type 2 diabetes. The first says that the ICD-10 code E11.9 is mapped to the standard SNOMED CT concept. The second is the inverse relationship (every link is stored in both directions). The third is a hierarchical relationship: type 2 diabetes is a subtype of “Diabetes mellitus” in SNOMED.
| concept_id_1 | concept_id_2 | relationship_id |
|---|---|---|
| 45561952 (ICD10 E11.9) | 201826 (SNOMED T2 diabetes) | Maps to |
| 201826 (SNOMED T2 diabetes) | 45561952 (ICD10 E11.9) | Mapped from |
| 201826 (SNOMED T2 diabetes) | 201820 (SNOMED Diabetes mellitus) | Is a |
What if the mapping isn't perfect?
Mapping to SNOMED CT isn’t always 1-to-1. The Book of OHDSI explicitly mentions “up-hill mappings”: when a source code has no exact equivalent, it gets mapped to a slightly broader SNOMED concept. The example it gives is vivid: ICD10CM W61.51 “Bitten by goose” has no exact equivalent in SNOMED, so it is mapped to SNOMED 217716004 “Peck by bird” — losing the fact that the bird was a goose. The community accepts these imperfections when the information loss is considered irrelevant for research, and welcomes feedback to improve the mappings.
CONCEPT_ANCESTOR — pre-computed hierarchies
- Role:
- Pre-computes the transitive closure of hierarchies: for every ancestor concept, lists all its descendants at every depth.
- One row per:
- Ancestor/descendant pair (the same concept appears multiple times depending on its position in the hierarchy).
- Connected to:
CONCEPTviaancestor_concept_idanddescendant_concept_id. Built automatically fromCONCEPT_RELATIONSHIP.
Medical vocabularies are hierarchical: Type 2 diabetes is a child of Diabetes, which is a child of Endocrine disease. When you want all patients with any kind of diabetes, you don’t want to list every subtype manually.
CONCEPT_ANCESTOR solves this by storing ahead of time every ancestor/descendant pair, at every depth in the hierarchy.
| Column | Content |
|---|---|
ancestor_concept_id | Parent concept |
descendant_concept_id | Child concept (at any depth) |
min_levels_of_separation | Minimum distance between the two |
max_levels_of_separation | Maximum distance (a concept can have several paths) |
Table preview — descendants of “Diabetes mellitus” (201820)
Four rows among the descendants of the SNOMED CT concept Diabetes mellitus. The first (min_levels = 0) is the concept itself: a concept is always its own ancestor, which makes queries like IN (SELECT descendant_concept_id …) straightforward. The next rows go down the hierarchy: type 1, type 2, and gestational diabetes two levels deep (a subtype of diabetes distinct from type 1 and type 2).
| ancestor_concept_id | descendant_concept_id | min_levels_of_separation | max_levels_of_separation |
|---|---|---|---|
| 201820 | 201820 (Diabetes mellitus) | 0 | 0 |
| 201820 | 201254 (T1 diabetes) | 1 | 1 |
| 201820 | 201826 (T2 diabetes) | 1 | 1 |
| 201820 | 4024659 (Gestational diabetes) | 2 | 2 |
This enables a query such as:
SELECT *
FROM condition_occurrence c
WHERE c.condition_concept_id IN (
SELECT descendant_concept_id
FROM concept_ancestor
WHERE ancestor_concept_id = 201820 -- Diabetes mellitus
)
Without CONCEPT_ANCESTOR, you’d have to do a recursive join on CONCEPT_RELATIONSHIP — much slower and more fragile.
Not all hierarchies are equal
The Book of OHDSI notes that a high-quality hierarchy exists only for two domains: drugs (via RxNorm) and conditions (via SNOMED CT). For procedures, measurements and observations, hierarchies are more partial or still being built. Keep this in mind when building concept sets in these domains: completeness is not guaranteed.
DRUG_STRENGTH — the actual dose of drugs
- Role:
- Gives the composition of every drug product: which active ingredient, in what amount, in what unit.
- One row per:
- Product / active ingredient pair (a combination product has several rows).
- Connected to:
CONCEPTviadrug_concept_id(the standard RxNorm product) andingredient_concept_id(the active ingredient).
As recalled in the previous article, DRUG_EXPOSURE doesn’t store the dose actually received by the patient: the quantity column gives only the number of units dispensed (tablets, ampoules, milliliters…). To compute the actual dose, you have to join DRUG_EXPOSURE with DRUG_STRENGTH, which holds the ingredient strength for each standard product.
DRUG_STRENGTH distinguishes two families of dosage forms via different columns:
- Solid or unit-dose forms (tablet, capsule, whole ampoule): the amount per unit lives in
amount_valueandamount_unit_concept_id. - Liquid or concentration-based forms (solution, infusion, syrup, patch): the strength is expressed as a
numerator_value / denominator_valueratio with their respective units.
| Column | Content |
|---|---|
drug_concept_id | Standard RxNorm product (e.g. ibuprofen 200 MG Oral Tablet) |
ingredient_concept_id | Active ingredient (e.g. ibuprofen) |
amount_value, amount_unit_concept_id | Amount per unit for solid forms (mg per tablet, per ampoule…) |
numerator_value, numerator_unit_concept_id | Amount of ingredient on the numerator of a concentration |
denominator_value, denominator_unit_concept_id | Volume / unit on the denominator (mL for an infusion, etc.) |
box_size | Number of units per box, if specified |
Table preview — two contrasting forms
Ibuprofen 200 mg oral tablet is a solid form: amount_value = 200 mg per tablet, the numerator/denominator columns stay empty. Injectable norepinephrine is a concentration: numerator_value = 0.128 mg per mL, denominator_value is left as NULL by convention (meaning 1 unit of the denominator).
| drug_concept_id | ingredient_concept_id | amount_value | numerator_value | denominator_value |
|---|---|---|---|---|
| 19078461 (ibuprofen 200 MG tab.) | 1177480 (ibuprofen) | 200 mg | NULL | NULL |
| 37354531 (norepinephrine 0.128 MG/ML) | 1321341 (norepinephrine) | NULL | 0.128 mg | 1 mL (implicit) |
A combination product = several rows
For drugs with several active ingredients — e.g. paracetamol + hydrocodone — DRUG_STRENGTH stores one row per ingredient, all pointing to the same drug_concept_id. When computing doses, you therefore always need to specify which ingredient you care about via ingredient_concept_id.
The full dose-calculation formulas (by dosage form, with or without concentration) live in the official OMOP dose-calculation documentation. For hands-on practice, the advanced SQL tutorial has dedicated exercises (total dose of a tablet, infusion rate of an IV drug).
Other vocabulary tables
CONCEPT, CONCEPT_RELATIONSHIP, CONCEPT_ANCESTOR and DRUG_STRENGTH carry the bulk of the system. Six auxiliary tables round it out. You rarely touch them in analytical queries, but it’s worth knowing what they’re for.
| Table | Role |
|---|---|
VOCABULARY | Catalog of the integrated vocabularies (SNOMED, ICD10, LOINC, RxNorm…) with their version, reference, and import date. This is the table to check to know which ATHENA version an instance is using. |
DOMAIN | Catalog of domains (Condition, Drug, Measurement, Observation, Procedure…) and the CDM table they route to. The reference behind the domain_id column in CONCEPT. |
RELATIONSHIP | Catalog of relationship_id values (Maps to, Is a, Subsumes, Has answer…) with their inverse and hierarchical level. Useful when you encounter an unfamiliar relationship in CONCEPT_RELATIONSHIP. |
CONCEPT_CLASS | Catalog of the concept classes used by each vocabulary (e.g. “Clinical Finding” in SNOMED, “ATC 2nd” in ATC). Reference for the concept_class_id column in CONCEPT. |
CONCEPT_SYNONYM | Textual variants of a concept: alternative labels, translations, official synonyms. Useful when searching by label and the exact term isn’t the one OHDSI picked. |
SOURCE_TO_CONCEPT_MAP | Mapping table maintained locally by each ETL to link its source codes to standard concepts. We cover it in detail in Building an OMOP ETL. |
Concept_id = 0 — OMOP’s “NULL”
A convention already met in the previous article: when a source code has no available mapping, its _concept_id is set to 0.
CONCEPT.concept_id = 0 actually exists in the dictionary; it carries the name “No matching concept”. It’s a design choice to avoid classic SQL NULLs and provide an explicit signal.
In the Standardized Vocabularies, there is no distinction made why a piece of information is not available; it might be because of an active withdrawal of information by the patient, a missing value, a value that is not defined or standardized in some way, or the absence of a mapping record in
CONCEPT_RELATIONSHIP. Any such concept is not mapped, which corresponds to a default mapping to the Standard Concept with the concept ID = 0.
In practice:
- Regularly count
concept_id = 0rows in each table — it’s the simplest mapping quality indicator. - A source code can be present (
source_valuenon-empty) and itssource_concept_idvalid, while the standard_concept_idis 0 if the source concept doesn’t have a mapping yet.
ATHENA — exploring the vocabularies without SQL
ATHENA is the centralized dictionary of OMOP vocabularies, accessed through a graphical interface. It exposes the same information you’d find in the CONCEPT, CONCEPT_RELATIONSHIP, and CONCEPT_ANCESTOR tables of an OMOP instance, but without having to write a SQL query every time you look up a concept: search by label, filters by domain, vocabulary, and standard status, and navigation through relationships and hierarchies in a few clicks.
With a (free) ATHENA account, you can download a vocabulary bundle ready to import into your own OMOP database — a required step for CONCEPT, CONCEPT_RELATIONSHIP and CONCEPT_ANCESTOR to be populated in your instance.
ATHENA is covered in more depth in the OHDSI tools ecosystem article.
In practice: concept sets
For clinical analyses, you rarely work with a single concept at a time. You build concept sets: collections of standard concepts that together represent the same clinical notion. For example, a “heart rate” concept set will gather all the LOINC codes under which this measurement can be recorded (variations by measurement context, method, patient position…), and a “serum creatinine” concept set will likewise gather the different LOINC codes used for the blood creatinine test.
A typical concept set combines several mechanisms:
- A few root concepts selected explicitly (for example the LOINC concept Heart rate).
- Inclusion of descendants via
CONCEPT_ANCESTORto capture all subtypes — especially useful for conditions and drugs, which have the most complete hierarchies. - Selective exclusion of descendants you don’t want (for example, excluding a variant measured in a specific context).
This is exactly what ATLAS lets you build without coding, or what you write directly in SQL for the exercises that follow. The official ATLAS documentation on concept sets walks through the workflow, and the INDICATE Data Dictionary provides 300+ ready-made clinical concept sets.
Going further
- Our interactive explorer also covers the vocabulary tables with their columns and keys.
- Chapter 5 of the Book of OHDSI is the complete official reference.
- ATHENA to explore concepts and their relationships hands-on.
- Three levels to keep apart for every clinical event: the raw local code (
_source_value), the source concept (_source_concept_id) and the standard concept (_concept_id). - Being part of the OHDSI Vocabularies doesn't mean being standard. ICD-10 is integrated, but SNOMED CT is the standard for diagnoses. The "standard / non-standard" decision is made by the OHDSI Vocabulary Working Group.
- The vocabularies rest on three tables:
CONCEPT(the dictionary),CONCEPT_RELATIONSHIP(the directed links between concepts),CONCEPT_ANCESTOR(the pre-computed hierarchies). - The "Maps to" relationship is the core mechanism linking a source concept to its standard. For sources that are already standard, the concept maps to itself.
- Filter on
standard_concept = 'S'in your queries to keep only reference concepts, and usedomain_idto know which event table the concept will land in. - High-quality hierarchies only exist for drugs and conditions. For other domains, be careful with concept sets built by hierarchy.
-
concept_id = 0flags an unmapped source code. Custom concepts (≥ 2 billion) let you track a local code that has no OHDSI equivalent — provided you follow the rules: dedicated vocabulary, never standard, mandatoryMaps to. - ATHENA is the centralized graphical dictionary of OMOP vocabularies: search, filters, navigation through relationships and hierarchies, without writing SQL.