From e332e3240901c2d81dd8cf6b6b983fbaff348bbf Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 14 Mar 2022 13:56:12 +0100 Subject: [PATCH 1/6] fixes #95 --- R/execution.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/execution.R b/R/execution.R index 9252b16a..05af921a 100644 --- a/R/execution.R +++ b/R/execution.R @@ -547,7 +547,8 @@ if (conceptCheckThresholdLoc == "default"){ if (!is.na(checkResults[i,]$ERROR)) { checkResults[i,]$FAILED <- 1 - } else if (is.na(thresholdValue)) { + } else if (is.na(thresholdValue) | thresholdValue == 0) { + # If no threshold, or threshold is 0%, then any violating records will cause this check to fail if (!is.na(checkResults[i,]$NUM_VIOLATED_ROWS) & checkResults[i,]$NUM_VIOLATED_ROWS > 0) { checkResults[i,]$FAILED <- 1 } From 880da7913f21eaf53a4708990a415b825ce5461f Mon Sep 17 00:00:00 2001 From: Clair Blacketer Date: Thu, 5 May 2022 14:42:06 -0400 Subject: [PATCH 2/6] Fix to DESCRIPTION file --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index bc8049d8..ddbbbe09 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: DataQualityDashboard Type: Package Title: Execute and View Data Quality Checks on OMOP CDM Database -Version: 1.3.1 +Version: 1.4.1 Date: 2020-02-28 Authors@R: c( person("Clair", "Blacketer", , "mblacke@its.jnj.com", role = c("aut", "cre")), From faa7c47456e9cfa14598c0fe38032bc3f1256175 Mon Sep 17 00:00:00 2001 From: Luis Alberto Alaniz Castillo Date: Mon, 23 May 2022 13:22:29 -0600 Subject: [PATCH 3/6] Adding latest version of new shiny app and changes to codeToRun.R and view.R --- DESCRIPTION | 4 +- NAMESPACE | 1 + R/execution.R | 368 ++++++-- R/view.R | 47 +- README.md | 24 +- _pkgdown.yml | 2 + docs/404.html | 117 +-- docs/LICENSE-text.html | 109 +-- docs/articles/CheckTypeDescriptions.html | 154 ++-- docs/articles/DataQualityDashboard.html | 99 +- docs/articles/DqdForCohorts.html | 30 +- docs/articles/Thresholds.html | 74 +- docs/articles/index.html | 123 +-- docs/authors.html | 178 ++-- docs/index.html | 201 ++-- docs/pkgdown.css | 83 +- docs/pkgdown.js | 4 +- docs/pkgdown.yml | 4 +- docs/reference/executeDqChecks.html | 298 ++---- docs/reference/index.html | 163 +--- docs/reference/viewDqDashboard.html | 136 +-- docs/reference/writeJsonResultsToTable.html | 156 +--- docs/sitemap.xml | 69 ++ extras/codeToRun.R | 50 +- extras/indexMultipleJsons.R | 132 +++ extras/updateThresholds.R | 222 +++++ inst/ResultsV2/About.Rmd | 81 ++ inst/ResultsV2/About.html | 534 +++++++++++ inst/ResultsV2/CDM_SOURCE.Rmd | 37 + inst/ResultsV2/CDM_SOURCE.html | 445 +++++++++ inst/ResultsV2/GitHub-Mark-32px.png | Bin 0 -> 1714 bytes inst/ResultsV2/load_data_10.R | 291 ++++++ inst/ResultsV2/server.r | 444 +++++++++ inst/ResultsV2/ui.r | 116 +++ inst/ResultsV2/www/GitHub-Mark-32px.png | Bin 0 -> 1714 bytes inst/ResultsV2/www/OHDSI.jpg | Bin 0 -> 6661 bytes inst/ResultsV2/www/ohdsi.png | Bin 0 -> 27800 bytes .../csv/OMOP_CDMv5.2.2_Check_Descriptions.csv | 5 +- .../csv/OMOP_CDMv5.3.1_Check_Descriptions.csv | 4 +- inst/csv/OMOP_CDMv5.3.1_Concept_Level.csv | 4 +- inst/csv/OMOP_CDMv5.3.1_Field_Level.csv | 600 ++++++------ inst/csv/OMOP_CDMv5.4_Check_Descriptions.csv | 4 +- inst/csv/OMOP_CDMv5.4_Concept_Level.csv | 4 +- inst/csv/OMOP_CDMv5.4_Field_Level.csv | 866 +++++++++--------- inst/shinyApps/www/js/loadResults.js | 6 +- .../sql_server/concept_plausible_gender.sql | 3 +- .../concept_plausible_value_high.sql | 2 + .../concept_plausible_value_low.sql | 2 + inst/sql/sql_server/field_cdm_datatype.sql | 2 + .../field_concept_record_completeness.sql | 9 +- inst/sql/sql_server/field_fk_class.sql | 2 + inst/sql/sql_server/field_fk_domain.sql | 3 +- inst/sql/sql_server/field_is_not_nullable.sql | 2 + inst/sql/sql_server/field_is_primary_key.sql | 4 +- .../field_is_standard_valid_concept.sql | 4 +- .../field_measure_value_completeness.sql | 2 + .../field_plausible_during_life.sql | 4 +- .../field_plausible_temporal_after.sql | 9 +- .../sql_server/field_plausible_value_high.sql | 2 + .../sql_server/field_plausible_value_low.sql | 2 + .../field_source_value_completeness.sql | 2 + .../sql_server/field_within_visit_dates.sql | 48 + inst/sql/sql_server/is_foreign_key.sql | 4 +- inst/sql/sql_server/result_dataframe_ddl.sql | 4 + .../sql_server/result_table_ddl_concept.sql | 4 + .../sql/sql_server/result_table_ddl_field.sql | 4 + .../sql/sql_server/result_table_ddl_table.sql | 4 + inst/sql/sql_server/table_cdm_table.sql | 29 + .../sql_server/table_concept_completeness.sql | 2 + .../sql_server/table_person_completeness.sql | 2 + man/executeDqChecks.Rd | 3 +- vignettes/DataQualityDashboard.html | 16 +- vignettes/DataQualityDashboard.md | 20 +- vignettes/DataQualityDashboard.rmd | 16 +- 74 files changed, 4414 insertions(+), 2085 deletions(-) create mode 100644 docs/sitemap.xml create mode 100644 extras/indexMultipleJsons.R create mode 100644 extras/updateThresholds.R create mode 100644 inst/ResultsV2/About.Rmd create mode 100644 inst/ResultsV2/About.html create mode 100644 inst/ResultsV2/CDM_SOURCE.Rmd create mode 100644 inst/ResultsV2/CDM_SOURCE.html create mode 100644 inst/ResultsV2/GitHub-Mark-32px.png create mode 100644 inst/ResultsV2/load_data_10.R create mode 100644 inst/ResultsV2/server.r create mode 100644 inst/ResultsV2/ui.r create mode 100644 inst/ResultsV2/www/GitHub-Mark-32px.png create mode 100644 inst/ResultsV2/www/OHDSI.jpg create mode 100644 inst/ResultsV2/www/ohdsi.png create mode 100644 inst/sql/sql_server/field_within_visit_dates.sql create mode 100644 inst/sql/sql_server/table_cdm_table.sql diff --git a/DESCRIPTION b/DESCRIPTION index ddbbbe09..37d17c1c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: DataQualityDashboard Type: Package Title: Execute and View Data Quality Checks on OMOP CDM Database -Version: 1.4.1 +Version: 1.4.0 Date: 2020-02-28 Authors@R: c( person("Clair", "Blacketer", , "mblacke@its.jnj.com", role = c("aut", "cre")), @@ -35,5 +35,5 @@ Suggests: rmarkdown, shiny, ggplot2 -RoxygenNote: 7.1.1 +RoxygenNote: 7.1.2 Encoding: UTF-8 diff --git a/NAMESPACE b/NAMESPACE index 1d00cafb..3f80e614 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,3 +4,4 @@ export(executeDqChecks) export(listDqChecks) export(viewDqDashboard) export(writeJsonResultsToTable) +export(writeJsonResultsToCsv) \ No newline at end of file diff --git a/R/execution.R b/R/execution.R index 05af921a..5d34ea7c 100644 --- a/R/execution.R +++ b/R/execution.R @@ -145,6 +145,8 @@ #' @param outputFile (OPTIONAL) File to write results JSON object #' @param verboseMode Boolean to determine if the console will show all execution steps. Default = FALSE #' @param writeToTable Boolean to indicate if the check results will be written to the dqdashboard_results table +#' @param writeToCsv Boolean to indicate if the check results will be written to the csv file +#' @param csvFile (OPTIONAL) CSV file to write results #' in the resultsDatabaseSchema. Default is TRUE. #' @param checkLevels Choose which DQ check levels to execute. Default is all 3 (TABLE, FIELD, CONCEPT) #' @param checkNames (OPTIONAL) Choose which check names to execute. Names can be found in inst/csv/OMOP_CDM_v[cdmVersion]_Check_Desciptions.csv @@ -172,20 +174,30 @@ executeDqChecks <- function(connectionDetails, verboseMode = FALSE, writeToTable = TRUE, writeTableName = "dqdashboard_results", + writeToCsv = FALSE, + csvFile = "", checkLevels = c("TABLE", "FIELD", "CONCEPT"), checkNames = c(), cohortDefinitionId = c(), cohortDatabaseSchema = resultsDatabaseSchema, - tablesToExclude = c(), + tablesToExclude = c("CONCEPT", "VOCABULARY", "CONCEPT_ANCESTOR", "CONCEPT_RELATIONSHIP", "CONCEPT_CLASS", "CONCEPT_SYNONYM", "RELATIONSHIP", "DOMAIN"), cdmVersion = "5.3.1", tableCheckThresholdLoc = "default", fieldCheckThresholdLoc = "default", conceptCheckThresholdLoc = "default") { + # Make sure the following checks are included: cdmTable, cdmField, measureValueCompleteness + if (!length(checkNames)==0){ + checkNames <- union(checkNames, c("cdmTable", "cdmField", "measureValueCompleteness")) + } + if (!length(checkLevels)==0){ + checkLevels <- union(checkLevels, c("TABLE", "FIELD")) + } + # Check input ------------------------------------------------------------------------------------------------------------------- if (!("connectionDetails" %in% class(connectionDetails))){ stop("connectionDetails must be an object of class 'connectionDetails'.") - } + } stopifnot(is.character(cdmDatabaseSchema), is.character(resultsDatabaseSchema), is.numeric(numThreads)) stopifnot(is.character(cdmSourceName), is.logical(sqlOnly), is.character(outputFolder), is.logical(verboseMode)) @@ -199,20 +211,28 @@ executeDqChecks <- function(connectionDetails, stopifnot(is.null(checkNames) | is.character(checkNames), is.null(tablesToExclude) | is.character(tablesToExclude)) stopifnot(is.character(cdmVersion)) + # Use UTF-8 encoding to address issue: "special characters in metadata #33" + saveEncoding <- getOption("encoding") + options("encoding" = "UTF-8") + # Setup output folder ------------------------------------------------------------------------------------------------------------ options(scipen = 999) - + # capture metadata ----------------------------------------------------------------------- - connection <- DatabaseConnector::connect(connectionDetails = connectionDetails) - sql <- SqlRender::render(sql = "select * from @cdmDatabaseSchema.cdm_source;", + if (!sqlOnly) { + connection <- DatabaseConnector::connect(connectionDetails = connectionDetails) + sql <- SqlRender::render(sql = "select * from @cdmDatabaseSchema.cdm_source;", cdmDatabaseSchema = cdmDatabaseSchema) - sql <- SqlRender::translate(sql = sql, targetDialect = connectionDetails$dbms) - metadata <- DatabaseConnector::querySql(connection = connection, sql = sql) - if (nrow(metadata)<1) { - stop("Please populate the cdm_source table before executing data quality checks.") + sql <- SqlRender::translate(sql = sql, targetDialect = connectionDetails$dbms) + metadata <- DatabaseConnector::querySql(connection = connection, sql = sql) + if (nrow(metadata)<1) { + stop("Please populate the cdm_source table before executing data quality checks.") + } + metadata$DQD_VERSION <- as.character(packageVersion("DataQualityDashboard")) + DatabaseConnector::disconnect(connection) + } else { + metadata <- NA } - metadata$DQD_VERSION <- as.character(packageVersion("DataQualityDashboard")) - DatabaseConnector::disconnect(connection) if (!dir.exists(outputFolder)) { dir.create(path = outputFolder, recursive = TRUE) @@ -249,27 +269,27 @@ executeDqChecks <- function(connectionDetails, startTime <- Sys.time() checkDescriptionsDf <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Check_Descriptions.csv", cdmVersion), - package = "DataQualityDashboard"), - stringsAsFactors = FALSE) + package = "DataQualityDashboard"), + stringsAsFactors = FALSE) -if (tableCheckThresholdLoc == "default"){ - tableChecks <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Table_Level.csv", cdmVersion), - package = "DataQualityDashboard"), - stringsAsFactors = FALSE, na.strings = c(" ",""))} else {tableChecks <- read.csv(tableCheckThresholdLoc, - stringsAsFactors = FALSE, na.strings = c(" ",""))} + if (tableCheckThresholdLoc == "default"){ + tableChecks <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Table_Level.csv", cdmVersion), + package = "DataQualityDashboard"), + stringsAsFactors = FALSE, na.strings = c(" ",""))} else {tableChecks <- read.csv(tableCheckThresholdLoc, + stringsAsFactors = FALSE, na.strings = c(" ",""))} -if (fieldCheckThresholdLoc == "default"){ + if (fieldCheckThresholdLoc == "default"){ fieldChecks <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Field_Level.csv", cdmVersion), - package = "DataQualityDashboard"), - stringsAsFactors = FALSE, na.strings = c(" ",""))} else {fieldChecks <- read.csv(fieldCheckThresholdLoc, - stringsAsFactors = FALSE, na.strings = c(" ",""))} + package = "DataQualityDashboard"), + stringsAsFactors = FALSE, na.strings = c(" ",""))} else {fieldChecks <- read.csv(fieldCheckThresholdLoc, + stringsAsFactors = FALSE, na.strings = c(" ",""))} -if (conceptCheckThresholdLoc == "default"){ - conceptChecks <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Concept_Level.csv", cdmVersion), - package = "DataQualityDashboard"), - stringsAsFactors = FALSE, na.strings = c(" ",""))} else {conceptChecks <- read.csv(conceptCheckThresholdLoc, - stringsAsFactors = FALSE, na.strings = c(" ",""))} + if (conceptCheckThresholdLoc == "default"){ + conceptChecks <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Concept_Level.csv", cdmVersion), + package = "DataQualityDashboard"), + stringsAsFactors = FALSE, na.strings = c(" ",""))} else {conceptChecks <- read.csv(conceptCheckThresholdLoc, + stringsAsFactors = FALSE, na.strings = c(" ",""))} # ensure we use only checks that are intended to be run ----------------------------------------- @@ -290,7 +310,7 @@ if (conceptCheckThresholdLoc == "default"){ # tableChecks <- tableChecks %>% dplyr::select_if(function(x) !(all(is.na(x)) | all(x==""))) # fieldChecks <- fieldChecks %>% dplyr::select_if(function(x) !(all(is.na(x)) | all(x==""))) # conceptChecks <- conceptChecks %>% dplyr::select_if(function(x) !(all(is.na(x)) | all(x==""))) - + checksToInclude <- checkDescriptionsDf$checkName[sapply(checkDescriptionsDf$checkName, function(check) { !is.null(eval(parse(text = sprintf("tableChecks$%s", check)))) | @@ -362,7 +382,7 @@ if (conceptCheckThresholdLoc == "default"){ ParallelLogger::logInfo("Execution Complete") } - + # write to table ---------------------------------------------------------------------- @@ -374,15 +394,27 @@ if (conceptCheckThresholdLoc == "default"){ cohortDefinitionId = cohortDefinitionId) } + # write to CSV ---------------------------------------------------------------------- + + if (!sqlOnly & writeToCsv) { + if (nchar(csvFile)==0) { + csvFile <- sprintf("%s.csv", sub(pattern = "(.*)\\..*$", replacement = "\\1", basename(allResults$outputFile))) + } + .writeResultsToCsv(checkResults = allResults$CheckResults, + csvPath = file.path(outputFolder, csvFile)) + } + if (sqlOnly) { invisible(allResults) } else { allResults } - - + ParallelLogger::unregisterLogger("DqDashboard") + # Reset encoding to previous value + options("encoding" = saveEncoding) + return(allResults) } @@ -453,12 +485,32 @@ if (conceptCheckThresholdLoc == "default"){ } } +.isStructureRelatedError <- function(errorMessage, + dbms) { + result <- TRUE + + #if (!is.na(errorMessage) & !is.na(dbms)) { + # if (dbms == "postgresql") { + # result <- + # stringr::str_detect(errorMessage, "relation(?s)(.*)does not exist") | + # stringr::str_detect(errorMessage, "column(?s)(.*)does not exist") + # } + #} + + result +} + .evaluateThresholds <- function(checkResults, tableChecks, fieldChecks, - conceptChecks) { + conceptChecks, + dbms = NA) { checkResults$FAILED <- 0 + checkResults$PASSED <- 0 + checkResults$IS_ERROR <- 0 + checkResults$NOT_APPLICABLE <- 0 + checkResults$NOT_APPLICABLE_REASON <- NA checkResults$THRESHOLD_VALUE <- NA checkResults$NOTES_VALUE <- NA @@ -481,7 +533,7 @@ if (conceptCheckThresholdLoc == "default"){ thresholdFilter <- sprintf("tableChecks$%s[tableChecks$cdmTableName == '%s']", thresholdField, checkResults[i,]$CDM_TABLE_NAME) notesFilter <- sprintf("tableChecks$%s[tableChecks$cdmTableName == '%s']", - notesField, checkResults[i,]$CDM_TABLE_NAME) + notesField, checkResults[i,]$CDM_TABLE_NAME) } else if (checkResults[i,]$CHECK_LEVEL == "FIELD") { @@ -492,9 +544,9 @@ if (conceptCheckThresholdLoc == "default"){ checkResults[i,]$CDM_FIELD_NAME) notesFilter <- sprintf("fieldChecks$%s[fieldChecks$cdmTableName == '%s' & fieldChecks$cdmFieldName == '%s']", - notesField, - checkResults[i,]$CDM_TABLE_NAME, - checkResults[i,]$CDM_FIELD_NAME) + notesField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME) } else if (checkResults[i,]$CHECK_LEVEL == "CONCEPT") { @@ -511,10 +563,10 @@ if (conceptCheckThresholdLoc == "default"){ notesFilter <- sprintf("conceptChecks$%s[conceptChecks$cdmTableName == '%s' & conceptChecks$cdmFieldName == '%s' & conceptChecks$conceptId == %s]", - notesField, - checkResults[i,]$CDM_TABLE_NAME, - checkResults[i,]$CDM_FIELD_NAME, - checkResults[i,]$CONCEPT_ID) + notesField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME, + checkResults[i,]$CONCEPT_ID) } else { thresholdFilter <- sprintf("conceptChecks$%s[conceptChecks$cdmTableName == '%s' & @@ -530,11 +582,11 @@ if (conceptCheckThresholdLoc == "default"){ conceptChecks$cdmFieldName == '%s' & conceptChecks$conceptId == %s & conceptChecks$unitConceptId == '%s']", - notesField, - checkResults[i,]$CDM_TABLE_NAME, - checkResults[i,]$CDM_FIELD_NAME, - checkResults[i,]$CONCEPT_ID, - as.integer(checkResults[i,]$UNIT_CONCEPT_ID)) + notesField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME, + checkResults[i,]$CONCEPT_ID, + as.integer(checkResults[i,]$UNIT_CONCEPT_ID)) } } @@ -546,7 +598,11 @@ if (conceptCheckThresholdLoc == "default"){ } if (!is.na(checkResults[i,]$ERROR)) { - checkResults[i,]$FAILED <- 1 + if (.isStructureRelatedError(checkResults[i,]$ERROR, dbms)) { + checkResults[i,]$FAILED <- 1 + } else { + checkResults[i,]$IS_ERROR <- 1 + } } else if (is.na(thresholdValue) | thresholdValue == 0) { # If no threshold, or threshold is 0%, then any violating records will cause this check to fail if (!is.na(checkResults[i,]$NUM_VIOLATED_ROWS) & checkResults[i,]$NUM_VIOLATED_ROWS > 0) { @@ -554,9 +610,118 @@ if (conceptCheckThresholdLoc == "default"){ } } else if (checkResults[i,]$PCT_VIOLATED_ROWS * 100 > thresholdValue) { checkResults[i,]$FAILED <- 1 - } + } + } + + missingTables <- dplyr::select( + dplyr::filter(checkResults, CHECK_NAME == "cdmTable" & FAILED == 1), + CDM_TABLE_NAME) + if (nrow(missingTables) > 0) { + missingTables$TABLE_IS_MISSING <- 1 + checkResults <- dplyr::mutate( + dplyr::left_join(checkResults, missingTables, by = "CDM_TABLE_NAME"), + TABLE_IS_MISSING = ifelse(CHECK_NAME != "cdmTable" & IS_ERROR == 0, TABLE_IS_MISSING, NA)) + } else { + checkResults$TABLE_IS_MISSING <- NA + } + + missingFields <- dplyr::select( + dplyr::filter(checkResults, CHECK_NAME == "cdmField" & FAILED == 1 & is.na(TABLE_IS_MISSING)), + CDM_TABLE_NAME, CDM_FIELD_NAME) + if (nrow(missingFields) > 0) { + missingFields$FIELD_IS_MISSING <- 1 + checkResults <- dplyr::mutate( + dplyr::left_join(checkResults, missingFields, by = c("CDM_TABLE_NAME", "CDM_FIELD_NAME")), + FIELD_IS_MISSING = ifelse(CHECK_NAME != "cdmField" & IS_ERROR == 0, FIELD_IS_MISSING, NA)) + } else { + checkResults$FIELD_IS_MISSING <- NA + } + + emptyTables <- dplyr::distinct( + dplyr::select( + dplyr::filter(checkResults, CHECK_NAME == "measureValueCompleteness" & + NUM_DENOMINATOR_ROWS == 0 & + IS_ERROR == 0 & + is.na(TABLE_IS_MISSING) & + is.na(FIELD_IS_MISSING)), + CDM_TABLE_NAME)) + if (nrow(emptyTables) > 0) { + emptyTables$TABLE_IS_EMPTY <- 1 + checkResults <- dplyr::mutate( + dplyr::left_join(checkResults, emptyTables, by = c("CDM_TABLE_NAME")), + TABLE_IS_EMPTY = ifelse(CHECK_NAME != "cdmField" & CHECK_NAME != "cdmTable" & IS_ERROR == 0, TABLE_IS_EMPTY, NA)) + } else { + checkResults$TABLE_IS_EMPTY <- NA } + emptyFields <- + dplyr::select( + dplyr::filter(checkResults, CHECK_NAME == "measureValueCompleteness" & + NUM_DENOMINATOR_ROWS == NUM_VIOLATED_ROWS & + is.na(TABLE_IS_MISSING) & is.na(FIELD_IS_MISSING) & is.na(TABLE_IS_EMPTY)), + CDM_TABLE_NAME, CDM_FIELD_NAME) + if (nrow(emptyFields) > 0) { + emptyFields$FIELD_IS_EMPTY <- 1 + checkResults <- dplyr::mutate( + dplyr::left_join(checkResults, emptyFields, by = c("CDM_TABLE_NAME", "CDM_FIELD_NAME")), + FIELD_IS_EMPTY = ifelse(CHECK_NAME != "measureValueCompleteness" & CHECK_NAME != "cdmField" & CHECK_NAME != "isRequired" & IS_ERROR == 0, FIELD_IS_EMPTY, NA)) + } else { + checkResults$FIELD_IS_EMPTY <- NA + } + + checkResults <- dplyr::mutate( + checkResults, + CONCEPT_IS_MISSING = ifelse( + IS_ERROR == 0 & + is.na(TABLE_IS_MISSING) & + is.na(FIELD_IS_MISSING) & + is.na(TABLE_IS_EMPTY) & + is.na(FIELD_IS_EMPTY) & + CHECK_LEVEL == "CONCEPT" & + is.na(UNIT_CONCEPT_ID) & + NUM_DENOMINATOR_ROWS == 0, + 1, + NA + ) + ) + + checkResults <- dplyr::mutate( + checkResults, + CONCEPT_AND_UNIT_ARE_MISSING = ifelse( + IS_ERROR == 0 & + is.na(TABLE_IS_MISSING) & + is.na(FIELD_IS_MISSING) & + is.na(TABLE_IS_EMPTY) & + is.na(FIELD_IS_EMPTY) & + CHECK_LEVEL == "CONCEPT" & + !is.na(UNIT_CONCEPT_ID) & + NUM_DENOMINATOR_ROWS == 0, + 1, + NA + ) + ) + + checkResults <- dplyr::mutate( + checkResults, + NOT_APPLICABLE = dplyr::coalesce(TABLE_IS_MISSING, FIELD_IS_MISSING, TABLE_IS_EMPTY, FIELD_IS_EMPTY, CONCEPT_IS_MISSING, CONCEPT_AND_UNIT_ARE_MISSING, 0), + NOT_APPLICABLE_REASON = + ifelse(!is.na(TABLE_IS_MISSING), sprintf("Table %s does not exist.", CDM_TABLE_NAME), + ifelse(!is.na(FIELD_IS_MISSING), sprintf("Field %s.%s does not exist.", CDM_TABLE_NAME, CDM_FIELD_NAME), + ifelse(!is.na(TABLE_IS_EMPTY), sprintf("Table %s is empty.", CDM_TABLE_NAME), + ifelse(!is.na(FIELD_IS_EMPTY), sprintf("Field %s.%s is not populated.", CDM_TABLE_NAME, CDM_FIELD_NAME), + ifelse(!is.na(CONCEPT_IS_MISSING), sprintf("%s=%s is missing from the %s table.", CDM_FIELD_NAME, CONCEPT_ID, CDM_TABLE_NAME), + ifelse(!is.na(CONCEPT_AND_UNIT_ARE_MISSING), sprintf("Combination of %s=%s, UNIT_CONCEPT_ID=%s and VALUE_AS_NUMBER IS NOT NULL is missing from the %s table.", CDM_FIELD_NAME, CONCEPT_ID, UNIT_CONCEPT_ID, CDM_TABLE_NAME), NA) + ) + ) + ) + ) + ) + ) + + checkResults <- dplyr::select(checkResults, -c(TABLE_IS_MISSING, FIELD_IS_MISSING, TABLE_IS_EMPTY, FIELD_IS_EMPTY, CONCEPT_IS_MISSING, CONCEPT_AND_UNIT_ARE_MISSING)) + checkResults <- dplyr::mutate(checkResults, FAILED = ifelse(NOT_APPLICABLE == 1, 0, FAILED)) + checkResults <- dplyr::mutate(checkResults, PASSED = ifelse(FAILED == 0 & IS_ERROR == 0 & NOT_APPLICABLE == 0, 1, 0)) + checkResults } @@ -579,15 +744,17 @@ if (conceptCheckThresholdLoc == "default"){ checkResults <- .evaluateThresholds(checkResults = checkResults, tableChecks = tableChecks, fieldChecks = fieldChecks, - conceptChecks = conceptChecks) + conceptChecks = conceptChecks, + dbms = connectionDetails$dbms) countTotal <- nrow(checkResults) countThresholdFailed <- nrow(checkResults[checkResults$FAILED == 1 & is.na(checkResults$ERROR),]) - countErrorFailed <- nrow(checkResults[!is.na(checkResults$ERROR),]) + countErrorFailed <- nrow(checkResults[checkResults$FAILED == 1 & + !is.na(checkResults$ERROR),]) countOverallFailed <- nrow(checkResults[checkResults$FAILED == 1,]) - countPassed <- countTotal - countOverallFailed + countPassed <- nrow(checkResults[checkResults$PASSED == 1,]) #countTotal - countOverallFailed countTotalPlausibility <- nrow(checkResults[checkResults$CATEGORY=='Plausibility',]) countTotalConformance <- nrow(checkResults[checkResults$CATEGORY=='Conformance',]) @@ -602,9 +769,15 @@ if (conceptCheckThresholdLoc == "default"){ countFailedCompleteness <- nrow(checkResults[checkResults$CATEGORY=='Completeness' & checkResults$FAILED == 1,]) - countPassedPlausibility <- countTotalPlausibility - countFailedPlausibility - countPassedConformance <- countTotalConformance - countFailedConformance - countPassedCompleteness <- countTotalCompleteness - countFailedCompleteness + #countPassedPlausibility <- countTotalPlausibility - countFailedPlausibility + countPassedPlausibility <- nrow(checkResults[checkResults$CATEGORY=='Plausibility' & + checkResults$PASSED == 1,]) + #countPassedConformance <- countTotalConformance - countFailedConformance + countPassedConformance <- nrow(checkResults[checkResults$CATEGORY=='Conformance' & + checkResults$PASSED == 1,]) + #countPassedCompleteness <- countTotalCompleteness - countFailedCompleteness + countPassedCompleteness <- nrow(checkResults[checkResults$CATEGORY=='Completeness' & + checkResults$PASSED == 1,]) overview <- list( countTotal = countTotal, @@ -612,8 +785,8 @@ if (conceptCheckThresholdLoc == "default"){ countErrorFailed = countErrorFailed, countThresholdFailed = countThresholdFailed, countOverallFailed = countOverallFailed, - percentPassed = round(countPassed / countTotal * 100), - percentFailed = round(countOverallFailed / countTotal * 100), + percentPassed = round(countPassed / (countPassed +countOverallFailed) * 100), + percentFailed = round(countOverallFailed / (countPassed +countOverallFailed) * 100), countTotalPlausibility = countTotalPlausibility, countTotalConformance = countTotalConformance, countTotalCompleteness = countTotalCompleteness, @@ -636,9 +809,9 @@ if (conceptCheckThresholdLoc == "default"){ Overview = overview) resultJson <- jsonlite::toJSON(result) - + if (nchar(outputFile)==0) { - endTimestamp <- format(endTime,"%Y%m%d%H%M%S") + endTimestamp <- format(endTime, "%Y%m%d%H%M%S") outputFile <- sprintf("%s-%s.json", tolower(metadata$CDM_SOURCE_ABBREVIATION),endTimestamp) } @@ -647,7 +820,7 @@ if (conceptCheckThresholdLoc == "default"){ ParallelLogger::logInfo(sprintf("Writing results to file: %s", resultFilename)) write(resultJson, resultFilename) - + result } @@ -725,7 +898,7 @@ writeJsonResultsToTable <- function(connectionDetails, ParallelLogger::logInfo(sprintf("Writing results to table %s", tableName)) ddl <- SqlRender::loadRenderTranslateSql(sqlFilename = "result_dataframe_ddl.sql", packageName = "DataQualityDashboard", tableName = tableName, dbms = connectionDetails$dbms) - + DatabaseConnector::executeSql(connection = connection, sql = ddl, progressBar = TRUE) tryCatch( @@ -740,6 +913,83 @@ writeJsonResultsToTable <- function(connectionDetails, ) } +.writeResultsToCsv <- function(checkResults, + csvPath, + columns = c("checkId", "FAILED", "PASSED", + "IS_ERROR", "NOT_APPLICABLE", + "CHECK_NAME", "CHECK_DESCRIPTION", + "THRESHOLD_VALUE", "NOTES_VALUE", + "CHECK_LEVEL", "CATEGORY", + "SUBCATEGORY", "CONTEXT", + "CHECK_LEVEL", "CDM_TABLE_NAME", + "CDM_FIELD_NAME", "CONCEPT_ID", + "UNIT_CONCEPT_ID", "NUM_VIOLATED_ROWS", + "PCT_VIOLATED_ROWS", "NUM_DENOMINATOR_ROWS", + "EXECUTION_TIME", "NOT_APPLICABLE_REASON", + "ERROR", "QUERY_TEXT"), + delimiter = "\t") { + tryCatch( + expr = { + ParallelLogger::logInfo(sprintf("Writing results to CSV file %s", csvPath)) + columns <- intersect(union(c("checkId", "FAILED", "PASSED", "IS_ERROR", "NOT_APPLICABLE"), columns), colnames(checkResults)) + if (is.element("QUERY_TEXT", columns)) { + checkResults$QUERY_TEXT <- stringr::str_replace_all(checkResults$QUERY_TEXT, "\n", " ") + checkResults$QUERY_TEXT <- stringr::str_replace_all(checkResults$QUERY_TEXT, "\r", " ") + checkResults$QUERY_TEXT <- stringr::str_replace_all(checkResults$QUERY_TEXT, "\t", " ") + } + if (is.element("ERROR", columns)) { + checkResults$ERROR <- stringr::str_replace_all(checkResults$ERROR, "\n", " ") + checkResults$ERROR <- stringr::str_replace_all(checkResults$ERROR, "\r", " ") + checkResults$ERROR <- stringr::str_replace_all(checkResults$ERROR, "\t", " ") + } + write.table(dplyr::select(checkResults, columns), file = csvPath, sep = delimiter, row.names = FALSE, na = "") + ParallelLogger::logInfo("Finished writing to CSV file") + }, + error = function(e) { + ParallelLogger::logError(sprintf("Writing to CSV file failed: %s", e$message)) + } + ) +} + +#' Write JSON Results to SQL Table +#' +#' @param jsonPath Path to the JSON results file generated using the execute function +#' @param csvPath Path to the CSV output file +#' @param columns (OPTIONAL) List of desired columns +#' @param delimiter (OPTIONAL) CSV delimiter +#' +#' @export +writeJsonResultsToCsv <- function(jsonPath, + csvPath, + columns = c("checkId", "FAILED", "PASSED", + "IS_ERROR", "NOT_APPLICABLE", + "CHECK_NAME", "CHECK_DESCRIPTION", + "THRESHOLD_VALUE", "NOTES_VALUE", + "CHECK_LEVEL", "CATEGORY", + "SUBCATEGORY", "CONTEXT", + "CHECK_LEVEL", "CDM_TABLE_NAME", + "CDM_FIELD_NAME", "CONCEPT_ID", + "UNIT_CONCEPT_ID", "NUM_VIOLATED_ROWS", + "PCT_VIOLATED_ROWS", "NUM_DENOMINATOR_ROWS", + "EXECUTION_TIME", "NOT_APPLICABLE_REASON", + "ERROR", "QUERY_TEXT"), + delimiter = "\t") { + tryCatch( + expr = { + ParallelLogger::logInfo(sprintf("Loading results from %s", jsonPath)) + jsonData <- jsonlite::read_json(jsonPath) + checkResults <- lapply(jsonData$CheckResults, function(cr) { + cr[sapply(cr, is.null)] <- NA + as.data.frame(cr) + }) + .writeResultsToCsv(checkResults = do.call(plyr::rbind.fill, checkResults), csvPath, columns, delimiter) + }, + error = function(e) { + ParallelLogger::logError(sprintf("Writing to CSV file failed: %s", e$message)) + } + ) +} + .needsAutoCommit <- function(connectionDetails, connection) { autoCommit <- FALSE if (!is.null(connection)) { diff --git a/R/view.R b/R/view.R index a71fb05f..5955df7c 100644 --- a/R/view.R +++ b/R/view.R @@ -24,16 +24,51 @@ #' #' @export viewDqDashboard <- function(jsonPath, launch.browser=NULL, display.mode=NULL, ...) { + + ensure_installed("shiny") + Sys.setenv(jsonPath = jsonPath) - appDir <- system.file("shinyApps", package = "DataQualityDashboard") - + appDir <- system.file("ResultsV2", package = "DataQualityDashboard") + if(is.null(display.mode)){ - display.mode="normal" + display.mode="normal" } - + if(is.null(launch.browser)){ - launch.browser=TRUE + launch.browser=TRUE } - + shiny::runApp(appDir = appDir, launch.browser = launch.browser, display.mode = display.mode, ...) } + + +# Borrowed from devtools: +# https://github.com/hadley/devtools/blob/ba7a5a4abd8258c52cb156e7b26bb4bf47a79f0b/R/utils.r#L44 +is_installed <- function(pkg, version = 0) { + installed_version <- + tryCatch( + utils::packageVersion(pkg), + error = function(e) + NA + ) + ! is.na(installed_version) && installed_version >= version +} + +# Borrowed and adapted from devtools: +# https://github.com/hadley/devtools/blob/ba7a5a4abd8258c52cb156e7b26bb4bf47a79f0b/R/utils.r#L74 +ensure_installed <- function(pkg) { + if (!is_installed(pkg)) { + msg <- + paste0(sQuote(pkg), " must be installed for this functionality.") + if (interactive()) { + message(msg, "\nWould you like to install it?") + if (menu(c("Yes", "No")) == 1) { + install.packages(pkg) + } else { + stop(msg, call. = FALSE) + } + } else { + stop(msg, call. = FALSE) + } + } +} diff --git a/README.md b/README.md index 65bc4694..7c6cafc2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The goal of the Data Quality Dashboard (DQD) project is to design and develop an Introduction ============ -This package will run a series of data quality checks against an OMOP CDM instance (currently supports v5.3.1 and v5.2.2). It systematically runs the checks, evaluates the checks against some pre-specified threshold, and then communicates what was done in a transparent and easily understandable way. +This package will run a series of data quality checks against an OMOP CDM instance (currently supports v5.4, v5.3.1 and v5.2.2). It systematically runs the checks, evaluates the checks against some pre-specified threshold, and then communicates what was done in a transparent and easily understandable way. Overview ======== @@ -33,7 +33,7 @@ Version 1 of the tool includes 20 different check types organized into Kahn cont After systematically applying the 20 check types to an OMOP CDM version approximately 3,351 individual data quality checks are resolved, run against the database, and evaluated based on a pre-specified threshold. The R package then creates a json object that is read into an RShiny application to view the results. - + Features @@ -42,6 +42,24 @@ Features - Analyzes data in the OMOP Common Data Model format for all data checks - Produces a set of data check results with supplemental investigation assets. +Data Requirements +================= + +Prior to execution the DataQualityDashboard package requires that the CDM_SOURCE table is properly populated. The following table is a guide to the expected contents of the CDM_SOURCE table. + +cdmFieldName | userGuidance | etlConventions +-- | -- | -- +cdm_source_name | The name of the CDM instance. | Descriptive name for the source data. +cdm_source_abbreviation | The abbreviation of the CDM instance. | The abbreviation should consistent for different release from the same source. +cdm_holder | The holder of the CDM instance. | The institution that controls access to the data.  If possible include contact information for who to contact to request access to the data. +source_description | The description of the CDM instance. | Add notes, caveats, special characteristics about the source data that would not be assumed from the general descriptive name.  This description intended to help analysists determine if the data is suitable for the problem they are studying. +source_documentation_reference | Reference to where one can find documentation about the source data. | Can include URL's, file name, source data experts contact information (if they agree to it) +cdm_etl_reference | Reference to where one can find documentation about the source to ETL into OMOP CDM. | Assuming there is a document or files (such as Rabbit in the Hat) describing the ETL.  May be the location of the ETL source and documentation repository. +source_release_date | The release date of the source data. | When the source data was made available for ETL'ing.  For sites doing incremental updates, the date the last increment made available.  This implies that for sites doing incremental updates the CDM Source table should be updated to reflect that changes were made to the CDM. +cdm_release_date | The release date of the CDM instance. | When the source data was made available for general use.  For sites doing incremental updates, this implies that the CDM Source table should be updated to reflect that changes were made to the CDM. +cdm_version | Identifies the CDM version | Enter the numeric portion of the version, e.g. 5.4 +cdm_version_concept_id | The Concept Id representing the version of the CDM. | SELECT concept_id WHERE domain = Metadata and vocabulary_id = CDM and concept_code like %[numeric portion of the version]% +vocabulary_version | The vocabulary version used in the ETL | Obtained by SELECT vocabulary_version FROM vocabulary WHERE vocabulary_id = 'None' Technology ========== @@ -63,7 +81,7 @@ DataQualityDashboard is licensed under Apache License 2.0 ### Development status -V1.0 ready for use. +V1.4 ready for use. # Acknowledgements diff --git a/_pkgdown.yml b/_pkgdown.yml index 869875b5..1aca2f4c 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -6,6 +6,8 @@ home: links: - text: Ask a question href: http://forums.ohdsi.org + - text: DQD Example Output + href: https://data.ohdsi.org/DataQualityDashboardMDCD/ navbar: structure: diff --git a/docs/404.html b/docs/404.html index 38bcb3ba..e8398995 100644 --- a/docs/404.html +++ b/docs/404.html @@ -1,66 +1,27 @@ - - - - + + + + - Page not found (404) • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - -
-
- + +
+ + + - - -
+
+
-
- +
+ + - - diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index 375e1d39..2edd805a 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -1,66 +1,12 @@ - - - - - - - -License • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -License • DataQualityDashboard - - + + - - -
-
- -
- -
+
+
-
- +
- - + + diff --git a/docs/articles/CheckTypeDescriptions.html b/docs/articles/CheckTypeDescriptions.html index 07e328ba..2837217b 100644 --- a/docs/articles/CheckTypeDescriptions.html +++ b/docs/articles/CheckTypeDescriptions.html @@ -19,6 +19,8 @@ + +
+
@@ -104,153 +106,153 @@

2022-03-03

%\VignetteEngine{knitr::knitr} %\VignetteIndexEntry{Data Quality Check Type Definitions} --> -
-

-Introduction

+
+

Introduction +

The DataQualityDashboard functions by applying 20 parameterized check types to a CDM instance, resulting in over 3,351 resolved, executed, and evaluated individual data quality checks. For example, one check type might be written as

The number and percent of records with a value in the cdmFieldName field of the cdmTableName table less than plausibleValueLow.

This would be considered an atemporal plausibility verification check because we are looking for implausibly low values in some field based on internal knowledge. We can use this check type to substitute in values for cdmFieldName, cdmTableName, and plausibleValueLow to create a unique data quality check. If we apply it to PERSON.YEAR_OF_BIRTH here is how that might look:

The number and percent of records with a value in the year_of_birth field of the PERSON table less than 1850.

And, since it is parameterized, we can similarly apply it to DRUG_EXPOSURE.days_supply:

The number and percent of records with a value in the days_supply field of the DRUG_EXPOSURE table less than 0.

-

Version 1 of the tool includes 20 different check types organized into Kahn contexts and categories (link to paper). Additionally, each data quality check type is considered either a table check, field check, or concept-level check. Table-level checks are those evaluating the table at a high-level without reference to individual fields, or those that span multiple event tables. These include checks making sure required tables are present or that at least some of the people in the PERSON table have records in the event tables. Field-level checks are those related to specific fields in a table. The majority of the check types in version 1 are field-level checks. These include checks evaluating primary key relationship and those investigating if the concepts in a field conform to the specified domain. Concept-level checks are related to individual concepts. These include checks looking for gender-specific concepts in persons of the wrong gender and plausible values for measurement-unit pairs.

+

Version 1 of the tool includes 20 different check types organized into Kahn contexts and categories (link to paper). Additionally, each data quality check type is considered either a table check, field check, or concept-level check. Table-level checks are those evaluating the table at a high-level without reference to individual fields, or those that span multiple event tables. These include checks making sure required tables are present or that at least some of the people in the PERSON table have records in the event tables. Field-level checks are those related to specific fields in a table. The majority of the check types in version 1 are field-level checks. These include checks evaluating primary key relationship and those investigating if the concepts in a field conform to the specified domain. Concept-level checks are related to individual concepts. These include checks looking for gender-specific concepts in persons of the wrong gender and plausible values for measurement-unit pairs.

This article will detail each check type, its name, check level, description, definition, and to which Kahn context, category, and subcategory it belongs.

-
-

-measurePersonCompleteness

+
+

measurePersonCompleteness +

Name: measurePersonCompleteness
Level: Table check
Context: Validation
Category: Completeness

Description: The number and percent of persons in the CDM that do not have at least one record in the cdmTableName table.

Definition: For each table indicated this check will count the number of persons from the PERSON table that do not have at least one record in the specified clinical event table. It may be that there are 100 persons listed in the PERSON table but only 30 of them have at least one record in the MEASUREMENT table. If the measurePersonCompleteness check is indicated for the MEASUREMENT table, the result will be 70%, meaning that 70% of the persons in the CDM instance do not have at least one record in MEASUREMENT.

-
-

-cdmField

+
+

cdmField +

Name: cdmField
Level: Field check
Context: Verification
Category: Conformance
Subcategory: Relational

Description: A value indicating if all fields are present in the cdmTableName table.

Definition: For each table indicated this check will go through and determine if all fields are present as specified based on the CDM version. If the field is present, the resulting value will be 0; if the field is absent the resulting value will be 100.

-
-

-isRequired

+
+

isRequired +

Name: isRequired
Level: Field check
Context: Validation
Category: Conformance
Subcategory: Relational

Description: The number and percent of records with a NULL value in the cdmFieldName of the cdmTableName that is considered not nullable

Definition: This check is meant to ensure that all NOT NULL constraints specified in the CDM version are followed. It will count up all records with a NULL value in the specified field of the specified table and return the percent of records in the table that violate the constraint.

-
-

-cdmDatatype

+
+

cdmDatatype +

Name: cdmDatatype
Level: Field check
Context: Verification
Category: Conformance
Subcategory: Value

Description: A yes or no value indicating if the cdmFieldName in the cdmTableName is the expected data type based on the specification.

Definition: At present this will check only that fields that are supposed to be integers are the expected datatype. For a given field, it will count the number of records with a non-null, non-integer value.

-
-

-isPrimaryKey

+
+

isPrimaryKey +

Name: isPrimaryKey
Level: Field check
Context: Verification
Category: Conformance
Subcategory: Relational

Description: The number and percent of records that have a duplicate value in the cdmFieldName field of the cdmTableName.

Definition: This check will make sure that all primary keys as specified in the CDM version are truly unique values in the database. While this should be caught by primary key constraints, some database management systems such as redshift do not enforce these.

-
-

-isForeignKey

+
+

isForeignKey +

Name: isForeignKey
Level: Field check
Context: Verification
Category: Conformance
Subcategory: Relational

Description: The number and percent of records that have a value in the cdmFieldName field in the cdmTableName table that does not exist in the fkTableName table.

Definition: This check will make sure that all foreign keys as specified in the CDM version have a value in the related primary key field. While this should be caught by foreign key constraints, some database management systems such as redshift do not enforce these.

-
-

-fkDomain

+
+

fkDomain +

Name: fkDomain
Level: Field check
Context: Verification
Category: Conformance
Subcategory: Value

Description: The number and percent of records that have a value in the cdmFieldName field in the cdmTableName table that do not conform to the fkDomain domain.

-

Definition: It is often the case that standard concept fields in the OMOP CDM should belong to a certain domain. All possible domains are listed in the vocabulary table DOMAIN and the expected domain for CDM fields are listed as part of the CDM documentation. For example, in the field PERSON.gender_concept_id all concepts in that field should conform to the gender domain. This check will search all concepts in a field and count the number of records that have concepts in the field that do not belong to the correct domain.

+

Definition: It is often the case that standard concept fields in the OMOP CDM should belong to a certain domain. All possible domains are listed in the vocabulary table DOMAIN and the expected domain for CDM fields are listed as part of the CDM documentation. For example, in the field PERSON.gender_concept_id all concepts in that field should conform to the gender domain. This check will search all concepts in a field and count the number of records that have concepts in the field that do not belong to the correct domain.

-
-

-fkClass

+
+

fkClass +

Name: fkClass
Level: Field check
Context: Verification
Category: Conformance
Subcategory: Computational

Description: The number and percent of records that have a value in the cdmFieldName field in the cdmTableName table that do not conform to the fkClass class.

Definition: There is the occasional field in the OMOP CDM that expects not only concepts of a certain domain, but of a certain concept class as well. The best example is the drug_concept_id field in the DRUG_ERA table. Drug eras represent the span of time a person was exposed to a particular drug ingredient so all concepts in DRUG_ERA.drug_concept_id are of the drug domain and ingredient class. This check will search all concepts in a field and count the number of records that have a concept in the field that do not belong to the correct concept class.

-
-

-isStandardValidConcept

+
+

isStandardValidConcept +

Name: isStandardValidConcept
Level: Field check
Context: Verification
Category: Conformance

Description: The number and percent of records that do not have a standard, valid concept in the cdmFieldName field in the cdmTableName table.

Definition: In order to standardize not only the structure but the vocabulary of the OMOP CDM, certain fields in the model require standard, valid concepts while other fields do not. For example, in the PERSON table, the field gender_concept_id MUST be a standard, valid concept: either 8532 or 8507. In contrast the field gender_source_concept_id can be any concept, standard or no. This check will count the number of records that have a concept in a given field that are not standard and valid.

-
-

-measureValueCompleteness

+
+

measureValueCompleteness +


Name: measureValueCompleteness
Level: Field check
Context: Verification
Category:Completeness

Description: The number and percent of records with a NULL value in the cdmFieldName of the cdmTableName.

Definition: This check will count the number of records with a NULL value in a specified field. This is different from the isRequired check because it will run this calculation for all tables and fields whereas the isRequired check will only run for those fields deemed required by the CDM specification. Often the thresholds for failure are set at different levels between these checks as well.

-
-

-standardConceptRecordCompleteness

+
+

standardConceptRecordCompleteness +

Name: standardConceptRecordCompleteness
Level: Field check
Context: Verification
Category: Completeness

Description: The number and percent of records with a value of 0 in the standard concept field cdmFieldName in the cdmTableName table.

Definition: It is important to understand how well source values were mapped to standard concepts. This check will count the number of records in a standard concept field (condition_concept_id, drug_concept_id, etc.) with a value of 0 rather a standard concept. NOTE for the field unit_concept_id in the MEASUREMENT and OBSERVATION tables both the numerator and denominator are limited to records where value_as_number is not null. This prevents over-inflation of the numbers and focuses the check to records that are eligible for a unit value.

-
-

-sourceConceptRecordCompleteness

+
+

sourceConceptRecordCompleteness +

Name: sourceConceptRecordCompleteness
Level: Field check
Context: Verification
Category: Completeness

Description: The number and percent of records with a value of 0 in the source concept field cdmFieldName in the cdmTableName table.

Definition: This check will count the number of records in a source concept field (condition_source_concept_id, drug_source_concept_id) with a value of 0. This is useful since source values that are represented by concepts in the vocabulary have automatic mappings to standard concepts. Using this check along with the standardConceptRecordCompletness check can help identify any vocabulary mapping issues during ETL.

-
-

-sourceValueCompleteness

+
+

sourceValueCompleteness +

Name: sourceValueCompleteness
Level: Field check
Context: Verification
Category: Completeness

Description: The number and percent of distinct source values in the cdmFieldName field of the cdmTableName table mapped to 0.

Definition: This check will look at all distinct source values in the specified field and calculate how many are mapped to 0. This should be used in conjunction with the standardConceptRecordCompletness check to identify any mapping issues in the ETL.

-
-

-plausibleValueLow

+
+

plausibleValueLow +

Name: plausibleValueLow
Level: Field check
Context: Verification
Category: Plausibility
Subcategory: Atemporal

Description: The number and percent of records with a value in the cdmFieldName field of the cdmTableName table less than plausibleValueLow.

Definition: This check will count the number of records that have a value in the specified field that is lower than some value. This is the field-level version of this check so it is not concept specific. For example, it will count the number of records that have an implausibly low value in the year_of_birth field of the PERSON table.

-
-

-plausibleValueHigh

+
+

plausibleValueHigh +

Name: plausibleValueHigh
Level: Field check
Context: Verification
Category: Plausibility
Subcategory: Atemporal

Description: The number and percent of records with a value in the cdmFieldName field of the cdmTableName table greater than plausibleValueHigh.

Definition: This check will count the number of records that have a value in the specified field that is higher than some value. This is the field-level version of this check so it is not concept specific. For example, it will count the number of records that have an implausibly high value in the year_of_birth field of the PERSON table.

-
-

-plausibleTemporalAfter

+
+

plausibleTemporalAfter +

Name: plausibleTemporalAfter
Level: Field check
Context: Verification
Category: Plausibility
Subcategory: Temporal

Description: The number and percent of records with a value in the cdmFieldName field of the cdmTableName that occurs prior to the date in the plausibleTemporalAfterFieldName field of the plausibleTemporalAfterTableName table.

Definition: This check is attempting to apply temporal rules to a CDM instance. For example, it will check to make sure that all visit records for a person in the VISIT_OCCURRENCE table occur after the person’s birth.

-
-

-plausibleDuringLife

+
+

plausibleDuringLife +

Name: plausibleDuringLife
Level: Field check
Context: Verification
Category: Plausibility
Subcategory: Temporal

Description: If yes, the number and percent of records with a date value in the cdmFieldName field of the cdmTableName table that occurs after death.

Definition: This check will calculate the number of records that occur after a person’s death. This is called plausibleDuringLife because turning it on indicates that the specified dates should occur during a person’s lifetime, like drug exposures, etc.

-
-

-plausibleValueLow

+
+

plausibleValueLow +

Name: plausibleValueLow
Level: Concept check
Context: Verification
Category: Plausibility
Subcategory: Atemporal

Description: For the combination of CONCEPT_ID conceptId (conceptName) and UNIT_CONCEPT_ID unitConceptId (unitConceptName), the number and percent of records that have a value less than plausibleValueLow.

Definition: This check will count the number of records that have a value in the specified field with the specified concept_id and unit_concept_id that is lower than some value. This is the concept-level version of this check so it is concept specific and therefore the denominator will only be the records with the specified concept and unit. For example, it will count the number of records that have an implausibly low value in the value_as_number field of the MEASUREMENT table where MEASUREMENT_CONCEPT_ID = 2212241 (Calcium; total) and UNIT_CONCEPT_ID = 8840 (milligram per deciliter). These implausible values were determined by a team of physicans and are meant to be biologically implausible, not just lower than the normal value.

-
-

-plausibleValueHigh

+
+

plausibleValueHigh +

Name: plausibleValueHigh
Level: Concept check
Context: Verification
Category: Plausibility
Subcategory: Atemporal

Description: For the combination of CONCEPT_ID conceptId (conceptName) and UNIT_CONCEPT_ID unitConceptId (unitConceptName), the number and percent of records that have a value higher than plausibleValueHigh.

Definition: This check will count the number of records that have a value in the specified field with the specified concept_id and unit_concept_id that is higher than some value. This is the concept-level version of this check so it is concept specific and therefore the denominator will only be the records with the specified concept and unit. For example, it will count the number of records that have an implausibly high value in the value_as_number field of the MEASUREMENT table where MEASUREMENT_CONCEPT_ID = 2212241 (Calcium; total) and UNIT_CONCEPT_ID = 8840 (milligram per deciliter). These implausible values were determined by a team of physicans and are meant to be biologically implausible, not just higher than the normal value.

-
-

-plausibleGender

+
+

plausibleGender +

Name: plausibleGender
Level: Concept check
Context: Validation
Category: Plausibility
Subcategory: Atemporal

Description: For a CONCEPT_ID conceptId (conceptName), the number and percent of records associated with patients with an implausible gender (correct gender = plausibleGender).

Definition: This check will count the number of records that have an incorrect gender associated with a gender-specific concept_id. This check is concept specific and therefore the denominator will only be the records with the specified concept. For example it will count the number of records of prostate cancer that are associated with female persons.

@@ -269,11 +271,13 @@

-

Site built with pkgdown 1.6.1.

+

+

Site built with pkgdown 2.0.2.

@@ -282,5 +286,7 @@

+ + diff --git a/docs/articles/DataQualityDashboard.html b/docs/articles/DataQualityDashboard.html index 0d6a3bbe..dd6eec07 100644 --- a/docs/articles/DataQualityDashboard.html +++ b/docs/articles/DataQualityDashboard.html @@ -19,6 +19,8 @@ + +
+
@@ -104,30 +106,30 @@

2022-03-03

%\VignetteEngine{knitr::knitr} %\VignetteIndexEntry{Getting Started} --> -
-

-Getting Started

+
+

Getting Started +


-
-

-R Installation

+
+

R Installation +

-install.packages("devtools")
-devtools::install_github("OHDSI/DataQualityDashboard")
+install.packages("remotes") +remotes::install_github("OHDSI/DataQualityDashboard")
-
-

-Note

+
+

Note +

To view the JSON results in the shiny application the package requires that the CDM_SOURCE table has at least one row with some details about the database. This is to ensure that some metadata is delivered along with the JSON, should it be shared. As a best practice it is recommended to always fill in this table during ETL or at least prior to running the DQD.

-
-

-Executing Data Quality Checks

+
+

Executing Data Quality Checks +

 
 # fill out the connection details -----------------------------------------------------------------------
-connectionDetails <- DatabaseConnector::createConnectionDetails(dbms = "", 
+connectionDetails <- DatabaseConnector::createConnectionDetails(dbms = "", 
                                                               user = "", 
                                                               password = "", 
                                                               server = "", 
@@ -146,7 +148,6 @@ 

# where should the logs go? ------------------------------------------------------------------------- outputFolder <- "output" -outputFile <- "results.json" # logging type ------------------------------------------------------------------------------------- verboseMode <- FALSE # set to TRUE if you want to see activity written to the console @@ -165,15 +166,11 @@

# "USE_MPP_BULK_LOAD" = TRUE) # which DQ check levels to run ------------------------------------------------------------------- -checkLevels <- c("TABLE", "FIELD", "CONCEPT") +checkLevels <- c("TABLE", "FIELD", "CONCEPT") # which DQ checks to run? ------------------------------------ -checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Desciptions.csv - -# which CDM tables to exclude? ------------------------------------ - -tablesToExclude <- c() +checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Descriptions.csv # run the job -------------------------------------------------------------------------------------- DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, @@ -187,12 +184,11 @@

verboseMode = verboseMode, writeToTable = writeToTable, checkLevels = checkLevels, - tablesToExclude = tablesToExclude, checkNames = checkNames) # inspect logs ---------------------------------------------------------------------------- -ParallelLogger::launchLogViewer(logFileName = file.path(outputFolder, cdmSourceName, - sprintf("log_DqDashboard_%s.txt", cdmSourceName))) +ParallelLogger::launchLogViewer(logFileName = file.path(outputFolder, cdmSourceName, + sprintf("log_DqDashboard_%s.txt", cdmSourceName))) # (OPTIONAL) if you want to write the JSON file to the results table separately ----------------------------- jsonFilePath <- "" @@ -201,13 +197,12 @@

jsonFilePath = jsonFilePath)

-
-

-Viewing Results

+
+

Viewing Results +

Launching Dashboard as Shiny App

-
DataQualityDashboard::viewDqDashboard(
-  jsonPath = file.path(getwd(), outputFolder, cdmSourceName, outputFile, cdmSourceName))
-)
+
+DataQualityDashboard::viewDqDashboard(jsonFilePath)

Launching on a web server

If you have npm installed:

    @@ -218,18 +213,18 @@

  1. Name the output file results.json and place it in inst/shinyApps/www

  2. Go to inst/shinyApps/www, then run:

-
http-server
+
http-server
-
-

-View checks

+
+

View checks +

To see description of checks using R, execute the command below:

-
View(read.csv(
-  system.file("csv","OMOP_CDMv5.3.1_Check_Descriptions.csv",
-    package="DataQualityDashboard"
-  ),
-  as.is=T)
-)
+
View(read.csv(
+  system.file("csv","OMOP_CDMv5.3.1_Check_Descriptions.csv",
+    package="DataQualityDashboard"
+  ),
+  as.is=T)
+)
@@ -244,11 +239,13 @@

-

Site built with pkgdown 1.6.1.

+

+

Site built with pkgdown 2.0.2.

@@ -257,5 +254,7 @@

+ + diff --git a/docs/articles/DqdForCohorts.html b/docs/articles/DqdForCohorts.html index 31a1a031..50183038 100644 --- a/docs/articles/DqdForCohorts.html +++ b/docs/articles/DqdForCohorts.html @@ -19,6 +19,8 @@ + +
+
@@ -104,9 +106,9 @@

2022-03-03

%\VignetteEngine{knitr::knitr} %\VignetteIndexEntry{Running the DQD on a Cohort} --> -
-

-DQD Cohort Functionality

+
+

DQD Cohort Functionality +

Running the Data Quality Dashboard for a cohort is fairly straightforward. There are two options in the executeDqChecks function, cohortDefinitionId and cohortDatabaseSchema. These options will point the DQD to the schema where the cohort table is located and provide the id of the cohort on which the DQD will be run. The tool assumes that the table being referenced is the standard OHDSI cohort table named COHORT with at least the columns cohort_definition_id and subject_id. For example, if I have a cohort number 123 and the cohort is in the results schema of the IBM_CCAE database, the executeDqChecks function would look like this:


 DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, 
@@ -140,11 +142,13 @@ 

-

Site built with pkgdown 1.6.1.

+

+

Site built with pkgdown 2.0.2.

@@ -153,5 +157,7 @@

+ + diff --git a/docs/articles/Thresholds.html b/docs/articles/Thresholds.html index 8b535273..8a9fbf46 100644 --- a/docs/articles/Thresholds.html +++ b/docs/articles/Thresholds.html @@ -19,6 +19,8 @@ + +
+
@@ -104,54 +106,54 @@

2022-03-03

%\VignetteEngine{knitr::knitr} %\VignetteIndexEntry{Failure Thresholds and How to Change Them} --> -
-

-DQD Failure Thresholds

-

As described in the introduction to the tool, the Data Quality Dashboard works by systematically applying 20 data quality check types to a database by leveraging the structure of the OMOP Common Data Model. This process results in over 3,300 potential data quality checks. These checks are then resolved against the database, each one producing a number and percent of records that fail. The percent failure is then compared against a number to determine if the check itself should be marked as a pass or a fail overall. Essentially, the threshold number is the percent of failed records for a particular check you are willing to accept. If the percent failures is lower than the threshold then it passes, otherwise the check fails.

+
+

DQD Failure Thresholds +

+

As described in the introduction to the tool, the Data Quality Dashboard works by systematically applying 20 data quality check types to a database by leveraging the structure of the OMOP Common Data Model. This process results in over 3,300 potential data quality checks. These checks are then resolved against the database, each one producing a number and percent of records that fail. The percent failure is then compared against a number to determine if the check itself should be marked as a pass or a fail overall. Essentially, the threshold number is the percent of failed records for a particular check you are willing to accept. If the percent failures is lower than the threshold then it passes, otherwise the check fails.

A default set of failure thresholds are shipped with the package. Many of these are general thresholds determined by CDM experts and were designed to test the minimum quality measures necessary to run an analysis on a database. They do not take into account an apriori knowledge of the database or data that is available. With that in mind, it is possible to change the failure thresholds and even set different thresholds for different databases.

-
-

-DQD Control Files

+
+

DQD Control Files +

There is a set of three csv files that underly the DQD. These files indicate which checks should be run and what their failure thresholds should be. There is one file per check level: TABLE, FIELD, and CONCEPT. This vignette will walk through how to update the field level check thresholds but the process is the same for all three files.

-
-

-Step 1: Find and copy the control files

-

The control files are located in the R package in the inst/csv folder and can also be downloaded here. In that location there should be four files per CDM version the DQD supports. These are:

+
+

Step 1: Find and copy the control files +

+

The control files are located in the R package in the inst/csv folder and can also be downloaded here. In that location there should be four files per CDM version the DQD supports. These are:

  • OMOP_CDMvx.x.x_Check_Descriptions.csv: This file contains the check types, their descriptions, and which sql file is associated with each. It does not contain any failure thresholds and should not need to be changed.
  • -OMOP_CDMvx.x.x_Table_Level.csv: This file has a list of all tables in the CDM version and any checks to be performed at this level as well as the failure thresholds associated. Right now only the checktype measurePersonCompleteness is considered a table level check. If you would like to change the failure thresholds for the measurePersonCompleteness check copy this file to a location the R instance can access.
  • +OMOP_CDMvx.x.x_Table_Level.csv: This file has a list of all tables in the CDM version and any checks to be performed at this level as well as the failure thresholds associated. Right now only the checktype measurePersonCompleteness is considered a table level check. If you would like to change the failure thresholds for the measurePersonCompleteness check copy this file to a location the R instance can access.
  • -OMOP_CDMvx.x.x_Field_Level.csv: This file has a list of all tables and fields in the CDM version and any checks to be performed at this level as well as the failure thresholds associated. The majority of the check types run by the DQD are field level checks. If you would like to change the failure thresholds for any of these checks copy this file to a location the R instance can access. An example of this file is seen in figure 1 below.
  • +OMOP_CDMvx.x.x_Field_Level.csv: This file has a list of all tables and fields in the CDM version and any checks to be performed at this level as well as the failure thresholds associated. The majority of the check types run by the DQD are field level checks. If you would like to change the failure thresholds for any of these checks copy this file to a location the R instance can access. An example of this file is seen in figure 1 below.

Figure 1: Field Level Control File Example

  • -OMOP_CDMvx.x.x_Concept_Level.csv: This file has a list of all concepts and any checks to be performed on that concept. For example, there are checks that evaluate biologically plausible ranges for measurement values, like plausibleValueLow. If you would like to change the failure thresholds for any of these checks copy this file to a location the R instance can access.
  • +OMOP_CDMvx.x.x_Concept_Level.csv: This file has a list of all concepts and any checks to be performed on that concept. For example, there are checks that evaluate biologically plausible ranges for measurement values, like plausibleValueLow. If you would like to change the failure thresholds for any of these checks copy this file to a location the R instance can access.
-
-

-Step 2: Turn On/Off Checks and Change Thresholds

-

Using the field level file as an example, when you open it there will be two columns listing the tables and fields in the OMOP CDM, as seen in figure 1. Moving horizontally through the file there will be a column named for each of the check types available to run at the field level. At the intersection of each check type and CDM field will be a cell with either a ‘Yes’ or ‘No’ value. A ‘Yes’ indicates that the check type will be run for that specific table and field. For example in figure 1 there is a ‘Yes’ in the isRequired column for the field person_id in the PERSON table. This means that the isRequired check will be run, substituting person_id for cdmFieldName and PERSON for cdmTableName.

+
+

Step 2: Turn On/Off Checks and Change Thresholds +

+

Using the field level file as an example, when you open it there will be two columns listing the tables and fields in the OMOP CDM, as seen in figure 1. Moving horizontally through the file there will be a column named for each of the check types available to run at the field level. At the intersection of each check type and CDM field will be a cell with either a ‘Yes’ or ‘No’ value. A ‘Yes’ indicates that the check type will be run for that specific table and field. For example in figure 1 there is a ‘Yes’ in the isRequired column for the field person_id in the PERSON table. This means that the isRequired check will be run, substituting person_id for cdmFieldName and PERSON for cdmTableName.

So instead of the generic check type: The number and percent of records with a NULL value in the cdmFieldName of the cdmTableName that is considered not nullable

The ‘Yes’ in cell C2 in figure 1 will resolve that check type to an individual data quality check: The number and percent of records with a NULL value in the person_id of the PERSON table that is considered not nullable

Using this method it is possible to turn checks on or off by changing the ‘Yes’/‘No’ values in the control files. This will affect individual checks only. If you would like to filter checks based on check level (TABLE, FIELD, CONCEPT), check type (turn off all fkClass checks, for example), or CDM table (turn off all checks for the COST table), this can be done at the execution step and does not need to be specified in the control file. The vignette Advanced DQD Execution Options details how to do this.

For each check type column in the control file there will be one or more additional columns based on the inputs the check type needs to function. For instance the isForeignKey check has the fields fkTableName and fkFieldName so that the check knows where to find the primary key associated with the foreign key. Each check type will also have a column named using the convention checktypeThreshold. This is the column that lists the threshold against which the check will be evaluated to determine a pass or fail. Similarly to how the ‘Yes’/‘No’ indicators work, the intersection of each CDM field and check type threshold field will hold a value that will be compared to the outcome of the check to determine if the check passes or fails. In figure 1 for the check that is turned on in cell C2 the threshold is listed in cell D2. In this case the value is 0 indicating that if any records in the database violate the rule then this check will fail.

To change the threshold for a check, input a value between 0 and 100. The threshold value is based on the percent of records that violate a check and indicates the percent of violating records you are willing to tolerate. A 0 thresholds means that any violating records will cause the check to fail and a 100 means that all records evaluated could violate the check and the check will still pass. After changing any thresholds in the control files, save the files in a location that the R instance can access.

-
-

-Step 2a: Documenting Metadata on Updated Thresholds

+
+

Step 2a: Documenting Metadata on Updated Thresholds +

In addition to thresholds, each check type will also have a column named using the convention checktypeNotes. These columns allow entry of any information about why a particular check threshold was changed for a certain database, or perhaps record a link to an issue tracking system to denote that a failure has been identified and a fix is in the works. If any notes are recorded these will be exposed in the shiny application.

-
-

-Step 3: Run the DQD Using the Updated Thresholds

-

Follow the instructions on the Getting Started page to set the parameters to run the Data Quality Dashboard. When running the execute function, point the package to the updated threshold files as shown in the example below. To do this, The options tableCheckThresholdLoc, fieldCheckThresholdLoc, conceptCheckThresholdLoc should contain the fully qualified location of the files. If you would like to revert to the default thresholds these options can be removed from the execute function call or be set to “default”.

+
+

Step 3: Run the DQD Using the Updated Thresholds +

+

Follow the instructions on the Getting Started page to set the parameters to run the Data Quality Dashboard. When running the execute function, point the package to the updated threshold files as shown in the example below. To do this, The options tableCheckThresholdLoc, fieldCheckThresholdLoc, conceptCheckThresholdLoc should contain the fully qualified location of the files. If you would like to revert to the default thresholds these options can be removed from the execute function call or be set to “default”.

DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, 
                                       cdmDatabaseSchema = cdmDatabaseSchema, 
                                       resultsDatabaseSchema = resultsDatabaseSchema,
@@ -183,11 +185,13 @@ 

-

Site built with pkgdown 1.6.1.

+

+

Site built with pkgdown 2.0.2.

@@ -196,5 +200,7 @@

+ + diff --git a/docs/articles/index.html b/docs/articles/index.html index 99d28934..3b1b0eb7 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -1,66 +1,12 @@ - - - - - - - -Articles • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Articles • DataQualityDashboard - - + + - - -
-
- -
- - -
- +
- - + + diff --git a/docs/authors.html b/docs/authors.html index e645b932..899e5307 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -1,66 +1,12 @@ - - - - - - - -Citation and Authors • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Authors and Citation • DataQualityDashboard - - + + - - -
-
- -
- -
+
-
-
- +
- - + + diff --git a/docs/index.html b/docs/index.html index 74926fe9..1e3b9fbe 100644 --- a/docs/index.html +++ b/docs/index.html @@ -19,6 +19,8 @@ + +
-
- +
+

The goal of the Data Quality Dashboard (DQD) project is to design and develop an open-source tool to expose and evaluate observational data quality.

-
-

-Introduction

-

This package will run a series of data quality checks against an OMOP CDM instance (currently supports v5.3.1 and v5.2.2). It systematically runs the checks, evaluates the checks against some pre-specified threshold, and then communicates what was done in a transparent and easily understandable way.

+
+

Introduction +

+

This package will run a series of data quality checks against an OMOP CDM instance (currently supports v5.4, v5.3.1 and v5.2.2). It systematically runs the checks, evaluates the checks against some pre-specified threshold, and then communicates what was done in a transparent and easily understandable way.

-
-

-Overview

-

The quality checks were organized according to the Kahn Framework1 which uses a system of categories and contexts that represent strategies for assessing data quality. For an introduction to the kahn framework please click here.

+
+

Overview +

+

The quality checks were organized according to the Kahn Framework1 which uses a system of categories and contexts that represent strategies for assessing data quality. For an introduction to the kahn framework please click here.

Using this framework, the Data Quality Dashboard takes a systematic-based approach to running data quality checks. Instead of writing thousands of individual checks, we use “data quality check types”. These “check types” are more general, parameterized data quality checks into which OMOP tables, fields, and concepts can be substituted to represent a singular data quality idea. For example, one check type might be written as

The number and percent of records with a value in the cdmFieldName field of the cdmTableName table less than plausibleValueLow.

This would be considered an atemporal plausibility verification check because we are looking for implausibly low values in some field based on internal knowledge. We can use this check type to substitute in values for cdmFieldName, cdmTableName, and plausibleValueLow to create a unique data quality check. If we apply it to PERSON.YEAR_OF_BIRTH here is how that might look:

The number and percent of records with a value in the year_of_birth field of the PERSON table less than 1850.

And, since it is parameterized, we can similarly apply it to DRUG_EXPOSURE.days_supply:

The number and percent of records with a value in the days_supply field of the DRUG_EXPOSURE table less than 0.

-

Version 1 of the tool includes 20 different check types organized into Kahn contexts and categories. Additionally, each data quality check type is considered either a table check, field check, or concept-level check. Table-level checks are those evaluating the table at a high-level without reference to individual fields, or those that span multiple event tables. These include checks making sure required tables are present or that at least some of the people in the PERSON table have records in the event tables. Field-level checks are those related to specific fields in a table. The majority of the check types in version 1 are field-level checks. These include checks evaluating primary key relationship and those investigating if the concepts in a field conform to the specified domain. Concept-level checks are related to individual concepts. These include checks looking for gender-specific concepts in persons of the wrong gender and plausible values for measurement-unit pairs. For a detailed description and definition of each check type please click here.

+

Version 1 of the tool includes 20 different check types organized into Kahn contexts and categories. Additionally, each data quality check type is considered either a table check, field check, or concept-level check. Table-level checks are those evaluating the table at a high-level without reference to individual fields, or those that span multiple event tables. These include checks making sure required tables are present or that at least some of the people in the PERSON table have records in the event tables. Field-level checks are those related to specific fields in a table. The majority of the check types in version 1 are field-level checks. These include checks evaluating primary key relationship and those investigating if the concepts in a field conform to the specified domain. Concept-level checks are related to individual concepts. These include checks looking for gender-specific concepts in persons of the wrong gender and plausible values for measurement-unit pairs. For a detailed description and definition of each check type please click here.

After systematically applying the 20 check types to an OMOP CDM version approximately 3,351 individual data quality checks are resolved, run against the database, and evaluated based on a pre-specified threshold. The R package then creates a json object that is read into an RShiny application to view the results.

-

+

-
-

-Features

+
+

Features +

  • Utilizes configurable data check thresholds
  • Analyzes data in the OMOP Common Data Model format for all data checks
  • Produces a set of data check results with supplemental investigation assets.
-
-

-Technology

+
+

Data Requirements +

+

Prior to execution the DataQualityDashboard package requires that the CDM_SOURCE table is properly populated. The following table is a guide to the expected contents of the CDM_SOURCE table.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
cdmFieldNameuserGuidanceetlConventions
cdm_source_nameThe name of the CDM instance.Descriptive name for the source data.
cdm_source_abbreviationThe abbreviation of the CDM instance.The abbreviation should consistent for different release from the same source.
cdm_holderThe holder of the CDM instance.The institution that controls access to the data.  If possible include contact information for who to contact to request access to the data.
source_descriptionThe description of the CDM instance.Add notes, caveats, special characteristics about the source data that would not be assumed from the general descriptive name.  This description intended to help analysists determine if the data is suitable for the problem they are studying.
source_documentation_referenceReference to where one can find documentation about the source data.Can include URL’s, file name, source data experts contact information (if they agree to it)
cdm_etl_referenceReference to where one can find documentation about the source to ETL into OMOP CDM.Assuming there is a document or files (such as Rabbit in the Hat) describing the ETL.  May be the location of the ETL source and documentation repository.
source_release_dateThe release date of the source data.When the source data was made available for ETL’ing.  For sites doing incremental updates, the date the last increment made available.  This implies that for sites doing incremental updates the CDM Source table should be updated to reflect that changes were made to the CDM.
cdm_release_dateThe release date of the CDM instance.When the source data was made available for general use.  For sites doing incremental updates, this implies that the CDM Source table should be updated to reflect that changes were made to the CDM.
cdm_versionIdentifies the CDM versionEnter the numeric portion of the version, e.g. 5.4
cdm_version_concept_idThe Concept Id representing the version of the CDM.SELECT concept_id WHERE domain = Metadata and vocabulary_id = CDM and concept_code like %[numeric portion of the version]%
vocabulary_versionThe vocabulary version used in the ETLObtained by SELECT vocabulary_version FROM vocabulary WHERE vocabulary_id = ‘None’
+
+
+

Technology +

DataQualityDashboard is an R package

-
-

-System Requirements

-

Requires R (version 3.2.2 or higher). Requires DatabaseConnector and SqlRender.

+
+

System Requirements +

+

Requires R (version 3.2.2 or higher). Requires DatabaseConnector and SqlRender.

-
-

-Support

+
+

Support +

-
-

-License

+
+

License +

DataQualityDashboard is licensed under Apache License 2.0

-
-

-Development status

-

V1.0 ready for use.

+
+

Development status +

+

V1.4 ready for use.

-
-

-Acknowledgements

+
+

Acknowledgements +

This project is supported in part through the National Science Foundation grant IIS 1251151.

1 Kahn, M.G., et al., A Harmonized Data Quality Assessment Terminology and Framework for the Secondary Use of Electronic Health Record Data. EGEMS (Wash DC), 2016. 4(1): p. 1244. ↩︎

@@ -162,30 +238,32 @@

-

Site built with pkgdown 1.6.1.

+

+

Site built with pkgdown 2.0.2.

@@ -221,5 +302,7 @@

Dev status

+ + diff --git a/docs/pkgdown.css b/docs/pkgdown.css index 1273238d..80ea5b83 100644 --- a/docs/pkgdown.css +++ b/docs/pkgdown.css @@ -56,8 +56,10 @@ img.icon { float: right; } -img { +/* Ensure in-page images don't run outside their container */ +.contents img { max-width: 100%; + height: auto; } /* Fix bug in bootstrap (only seen in firefox) */ @@ -78,11 +80,10 @@ dd { /* Section anchors ---------------------------------*/ a.anchor { - margin-left: -30px; - display:inline-block; - width: 30px; - height: 30px; - visibility: hidden; + display: none; + margin-left: 5px; + width: 20px; + height: 20px; background-image: url(./link.svg); background-repeat: no-repeat; @@ -90,17 +91,15 @@ a.anchor { background-position: center center; } -.hasAnchor:hover a.anchor { - visibility: visible; -} - -@media (max-width: 767px) { - .hasAnchor:hover a.anchor { - visibility: hidden; - } +h1:hover .anchor, +h2:hover .anchor, +h3:hover .anchor, +h4:hover .anchor, +h5:hover .anchor, +h6:hover .anchor { + display: inline-block; } - /* Fixes for fixed navbar --------------------------*/ .contents h1, .contents h2, .contents h3, .contents h4 { @@ -264,31 +263,26 @@ table { /* Syntax highlighting ---------------------------------------------------- */ -pre { - word-wrap: normal; - word-break: normal; - border: 1px solid #eee; -} - -pre, code { +pre, code, pre code { background-color: #f8f8f8; color: #333; } +pre, pre code { + white-space: pre-wrap; + word-break: break-all; + overflow-wrap: break-word; +} -pre code { - overflow: auto; - word-wrap: normal; - white-space: pre; +pre { + border: 1px solid #eee; } -pre .img { +pre .img, pre .r-plt { margin: 5px 0; } -pre .img img { +pre .img img, pre .r-plt img { background-color: #fff; - display: block; - height: auto; } code a, pre a { @@ -305,9 +299,8 @@ a.sourceLine:hover { .kw {color: #264D66;} /* keyword */ .co {color: #888888;} /* comment */ -.message { color: black; font-weight: bolder;} -.error { color: orange; font-weight: bolder;} -.warning { color: #6A0366; font-weight: bolder;} +.error {font-weight: bolder;} +.warning {font-weight: bolder;} /* Clipboard --------------------------*/ @@ -365,3 +358,27 @@ mark { content: ""; } } + +/* Section anchors --------------------------------- + Added in pandoc 2.11: https://github.com/jgm/pandoc-templates/commit/9904bf71 +*/ + +div.csl-bib-body { } +div.csl-entry { + clear: both; +} +.hanging-indent div.csl-entry { + margin-left:2em; + text-indent:-2em; +} +div.csl-left-margin { + min-width:2em; + float:left; +} +div.csl-right-inline { + margin-left:2em; + padding-left:1em; +} +div.csl-indent { + margin-left: 2em; +} diff --git a/docs/pkgdown.js b/docs/pkgdown.js index 7e7048fa..6f0eee40 100644 --- a/docs/pkgdown.js +++ b/docs/pkgdown.js @@ -80,7 +80,7 @@ $(document).ready(function() { var copyButton = ""; - $(".examples, div.sourceCode").addClass("hasCopyButton"); + $("div.sourceCode").addClass("hasCopyButton"); // Insert copy buttons: $(copyButton).prependTo(".hasCopyButton"); @@ -91,7 +91,7 @@ // Initialize clipboard: var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { text: function(trigger) { - return trigger.parentNode.textContent; + return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); } }); diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index d15168ef..a5e0307b 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -1,10 +1,10 @@ pandoc: 2.11.3.2 -pkgdown: 1.6.1 +pkgdown: 2.0.2 pkgdown_sha: ~ articles: CheckTypeDescriptions: CheckTypeDescriptions.html DataQualityDashboard: DataQualityDashboard.html DqdForCohorts: DqdForCohorts.html Thresholds: Thresholds.html -last_built: 2022-03-03T17:52Z +last_built: 2022-03-31T19:31Z diff --git a/docs/reference/executeDqChecks.html b/docs/reference/executeDqChecks.html index fcc6b0ad..efe4e3d0 100644 --- a/docs/reference/executeDqChecks.html +++ b/docs/reference/executeDqChecks.html @@ -1,67 +1,12 @@ - - - - - - - -Execute DQ checks — executeDqChecks • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Execute DQ checks — executeDqChecks • DataQualityDashboard - + + - - - -
-
- -
- -
+
@@ -138,146 +74,104 @@

Execute DQ checks

Execute DQ checks

-
executeDqChecks(
-  connectionDetails,
-  cdmDatabaseSchema,
-  resultsDatabaseSchema,
-  vocabDatabaseSchema = cdmDatabaseSchema,
-  cdmSourceName,
-  numThreads = 1,
-  sqlOnly = FALSE,
-  outputFolder = "output",
-  outputFile = "",
-  verboseMode = FALSE,
-  writeToTable = TRUE,
-  writeTableName = "dqdashboard_results",
-  checkLevels = c("TABLE", "FIELD", "CONCEPT"),
-  checkNames = c(),
-  cohortDefinitionId = c(),
-  cohortDatabaseSchema = resultsDatabaseSchema,
-  tablesToExclude = c(),
-  cdmVersion = "5.3.1",
-  tableCheckThresholdLoc = "default",
-  fieldCheckThresholdLoc = "default",
-  conceptCheckThresholdLoc = "default"
-)
- -

Arguments

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
connectionDetails

A connectionDetails object for connecting to the CDM database

cdmDatabaseSchema

The fully qualified database name of the CDM schema

resultsDatabaseSchema

The fully qualified database name of the results schema

vocabDatabaseSchema

The fully qualified database name of the vocabulary schema (default is to set it as the cdmDatabaseSchema)

cdmSourceName

The name of the CDM data source

numThreads

The number of concurrent threads to use to execute the queries

sqlOnly

Should the SQLs be executed (FALSE) or just returned (TRUE)?

outputFolder

The folder to output logs and SQL files to

outputFile

(OPTIONAL) File to write results JSON object

verboseMode

Boolean to determine if the console will show all execution steps. Default = FALSE

writeToTable

Boolean to indicate if the check results will be written to the dqdashboard_results table -in the resultsDatabaseSchema. Default is TRUE.

checkLevels

Choose which DQ check levels to execute. Default is all 3 (TABLE, FIELD, CONCEPT)

checkNames

(OPTIONAL) Choose which check names to execute. Names can be found in inst/csv/OMOP_CDM_v[cdmVersion]_Check_Desciptions.csv

cohortDefinitionId

The cohort definition id for the cohort you wish to run the DQD on. The package assumes a standard OHDSI cohort table called 'Cohort' -with the fields cohort_definition_id and subject_id.

cohortDatabaseSchema

The schema where the cohort table is located.

tablesToExclude

(OPTIONAL) Choose which CDM tables to exclude from the execution.

cdmVersion

The CDM version to target for the data source. By default, 5.3.1 is used.

tableCheckThresholdLoc

The location of the threshold file for evaluating the table checks. If not specified the default thresholds will be applied.

fieldCheckThresholdLoc

The location of the threshold file for evaluating the field checks. If not specified the default thresholds will be applied.

conceptCheckThresholdLoc

The location of the threshold file for evaluating the concept checks. If not specified the default thresholds will be applied.

- -

Value

+
+
executeDqChecks(
+  connectionDetails,
+  cdmDatabaseSchema,
+  resultsDatabaseSchema,
+  vocabDatabaseSchema = cdmDatabaseSchema,
+  cdmSourceName,
+  numThreads = 1,
+  sqlOnly = FALSE,
+  outputFolder = "output",
+  outputFile = "",
+  verboseMode = FALSE,
+  writeToTable = TRUE,
+  writeTableName = "dqdashboard_results",
+  checkLevels = c("TABLE", "FIELD", "CONCEPT"),
+  checkNames = c(),
+  cohortDefinitionId = c(),
+  cohortDatabaseSchema = resultsDatabaseSchema,
+  tablesToExclude = c("CONCEPT", "VOCABULARY", "CONCEPT_ANCESTOR",
+    "CONCEPT_RELATIONSHIP", "CONCEPT_CLASS", "CONCEPT_SYNONYM", "RELATIONSHIP", "DOMAIN"),
+  cdmVersion = "5.3.1",
+  tableCheckThresholdLoc = "default",
+  fieldCheckThresholdLoc = "default",
+  conceptCheckThresholdLoc = "default"
+)
+
+
+

Arguments

+
connectionDetails
+

A connectionDetails object for connecting to the CDM database

+
cdmDatabaseSchema
+

The fully qualified database name of the CDM schema

+
resultsDatabaseSchema
+

The fully qualified database name of the results schema

+
vocabDatabaseSchema
+

The fully qualified database name of the vocabulary schema (default is to set it as the cdmDatabaseSchema)

+
cdmSourceName
+

The name of the CDM data source

+
numThreads
+

The number of concurrent threads to use to execute the queries

+
sqlOnly
+

Should the SQLs be executed (FALSE) or just returned (TRUE)?

+
outputFolder
+

The folder to output logs and SQL files to

+
outputFile
+

(OPTIONAL) File to write results JSON object

+
verboseMode
+

Boolean to determine if the console will show all execution steps. Default = FALSE

+
writeToTable
+

Boolean to indicate if the check results will be written to the dqdashboard_results table +in the resultsDatabaseSchema. Default is TRUE.

+
checkLevels
+

Choose which DQ check levels to execute. Default is all 3 (TABLE, FIELD, CONCEPT)

+
checkNames
+

(OPTIONAL) Choose which check names to execute. Names can be found in inst/csv/OMOP_CDM_v[cdmVersion]_Check_Desciptions.csv

+
cohortDefinitionId
+

The cohort definition id for the cohort you wish to run the DQD on. The package assumes a standard OHDSI cohort table called 'Cohort' +with the fields cohort_definition_id and subject_id.

+
cohortDatabaseSchema
+

The schema where the cohort table is located.

+
tablesToExclude
+

(OPTIONAL) Choose which CDM tables to exclude from the execution.

+
cdmVersion
+

The CDM version to target for the data source. By default, 5.3.1 is used.

+
tableCheckThresholdLoc
+

The location of the threshold file for evaluating the table checks. If not specified the default thresholds will be applied.

+
fieldCheckThresholdLoc
+

The location of the threshold file for evaluating the field checks. If not specified the default thresholds will be applied.

+
conceptCheckThresholdLoc
+

The location of the threshold file for evaluating the concept checks. If not specified the default thresholds will be applied.

+
+
+

Value

If sqlOnly = FALSE, a list object of results

+
+
-
- +
- - + + diff --git a/docs/reference/index.html b/docs/reference/index.html index e87a186d..728f26ca 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -1,66 +1,12 @@ - - - - - - - -Function reference • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Function reference • DataQualityDashboard + + - - - - -
-
- -
- -
+
- - - - - - - - - - -
-

Execution

-

Function for running data quality checks

+ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+

Execution

+

Function for running data quality checks

+

executeDqChecks()

Execute DQ checks

+

writeJsonResultsToTable()

Write JSON Results to SQL Table

-

View Dashboard

-

Function for viewing the data quality dashboard

+
+

View Dashboard

+

Function for viewing the data quality dashboard

+

viewDqDashboard()

View DQ Dashboard

- +
+
-
- +
- - + + diff --git a/docs/reference/viewDqDashboard.html b/docs/reference/viewDqDashboard.html index 3801fd17..63bd84d8 100644 --- a/docs/reference/viewDqDashboard.html +++ b/docs/reference/viewDqDashboard.html @@ -1,67 +1,12 @@ - - - - - - - -View DQ Dashboard — viewDqDashboard • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -View DQ Dashboard — viewDqDashboard • DataQualityDashboard + + - - - - -
-
- -
- -
+
@@ -138,47 +74,39 @@

View DQ Dashboard

View DQ Dashboard

-
viewDqDashboard(jsonPath, launch.browser = NULL, display.mode = NULL, ...)
- -

Arguments

- - - - - - - - - - -
jsonPath

The path to the JSON file produced by executeDqChecks

...

Extra parameters for shiny::runApp() like "port" or "host"

+
+
viewDqDashboard(jsonPath, launch.browser = NULL, display.mode = NULL, ...)
+
+
+

Arguments

+
jsonPath
+

The path to the JSON file produced by executeDqChecks

+
...
+

Extra parameters for shiny::runApp() like "port" or "host"

+
+
-
- +
- - + + diff --git a/docs/reference/writeJsonResultsToTable.html b/docs/reference/writeJsonResultsToTable.html index f64f2282..a2d31a1b 100644 --- a/docs/reference/writeJsonResultsToTable.html +++ b/docs/reference/writeJsonResultsToTable.html @@ -1,67 +1,12 @@ - - - - - - - -Write JSON Results to SQL Table — writeJsonResultsToTable • DataQualityDashboard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Write JSON Results to SQL Table — writeJsonResultsToTable • DataQualityDashboard - - - - + + -
-
- -
- -
+
@@ -138,58 +74,48 @@

Write JSON Results to SQL Table

Write JSON Results to SQL Table

-
writeJsonResultsToTable(
-  connectionDetails,
-  resultsDatabaseSchema,
-  jsonFilePath,
-  writeTableName = "dqdashboard_results",
-  cohortDefinitionId = c(),
-  useMppBulkLoad = FALSE
-)
- -

Arguments

- - - - - - - - - - - - - - -
connectionDetails

A connectionDetails object for connecting to the CDM database

resultsDatabaseSchema

The fully qualified database name of the results schema

jsonFilePath

Path to the JSON results file generated using the execute function

+
+
writeJsonResultsToTable(
+  connectionDetails,
+  resultsDatabaseSchema,
+  jsonFilePath,
+  writeTableName = "dqdashboard_results",
+  cohortDefinitionId = c(),
+  useMppBulkLoad = FALSE
+)
+
+
+

Arguments

+
connectionDetails
+

A connectionDetails object for connecting to the CDM database

+
resultsDatabaseSchema
+

The fully qualified database name of the results schema

+
jsonFilePath
+

Path to the JSON results file generated using the execute function

+
+
-
- +
- - + + diff --git a/docs/sitemap.xml b/docs/sitemap.xml new file mode 100644 index 00000000..65b0e0e9 --- /dev/null +++ b/docs/sitemap.xml @@ -0,0 +1,69 @@ + + + + /404.html + + + /LICENSE-text.html + + + /_site/404.html + + + /_site/LICENSE-text.html + + + /_site/authors.html + + + /_site/index.html + + + /_site/reference/executeDqChecks.html + + + /_site/reference/index.html + + + /_site/reference/viewDqDashboard.html + + + /_site/reference/writeJsonResultsToTable.html + + + /articles/CheckTypeDescriptions.html + + + /articles/DataQualityDashboard.html + + + /articles/DqdForCohorts.html + + + /articles/GettingStarted.html + + + /articles/Thresholds.html + + + /articles/index.html + + + /authors.html + + + /index.html + + + /reference/executeDqChecks.html + + + /reference/index.html + + + /reference/viewDqDashboard.html + + + /reference/writeJsonResultsToTable.html + + diff --git a/extras/codeToRun.R b/extras/codeToRun.R index 8d63e80b..c4cce2a2 100644 --- a/extras/codeToRun.R +++ b/extras/codeToRun.R @@ -2,26 +2,28 @@ # fill out the connection details ----------------------------------------------------------------------- -connectionDetails <- DatabaseConnector::createConnectionDetails(dbms = "", user = "", - password = "", server = "", - port = "", extraSettings = "") +connectionDetails <- DatabaseConnector::createConnectionDetails(dbms = 'postgresql', user = Sys.getenv('user'), + password = Sys.getenv('pw'), server = 'testnode.arachnenetwork.com/synthea', + port = '5441', pathToDriver='c:/jdbcDrivers') -cdmDatabaseSchema <- "yourCdmSchema" # the fully qualified database schema name of the CDM -resultsDatabaseSchema <- "yourResultsSchema" # the fully qualified database schema name of the results schema (that you can write to) -cdmSourceName <- "Your CDM Source" # a human readable name for your CDM source +cdmDatabaseSchema <- "CDM_531" # the fully qualified database schema name of the CDM +resultsDatabaseSchema <- "CDM_531" # the fully qualified database schema name of the results schema (that you can write to) +cdmSourceName <- "synthea" # a human readable name for your CDM source cdmVersion <- "5.4" # the CDM version you are targetting. Currently supporst 5.2.2, 5.3.1, and 5.4 +numThreads <- 4 + # specify if you want to execute the queries or inspect them ------------------------------------------ sqlOnly <- FALSE # set to TRUE if you just want to get the SQL scripts and not actually run the queries # where should the logs go? ------------------------------------------------------------------------- -outputFolder <- "output" +outputFolder <- "C:/Users/LuisAlaniz/Documents/synthea" # logging type ------------------------------------------------------------------------------------- -verboseMode <- FALSE # set to TRUE if you want to see activity written to the console +verboseMode <- TRUE # set to TRUE if you want to see activity written to the console # write results to table? ----------------------------------------------------------------------- -writeToTable <- FALSE # set to FALSE if you want to skip writing to results table +writeToTable <- TRUE # set to FALSE if you want to skip writing to results table # if writing to table and using Redshift, bulk loading can be initialized ------------------------------- @@ -46,24 +48,26 @@ tablesToExclude <- c() # run the job -------------------------------------------------------------------------------------- DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, - cdmDatabaseSchema = cdmDatabaseSchema, - resultsDatabaseSchema = resultsDatabaseSchema, - cdmSourceName = cdmSourceName, - numThreads = numThreads, - sqlOnly = sqlOnly, - outputFolder = outputFolder, - verboseMode = verboseMode, - writeToTable = writeToTable, - checkLevels = checkLevels, - tablesToExclude = tablesToExclude, - checkNames = checkNames) - -# inspect logs ---------------------------------------------------------------------------- + cdmDatabaseSchema = cdmDatabaseSchema, + resultsDatabaseSchema = resultsDatabaseSchema, + cdmSourceName = cdmSourceName, + numThreads = numThreads, + sqlOnly = sqlOnly, + outputFolder = outputFolder, + outputFile = paste0("results_", cdmSourceName, ".json"), + verboseMode = verboseMode, + writeToTable = writeToTable, + checkLevels = checkLevels, + tablesToExclude = tablesToExclude, + checkNames = checkNames) + + ParallelLogger::launchLogViewer(logFileName = file.path(outputFolder, sprintf("log_DqDashboard_%s.txt", cdmSourceName))) # (OPTIONAL) if you want to write the JSON file to the results table separately ----------------------------- -jsonFilePath <- "" # put the path to the outputted JSON file +jsonFilePath <- file.path(outputFolder, paste0("results_", cdmSourceName, ".json")) # put the path to the outputted JSON file + DataQualityDashboard::writeJsonResultsToTable(connectionDetails = connectionDetails, resultsDatabaseSchema = resultsDatabaseSchema, jsonFilePath = jsonFilePath) diff --git a/extras/indexMultipleJsons.R b/extras/indexMultipleJsons.R new file mode 100644 index 00000000..ecc8f4f9 --- /dev/null +++ b/extras/indexMultipleJsons.R @@ -0,0 +1,132 @@ +# @file studyathonEngineering +# +# Copyright 2020 Observational Health Data Sciences and Informatics +# +# This file is part of DataQualityDashboard +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Potential verbiage for paper introduction: +# The 'DataQualityDashboard' package provides a framework for data quality assessment for data in the OMOP CDM format. +# For the purposes of this study a subset of data quality checks were determined to be critical for data quality assessment. +# The results of those assessments are summarized and the complete results available as an appendix. + +#' Index +#' +#' @param inputFolder Location of all DataQualityDashboard results +#' @param outputFolder Location to store summary and result files +#' +#' @export + +library("dplyr") + +subsetDataQualityChecks <- function(inputFolder, outputFolder) { + overallResults <- data.frame() + overallChecks <- data.frame() + + checkNames <- c("cdmField", "isRequired", "cdmDatatype", "isPrimaryKey", "isForeignKey", "fkDomain", "fkClass", "isStandardValidConcept") + tables <- c("PERSON", "OBSERVATION_PERIOD", "VISIT_OCCURRENCE", "CONDITION_OCCURRENCE", "DRUG_EXPOSURE", "PROCEDURE_OCCURRENCE", "MEASUREMENT", "OBSERVATION", "DRUG_ERA", "CONDITION_ERA") + excludedFieldNames <- c("device_exposure_id", "visit_detail_id", "note_id", "specimen_id", "location_id", "care_site_id", "provider_id", "payer_plan_period_id", "dose_era_id", "drug_source_concept_id", "observation_source_concept_id", "condition_source_concept_id", "procedure_source_concept_id", "modifier_source_value", "measurement_time", "route_concept_id") + + resultFiles <- list.files(path = inputFolder, full.names = T, pattern = "json") + for (f in resultFiles) { + writeLines(paste("processing", f)) + fileContents <- readLines(f, warn = FALSE) + fileContentsConverted <- iconv(fileContents, 'utf-8', 'utf-8', sub = '') + resultJson <- rjson::fromJSON(fileContentsConverted,simplify=T) + + # convert results to dataframe + checkResults <-resultJson$CheckResults + checkResultsDf <- lapply(checkResults, function(cr) { + cr[sapply(cr, is.null)] <- NA + as.data.frame(cr) + }) + checkResultsDf <- do.call(plyr::rbind.fill, checkResultsDf) + + # subset results to specified checkNames and tables + checkResultsSubset <- checkResultsDf %>% filter(CDM_TABLE_NAME %in% tables & CHECK_NAME %in% checkNames & !(CDM_FIELD_NAME %in% excludedFieldNames)) + checkResultsSubsetJson <- rjson::toJSON(unname(split(checkResultsSubset, 1:nrow(checkResultsSubset)))) + resultJson$CheckResults <- unname(split(checkResultsSubset, 1:nrow(checkResultsSubset))) + + checkResultsSubsetFailed <- checkResultsSubset %>% filter(FAILED == 1) + checkResultsSubsetFailedJson <- rjson::toJSON(unname(split(checkResultsSubsetFailed, 1:nrow(checkResultsSubsetFailed)))) + write(checkResultsSubsetFailedJson,file.path(outputFolder,paste0(basename(f),".failed.json"))) + + countTotal <- nrow(checkResultsSubset) + countThresholdFailed <- nrow(checkResultsSubset[checkResultsSubset$FAILED == 1 & + is.na(checkResultsSubset$ERROR),]) + countErrorFailed <- nrow(checkResultsSubset[!is.na(checkResultsSubset$ERROR),]) + countOverallFailed <- nrow(checkResultsSubset[checkResultsSubset$FAILED == 1,]) + + countPassed <- countTotal - countOverallFailed + + countTotalPlausibility <- nrow(checkResultsSubset[checkResultsSubset$CATEGORY=='Plausibility',]) + countTotalConformance <- nrow(checkResultsSubset[checkResultsSubset$CATEGORY=='Conformance',]) + countTotalCompleteness <- nrow(checkResultsSubset[checkResultsSubset$CATEGORY=='Completeness',]) + + countFailedPlausibility <- nrow(checkResultsSubset[checkResultsSubset$CATEGORY=='Plausibility' & + checkResultsSubset$FAILED == 1,]) + + countFailedConformance <- nrow(checkResultsSubset[checkResultsSubset$CATEGORY=='Conformance' & + checkResultsSubset$FAILED == 1,]) + + countFailedCompleteness <- nrow(checkResultsSubset[checkResultsSubset$CATEGORY=='Completeness' & + checkResultsSubset$FAILED == 1,]) + + countPassedPlausibility <- countTotalPlausibility - countFailedPlausibility + countPassedConformance <- countTotalConformance - countFailedConformance + countPassedCompleteness <- countTotalCompleteness - countFailedCompleteness + + cdmSourceChecks <- checkResultsSubset + cdmSourceChecks$CDM_SOURCE_NAME <- resultJson$Metadata[[1]]$CDM_SOURCE_NAME + overallChecks <- dplyr::bind_rows(overallChecks, cdmSourceChecks) + + overview <- list( + cdmSourceName = resultJson$Metadata[[1]]$CDM_SOURCE_NAME, + countTotal = countTotal, + countPassed = countPassed, + countErrorFailed = countErrorFailed, + countThresholdFailed = countThresholdFailed, + countOverallFailed = countOverallFailed, + percentPassed = round(countPassed / countTotal * 100), + percentFailed = round(countOverallFailed / countTotal * 100), + countTotalPlausibility = countTotalPlausibility, + countTotalConformance = countTotalConformance, + countTotalCompleteness = countTotalCompleteness, + countFailedPlausibility = countFailedPlausibility, + countFailedConformance = countFailedConformance, + countFailedCompleteness = countFailedCompleteness, + countPassedPlausibility = countPassedPlausibility, + countPassedConformance = countPassedConformance, + countPassedCompleteness = countPassedCompleteness + ) + + resultJson$Overview <- overview + write(rjson::toJSON(resultJson),file.path(outputFolder,paste0(basename(f),".subset.json"))) + + overviewDf <- as.data.frame(overview) + overallResults <- rbind(overallResults, overviewDf) + } + return(list(networkResults = overallResults, networkChecks = overallChecks)) +} + +networkResults <- subsetDataQualityChecks("D:/Studies/Studyathon","D:/Studies/Studyathon/output") +View(networkResults) + +#DataQualityDashboard::viewDqDashboard(file.path(outputFolder, "results_AD_Momentum.json.subset.json")) +#View(test$networkChecks) +#View(test$networkResults) + +# applying a > 5% percentage of violating rows +networkSummary <-networkResults$networkChecks %>% filter(PCT_VIOLATED_ROWS > 0.05) %>% group_by(CHECK_DESCRIPTION) %>% summarise(failed=sum(FAILED)) +View(networkSummary) diff --git a/extras/updateThresholds.R b/extras/updateThresholds.R new file mode 100644 index 00000000..f411ec44 --- /dev/null +++ b/extras/updateThresholds.R @@ -0,0 +1,222 @@ +## Update thresholds and reevaluate external to the initial run + +## Read the json file +jsonFilePath <- "C:/Users/mblacke/Desktop/DQD/MDCD/results_IBM_MDCD_(v1327).json" + +# jsonFilePath <- "C:/Users/mblacke/Desktop/DQD/CCAE/results_ccae_v992.json" + +## Read in jsonData from the path +jsonData <- jsonlite::read_json(jsonFilePath) +checkResults <- lapply(jsonData$CheckResults, function(cr) { + cr[sapply(cr, is.null)] <- NA + as.data.frame(cr) +}) + +## Take the checkResults and make into a dataFrame +df <- do.call(plyr::rbind.fill, checkResults) + +## Read in the thresholds + +tableChecks <- read.csv("C:/Users/mblacke/OneDrive - JNJ/DQD_Thresholds/MDCD/OMOP_CDMv5.3.1_Table_Level_MDCD.csv", + stringsAsFactors = FALSE, na.strings = c(" ","")) + +fieldChecks <- read.csv("C:/Users/mblacke/OneDrive - JNJ/DQD_Thresholds/MDCD/OMOP_CDMv5.3.1_Field_Level_MDCD.csv", + stringsAsFactors = FALSE, na.strings = c(" ","")) + +conceptChecks <- read.csv("C:/Users/mblacke/OneDrive - JNJ/DQD_Thresholds/MDCD/OMOP_CDMv5.3.1_Concept_Level_MDCD.csv", + stringsAsFactors = FALSE, na.strings = c(" ","")) + +# if (conceptCheckThresholdLoc == "default"){ +# conceptChecks <- read.csv(system.file("csv", sprintf("OMOP_CDMv%s_Concept_Level.csv", "5.3.1"), +# package = "DataQualityDashboard"), +# stringsAsFactors = FALSE, na.strings = c(" ",""))} else {conceptChecks <- read.csv(conceptCheckThresholdLoc, +# stringsAsFactors = FALSE, na.strings = c(" ",""))} + + +## Remove the thresholds, failures, and notes from existing results + +checks <- subset(df, select = -c(FAILED, THRESHOLD_VALUE)) #NOTES_VALUE column should be removed also if it exists + +## use the .evaluateThreshold function to add the new thresholds + +checkResults <- evaluateThresholds(checkResults = checks, + tableChecks = tableChecks, + fieldChecks = fieldChecks, + conceptChecks = conceptChecks) + +## Recalculate totals and regenerate JSON + +countTotal <- nrow(checkResults) +countThresholdFailed <- nrow(checkResults[checkResults$FAILED == 1 & + is.na(checkResults$ERROR),]) +countErrorFailed <- nrow(checkResults[!is.na(checkResults$ERROR),]) +countOverallFailed <- nrow(checkResults[checkResults$FAILED == 1,]) + +countPassed <- countTotal - countOverallFailed + +countTotalPlausibility <- nrow(checkResults[checkResults$CATEGORY=='Plausibility',]) +countTotalConformance <- nrow(checkResults[checkResults$CATEGORY=='Conformance',]) +countTotalCompleteness <- nrow(checkResults[checkResults$CATEGORY=='Completeness',]) + +countFailedPlausibility <- nrow(checkResults[checkResults$CATEGORY=='Plausibility' & + checkResults$FAILED == 1,]) + +countFailedConformance <- nrow(checkResults[checkResults$CATEGORY=='Conformance' & + checkResults$FAILED == 1,]) + +countFailedCompleteness <- nrow(checkResults[checkResults$CATEGORY=='Completeness' & + checkResults$FAILED == 1,]) + +countPassedPlausibility <- countTotalPlausibility - countFailedPlausibility +countPassedConformance <- countTotalConformance - countFailedConformance +countPassedCompleteness <- countTotalCompleteness - countFailedCompleteness + +overview <- list( + countTotal = countTotal, + countPassed = countPassed, + countErrorFailed = countErrorFailed, + countThresholdFailed = countThresholdFailed, + countOverallFailed = countOverallFailed, + percentPassed = round(countPassed / countTotal * 100), + percentFailed = round(countOverallFailed / countTotal * 100), + countTotalPlausibility = countTotalPlausibility, + countTotalConformance = countTotalConformance, + countTotalCompleteness = countTotalCompleteness, + countFailedPlausibility = countFailedPlausibility, + countFailedConformance = countFailedConformance, + countFailedCompleteness = countFailedCompleteness, + countPassedPlausibility = countPassedPlausibility, + countPassedConformance = countPassedConformance, + countPassedCompleteness = countPassedCompleteness +) + +result <- list(startTimestamp = jsonData$startTimestamp, + endTimestamp = jsonData$endTimestamp, + executionTime = jsonData$executionTime, + CheckResults = checkResults, + Metadata = jsonData$Metadata, + Overview = overview) + +resultJson <- jsonlite::toJSON(result) +write(resultJson, "C:/Users/mblacke/Desktop/DQD/MDCD/results_IBM_MDCD_(v1327)_thresholds.json") + +DataQualityDashboard::viewDqDashboard("C:/Users/mblacke/Desktop/DQD/MDCD/results_IBM_MDCD_(v1327)_thresholds.json") + + + + + + + + + +evaluateThresholds <- function(checkResults, + tableChecks, + fieldChecks, + conceptChecks) { + + checkResults$FAILED <- 0 + checkResults$THRESHOLD_VALUE <- NA + checkResults$NOTES_VALUE <- NA + + if("ERROR" %in% colnames(checkResults) == FALSE){ + checkResults$ERROR <- NA + } + + for (i in 1:nrow(checkResults)) { + thresholdField <- sprintf("%sThreshold", checkResults[i,]$CHECK_NAME) + notesField <- sprintf("%sNotes", checkResults[i,]$CHECK_NAME) + + # find if field exists ----------------------------------------------- + thresholdFieldExists <- eval(parse(text = + sprintf("'%s' %%in%% colnames(%sChecks)", + thresholdField, + tolower(checkResults[i,]$CHECK_LEVEL)))) + + if (!thresholdFieldExists) { + thresholdValue <- NA + notesValue <- NA + } else { + if (checkResults[i,]$CHECK_LEVEL == "TABLE") { + + thresholdFilter <- sprintf("tableChecks$%s[tableChecks$cdmTableName == '%s']", + thresholdField, checkResults[i,]$CDM_TABLE_NAME) + notesFilter <- sprintf("tableChecks$%s[tableChecks$cdmTableName == '%s']", + notesField, checkResults[i,]$CDM_TABLE_NAME) + + } else if (checkResults[i,]$CHECK_LEVEL == "FIELD") { + + thresholdFilter <- sprintf("fieldChecks$%s[fieldChecks$cdmTableName == '%s' & + fieldChecks$cdmFieldName == '%s']", + thresholdField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME) + notesFilter <- sprintf("fieldChecks$%s[fieldChecks$cdmTableName == '%s' & + fieldChecks$cdmFieldName == '%s']", + notesField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME) + + + } else if (checkResults[i,]$CHECK_LEVEL == "CONCEPT") { + + if (is.na(checkResults[i,]$UNIT_CONCEPT_ID)) { + + thresholdFilter <- sprintf("conceptChecks$%s[conceptChecks$cdmTableName == '%s' & + conceptChecks$cdmFieldName == '%s' & + conceptChecks$conceptId == %s]", + thresholdField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME, + checkResults[i,]$CONCEPT_ID) + notesFilter <- sprintf("conceptChecks$%s[conceptChecks$cdmTableName == '%s' & + conceptChecks$cdmFieldName == '%s' & + conceptChecks$conceptId == %s]", + notesField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME, + checkResults[i,]$CONCEPT_ID) + } else { + + thresholdFilter <- sprintf("conceptChecks$%s[conceptChecks$cdmTableName == '%s' & + conceptChecks$cdmFieldName == '%s' & + conceptChecks$conceptId == %s & + conceptChecks$unitConceptId == '%s']", + thresholdField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME, + checkResults[i,]$CONCEPT_ID, + checkResults[i,]$UNIT_CONCEPT_ID) + notesFilter <- sprintf("conceptChecks$%s[conceptChecks$cdmTableName == '%s' & + conceptChecks$cdmFieldName == '%s' & + conceptChecks$conceptId == %s & + conceptChecks$unitConceptId == '%s']", + notesField, + checkResults[i,]$CDM_TABLE_NAME, + checkResults[i,]$CDM_FIELD_NAME, + checkResults[i,]$CONCEPT_ID, + checkResults[i,]$UNIT_CONCEPT_ID) + } + } + + thresholdValue <- eval(parse(text = thresholdFilter)) + notesValue <- eval(parse(text = notesFilter)) + + checkResults[i,]$THRESHOLD_VALUE <- thresholdValue + checkResults[i,]$NOTES_VALUE <- notesValue + } + + if (!is.na(checkResults[i,]$ERROR)) { + checkResults[i,]$FAILED <- 1 + } else if (is.na(thresholdValue)) { + if (!is.na(checkResults[i,]$NUM_VIOLATED_ROWS) & checkResults[i,]$NUM_VIOLATED_ROWS > 0) { + checkResults[i,]$FAILED <- 1 + } + } else if (checkResults[i,]$PCT_VIOLATED_ROWS * 100 > thresholdValue) { + checkResults[i,]$FAILED <- 1 + } + } + + checkResults +} + \ No newline at end of file diff --git a/inst/ResultsV2/About.Rmd b/inst/ResultsV2/About.Rmd new file mode 100644 index 00000000..85ffa0d8 --- /dev/null +++ b/inst/ResultsV2/About.Rmd @@ -0,0 +1,81 @@ +--- +title: "ABOUT" + +output: + html_document: + theme: flatly +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +The Data Quality Dashboard applies a Harmonized Data Quality Assessment Terminology to data that has been standardized in the OMOP Common Data Model. + +```{r github_1, echo=FALSE} +knitr::include_graphics("GitHub-Mark-32px.png") +``` + +[Data Quality Dashboard](https://github.com/ohdsi/DataQualityDashboard) + +```{r github_2, echo=FALSE} +knitr::include_graphics("GitHub-Mark-32px.png") +``` + +[OMOP Common Data Model Repository](https://github.com/ohdsi/commondatamodel) + +**References** + +[Harmonized Data Quality Assessment Terminology and Framework for the Secondary Use of Electronic Health Record Data.](https://www.ncbi.nlm.nih.gov/pubmed/27713905) + +### New Flags. + +**DQ Check Status Flag** + +In the initial release of the DQD, all DQ checks were assigned a status of pass or fail resulting in skewed results under certain conditions. In order to provide results that more accurately reflect the quality of data contained in a CDM instance, the number of status flags were expanded to address scenarios where pass/fail is not appropriate.The new set of mutually exclusive status states are listed below in priority order. + +- Is Error -- if SQL error occurred during execution. + +- Non_applicable -- if DQ check is not applicable for reasons explained below. + +- Failed -- if (violated rows/denominator) < threshold) + +- Passed -- if (violated rows/denominator) > threshold) + +**Non_applicable flag.** + +The results of a DQ check may not be applicable to a given CDM instance depending on the implementation and content of the instance. For example, the DQ check for plausible values of HbA1c lab results would pass with no violations even if there were no results for that lab test in the database. It is not uncommon to have \> 1000 DQ checks that do not apply to a given CDM instance. The results from DQ checks that are not applicable skew to overall results.Listed below are the scenarios for which a DQ check result is flagged as non_applicable: + +1. If the cdmTable DQ check determines that a table does not exist in the database, then all DQ checks (except cdm_table) addressing that table are flagged as non_applicable. + +2. If a table exists but is empty, then all field level checks for that table are flagged as non_applicable, except for cdmField checks, which evaluates if the field is defined or not. A cdmField check is marked as not_applicable if the CDM table it refers to does not exist (tested by cdmTable). An empty table is detected when the measureValueCompleteness DQ check for any of the fields in the table returns a denominator count = 0 (NUM_DENOMINATOR_ROWS=0). + +3. If a field is not populated, then all field level checks except for measureValueCompleteness and isRequired are flagged as non_applicable. + + a. A field is not populated if the measureValueCompleteness DQ check finds denominator count \> 0 and number of violated rows = denominator count (NUM_DENOMINATOR_ROWS \> 0 AND NUM_DENOMINATOR_ROWS = NUM_VIOLATED_ROWS). + + b. The measureValueCompleteness check is marked as not applicable if: + + a. The CDM table it refers to does not exist or is empty. + + b. The CDM field it refers to does not exist. + + c. The isRequired check is marked as not applicable if: + + a. The CDM table it refers to does not exist or is empty. + + b. The CDM field it refers to does not exist. + +4. Flagging a Concept_ID level DQ check as non_applicable depends on whether the DQ check logic includes a UNIT_CONCEPT_ID. There are two scenarios for DQ checks evaluating specific Concept_ids. + + a. The DQ check does not include a UNIT_CONCEPT_ID (value is null). A DQ check is flagged as non_applicable if there are no instances of the Concept_ID in the table/field.E.g. plausibility checks for specific conditions and gender. Both pregnancy and male do not have UNIT_CONCEPT_IDs. + + b. The DQ check includes a UNIT_CONCEPT_ID. A DQ check is flagged as non_applicable if there are no instances of both concept and unit concept IDs in the table/field. E.g. all DQ checks referencing the concept_ID for HbA1c lab results expressed in mg/dl units will be flagged as non_applicable if there are no instances of that concept_ID in the table/field addressed by the DQ check. + +**Is_error Flag.** + +A DQ check is assigned a status of is_error if the check returns a SQL execution error that is not considered structure-related (i. e. caused by a missing table or a missing field. DQD uses new isStructureRelatedError function to parse the error message to determine if it is structure-related or not. This function parses the error message according to the value of the dbms parameter. isStructureRelatedError function will return TRUE if dbms is unknown. + +------------------------------------------------------------------------ + +Apache 2.0 Open Source Software - Brought to you by OHDSI diff --git a/inst/ResultsV2/About.html b/inst/ResultsV2/About.html new file mode 100644 index 00000000..633a76a4 --- /dev/null +++ b/inst/ResultsV2/About.html @@ -0,0 +1,534 @@ + + + + + + + + + + + + + +ABOUT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +

The Data Quality Dashboard applies a Harmonized Data Quality +Assessment Terminology to data that has been standardized in the OMOP +Common Data Model.

+

+

Data Quality +Dashboard

+

+

OMOP Common Data +Model Repository

+

References

+

Harmonized +Data Quality Assessment Terminology and Framework for the Secondary Use +of Electronic Health Record Data.

+
+

New Flags.

+

DQ Check Status Flag

+

In the initial release of the DQD, all DQ checks were assigned a +status of pass or fail resulting in skewed results under certain +conditions. In order to provide results that more accurately reflect the +quality of data contained in a CDM instance, the number of status flags +were expanded to address scenarios where pass/fail is not +appropriate.The new set of mutually exclusive status states are listed +below in priority order.

+
    +
  • Is Error – if SQL error occurred during execution.

  • +
  • Non_applicable – if DQ check is not applicable for reasons +explained below.

  • +
  • Failed – if (violated rows/denominator) < threshold)

  • +
  • Passed – if (violated rows/denominator) > threshold)

  • +
+

Non_applicable flag.

+

The results of a DQ check may not be applicable to a given CDM +instance depending on the implementation and content of the instance. +For example, the DQ check for plausible values of HbA1c lab results +would pass with no violations even if there were no results for that lab +test in the database. It is not uncommon to have > 1000 DQ checks +that do not apply to a given CDM instance. The results from DQ checks +that are not applicable skew to overall results.Listed below are the +scenarios for which a DQ check result is flagged as non_applicable:

+
    +
  1. If the cdmTable DQ check determines that a table does not exist +in the database, then all DQ checks (except cdm_table) addressing that +table are flagged as non_applicable.

  2. +
  3. If a table exists but is empty, then all field level checks for +that table are flagged as non_applicable, except for cdmField checks, +which evaluates if the field is defined or not. A cdmField check is +marked as not_applicable if the CDM table it refers to does not exist +(tested by cdmTable). An empty table is detected when the +measureValueCompleteness DQ check for any of the fields in the table +returns a denominator count = 0 (NUM_DENOMINATOR_ROWS=0).

  4. +
  5. If a field is not populated, then all field level checks except +for measureValueCompleteness and isRequired are flagged as +non_applicable.

    +
      +
    1. A field is not populated if the measureValueCompleteness DQ check +finds denominator count > 0 and number of violated rows = denominator +count (NUM_DENOMINATOR_ROWS > 0 AND NUM_DENOMINATOR_ROWS = +NUM_VIOLATED_ROWS).

    2. +
    3. The measureValueCompleteness check is marked as not applicable +if:

      +
        +
      1. The CDM table it refers to does not exist or is empty.

      2. +
      3. The CDM field it refers to does not exist.

      4. +
      5. The isRequired check is marked as not applicable if:

        +
          +
        1. The CDM table it refers to does not exist or is empty.

        2. +
        3. The CDM field it refers to does not exist.

        4. +
      6. +
    4. +
  6. +
  7. Flagging a Concept_ID level DQ check as non_applicable depends on +whether the DQ check logic includes a UNIT_CONCEPT_ID. There are two +scenarios for DQ checks evaluating specific Concept_ids.

    +
      +
    1. The DQ check does not include a UNIT_CONCEPT_ID (value is null). +A DQ check is flagged as non_applicable if there are no instances of the +Concept_ID in the table/field.E.g. plausibility checks for specific +conditions and gender. Both pregnancy and male do not have +UNIT_CONCEPT_IDs.

    2. +
    3. The DQ check includes a UNIT_CONCEPT_ID. A DQ check is flagged as +non_applicable if there are no instances of both concept and unit +concept IDs in the table/field. E.g. all DQ checks referencing the +concept_ID for HbA1c lab results expressed in mg/dl units will be +flagged as non_applicable if there are no instances of that concept_ID +in the table/field addressed by the DQ check.

    4. +
  8. +
+

Is_error Flag.

+

A DQ check is assigned a status of is_error if the check returns a +SQL execution error that is not considered structure-related (i. e. +caused by a missing table or a missing field. DQD uses new +isStructureRelatedError function to parse the error message to determine +if it is structure-related or not. This function parses the error +message according to the value of the dbms parameter. +isStructureRelatedError function will return TRUE if dbms is +unknown.

+
+

Apache 2.0 Open Source Software - Brought to you by +OHDSI

+
+ + + + +
+ + + + + + + + + + + + + + + diff --git a/inst/ResultsV2/CDM_SOURCE.Rmd b/inst/ResultsV2/CDM_SOURCE.Rmd new file mode 100644 index 00000000..4408a4d7 --- /dev/null +++ b/inst/ResultsV2/CDM_SOURCE.Rmd @@ -0,0 +1,37 @@ +--- +title: "CDM SOURCE" + +output: + html_document: + theme: flatly +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + + +```{r df, include=FALSE} +library(jsonlite) +library(dplyr) + +jsonFilePath <- "C:/Users/LuisAlaniz/Documents/output/synthea-20220430194102.json" + +data <- data.frame(fromJSON(jsonFilePath)) + +data <- tibble(data) + +dataM <- select(data, contains("Metadata")) %>% + rename_(.dots=setNames(names(.), gsub("Metadata.", "", names(.)))) %>% + filter(row_number()==1) +``` + + +CDM Source Name: `r dataM$CDM_SOURCE_NAME` +CDM Source Abbreviation: `r dataM$CDM_SOURCE_ABBREVIATION` +CDM Holder: `r dataM$CDM_HOLDER` +Source Description: `r dataM$SOURCE_DESCRIPTION` +Source Release Date: `r dataM$CDM_RELEASE_DATE` +CDM Version: `r dataM$CDM_VERSION` +Vocabulary Version: `r dataM$VOCABULARY_VERSION` +Data Quality Dashboard version: `r dataM$DQD_VERSION` \ No newline at end of file diff --git a/inst/ResultsV2/CDM_SOURCE.html b/inst/ResultsV2/CDM_SOURCE.html new file mode 100644 index 00000000..b445b5f8 --- /dev/null +++ b/inst/ResultsV2/CDM_SOURCE.html @@ -0,0 +1,445 @@ + + + + + + + + + + + + + +CDM SOURCE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +

CDM Source Name: Synthea synthetic health database
+CDM Source Abbreviation: Synthea
+CDM Holder: OHDSI Community
+Source Description: SyntheaTM is a Synthetic Patient Population +Simulator. The goal is to output synthetic, realistic (but not real), +patient data and associated health records in a variety of +formats.
+Source Release Date: 2019-10-07
+CDM Version: v5.3
+Vocabulary Version: v5.0 17-JUN-19
+Data Quality Dashboard version: 1.0.0

+ + + + +
+ + + + + + + + + + + + + + + diff --git a/inst/ResultsV2/GitHub-Mark-32px.png b/inst/ResultsV2/GitHub-Mark-32px.png new file mode 100644 index 0000000000000000000000000000000000000000..8b25551a97921681334176ee143b41510a117d86 GIT binary patch literal 1714 zcmaJ?X;2eq7*4oFu!ne{XxAht2qc?8LXr|_LPCfTpaBK7K$c{I0Ld=NLIOeuC;@2) zZ$K%a)k+m-s0>xHmKxL%0V&0TRzzznhgyqrIC$F)0{WwLXLrBvd*^wc_uSc%h%m9E z{W5z3f#4_!7RvAyFh6!S_*<8qJ%KOIm?#E|L=rJQq=gB5C6WLG5;c?r%V0>EmEH#X z5eSwPRa6WXBMs#$5H%GtW2go-in9p>zW@UYDNNWc^XOXZQ? z1QjEV00I#$3^1wQUJ8&-2UsjB-G|9y(LDhMNN3PM{APL4eYi{(m*ERcUnJa{R+-3^ z34^A6;U^v`8N*O6ji%S@sd{fJqD`XFIUJ5zgTe5^5nj414F(y!G&=H(f)Lgzv?>%+ zAsWD}2qhpH7>|TU`X&W6IxDNuO_vET7|j5oG&&VDr!)hUO8+0KR?nh!m<)a!?|%yG zqOwq!CWCcIhE{<$E|F|@g>nP6FoYr6C<8>D?ID9%&5J(4oSbR1I^byW*g@__U z4QsF&uJSEcFeleM3~ChjEQGbHOjsGDMbyAl(p=Ttv9RaVo8~I#js@@Y9C^_2U})yn zzSHU%6FxuY?d;&65MyR({^lU*3$z$ZllDb(o&<7d;A_`h2U+3~BJ2Hv`{W}KEU801#cv_B|9Cm!ynR{S`AMsSn z;7E=B;mb!wx$L;S>yGXG^6=&WlQn9$s?&L%Y1D8TI^MlKB1DqsEng$>f4=xYWBoPI z_S1p!sJ#d2?YI4kPA{k}Eby?F=f-J9zIc`YDl^pzjVm~9ebE?Hn?t0Nx+la|D0MB; z9)2xv1G>a1|A9kQ>~DV<=X3-4yC&n!m8-3K#P z{X@0zRuQsy$+N ziSCoLJU{Z$nQy4A4Y5UJ07$5FA~qL2%Q+cLaqDU?Lz3?=BC5;Nk6BbTmmceEaM>-Z zi>O&-dSE=%ex;vcvCOk{*JQ5^_4M z4lW7%l9IqY(z7pV(?I@@8=KPFO82)O{VDI18-*d-k$YmI^XiuPs_LuFw<^ZcD}yP5 c*NrbeloN*74g`U%%F6r~k%+>C^#XapzmV0H-2eap literal 0 HcmV?d00001 diff --git a/inst/ResultsV2/load_data_10.R b/inst/ResultsV2/load_data_10.R new file mode 100644 index 00000000..33999313 --- /dev/null +++ b/inst/ResultsV2/load_data_10.R @@ -0,0 +1,291 @@ +library(plyr) +library(dplyr) +library(tidyr) +library(jsonlite) +library(janitor) + +jsonFilePath <- Sys.getenv("jsonPath") + +data <- data.frame(fromJSON(jsonFilePath)) + +data <- tibble(data) + +dataT <- select(data, contains("CheckResults")) %>% + rename_(.dots = setNames(names(.), gsub("CheckResults.", "", names(.)))) + +################################################ +#### TIBBLE OVERVIEW #### +################################################ + +summaryParts1 <- function(data_tab, variable) { + part <- + select(data_tab, + c(CATEGORY, CONTEXT, PASSED, FAILED, NOT_APPLICABLE, IS_ERROR)) %>% + mutate(CATEGORY = as.factor(CATEGORY)) %>% + mutate(CONTEXT = as.factor(CONTEXT)) %>% + group_by(CATEGORY, CONTEXT) %>% + dplyr::summarise("sum" := sum({ + { + variable + } + })) %>% + spread(CONTEXT, sum) %>% + ungroup() %>% + mutate(Total = Validation + Verification) +} + +summaryParts2 <- function(data_tab, variable) { + part <- + select(data_tab, + c(CATEGORY, CONTEXT, PASSED, FAILED, NOT_APPLICABLE, IS_ERROR)) %>% + mutate(CATEGORY = as.factor(CATEGORY)) %>% + mutate(CONTEXT = as.factor(CONTEXT)) %>% + group_by(CATEGORY, CONTEXT) %>% + dplyr::summarise("sum" := sum({ + { + variable + } + })) %>% + spread(CONTEXT, sum) %>% + ungroup() +} + +# Checks if a string is in column name +# https://stackoverflow.com/questions/60978376/r-to-identify-whether-column-names-in-a-dataframe-contains-string +checkString <- function(dat, pat) any(grepl(pat, dat$CONTEXT)) + +if (checkString(dataT, "Validation")) { + part1 <- summaryParts1(dataT, PASSED) + + part1 <- dplyr::rename(part1, Validation.Pass = Validation) %>% + dplyr::rename(Verification.Pass = Verification) %>% + dplyr::rename(Total.Pass = Total) + + part2 <- summaryParts1(dataT, FAILED) + + part2 <- dplyr::rename(part2, Validation.Fail = Validation) %>% + dplyr::rename(Verification.Fail = Verification) %>% + dplyr::rename(Total.Fail = Total) + + part3 <- summaryParts1(dataT, NOT_APPLICABLE) + + part3 <- dplyr::rename(part3, Validation.Not_Applicable = Validation) %>% + dplyr::rename(Verification.Not_Applicable = Verification) %>% + dplyr::rename(Total.Not_Applicable = Total) + + part4 <- summaryParts1(dataT, IS_ERROR) + + part4 <- dplyr::rename(part4, Validation.Error = Validation) %>% + dplyr::rename(Verification.Error = Verification) %>% + dplyr::rename(Total.Error = Total) + + data1 <- inner_join(part1, part2, by = "CATEGORY") + data1 <- inner_join(data1, part3, by = "CATEGORY") + data1 <- inner_join(data1, part4, by = "CATEGORY") + + data1 <- + mutate(data1, Validation.PctPass = (Validation.Pass / (Validation.Pass + Validation.Fail)) * + 100) %>% + mutate(Verification.PctPass = (Verification.Pass / (Verification.Pass + Verification.Fail)) * + 100) %>% + mutate(Total.PctPass = (Total.Pass / (Total.Pass + Total.Fail)) * 100) %>% + adorn_totals() + + data1$Validation.PctPass[4] = (data1$Validation.Pass[4] / (data1$Validation.Pass[4] + data1$Validation.Fail[4])) * + 100 + data1$Verification.PctPass[4] = (data1$Verification.Pass[4] / (data1$Verification.Pass[4] + data1$Verification.Fail[4])) * + 100 + data1$Total.PctPass[4] = (data1$Total.Pass[4] / (data1$Total.Pass[4] + data1$Total.Fail[4])) * + 100 +} else{ + part1 <- summaryParts2(dataT, PASSED) + + part1 <- dplyr::rename(part1, Verification.Pass = Verification) + + part2 <- summaryParts2(dataT, FAILED) + + part2 <- dplyr::rename(part2, Verification.Fail = Verification) + + part3 <- summaryParts2(dataT, NOT_APPLICABLE) + + part3 <- dplyr::rename(part3, Verification.Not_Applicable = Verification) + + part4 <- summaryParts2(dataT, IS_ERROR) + + part4 <- dplyr::rename(part4, Verification.Error = Verification) + + + data1 <- inner_join(part1, part2, by = "CATEGORY") + data1 <- inner_join(data1, part3, by = "CATEGORY") + data1 <- inner_join(data1, part4, by = "CATEGORY") + + data1 <- + mutate(data1, Verification.PctPass = (Verification.Pass / (Verification.Pass + Verification.Fail)) * + 100) %>% + adorn_totals() + + data1$Verification.PctPass[3] = (data1$Verification.Pass[3] / (data1$Verification.Pass[3] + data1$Verification.Fail[3])) * + 100 +} + +################################################ +#### TIBBLE TABLE CENTRIC PIVOT #### +################################################ + +getViolatedRowsQuery <- function(queryText) { + stringr::str_match(string = queryText, pattern = "(?i)(\\/\\*violatedRowsBegin\\*\\/)(?s)(.*)(\\/\\*violatedRowsEnd\\*\\/)")[3] +} + +if (checkString(dataT, "Validation")) { + data2 <- mutate(dataT, CATEGORY = factor(CATEGORY)) %>% + mutate(SUBCATEGORY = if_else(SUBCATEGORY == "", "None", SUBCATEGORY)) %>% + mutate(SUBCATEGORY = factor(SUBCATEGORY)) %>% + mutate(CONTEXT = factor(CONTEXT)) %>% + mutate(CHECK_NAME = factor(CHECK_NAME)) %>% + mutate(CHECK_LEVEL = factor(CHECK_LEVEL)) %>% + replace_na( + list( + NUM_VIOLATED_ROWS = 0, + PCT_VIOLATED_ROWS = 0, + FAILED = 0, + IS_ERROR = 0, + NOT_APPLICABLE = 0, + THRESHOLD_VALUE = 0 + ) + ) %>% + replace_na(list(NUM_DENOMINATOR_ROWS = 1, PASSED = 0)) %>% + mutate(CHECKS = 1) %>% + mutate(PCT_PASSED = (PASSED / (PASSED + FAILED)) * 100) %>% + mutate(PCT_VIOLATED_ROWS = NUM_VIOLATED_ROWS / NUM_DENOMINATOR_ROWS * + 100) %>% + mutate(CHECK_STATUS = PASSED + 2 * FAILED + 3 * IS_ERROR + 4 * NOT_APPLICABLE) %>% + mutate(CHECK_LEVEL = recode_factor( + CHECK_LEVEL, + TABLE = "Table", + FIELD = "Field", + CONCEPT = "Concept" + )) %>% + mutate( + CHECK_STATUS = recode( + CHECK_STATUS, + `1` = "Pass", + `2` = "Fail", + `3` = "Is Error", + `4` = "Not Applicable" + ) + ) %>% + select( + !c( + IS_ERROR, + NOT_APPLICABLE, + PASSED, + EXECUTION_TIME, + SQL_FILE, + CONCEPT_ID, + UNIT_CONCEPT_ID, + CDM_FIELD_NAME + ) + ) %>% + relocate( + CDM_TABLE_NAME, + CHECK_NAME, + checkId, + CHECK_DESCRIPTION, + CHECK_STATUS, + CATEGORY, + SUBCATEGORY, + CONTEXT, + CHECK_LEVEL, + FAILED, + CHECKS, + PCT_PASSED, + NUM_VIOLATED_ROWS, + NUM_DENOMINATOR_ROWS, + PCT_VIOLATED_ROWS, + THRESHOLD_VALUE + ) +} else{ + data2 <- mutate(dataT, CATEGORY = factor(CATEGORY)) %>% + mutate(SUBCATEGORY = if_else(SUBCATEGORY == "", "None", SUBCATEGORY)) %>% + mutate(SUBCATEGORY = factor(SUBCATEGORY)) %>% + mutate(CONTEXT = factor(CONTEXT)) %>% + mutate(CHECK_NAME = factor(CHECK_NAME)) %>% + mutate(CHECK_LEVEL = factor(CHECK_LEVEL)) %>% + replace_na( + list( + NUM_VIOLATED_ROWS = 0, + PCT_VIOLATED_ROWS = 0, + FAILED = 0, + IS_ERROR = 0, + NOT_APPLICABLE = 0, + THRESHOLD_VALUE = 0 + ) + ) %>% + replace_na(list(NUM_DENOMINATOR_ROWS = 1, PASSED = 0)) %>% + mutate(CHECKS = 1) %>% + mutate(PCT_PASSED = (PASSED / (PASSED + FAILED)) * 100) %>% + mutate(PCT_VIOLATED_ROWS = NUM_VIOLATED_ROWS / NUM_DENOMINATOR_ROWS * + 100) %>% + mutate(CHECK_STATUS = PASSED + 2 * FAILED + 3 * IS_ERROR + 4 * NOT_APPLICABLE) %>% + mutate(CHECK_LEVEL = recode_factor( + CHECK_LEVEL, + TABLE = "Table", + FIELD = "Field", + CONCEPT = "Concept" + )) %>% + mutate( + CHECK_STATUS = recode( + CHECK_STATUS, + `1` = "Pass", + `2` = "Fail", + `3` = "Is Error", + `4` = "Not Applicable" + ) + ) %>% + select( + !c( + IS_ERROR, + NOT_APPLICABLE, + PASSED, + EXECUTION_TIME, + SQL_FILE, + CDM_FIELD_NAME + ) + ) %>% + relocate( + CDM_TABLE_NAME, + CHECK_NAME, + checkId, + CHECK_DESCRIPTION, + CHECK_STATUS, + CATEGORY, + SUBCATEGORY, + CONTEXT, + CHECK_LEVEL, + FAILED, + CHECKS, + PCT_PASSED, + NUM_VIOLATED_ROWS, + NUM_DENOMINATOR_ROWS, + PCT_VIOLATED_ROWS, + THRESHOLD_VALUE + ) +} + +DQ_CHECK_SQL <- lapply(dataT$QUERY_TEXT, getViolatedRowsQuery) +DQ_CHECK_SQL_1 <- ldply(DQ_CHECK_SQL) + +data2 <- mutate(data2, SQL_VIOLATED = DQ_CHECK_SQL_1$V1) %>% + relocate(SQL_VIOLATED, .after = last_col()) %>% + relocate(QUERY_TEXT, .after = last_col()) + + +rm("DQ_CHECK_SQL", "DQ_CHECK_SQL_1") + +data2$FAILED <- as.integer(data2$FAILED) +data2$CHECKS <- as.integer(data2$CHECKS) + +rm("part1", "part2", "part3", "part4", "data") + +#write.csv(data, "data3.csv") + diff --git a/inst/ResultsV2/server.r b/inst/ResultsV2/server.r new file mode 100644 index 00000000..139f50f6 --- /dev/null +++ b/inst/ResultsV2/server.r @@ -0,0 +1,444 @@ +library(shiny) +library(reactable) +library(htmlwidgets) +library(htmltools) +library(formattable) +library(shinyWidgets) +# library(shinythemes) +library(dplyr) +source("load_data_10.R") + +server <- function(input, output) { + ################################################ + #### Panel: Overview #### + ################################################ + if (checkString(dataT, "Validation")) { + output$summary_dt1 <- renderUI({ + reactable( + data1, + striped = TRUE, + highlight = TRUE, + bordered = TRUE, + theme = reactableTheme( + borderColor = "#dfe2e5", + # stripedColor = "#ecf0f1", + highlightColor = "#f0f5f9", + cellPadding = "8px 12px", + ), + rowStyle = function(index) { + if (index == 4) + list(fontWeight = "bold") + }, + columns = list( + CATEGORY = colDef(name = "Category", minWidth = 80), + Validation.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Verification.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Total.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Validation.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Verification.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Total.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Validation.Not_Applicable = colDef( + name = "Not Applicable", + minWidth = 60, + align = "center" + ), + Verification.Not_Applicable = colDef( + name = "Not Applicable", + minWidth = 60, + align = "center" + ), + Total.Not_Applicable = colDef( + name = "Not Applicable", + minWidth = 60, + align = "center" + ), + Validation.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Verification.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Total.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Validation.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Verification.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Total.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ) + ), + columnGroups = list( + colGroup( + name = "Validation", + columns = c( + "Validation.Pass", + "Validation.Fail", + "Validation.Not_Applicable", + "Validation.Error", + "Validation.PctPass" + ) + ), + colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.Not_Applicable", + "Verification.Error", + "Verification.PctPass" + ) + ), + colGroup( + name = "Total", + columns = c( + "Total.Pass", + "Total.Fail", + "Total.Not_Applicable", + "Total.Error", + "Total.PctPass" + ) + ) + ) + ) + }) + } else{ + output$summary_dt1 <- renderUI({ + reactable( + data1, + striped = TRUE, + highlight = TRUE, + bordered = TRUE, + theme = reactableTheme( + borderColor = "#dfe2e5", + # stripedColor = "#ecf0f1", + highlightColor = "#f0f5f9", + cellPadding = "8px 12px", + ), + rowStyle = function(index) { + if (index == 4) + list(fontWeight = "bold") + }, + columns = list( + CATEGORY = colDef(name = "Category", minWidth = 80), + Verification.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Verification.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Verification.Not_Applicable = colDef( + name = "Not Applicable", + minWidth = 60, + align = "center" + ), + Verification.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Verification.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ) + ), + columnGroups = list( + colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.Not_Applicable", + "Verification.Error", + "Verification.PctPass" + ) + ) + ) + ) + }) + } + + + ################################################ + #### Panel: Results #### + ################################################ + + output$summary_dt2 <- renderUI({ + filteredTable <- filter(data2, CATEGORY %in% input$cat) %>% + filter(SUBCATEGORY %in% input$subcat) %>% + filter(CONTEXT %in% input$cont) %>% + filter(CHECK_NAME %in% input$check_na) %>% + filter(CHECK_LEVEL %in% input$check_le) %>% + filter(CHECK_STATUS %in% input$check_st) + + reactable( + filteredTable, + groupBy = c("CDM_TABLE_NAME", "CHECK_NAME", "CHECK_LEVEL"), + defaultSorted = list( + CDM_TABLE_NAME = "asc", + CDM_TABLE_NAME = "asc", + CDM_TABLE_NAME = "asc" + ), + defaultColDef = colDef(footerStyle = list(fontWeight = "bold")), + striped = TRUE, + highlight = TRUE, + theme = reactableTheme( + borderColor = "#dfe2e5", + # stripedColor = "#ecf0f1", + highlightColor = "#f0f5f9", + cellPadding = "8px 12px", + ), + columns = list( + CDM_TABLE_NAME = colDef( + name = "Table Name", + sortable = FALSE, + minWidth = 170, + align = "left", + footer = "TOTAL", + aggregated = JS("function(cellInfo) { + return cellInfo.value + }") + ), + CHECK_NAME = colDef( + name = "Check Name", + sortable = FALSE, + minWidth = 140, + align = "left", + aggregated = JS("function(cellInfo) { + return cellInfo.value + }") + ), + CHECK_LEVEL = colDef( + name = "Check Level", + sortable = FALSE, + minWidth = 100, + align = "left", + aggregated = JS("function(cellInfo) { + return cellInfo.value + }") + ), + CHECK_DESCRIPTION = colDef( + name = "Check Description", + sortable = FALSE, + minWidth = 140, + align = "left", + aggregated = JS("function(cellInfo) { + return cellInfo.value + }") + ), + FAILED = colDef( + name = "# Failed", + align = "center", + footer = function(values) + comma(sum(values), digits = 0), + aggregate = "sum", + minWidth = 55, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 0) + ), + CHECKS = colDef( + name = "# Checks", + align = "center", + footer = function(values) + comma(sum(values), digits = 0), + aggregate = "sum", + minWidth = 55, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 0) + ), + PCT_PASSED = colDef( + name = "% Passed", + align = "center", + aggregate = JS( + "function(values, rows) { + let totalFailed = 0 + let totalChecked = 0 + rows.forEach(function(row) { + totalFailed += row['FAILED'] + totalChecked += row['CHECKS'] + }) + return (1 - (totalFailed / totalChecked))*100 + }" + ), + minWidth = 55, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 0) + ), + NUM_VIOLATED_ROWS = colDef( + name = "# Violated Rows", + align = "center", + footer = function(values) + comma(sum(values), digits = 0), + aggregate = "sum", + minWidth = 110, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 0) + ), + NUM_DENOMINATOR_ROWS = colDef( + name = "Total # of Rows", + align = "center", + footer = function(values) + comma(sum(values), digits = 0), + aggregate = "sum", + minWidth = 110, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 0) + ), + PCT_VIOLATED_ROWS = colDef( + name = "Avg. % Violated", + align = "center", + aggregate = JS( + "function(values, rows) { + let totalNumerator = 0 + let totalDenominator = 0 + rows.forEach(function(row) { + totalNumerator += row['NUM_VIOLATED_ROWS'] + totalDenominator += row['NUM_DENOMINATOR_ROWS']}) + return (totalNumerator / totalDenominator)*100}" + ), + minWidth = 65, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 1) + ), + THRESHOLD_VALUE = colDef( + name = "Max. Threshold Value", + align = "center", + footer = function(values) + comma(max(values), digits = 0), + aggregate = "max", + minWidth = 70, + sortable = FALSE, + format = + colFormat(separators = TRUE, digits = 0) + ), + + CATEGORY = colDef(show = FALSE), + SUBCATEGORY = colDef(show = FALSE), + CONTEXT = colDef(show = FALSE), + checkId = colDef(show = FALSE), + CHECK_STATUS = colDef(show = FALSE), + QUERY_TEXT = colDef(show = FALSE), + SQL_VIOLATED = colDef(show = FALSE), + ERROR = colDef(show = FALSE), + NOT_APPLICABLE_REASON = colDef(show = FALSE) + ), + + # pagination = TRUE, + defaultPageSize = 25, + height = 850, + showPageInfo = FALSE, + wrap = TRUE, + # resizable = TRUE, + pagination = FALSE, + details = colDef( + name = "", + details = JS( + "function(rowInfo) + { + return 'Details for row: ' + rowInfo.index + '
' +
+          'Status: '.bold() + '\\n' +
+          rowInfo.row['CHECK_STATUS']
+          + '\\n' +
+          'Not applicable reason: '.bold() + '\\n' +
+          rowInfo.row['NOT_APPLICABLE_REASON']
+          + '\\n' +
+          'Error: '.bold() + '\\n' +
+          rowInfo.row['ERROR']
+          + '\\n' +
+          'Data Quality Check SQL: '.bold() +rowInfo.row['QUERY_TEXT']
+          + '\\n' +
+          'SQL for Violated Rows: '.bold() + '\\n' +
+          rowInfo.row['SQL_VIOLATED']
+          + '\\n' +
+          '
'}" + ), + html = TRUE, + width = 25 + ) + ) + }) + + ################################################ + #### Panel: CDM SOURCE #### + ################################################ + + getPageSource <- function() { + return(includeHTML("CDM_SOURCE.html")) + } + output$Source <- renderUI({ + getPageSource() + }) + + ################################################ + #### Panel: ABOUT #### + ################################################ + + getPageAbo <- function() { + return(includeHTML("About.html")) + } + output$Abo <- renderUI({ + getPageAbo() + }) +} diff --git a/inst/ResultsV2/ui.r b/inst/ResultsV2/ui.r new file mode 100644 index 00000000..5b1afa28 --- /dev/null +++ b/inst/ResultsV2/ui.r @@ -0,0 +1,116 @@ +library(shiny) +library(reactable) +library(htmlwidgets) +library(htmltools) +library(formattable) +library(shinyWidgets) +library(shinythemes) +source("load_data_10.R") + +ui <- tagList( + navbarPage( + title = div( + "DATA QUALITY ASSESSMENT", + img( + src = "ohdsi.png", + height = "50px", + style = "position: absolute; + top: 1px; + right: 15px;" + ) + ), + + + theme = shinythemes::shinytheme("flatly"), + + + ################################################ + #### Panel: OVERVIEW #### + ################################################ + + shiny::tabPanel("OVERVIEW", + mainPanel(uiOutput("summary_dt1"), + width = 12)), + + + ################################################ + #### Panel: TABLE CENTRIC PIVOT #### + ################################################ + + shiny::tabPanel( + "RESULTS", + sidebarLayout( + mainPanel(uiOutput("summary_dt2"), + width = 10), + sidebarPanel( + width = 2, + pickerInput( + inputId = "cat", + label = "Category", + choices = as.vector(unique(data2$CATEGORY)), + multiple = TRUE, + selected = as.vector(unique(data2$CATEGORY)), + options = list(`actions-box` = TRUE) + ), + pickerInput( + inputId = "subcat", + label = "Subcategory", + choices = as.vector(unique(data2$SUBCATEGORY)), + multiple = TRUE, + selected = as.vector(unique(data2$SUBCATEGORY)), + options = list(`actions-box` = TRUE) + ), + pickerInput( + inputId = "cont", + label = "Context", + choices = as.vector(unique(data2$CONTEXT)), + multiple = TRUE, + selected = as.vector(unique(data2$CONTEXT)), + options = list(`actions-box` = TRUE) + ), + pickerInput( + inputId = "check_na", + label = "Check Name", + choices = as.vector(unique(data2$CHECK_NAME)), + multiple = TRUE, + selected = as.vector(unique(data2$CHECK_NAME)), + options = list(`actions-box` = TRUE) + ), + pickerInput( + inputId = "check_le", + label = "Check Level", + choices = as.vector(unique(data2$CHECK_LEVEL)), + multiple = TRUE, + selected = as.vector(unique(data2$CHECK_LEVEL)), + options = list(`actions-box` = TRUE) + ), + pickerInput( + inputId = "check_st", + label = "Check Status", + choices = as.vector(unique(data2$CHECK_STATUS)), + multiple = TRUE, + selected = as.vector(unique(data2$CHECK_STATUS)), + options = list(`actions-box` = TRUE) + ) + ), + position = "right" + ) + ), + + + ################################################ + #### Panel: METATDATA #### + ################################################ + + shiny::tabPanel("CDM SOURCE", + htmlOutput("Source")), + + ################################################ + #### Panel: ABOUT #### + ################################################ + + shiny::tabPanel("ABOUT", + htmlOutput("Abo")), + ) +) + diff --git a/inst/ResultsV2/www/GitHub-Mark-32px.png b/inst/ResultsV2/www/GitHub-Mark-32px.png new file mode 100644 index 0000000000000000000000000000000000000000..8b25551a97921681334176ee143b41510a117d86 GIT binary patch literal 1714 zcmaJ?X;2eq7*4oFu!ne{XxAht2qc?8LXr|_LPCfTpaBK7K$c{I0Ld=NLIOeuC;@2) zZ$K%a)k+m-s0>xHmKxL%0V&0TRzzznhgyqrIC$F)0{WwLXLrBvd*^wc_uSc%h%m9E z{W5z3f#4_!7RvAyFh6!S_*<8qJ%KOIm?#E|L=rJQq=gB5C6WLG5;c?r%V0>EmEH#X z5eSwPRa6WXBMs#$5H%GtW2go-in9p>zW@UYDNNWc^XOXZQ? z1QjEV00I#$3^1wQUJ8&-2UsjB-G|9y(LDhMNN3PM{APL4eYi{(m*ERcUnJa{R+-3^ z34^A6;U^v`8N*O6ji%S@sd{fJqD`XFIUJ5zgTe5^5nj414F(y!G&=H(f)Lgzv?>%+ zAsWD}2qhpH7>|TU`X&W6IxDNuO_vET7|j5oG&&VDr!)hUO8+0KR?nh!m<)a!?|%yG zqOwq!CWCcIhE{<$E|F|@g>nP6FoYr6C<8>D?ID9%&5J(4oSbR1I^byW*g@__U z4QsF&uJSEcFeleM3~ChjEQGbHOjsGDMbyAl(p=Ttv9RaVo8~I#js@@Y9C^_2U})yn zzSHU%6FxuY?d;&65MyR({^lU*3$z$ZllDb(o&<7d;A_`h2U+3~BJ2Hv`{W}KEU801#cv_B|9Cm!ynR{S`AMsSn z;7E=B;mb!wx$L;S>yGXG^6=&WlQn9$s?&L%Y1D8TI^MlKB1DqsEng$>f4=xYWBoPI z_S1p!sJ#d2?YI4kPA{k}Eby?F=f-J9zIc`YDl^pzjVm~9ebE?Hn?t0Nx+la|D0MB; z9)2xv1G>a1|A9kQ>~DV<=X3-4yC&n!m8-3K#P z{X@0zRuQsy$+N ziSCoLJU{Z$nQy4A4Y5UJ07$5FA~qL2%Q+cLaqDU?Lz3?=BC5;Nk6BbTmmceEaM>-Z zi>O&-dSE=%ex;vcvCOk{*JQ5^_4M z4lW7%l9IqY(z7pV(?I@@8=KPFO82)O{VDI18-*d-k$YmI^XiuPs_LuFw<^ZcD}yP5 c*NrbeloN*74g`U%%F6r~k%+>C^#XapzmV0H-2eap literal 0 HcmV?d00001 diff --git a/inst/ResultsV2/www/OHDSI.jpg b/inst/ResultsV2/www/OHDSI.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7f38c707676e339f3c578773c50b8b4495ff2970 GIT binary patch literal 6661 zcmZu!cQl+&_kY%EA;BhkFRKSpS6QOB1R+RlwCJ71Y9SE`(RQ&)5-mZ3=)FYmM6c0; zAWB#zdjD;{-}Aob{o^;!nYnYGxo7S@^ZCrZcdjO{762-3buD!O1OfmM{sXRNfY-n^ zViKyGlr)r76tt97R5Wz-5K1~4I$C-vIz}2=I$C_EXW?U~XXIs~rRNak6hrb=)gs++b z2q~}tEPz3r009I9hJdcx0cN~|1Ypo#U;ooU!~{engkVzqsx}n>0uvAr6Oj@VUn2zL zHU4T7LWo3(Z*nN_rD0SgfeJ`#6LqK-;qw-YDG;yd55Y~3`lgK z@`R~Ud1!`+8iYr%hlgV|!y};oBR;{8Vk(uP*wbtC^S&E2`?i5gmg(vk0*x4?IVwTF zcHp}8y}2d3(vP(RaDYimi~BeIXT5_jP5tpJpRC3$CRVQiS-lfM-D}HjR3BV2Dxw!J z%Ny=H9>o^F;@^XGX5BU^i3z34Q!}@CED2|9y@vjqMF)S(Hzo^<4fwVct5(i2KdB=n2 za+tqx)ly@tx^^2@md-g4d=*aghx_AVY)ucvn}nQ2Y>h<;gT5%inI`UH#|#}UFEKZ_ z+@#J!w{eDc)opA+OR-(uf^n0-UZ8TiHuItSVQBql6wr7a&&FDAyd%-Q{#OUWKEyG- zuHU9r*c1n)^Zl_8C!fNE;Kfbpzl;?|G0HxS4kFN5-~b*fa$wB%)Qe<`GY1fXo>JIV z3k&5Gkx=Jx;q;a#VnT)r8{aW4N?OeHTxM312h|XTZEDx~D~!G!hAYX4d_pdH=^Z7* zs>2U3L64}1U1V!RG@84-LvZN|`QdV?%9Ia<&%Gb%0Hbe*>N1l57{GB%TEW|1#Je4h z1IUK3N;d(`W$y3s$%~U=6zgb>3O=5>Acz(3pT?Y zT|6<=SaV5S>z&BRoOkOP-UGA~<4p7vY6CsB%*Qli681e3t`&)Yyo)B)((GL^pw zF4;BX!C(&55%AGU9#!TKuYTE99X; zwQ+h{98$=kc2_2`6j7kU62cUMvyV}#b6xZ#D;N!fIcYpV8e6@NFKaQV%I|m*p+YyI z3EEl-dTA)QkM)<5*cVzDt)AFUOv-xSx8hfzb!MBnmSWDceLrxmGGnvVJ$5ws>~cK0 z{NA;x>po`#u)BE*&KgGH{UQ^Zs}#7+yFyWY8P27CeiDrMwAO({@cCu;V$Eu<`^K5IgGJiFVQj zi%-}?vp!+43hB-aW(O`?f0z$(a!FxTrF-y(mE~oaga9V&J@ivte$QAz&Mh?_GE|R#p^!s2 zq=LYw{O;ULgC@1_wE8z$54ZbV2l%-PmuMtB4VFT_`fCr}m2Pn5dY(#P8%|j~dHcyx zM}zOLYBZ#dQ=C~wWSn~ZdK?-HdsDhVThH_c97mq!uQ|k;evsf&adyAt<-rx;U(fa- z2IGpkAL(5>u~W0iN2Hzh=r6@g)RY~_uVR-o^FIH9 zH>{d;y=eBdkZ_fXV~2F|wFIBQgW@^ED{%GWUAK0mpJj4(3pm;KRz&UpF5VWuJlQa9 zI8`}y)jN8B1q2){n5W+{Z4_SO!7cjZ)n#3EyBA+3mUoKgu6NXVx>?G2A!lj0sM@*T zPY=SXZR=7N=n@B@SS{#^?nt1vu+?`r>@c$SYtRO+HUD|PjSXk!k@J3}z70WUAwNi) zPYG(FnI-JutX`h#0?fs>uS!d1ZXrv+0p(rH-ufG|BZhDnrj$R-NBOkR6b_4cqUq~& z!3F_K=8jc-Kt2Xskf8Bbuko)Q%Y5u=!y_jrHm=?|oIT4G0BYt|-HQ9QEj!?2e=^(X zfN*8{CK?h=PZ|G(PmQ+UbmTAMWMd)2iVqNqU@;#cuA3R0>^34yI!E(F z=lX?3$-LXq+%aFF_?DHJLB&RIBzBPERPo!ezvu;rn7MS(>b!ImaK>$#us>Dscab5S>E5yhubMRckj?C6|YgFoHNZAF;b)PBj zdtJX{f{*g4OpX%0(Db5r!4Fq)h&`QB^_P#BNqQF0kfAOwM*&uO9X8Om(bS69todHS zs-3a8_G(ST)&#OI?Kf2g0#@OyMt_Hm*C1e#Gs>z6nUCRJ@K9BYHKNXi&}u@%qo8AS zob5jXA~d^uIasS}{ojs!I{0y%wk^2Qpykp1F9O<#5lv?$uT({6#abj!GawG#GF$Cg zc_S6Zn)HC>5#Pqwc|(Q%rd#!=iC#TC;nS076|W1LRN^69g`XR8t-pWQ7Z>Bm+V5Yg z(Z*=6wI?i}>Z4x%ienoDszv+&tP4;JC&*Z*kg)T~l2RTm@g2OiLoQOmi;=!(@qD}) zl`W{-c59x`%kA^>LEfMSa`f8TGA#VEOSBhTCtnbk#4aDh${yNl^hyKS23h+Ai(Y;{ zcm>eBojSaT+0}mGruwUS=kQk;`fFG9rRLeR^U2X_OgwWdi|)l+Z{5whH(dSBbh_!Z z+O1u{iu4Pp0FP*>Y}%o`om|N!JVuhvVe&e!YuccDXR>9QRh7GX+u7U|kQO*mLxkn* zL6A09jBUmJjCLzei+y-ccb%2Kb3%J(-0NSi*-$YWd+|jl3DH2fLNC3MxqlPm(lbItI80d`5KlvHwnywY>h1 zvk|Ux(~_Cd^f#o_v^K&cg`#@!a26zF-VVw8tQcOV1XVTR`4|ONr82csnNZ-JD^)em zuJOiKR%&)bEcDW$##zNHJ5!@^Wef90!CS(m2L$;Q728<#4yJp{aV-T7`>8s?7FiV< zfb9(~{u!&wv10HBtNQ2;bFhB*MVu#A%9Uwik*^KGIK(&+%s3niwgd%1jQ4Zs*Jg%F z4rXNsSc88q8eLm)xh>)Y&O`M(sNDMOXKh@kEn4XLG~$Q);jBDYTeH9-@EN%`aFT9* z9#kWoOrLTK%=kAvz0|BemBV=3sPUhQPx*RW0bR3&m4=&1VqIvvnip#!wRt5DTd*$< zw(@#vKL#}3*18yw6E8Tyn&iIA`_LFV60U|EB)N)_AYT@wQ!+c&v|C*zrkiJ4PN)=K^EK}D z3aD`MR`6ZSsAga)BeGZ@Ov>uvNs^^MmEJskgDJ0Tgp&aIBK}BWBtA{++T?mg;H3}N zH&IY(*irleNIjYx*=PstJ*i_DhIOh-P@1juNeAID0tN?O1L}q@k*L zZcT#f6CL{I`6q_oj9JXQe4A=orhU<6t2S6O%I+1ki*$4$liReV`tW@GMb`HY6l&*F zwvB!j-!y$EFi~LxOcD&3s31(2>?%ytK?Yt`Xrl?3jlQ2~y`~bx$K9tB7O}KIr|=J% zWC#9|$-K`VBL2<%8J9IvOOtr=j$S(85sujkm^_y5uTXQlFX!>1mtFyr7+k0DzX3zcJ&y~)&;`snf2 zy+eg0%vbbIedlh4jjuG4e4+R_o3-bC9`3b|Swqfp?tx(udIc6G{XDRXJ7t=d&csar znJ&q~?$N4|Q?Ju4smsF`F9JkjRZVXHa)r=p<#P5w2q6SSSiZgWd92fTzmBl zF<#O?ij@9yerDw6;8oUhw}C=*z=R>S?_5+zxXyr>#?$JD`C0EtA3tJB8qa%X5SP$Vq=$-H&3jL z8_^hgh>Ja(Z#(`on{PAkIIU|R$*+$PqIegTOVoTF*kI9*PRDTh%xkOg~W}mR2jeI<1(8 zTJT#76#eXpGq&n-&ulk;e%V?y2!6NN6(v&}v+8-0UnL%PEd^PoerUD>Pn3EbWs3M| zFENQB7yDs_O5E?r0q^+5SU4Ly-?MXP?lQS;tWBLq*2=C}rkF5hLP+*Ni-0p>j1Hn| zeojt?GBY$Rl+CsW%x2x(d~?AYWe2DZ;fCcGpf$%EPr62oCabqPXMV?+K+mLwLmCZt zDx+Oo7z?ab5YoVHl2Sk9^ko>q&lz8%blw-au7=zR5_EN-fT2iEO=}|y?Olo_SM`)K z!5F##jh{G#8aqD-DSm%F-F#Ee{GD(SU%Sh7HxM49P_lr;jW!21@dHLNoSYZQ%^dQ! z4{`?#B^0C863E@A&2_i~JAp5WR0s39bPJGg78KTnty|6XCt}Uf!P{A8X9y z2{?NQ;~+N45Aw{;bE-R$HK45 zetr>SE@G2MJ|O6Uc=g&UA3c5Sy!t%f2Q(d21zYjwZ!PH>xG>&yz%|{Of4^K+lMU@Q zSs9xFaP@Y&s^G2&NqUlvD{5G?P2CD;EX*Lvz}NR&Br@}puK6w63atQX1C zIZb)%J=_pqFBPT#KbcrN_NDeU&Lr%OmQn^tt#ZN`S*7Li#{{Q3n^%Xmp(~vw`E!pu z=XJ7P+^M*ZB&2dtS9LS4=el_l{m3QOP8uWlsSJ@--Er!y@$5Kt@bb+?l1-^BiMw^1 z=yxT<)*iRrRN?PQqU9s*?VgASC9cLMw@2vb7d*N2$G>eFRH@@62~I~2XO7>r1b&~3 z-(WgU*(RfJ8gm!jO5G&eKM~7VE6D{7D6ZeQJd0pUOzPDZsN@fy=NM<*J0U8|%7L_Z zr%a*I4m%FOvqZi7_7jPvTj-{g!kw~hIc;l}v}G%|y}Idq))v~aLI(2lCJCd1@|Kdf zx?7vBIJpIxFD)K#bvNdXr4E1WFkke3kG3it-wSwNU~Qc$FRb!bej_D>Rx)M1uJ-z@ zH#4!VYp-}zHS(xjma>5)xtFd3!LYJ_@pz_m;4e@Vya7Y6O#}|3R92sl))Ol_$TleO zr7-zCIe`!3Uw+>Eq*2hDs%ls#Qv4f;Q1PYBOa9z4QtFRbLN)$e&O|;cZbEXtIfP2G zi@HWgCN zwfvrE4d;@4J&grJl08KTDbz*9wvAcx3b@^{QH~=VQym{BldRF;xuPDs~>s>d;aA_;EZzUg!&>Q?}X4~-)-x|Q=Ny+ z*$+NH$e^CmwlY$~a*}cql0&cQ7<^(kz}KFiB?(RV4Dd%xrmv}lA8bNM%OW)-Tl%HA zI5Pm{PmHfe3MFXJ?^9e0NKBg8h>G4)hz@kYoXNY619~437FoYac2O=LGOjY-@#wFY k2_2ns74?aF!u(x(gj9Bv4c-<0GxZRE*4e(gf>%@j2XknU;s5{u literal 0 HcmV?d00001 diff --git a/inst/ResultsV2/www/ohdsi.png b/inst/ResultsV2/www/ohdsi.png new file mode 100644 index 0000000000000000000000000000000000000000..40b24a91a52bf052c4f490796d3505318ce3e1ea GIT binary patch literal 27800 zcmeFZ=R2I=_XSMy37I5F5Hbi6%n-e|AR)>qgAlzldL6xsjNS*M6D3NBPIS>T(R+y! zy%W9j+)2LA@AdNsJTF|iGP%#3bDy)%+H0-7B}54>O>mFm9u5u;0Ziu2TO6EQhQQD3 zyLiASgqlX)z#spay;gXQgHsmib)g&!{Qa4+%v%K=qIdN-znDXG%yrQwwVZ4vtJ$8pc&sb(}1yztPnrvzKEC z>=Dbx;djXP?CF2XPfYQi{J?2@pkN)G|LV=7N4S#FAN_E%Gi8c`jc6J34TxkODj9Kv z=I5J8jmdhsyYDV9pL8|OO_}XFo=kdXRI%aEE7GvB-@)8^mIVEU?;$X(9w0qXc7=oI z=7*b$!=bre(DZtz;qhx%O=Fyx?GnHd9e8fAU6=+pEV1YDp0r5kM@u__Bl1| z0xS2)?92aKkf_bcF+Het*t=E7CKqLEY18}B6Uh}TaO-`hSZw_FrHXYnCTxMc9v@Da z*)p)Y3|^$lc4RA%eNai20fvc6`Mrb zJw7->)wiCx-Vmj%(BjZbdRsN`b-0@^xQCG6eQOgQ!OhJbQA34^srlHv=__=De z-C0N>&lM^YILWwkbx~{|avIYYaY408{6yXibOsKyTCf5Q_~FpwKK_3D@kd;z_p}_h z)xMDl+~P02b^6}mA>r69vS56y9}(AUwuuM#UOk$)bL=mxbbI49ojES_6}|ugn_u@Y zp&HPRAHKnV;U88F@EULr9{y)Y%k}2{674&g`&@oK&+tr$YF~>gJtHNQlyG=RL@ZuA zK$d^^MZk+pt^7ylWI}gz{ffnJ4~UqPCj0vY%(mT?_b({rDk7k4doTey4*W3BYfqJm zxBBhuH@xOn@rS6E?caA!g}m^o-)FQ{+%829jUqf zz->K7Wg6~9xMPHyK?tKe6SuZ}wm7#0x1PCBU64t)7cBJH@6_C-B1#Bi?&6*ATflQ5 zsc~;0)w^%^;iRo%Z}ODbOQh+(?`^Tj45$o=(_I&of%q*$?o9sy@tQYoGH#Oe#G@f& z?Ksa9YC<$#zl1l4Q!zBrVWSUWY&kOM=*n0plvBD>)M2PR#47eF_K^v$JG3^&E9Nrs zQqBLlA^ki<3ub~*nPHHPlW|X+n7x2uoxWC$OS)WVKWB*mYr)hIR~;8ds$%&;HGYJt zz_38mBDAugGQ+9dsmv+%@ZCBLTohg%p7KB&qQ6qwBbmf`PkiuWjgm$jYn;aqh93ft zB}Ownlu7a>N9^*iM!=fjNkn;Oxn}vhax)WY^ScTuE0S_q@dNOIK=a)MMs^3SR?Tu_ zSU0+b!4VmXj6_n^ir1>u3L|%y*Y|DrL-y;Jg_mfUK9U|jzD3IQnDB+p+eEdT7gI0F zN$)>aWSmv^k3WpR6+g!GRBb~g`JI~bu@d~Ah$yH-H%LO%NA+gzj?LN-3jvgF4* zRuz%F^Kdpf*DUBD^P0#Zn3sW9kvCK8i&pbgLtUgtut&N_;W-_FKb{1gTDE+)wy~7T zyJ2;1^$N{{CNjOS%*Q2FiiPS{aBXQ}dCwG=pyQm#)W`&QB)pkg15$;xR_qE>`fr9wSmPqUI7D+Qqsl|4<|6IYU4lCCXt?K-&%x$14;e6IX+=Cc;p z$fOpozVZ*nkOixAX9vkaJF&HK25!5uO9eJq=mW_zmekCsA@42v4xK--<o2P4(3bKgKj#b<MJmt|k5wNviX-#fk2_S5?7sI|1ss_pKaVUzJqq+-BUtCb`~ za#@llRI_8eiR(;_H#ng7`g?WLK1$=#idQM~;aai73KJJ-) ztjDUardJVFs#s%})0&s%*t~MBdm*OUsXkkPEVlfj_IXxW#MRH+;P=PH77WF5a#r$5 zP)*Rzn8!%u z8NQ|KwC9HNbOqAOQSsE{SNSK#o59Q9la$8?o1m{1sl&@U({JLghlBPm^Oo|KNj{TA z#G1zD!$-G#o*QfGbPtoM%zDD05=f@Y+_e&xh^p5L1 z$9#|XQkM7+90Tl@=cv8A+{Q0Nx31c~R`9oiLZdur>P6jsJ!+yGN`F(Hpbjqh|6`&C zXeP*BM$-`ohmG#f53buMF&E%NS|>>jCkZ6N(8p5zQU>uGBxa@2fKItu-yWu?x4_I@@v}Y`xfN9BWLk z$rw)a+Q+8A(DW8%*K@fgXnL5|voH=AI)_>V1$=t+?YTUfz5t)h5cn67(z~(ru#NYU ziS)3yL@cfJFtmrkBM1yVa{K=u^8aDS;I8{vsGY}%g>_77rpMOwjm-~Ig`;Mh4PUb+ z4w<)IEUn4gDO;){vdO`|5Ff@T_okY}$0~pD6~#h>z`+oxDv|uA^D%??cq(B4LbD&J_Rq zM(2tCqvfRml>eq9)&a{UtdHzn+Q9Pic`tkJDz5Q-%SeK^{acj9o$fFiIni{l7lM46 zYTA%-+2Rx>`$wjYaI2doTM&1^XTwKhJwRk)#$!Nt$TLsR70Qd)l62TJ*A_M(qlcjt z4cxWr3l{z0f2$ta|42^W9ZCZylubO-k}{J`T-IW$`|gfDaa38gy zy!pS^?_7jpJ<%r+9Z;pboo%Y#G+X9c9Sj+1qI@i${#JyqP8FH9w2jE|ExT*g$$pUb zSsFHkQUB>Q*S)2A?2jhCDf5?H>xDRry9QOawt%3Hy-(kFI`Rh|2xeT-c?>sc zIt=dc{SPKT`l3r4PW^$H>_;a+e?lwc*M^HhzW5b7f|)pr8_#+Fjv0(1nO#fTu6w&b zjq=u4aj8aG`KuA-H5_k5err8(;Man3`eMRzMUD4WrqeqS-6L~ z3cutQ*eqUm1wl#}vrToJon*?L!4~hx4BH&XP!S2!a~;chHKlQ{Xo zkad&_2TyDLVJ>HPe1jisXu^xh{Y|SytuTE(VAiWSqM^QK8vvvTW56N0c(hhIUdG%ljfJZFejVurjh zx4mo_wPZ5AbI5Q63+E7JD44c5Z{AbIDILXjl%be7Y3wL6zAt|#Z*Moz>tlHGjNl~u zJWkSz!6QCu=71*^dKIOS{aiSd47Fn)(%DpIeQ675GGIGN_H{A6$8$2d!Hw{(h=t^5 z=ZTFxwYFSUC;iO~J+@^nKA3pZatWI}P5=)VTk{CvBo3d=S$*OL9D_{#Qti*gpTj7R zf|eLSx?6T}4RlEx>r&?!hZn#3vDzda0?7CQ(x(a2Y=&oUWK)nmv$7a5`~*5H0MjX3 zJ1>R2&JA)m;fP8;YqYnVIGxCjuID?X^>dh23%-Ep_r3Q!oLJTRiHf9jxdPv0s^n?@ zq)`{cdv5Fo{d>?K`IA>9p+h$>=&D+uTcp8$#^WR#LGSx~PP)Co>-#`3vZm^|OSE1WSEucV(qq_aq7(Ej zVQo?;9y`1Zs;$?`$A0i$&DbEw94zr@Vd`m0$Tj61ChvY94XIv6tqd)Z>b}1aFf2ja zsl0%XQRY7lSP|FTff>_)2(BBR!zeIq#6pu5OQ$)g!rt7#MqPGApLl!!D2Y2lyw&K^ zt`jI?B>d+)ji%9Cnm`l|r>5jH7Odm`%=n9 z1VODS@DZ3)pUPh)(ViEINWoU-z||&7&LOY7i8Pb^WOW_{^*;b zOP`FF%!c|9-EB>mvQ zQX+%iC_^byJ~>uzVo1`;Hc5U}vUTF&Al>v(Qm>u~gtyo!(@Bhl@4oeHuHMeyBeJs~%E zA&iJhU9l!3J}H7}o}N18+ayn)g*0EJl@DnJX;lTGphH$%Yx*Zyf@n#N3MSj05{dV1 z$|so%KC;(WZ0Q4cF59qTBo~+hP7DYt zAN2OHj!Lubx%@9`ndE1L-~e*nZ%J>>YSGIh*(4U$j7<}(&Q&I%9pv5mQSvpCA8fa* zo76oM6&k#e;^0wXZShQ(4_reAnkb7q@624r}|TVHIQ~%7%bc-z!>JG3(etA3~mxp(=G$qkpgn%2N#L z1OOsW_{`)+hoUseK~pidfn&X*fVpD~K|;Z&=QFI{3bhgwFqe0GYFK--iQr-Fsd*`C zxE?d7>1>vs zcx&Z8Fy2g&I>FwX*fVP6%U6bJAZ#pS4;Xs<2+neG!%8XoUgU$=%cuEk&7J-;tJs(R zAw!YS&!F?vvBJdi&XYUjtTsNFftlG`MV@x@YRuo*qN$P}Tz!U`d0A?pEHKj0X_c?$ zsps>D{nFhs6rwxZ#w)4A<{3+rB&~s-p=^Zhr6*ws8RsZr9-8Q$7vI>>_Vulwx@EGB zALWi7@&?G$R!bPs=F$qY7*>c-X099ZGw_@*l@fN4Cs=8FvG#S76gwvKdcL8vGX2K( zPKts7NEY2gMb50$nBN7~gT4@EZlf*d=s*;tl?WyvApSFiDHFRPo52njMlQg^DqLGL zZdge5fbDAcV9|*zGJKR<XtGqu+u^J1bR~7HA4)E7FB=y*zcm` zs@4xWOzl|7SY0QgguD4baK#<8g&MP z&62yC1i`~wKjQ4Iu(1HAw{9}S+Y(3Q3|8D7_LvcyZ|}?Ub#WVBEauVk%aP1vCkX&i zW@N-&(k2nZkv^R6zQ{XGnR)|qk!?g312bbYR7L9TR{_#i zn+MYa_W#W#KCC+##tXc{Op9k;+n>%0jvCWlH%*}DZT=%M2DDPdS;aQGfkE@Ie?Xsv zqE;)ofO$^AoWD$W-=>L^c3Nm}Y>64mdK%~q-~bH6%o%+|m2bHn5f2w* zSBn+$wl*0eWmhbwucQu`v5KL**X?fJU@LnCr#T)%?WpdS#|VxJCmFnU4`1o ze?KC=zBu)6_-}6D*?>x<1hpNYDz-+2IRvf13PFF_(Max7lDeRb%y6>Ri6sm+;fIW+ zREu*7>eg1bm$CTT(++9{!Y^(M4jR|#rR2LdK+YzL!>8Adi-Gh%m$#{x7&4>nEMQ-+ zG_RJ8eTSh|_oSnuoGq=@NKrUBk@3={!Nj8Lp*`|_t-7_la?@YGzPUuaBVTK}N=GTQ zgdMJ;3cT)frVTY=5hTTwMkLp9N=^>F1KcELih--`s4o;33Cb113|?*`Dqw}!e+zzG z3|>%~${?C^jh}AMKr>+ouwT^;(HSXTjLU~vMR1A4}@Sz4YsU?IUMTonQvK_ zW(4Sku|%2ebCkklZUPNr=JVvO*b^CQgpfCbCye0?zWT&KPPz zjbBzL_GL@GvN#HAW}3CvHiOU~7Yl!KZcNo(>%<#_@->1y=70(QZW)!%xxEPD*$JO+ zeh5mg`fS(pwfL$h0XeH<%^b#)+ALFjVw1# zwx&me{C=pyVu8VjW0lxlsOvl>#Y@o#9E;6U+fQ|9kA_UZbDp|?0OZf5nyG=cE`K*; z%I-Mx7Jp<;%jdHdwy=u~m5b_`LVk8UF|m9)oEJ*ue%bhCjO82#QkOYvD)ik8dhKnn zOBgVbHD|)u?pAhb3%0N}uleybN*zwPOi6;AMO~iI5e zs96(Lz|JpE2(M!s&j64?h8s9WJB3L397@t-tq=DY(kyi9S-p>psQ#BilUyhuzRUYu0wyYdEr zIwJYRs|7Bzh~X%bd!?G>EeAfb{L*oij_G+!vMRXU# z7D1{O(bpTeXi@{8!{U`&*@@LpRHK1{8~ZZ#_lx+Ljha7uTa-k3aN#(L65rARkdhgi z&eBfy;eKRE;#Qh`!J>#~BS0wX{P^u6$hi|6Ait*uP@6#lFU#e?uuX$UxtT`#4+AD@ zyUiVZ;(uoeSGnAkXnpFbW6;CP-uw&5p=hBz>Ju3F++sUYA@M3}eS;l<4EypEE09R0wJ@g- z6)|8L!M{UDXLjXW80joN00)ehAjjC=r!Ey%@izFXA-qzVMsDJQcXYC(pCMtDl0w9k z%Pyv8L-DIS@)a_LYe?&F9RAs>pyhH<0-yfJaIzpx%KK#zhR0!x=M4o4HpgLjZF4fI zSILAP!<;JJ{Wh_z=-VX6+_H{9_Ds|fGL+i#2X^=n&nRl5i2Aiql_CRG@vn_cCPT6% zcdQw)=o51aH(f*1FbtDIjqOGosN~LDW?-d!Kj|9`^zwoERJ?kEHG_Ly#P@ShVub~1 zUM9Qb75a+uf950%v(C7z3g2+}%F6oAR#j^1?q3FN5pM2}9a;(i4oCx?QCo+tJn~SuhVUjWN*LoE`rWT|MxGn(bH~ix`W!Vpn zEzl)lZ)m01X({U23i%lTE|O#`tFe;%r8A5K-e#e7tgvQ(bHepmT9``o*WLlEbLVq; zm2YTzAdKR|+MmYu++x+HJ?>g61|>Z17gFGpI+3lBnI^FxZhsneBBLR0Cr(LqkHfRM zz>&-_IW&yE!Cvn(uvqbMaG56gB^>kxT!S%d=1L~y)904h$0+nCQ=8f{mEUMe9SJ!1 z;tLTORQ|KedZ!b`L|N$eZpl)HNuDdW_F(OPm?vx0&7*!*V@KdYLoR-?X~OX_xxqgv zb}}yY!K21@OhMiP-mI)B$;8}1sp6hs*7Mk{xci)N)LSnR=AH^&Gap= zLWxYxSEn)g9tL93Z+q{wo`i8IJn|HBGuCyYJ#IsN!e;+4r5JPqXl&Kf;Y+@aj$w;)@$GI1Vun)T-Oc3d_yDCDMDXZ25t%KDq$HZneBzg4 zksCalomCv}JbD}Tg__dgh_r+xtm(bP3m^^=%w0VtN>X75R{&OgMevBuDFA8m`%4Dv z8eiA_bCf3zuWr9WjgB{l8PXui;mCH>`WIaC=3jyc$lY6Xb9NbwS=t#Jiqn*2;2`xr zjtj{Ta0N|EJSVN0$E9&2Bi3rxfRl5#Hb zuBd$3ZkUKzSd-@Ku&!PLs%J^d6rd7(r}hL7#G_n98S)PH9T4y4m+l8kCkP(-OJO8$ z|Ico7A;u=LRQp>)o-}#8dmz`uzE&3Y1c!|5@SJo2d6VqH?Cjsdn(o_v4|sBs?Pi?S z(HU1tdfB^#LF6!H+uS?xYRV5!))f<^F9X|&{f*NSq_O#y9rBx(4xha;|*1=63%v*0RtUz|{S`8_-f(-wm51AV3LK_-}FEXgBs zGVTAE?1`#|!)yUh^76^nyRlzl#S)b3kL4!(eBHnb_$RpKxHqkc9K<(}o~^Kfy91di zw#Ml?96?WzDw%j_Hx2#Xd6W`2xZuTUc-ui6IMU`dDxYx^*_qw53qvxLk5UtsjcBR> zC^BSnS-R{l^@hj|Qvk_(eMCUA!{T$wU(DmAbFl{7P|2kT(-%4u(xk{i^<^6_9BMCl z=Q%*0H>U2dT4AvJrSr(Y%RS5h_SeIMb%>mpZ@@8XQR1Bk+a_iXIz%Y?ModYVl<1t{*YF;Pm^ohhv}#+^BB?CBDLT_?vQ#Kngsix zSydguGt1WSkC^-Xuu=lQZU}IuMdN6Qmo;ktUDPdwJS#m zo~Nm6CXnC6z#Hz@qdcjZzL`z3y4xNxMx;n;aG#*oWgNkytRJ>w-%Ow4T|e`(=uPW&UDF>FV@qlkQFce3>5 zr~5TuVQVqfYa*@`fph?aqKQ-H=KBS>WO2EGF{34Rj}y~7(OfArCwr|d0>4GM%k+&+ zTS|+sS-x7qwCbH<(s?}S3nP#1Ul5JuTX}%}Nz6t%cD|kL^(^yo0H(j6WXIyl0z8_H z<7u-$z=ei<{|kOq$?@Xhav!SrdY(7&PIB*sCM_Sv0>MCzP>ni)?7UwRdTvq9(wcLo zB=g&}Ob%>;ab(bWy_hk&zhKFFuaxdbKJ_@!-u#LlBB$Wro!}9>SH{n9!bUebKPydP zKl?GfGQ26H6qGR>t#GQl@T+^KTP9f`jHBSGmxr$ea*k_=$subPuc&+bCn)82)QfBn zmfhhnyFqBwr&*v4YK7Hn6DU?@4HI z^RHOZF}CZ)zRVBDkoyv{%ju0KYruXx|;k2qI2Knl~IWR>r-HI?@PVL7n)<) zM`i#c^LPWc(DbIQb>}Lq{Y?fEV`kBmlk0jezk%1R{WnV^Tb8&%5gJtuqA5xmSGD0A z%0)DBO8FM&e^D0V95h#wKp(}Dy!<)`osn>ly}PuB z;1M~25z66(daxOC0aj8jm;nP2y6%^U&Sh>$Vw-ZwV->fgTRDJ6Qa5a|x zih}}AYo(RSU*z596}{DRotLIg7*rBbi3K2*;n=zE{MoZuiCE^in7_5xm2{4(_qVqA zK+?zRrO*`-&E3M5>FS~Lorm1tScJEM zuyE;@{lie|v|5qp(WVZ(FaLqSibPb7Cj>uk@Vv}-rF3IYzh-Q?4XX(-k2U|Bu_a~T z#7{;{s*F;FpJ_^onSo(i3S`}UGim0Us^Paj_mCY|n0VNn&m768X#Py@HIoR_ zWHzu7jVR5ZU%F+6>VOi8qj8hk!FN<{{DIMd=S-vLPspxfpQ_YMCXTScysaE7zo^Db zA$K1j;~KX1%jQxsfq`}cC&Dvmd%2o5X2s+YbuxN8Zuw&N7Rd7jhHC0$qo^s$BXUiF5uT<~TPb!yRZ zi$BpFmRQG-`W!)^n`HCgc&TjExKLwCFw3Jz^5TAIPO*=f=8GD;*8M!p{UEuWjGpsn ze%mC3AFY+8hR*+|I6YgPv}j}*RqNb14Vl&yMvb%U8LSs}H_T!uA8OeQ6v}r4K`#or zAU3P@ZfzkrCX%%bkxZ=Q%YeDax(#pKlY9~|z|vsYl;yG29)f)u+n*4V8-DHLs#sHN zh^ePf#o0Oc3$AnmaCOw1d0r@Mu{&S5S;pL>HaQ5w{+U|1~qLE2>KOvts^y~ZKL0J@A%V|-O&W7Sk;K+nCOR$N;$G)>;kBd zHj*TtxVUqvYgq!|Qy~WFxqDR?PWB;Uuep#~{b*?kAo|eLlaCKC+`$(25_=J~NmmgS zrOFvsLDN~!3h4fq`x9Az^;!;IRZQfyZMA7Re5IM`tw)+5!%SiV^6U1#q6m&t+tUKn z9+xOIH0av=zf41*;5(Ddj`Nnp46jthR{Q|a>nWySn?$7|MUlNoZ0f8oeD6O7BIciW zSL?-FYu4&hN^4LZa`AjTY}i`I&M63p)dc=sw9{mb+QGcZW-qZ%vDrM~$PCbo5@z}c z@(zk4$jeuWs6JwY6@M%t@tj(-8+)AWRgQ1NC|P*D{S|a)!m`&TBjIJ0N1V{=U+`rW zhDQt%_y)5+X~I}nT8XIlY-LP0gxBqLF71tG<1O%G70|l?Z*Kg95$N+jbh}d|;zTCU zOQc`Qtj&G}wNk?WBHOk>z)&&fyeoXC8hZk4L3eDID)6|;U(G!H)oTC!hC^x1SG#n? zPz61We6g<7jGN2QvMxqzhMmOp8zFPHM?>x)&^m*lXT|)rKP!vexGCCVytE!P3Cn66>0sAqeh zrqs5uP^Q(*JR&E;$Ra^Z`rc2-AxfBIeIN55jJ5pka2%)cx7nO#%wSC^bgvg{)19xa zE+fF}e#~V_lXqep(=*kUW169G3YcoZ{l}jFLVc382>!p6w%8f}##PbuNRfi87^7*T z{k{;=5OQETdj~^rmvosKUa6KLJE7f$orRdmt>Lu>_!@XF<7q(KK25+vyj|0tR^76Qyv_TM_`Q@9PI$$$Z0mUw4lvMFImT~w4fv`3pSUSU?CMfOZhsSryh@pC zx!sY#i=Xr~vVB@oZ4%0_zFrrb2I{8(J}w*Yy|);1GhLQ`R{S8yWsgiU4shr#tFh2` zQQ58K#FVA|x>9Xba^htp@#OUN>QQp*UqHT{6&O=?jFO+T^IqMbR#uBGpNt~D4;*g* zDGg`SlWIHhTlxgxdV0FkSwGF^ap+b=N)^4_dv#E4Mo2jLII|THDg1~#Q8Xahx%~Z2+u@zg68=5MwzqD zcw3c-K2x@Zo7#TdM%f@Q$&UX^bueuBPZI)A;k50c$-PlnN4cDtG!vF~CK8SzC}t19xEOA; z`ff#R3az)7M}{rsA$Z`2r9b~Lq&Aedy%{qdOb)<7U0dkfrnXQ;N ztExS%JKwt*#@HUolD+pU8uwyF&1$pE2B{>zD`4^YAGDQy%ov&?D7D)pr zmuA2u8fl`TzpS`Xm1^s--j;|}$0&0j*DL4SDNCU-k&=mlI~Sm|k*=jlkUA4GU$M*h3L*9a&7Ba#Vd0v9kG#E5Q2wlTK|VgbdP_ZI8mi56i`)KMu72J4u#AWP)oljyRGwmYj@N%#U`nA zGPOxv_f)3!H33CEA?^)zJ-r=!wy9VC1k`X{Z3unPD=yJtx~#4mm2E$WT4um3s%FmI zvLP?lk=kDDPx;i`q}Y=lS465_G0i5~#o_KU-z;&cX zO8I(GnIakqb|#-qKCCtS-M+*Iy7*;UtKZ7CJVJ3SoBRRTjkWjK!O_KEd&2Dx?vk?= z&eoFH3QpvPPj!V`sFR2Gx9W8WLwFX`0*+r;kK|<}(_e)Fg92Sh3mXdvK;9p1RYWWU z51@cr(F0Z}#9YqkD_28w*aj3b>v{F#HT*0l|5c78_7?$$y2$vF-d*)5pSMOyoVIhE zjf1jU%dVJjfZF&1g&5O3)m*Vv&^Kck-S2oU(X!6P$97W{9vCI6(a>V)od^QVXw#zm zQ8E*kv+>3xrlLfw*{0LvXIbsz8n6hj_vXND@9?nQU*2%|%}BrYV3+A@grVIN&-MxC zF+R-8ofLayxs5N}Hr^{YJXu6!vd|;0GURX8=lM@x-lc>ZKT7y|HY2qVs6wP-Oa!Bb zV{Nh#cUbAvwApl`#OS9FP6Gh@CKW|VLjR{}bc2#IbvNyBX48T-@#!aq*7zSX2U)%o zw4kf@DXHCJVfqaA>@%uZB|q;^;mO-c0QSe_i~+wjM{ao$zIYVduX6Li32Q|g?&srbpp zR-rf9b@YKtD=8s^E?;`06+U2pbG>e#-~p0<&!DIzWQ|)Hm!Q~Y;0B6 zx~<5C{%&&{pEQo!$Bh7)!RPhxb9k()4KhEd|XCkWMDa!>_Qj0s>|wn!rSlh?9CfdH@#PGoaqx@$8sIOwuE>QuzrM%nZ- zH1td=L>1H(!=6Vp?`m>ak_PR{xG>SdfPnquez-0=U>}Vxew-0;mp{s&mh#^>YEfT=88d0ENIVh-+rqs~ z(0u>8`m|8}5I_>*M|j?tZxzhDBlmkY91N>vMB@gg#L-%2f34bW0nvG$r2(-!Wh@<( zje%iS+3BhxE|E?4Eb2p?`e-4b1*KSo8GJqyodDko79;dzh$^NQu6VZ}vm}L}FCYMr z>$ifm?zz^!Kfr=DkVbT(b`2ExY~4Hi(OqrCI~8#`a3C6)p$se%*A?M`o4nZNLg|SA zO0+ABYt#X7bH_G~X45+Z29a*&&&#i$yIK}zn?2Q{D8NGF!#zjEh>_wOxzpNTsyR6> z|5w7~-|52cj4m4J(yf2Ki6i?!cnnC0E-uS)F?1SQ5pZdo0pmi~%?&AjBp}0MvTU@| z+bv`45(sEqa_@#yaFh3b2NyaA1FX!(PEk}#gpim!)lPv;O)B}8(A4f9l`!S3gWOz7 z0mxPMzx2WPG}iw0Nwf$fo6hdJLY8>kb8TVHnEaF@^yhe*VG3`tNKIVfD1)U zBO|IRLf9uOR(c;3lN+c~toWyZ1mYLj1nToIYhMjj6G7|gohA};oB=T+RrcUuZNnit zJ+9PFdRPKz7(SX<3&gfyCw~CG7+btju!C&1&2-bZOq`w6xc~K~Pvwim>Z?Y5XnXM8 z@w2qTgAU&A=nCr;syOR+Qa3J1sH8GSjB@>KTv0W@0vg`&T%NLp^J?`SFrYDdn&Eqz ze=?zIQlk4Z{SFI{s>q*inX5cz2&s`7d$vm>%RGHC{g;rxH=W;8m20H;JI_{w`B8qz zM;uR+{UI*P&iw;iEE(XKd5R=YpwUQHk3(PLfS5% zg}OnK^Svvl-0_1`W$qayO({Ut!<_m8uwdQ_kf;G>^=6AtDy^PDPYV0Rx0-L7!@p0K z^sw519npss#e%!duWT_5{F7@pz9h5uJ1HEFEU>CSf(*Jf!q^m8H;yP-`Z1af`IWOo z4GK77IgwAaNj`aq=ZQU*o3h>Le!HPdLU>DN$QOVjt+M{*(+vkD+t^YI?cs0liA=w0 z=%p_EU{hkN@8$i3?#jURrM5FaHc0GGa-lH^|CB6Q2K@L7HU6>}=ql+_Fg=ijxER;y z!xak=TrZ_kmt#Bb_rb_9i$Fw#U5dRo8c6JRdRhc>FC?bJn~|)8?muLVyI3}##*P-Z z7>&ioqHV|xm}~rlZp-Gp3&&LGl#AJTRTs|;~11Lg}*C(~EQCEDoSo2ia*J0>r zbL=*H)B|nPzDwd`>Z>O;g#14P+pc;t13k(H+qtdV4;Wp%NMBgBV$HY%SuwMRVR`;I zi|Mr5W?%E8W?6w4tomR7x5EBrVHd!lk5BJV=GU)n=X4l_?5JV$fDIoefq!G0B0;n5 zJVQW$vT^2>Eli6ejDz<~xmDLqqOFRf2W2sRomeWpaR3mL=WCOI0aJ6oJZ#e7I8fQ| zZLn3_v5D zwI=_{FxtP7L*gKGsdY44Y9k*t*<%;4%#CRY5?I8Bz~J!eZ942sY-aCEx&OIL@Gym4 z39A?GUs3!_5#uF5*j@2r!@wR zq5UV>OMq#>jRVk|)FC2OR0R{|4|ch6sX4ox-#2;1NA7p{&%1ty$)T4 z^AYfW3`imumr4OM!LV%`|AaMrezDcwG~5-C^Z?o+j~Ep~|HfD{>(BJk>{w9`&fZoj zb3O;FR3D6W{kjzi+ppY@wbI~-E-=ZC%BNnbpQj?z*&cB`Ktr?EUJq(#S;C>f#9T6S zEHa55@L|}qJ$e|oW2dXaJA(pSb`>-%Z76@^Yl;rAA^j}77UAq@}nzZ5YknwJbrikU6n%n65 zXE#bxN7eF)z3WCK7tyK0XBy=S;HuSApf;@jLuQCx1I5aY5uCWsN2(4>*8>J=^qHD& zDgxxn8pQpkyS#tb3)>Yd7pLqg(CD>^@^(c-zCE{g|9{&1?nkQsKl;iW-6Zc2*_Atz znHA~sP8rus%U+om*9_T>+eC72*(163y4JPVCAx`n5t->;dlT38eX7s*Px$`!{h8-= zU*q|FoX2^bbJU4%`mOb=1ZsHkkFO>N&?Q6Qe zd{f51v`jXXsKZH8u*v0ty1+T1th1)i2p(@+A2kbB7#f^U51f1X;ZV&zzG+#C7TyP3 zSm;|%3^kwWB=yE0$lLr15)k(j;Nd%8}o%8u;q#}zYjLVt>p8CG+1B^rC} z80Nzzfl}PHYHvL%zbRHSRt+wlFC5f1cZhMvMQ~~$G!~n3N53E2>A0&K8*MN<1HoLL zB93NC!~M0L?ardFgM(Y&%dmfhl7II|IQi?a0B2&!>t+>vGCu6B5mGTtj;U4nyh4ou z87Jj$KzjLvQw4^27cKvHLSZg^UpCBZt-nSK)|V%&;OU|7hjJX2)EWDDy#Hgnc3zc{ z_kUnSUp{$_Qine~%p{Ix2`7#(@7N#R)|84rK5p~SF(|}4_0RMtdF%&v)K4uxhxY6d z1Bzj^4k7}aWoH-lsQ-bNgY|WB!@-@Oqwr5)vFiZoF&!I`v z-gH75;FuKOMQ%3efZDk}Qw!1kz)#|Z&izOncYz2r4Z8nVov-wJsg*F_mo$vyy%U9d z2CNlZ>)MVA-z~Ve@a4n#H|OuQ{(cFtjw@VV7-`IxBk7jC_^X*p<62)wh5U8(m3fs@ z{#1s)0>#xdZ20N@} zKMHgqQ+p*Y={d^}__g^b4~XIc@F*A~(2;nKm}o*1@n~Y9DA#)Y@A;~i^K8$;Z{3$L z{aOO(2%u`rag~5n)a9gT*2w!fNT>GvUklfEYp`O|*J_%_$--oCqW3h)sI0`dnCGMH-;OG<^*A3}i7xnc)|X}gtROx*Z) zNb>Mt{XH$$W{DMAZrgXk*d@kRhb*oK_(#znv~G;XZmOP5i+%g-sW_%TyKX?WP6)?< zjVywr{KE9ZQTRes-5*@b(+q0X{|o>-mzBc+|JI;e*}PZ;TpN3ghD4<&vJ!J_f&Z<< z09{2Ez}JJuGtPE#RrJMqeX!Tr5UD6BGav%r2(T+EF=&b>I@%3$k^HGnhgmKcnm=S` zV?NFJukh}}E~U5Itdfn-p7fz())zsWuY7LoMEfY1j6MZ+pcpl1$mq!`J9TRrc2z57i0?+Ix zR-)8=Q3^Ekvy{Z(!B|utlDlnD&)rya-gfp-;#!oXD2mPQq@qymL%%Le5Hcm%B0I3> z&^O%APKdyqlWqE*E0pmcIG+Z_2w@XcDKxhRc!Y)&T3j- z*c^mz)6&+S&DVFT%doTW;qpBWcpu6#Jz}7F@2V76mclc_iOnNdLghy-=4axik`Za8 z6Qu& zyVdW*>H(#J7(4VdlO_mG%Jz3gK~oGy833!iz@q2zRo{BMF_e2fD%<+^gAdaavB1)) zCSIRo&|QU(f(?RmHEw+3NsPR-6B*bs6a<=EccP%yMZ&zVQ-%1Ox8!=H3v;SXSIPnS zZi=+b)6(be%P;1A*h;HV&@!57{CXGGC9M4&%^|>&OTj zVgjN8I?;ZR&~dB#H*Qd^>KYKb`qX0?cak5=+0xb?gDYBUc*$%M_FB&!2OJ?A!=cyi z9VR993jm?Ms!aJ)e80cG(m!W%m;pQXtQIlH3&}dS-8eTGlB>1$a|vrO{pG&AZR@WB zN(lHxQTlw6%B??QnIKTw8`;PFO7$O)11H_wodePZBoGn zy^W3$+HIZ^)l@4cc{b27`1%vf=%k_T+s)_Pf}KBYZq0a&nG941u4OZ)^9q7Fy{&%d z8_y~^T}|q-%QHSgU8e2XLbWHlVi#CJBYO=zq~}K>^3Xi4TkQ~JGEfSo~Y4Zxr4M7E8(btVcb`G2ZApFd9A!XUJmw0 zUYjE0U&FFY%}VZ*>Y|OaszxX(p(MlxvomjhvUDJc4*Uq?#4y zgr*WYm=x#OX)6!bU!lx^Wqx@>PyNYv4H|PIud(Ebu&>-ULy#Z#?ew46P+Mx?uvi*X zXyW4GV9$QlO;`XM_AWVQAZKo=Y+c!o^9cMVI)&=$)2|icl>-`7UkjKCL4#5qq{3OiB`x)4d zNKdEdls%*TX$_jS{9R&>^UPPF5-mx+5g8im)FuC6?1v3J5IJhQ^x1JPU@_f;cr7rm zoH4<&kE-C+Zbz{--$9J1RGv<92lF9Uj*d;vV?^`#XQf<}RFR4B@6a9Wbe#1>z4qN6e0I*oW708a zq(L9|Yk8#c?ol(7vgyN+(nd4YKWI^)&=?VZWkjEK-RVx$%qIb^ksil#0pK?~7^`Hc zUX8+zq%@hSaS1=ZTWmtJ)une>dqrImU&1;ix1W8A47kFO62_{a=@pYv*;cN zr}${_^QSdTXj|g>LD;1{;ofunw+j7s+u6AcUIeIRwLZi5u);7_(69&UXZ`L22^0|V znu-XlGIaM2Sit>ylJp!HDImp6=U>Gng4reJjwW>@2|0G{AI2BbxE4hcuQB>gd<|H= zO?axfQHvsq*gPR%ufk5Rf{K*7ZrTZW7ZlC6lm3QY;?Q%V5KZHTC$1|<{(YJ!tb*%J zkbVmh6hQHmKRhxQP0~md_(P4Z=t!J&lq4i;ayApo`N{ft`!Cqs`|42vR4# z5PP85y9X^s^zH!V?6#tD&D*$zpYk>KEH@K!Q(AI76-$ja^UGi^Yc$fhg(^Zdrzx7~VUanPcad%vY@F5%SajdHjSaqd*6=DT>D} z=4y}5jXrQ&%U1Se3?p&=Ky45N_t33e*DzzT`0uN5u}`d#N~Koptu`v%1iQ9Kq?h*E zO{T;=xZt5WXJqRa?su+qNZK|gg6&O)gZCyD-eP{RU@x5I6TdV=73}KS(L}|N`2h{C zb!jxsK-*8R(k3K^6;Y%=)b_zaV_#%J z=S7ZH?g-&I05xEC$MYujh#p8VgXq7kn#q=oGPJTr>d*jBEX^;pR~a&+Z!OkflUE1Uz5cB$iob-3B9V834zOOaze7ldk+ z*A&=deM>zws5!&XG%YK0x#gs{^lxk*ljU93A+GC_g!Y=<&{zwZF@j|*;1DH?e_A!z z0TQD3guxYL+P8N-5g%S6-(l(|Fe!p@p1gU_qORHIUzp+!wp-wsXRnrOY+Sp(hb$7| z&GCrMzx!}`()BRB;595Hfv2L}8uvuD!jQ*zIB|j&VaPt3l;~S`G3=ynbf3PvInqUF z?~P~IIzTHwQXm*LXaT#Ntp{o#aB+-ua>0Jrkq;#bIF%?5=qO;m%eOO&%v54tdc*{m zgLzBxfrZG7m0zg)VR->Z^%t{I*-ay`;NHpa91H5R{E4>1;>D_32yUCaklawymADxr zD$BPo8{@rp;-QH$K_L(L{wEh8J^0OHXMMeIPO46|>{y!Tt^r>!4X>haA_7K=6U#(G z$3&hMpo&64?K}#)un`2V&>9+dxW*O?x|C$o4sBlr3;f5~UsjyZo*$DMMCP{L-GPq% z*8vbQP)VDV7Aj8or1|t!j$CtXUilcwwXozyMoYOXR(kNET)2?ym0jtQqx${%hT(kd ze|?2K;rJ`^l5@CH8&^iD{h&U8C5JD~U+>qG$PsW$eQxf7F`FlfAig}@{Qy*x?Tw)n%XaOXvFkd*caWrCw3m$U@Ejs%Gso=e-AYG701`1fZq`s%wYbs@VN7_R(cu>ar!r;{VkfuPmfO~O#i!d? zVcUuf-!bLQ@@W%lZ@s?}Q>IjlsJl=FW(u@n$`ejNBp>*}z1C5Crbs`sDG`XnfQl{` z=slIkUe^qQ&O(EB<~SmHaEPUm9k#wc`=`G#wW^H)>_VkNUx&(yxNcV4} zn_)`-HltQl-WsVmm&_^H@pFe0Kfd?x=*w+0AU5r=^rpK6gRq*!UKQs901_{Y+NIeX z7e9&tB>ANPtF`lMU(dN+RI=^M$a3Gx-T%Fbjh9@Ab@e9E-?XUT<>y&sET(kR^QUC5fDGPD0&HRxpE~)k8-ZHOQEE5;7c%!a0tLhJI4`qY%>K!WF zIZ3huh?0;4XM<}3=dh(VYn8&U3V+Cd!gzPmX%q#(?c6A~#xu$FNu_UI6mMof&Fz2F zLxNo0H!jit4mWr=>N0Z-PlchQZ@a4D3Wc5vAmbECXKLHGTsA=@t5^BaW|!>EzQ5v@ zI;n7(1&h_irJfTy?x{(DQR%Q^y(w>DNY)QFngHU`C1683ou;+B@X#) zipbmO>Yre%JCPHLQ(xRtUj5mT68>S(uZvE^ZnNK6WwnJhp}> zC0wbEm}t}6bmFu|473rh##XdO;N)zF)2;>aGM^SsHFS(+fD@qKWG_RLQX0M^ug!Pch#amys8m21VRdYd;p1Ia%?)&GIq7HhcA6EA zRt^@eLd(u3l&n>Ts_PzC+vr^UP07C#o#2-I=&P#dPL7m zO5Qrt`Iq{hVz5-zE!n)q_upIjQb9jGJoVuy?N*CjURy@F6Udi3P=Z{xkq#=pASu4k zoq_f-FEtiHEu;Y15P`=OTfX>--VW5Fl~#7~h76?m*t3VGmDt21bAsT#G95kx{L%q~ z#|wTwQDFVxR{Z`hP`?gNweA#3VMBgp7PU`JQ``Z4BLHVb+^>%zBtjQa11^(5fg0VL zuK1TopP#)ahBN3i&Jm97EClmFJ5j}7B|DAG4Y;yj-zlLe^NR4=3u7eCoKrlu^Oxai zF!jM0FP?~7@=>}e#+n^dlg%Z~rtR7|gGjdB(RgAJi9HAwbUTU~EI}SvOC!u9nT!pl ze%9)pZ;V?XtpO%gF~&ptk?`*@eF5I>24zrgZLTN;px4f0!0}pB-OoXCL!1-4Cz4PL zCPB;7F&U#I#SxtZ#f8`qOK?z` z$Bu4DNFZt@l|jEtZS|a*RPLn>J=neHS08@O6!-~<>qM~zeTI(7NK!Q(M2jhDs>t*_ACV%!(sZAX|lq)@j=*Z3Ln(Vb1>b*Hrtgs^|ZH_eH*`87=FEcyb z9`REgM|vHnOFdSo?&=z_l0-?PocgRSZbDjPx)1i}K-ap&=>pzNtB1>!<<}IKFu$@~ z8_@#hID%B|nSkqSN|ypPs5MJ%4$uMsPK7Xwtcii8j1gSdc zn7yCCYaO5f0>F_aRy47|S9yhl5`ZHmlvzn_8p!sNpKuZ8l5IYR@<`2+#LEd9V+uRK zDiAi{IgRbungkSe>$E?|?OxAkwxQ3Vm{T@3X2H2((rs{wazIdd*;at>q;apkSpc8> z**R2Ar;-uNF>_NA>|R%lMBl_sDDRE#XST2Q-nzvGlRyZW+s+R#*_Px^Y>S5srbSFJ z3hcM((hksMQ2BzL|6@eY6ra+2>S2mBIF|a)57FfeSr?KM^?S4zYTzjU)y2f2T(IUN z_L{aJFe@wsxq!T%R1YXn8&9@=5lBwTdZs2Kb!Oj%Pk~ml0N4`L%&Cr&QT$LDShb9G zFj(i;-3RnSY7{t+Sk_Ot-9j3)c7aCh(t(5(cOYSvKWYwTg#wq?X4mV<5maK(3kBd( zUq$StPLUm(vqjv zFeN9jM@*TE+(pGBDY6p1pjo5EXcLE!)BI zB*_aSsga@_uXAywl-^1)Y|j?fY8;IoN{@h|1v}pnIpW~?n10Csqcx=fsVW8H(ZNd6 zD`E{i_%nY^D)cWd>AD!ufZcaQ@h7grM0BN$G*|6RaTq?cn}Ee}RB#Kp3qFT>wR52^6v*2nAig~lsNpnS?Z80#rz`>um%EH7Zb>viYj6L1RR2P~cIR;lv+ z?!JIXU$GT7NUYaBpi7J_gmGoQ!_UDZ?Zt5*f;W1_H z&+^LMVcI%1gkE<2II^%od|FSe@~BE*#0JN-Y#gzPX83)G05 z3vWCP7pB{tRjpBe+KvU9&R7ZZ_t(2N+yblbt42)>jxVIn{V@eqlAe(7C(7cW$(-ya zqi?@dvv?Fd*st=DoxN7933})GDGtTOP#MRj)+MKULvp=BwbG@k2juW0Pcxu7BT|&S zytb+?mM38&`F#^-fhXXRM*l!pimmXD>1bY{U|9u>pUQZ%8ii9WEiP&p*u8rf&!TS-IH5{jAc+&5O{R@Awg%n^G zbZdbPaoZedPj8w(*dK4P7ubF(=DmmzpcT0lHzwKf#y2 zi-zW4YFQf;ZQDQBI*Z@$!*X=;L&8Bfp%CAz5X$4&Gq5r4!nMtsatoM-(B$N3cfwnO zyH~+UNyOAMHR+MON~!5mAl{VHQY0QVAHJd+eMv{k47vWgJH_oE%L2m=NgM~<3B0j4 z`v7(Ol|BzniXrKMLHeu%;cDr@3XRi!y2lSQ_ow6Pz|p-9+M@%NDM3TouEg5A{UFSa zYfoA2yeNB22zllrvex?&?{3o+7s)CS(SYi-(%iL8J%n)T_m^p($A{q4NYpn32cj%~ zjUt=C5m~N=_w4gX1x3peIrBCNk{HR7Cm_~Hye13MDx@~R^H6~YA1OVACxjMrHoag3gRuXmVb6P<`V2X2t&?J(m4ns9x4LURMk7Y*0MDqyI95#1q z_Q`e%*nz#~=_5V4?8%9Q#suo&@hFd+dinWI25 zGmS9zfnnlBi09!F0mCJE*YQHxeIU@Xka~OLg(V?kVznNtBCdS3NO;q6$W1~wx($}U zTI6Tle+vgFXdK~WwF%(f9)V}UT4BOx6eU5PDZUscIxn{I@#n8u4P`~Z8y|Re{#a;G z{KdMk;3>!1_FAiV;GLd(3kon;vCLE&9aPcJ-H=^(_x_m)vsb-RF2l$lKnn`hZye`5 zcG1AF)3vCDV;Wg}G*2tN8;r$fOS&_QENP90IvDjJ4iF^40wx0or+=m#NJ}R^ZvV6W zwA^My=!fva)RqI)*H*XBj=w3i6aX7jhTTC#?DdedW5`FlO{;;o$ok@#?GS3~$~0Yx z>wAg{)N(&SIN6h<--Wrqo$FvT*U!Q&yjqg+tG^1zcJs6(K@3=s^TWQ3QRpRo;OAXa zy3yz`%pnaPsBGomNi{}LQhe%ct1rszP&m;qNp5=OHa(j1$ATjq7VDuc42&@Z2k%w- zFr_x+0{Yiy5QP3YTj&o^`uzYZ%OSl0_Y&0A&LPoVrRhWmHq0jKF&JU2>D9YfJ}6hM%_$i zMM&oePkIB2Rx=S=4tAZY1nUUs@jg~?DvqsE(kbzH4mf6SQ3sbfZ3Hpq>X_An7>|3| zwFmwM8mba}?sq^NQF8&^qNB9~cS1RT?)xY#kD|&W#n7}9w(w&lLq+d`R4|n5cus4? zY3m$s^NLcqB4qDJAhqnX;#nb6xP&C>u4VVEtvLeq#1T~nr?%x8m)8o5R zE_GM=P`I+tAUMVX%~-b2q7!7zlK;G(iVGzaSY8|Zwi}s$yV&8j$1L3r!gzwh$w%?R zIl#4nxMQw33*Q65;$UTfQmM;BM|auHe2Jg5bPfP-1h0Y8eeuVz0cg;%Yxt5Me-!#A^uHyW0mh?etK~Np)x z$;h!+wc@c|t;ugdbZ&wuz|H0&nXY}*gkR&3*2bAvDE&H<;-A(`Lx6c6T$`(u1yc+jSKNw3m3G!NW-^pz93Q=)#i`EpKmVhe<} zn`Y(`03kdqKh|Hw3}8q^CFLm};N7FmY)_K>vOtwUHtiKn9*E;)&}RPM4?ZGENpdX=DG@(yZ;~w40sy{ekuPJjg)eP8t$d@O0>VGI zuf;$e$il$Mv)}JglS%W>1hK&+Me$M_ZW|6AfC<`PQ$i^&$dBN%(`ONainJAvgWW%H z1M9`h!}za0+T#n+XQhx1(k;LiT^`xkYk@omTf;n20Q%R-u`~L&b;rqL1XTysmP0(4 z=D0|gFSA%90zCfogMCn-20`IsScBeIrM$qX9862sEfnHczMMm-zig#6G%T+!dhTTI z`ETUWK~%V_?cacY#{W ER-> OP. This should line up with the logic chosen to determine how visits are created.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,VISIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,visit_source_concept_id,No,,,integer,0,,,If the visit source value is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,admitting_source_concept_id,No,,,integer,0,,"Use this field to determine where the patient was admitted from. This concept is part of the visit domain and can indicate if a patient was admitted to the hospital from a long-term care facility, for example.","If available, map the admitted_from_source_value to a standard concept in the visit domain.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,admitting_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was admitted from. Typically this applies only to visits that have a length of stay, like inpatient visits or long-term care visits.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ADMITTING_SOURCE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,discharge_to_concept_id,No,,,integer,0,,"Use this field to determine where the patient was discharged to after a visit. This concept is part of the visit domain and can indicate if a patient was discharged to home or sent to a long-term care facility, for example.","If available, map the discharge_to_source_value to a standard concept in the visit domain.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,discharge_to_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was discharged to after a visit, as in they went home or were moved to long-term care. Typically this applies only to visits that have a length of stay of a day or more.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DISCHARGE_TO_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,preceding_visit_occurrence_id,No,,,integer,0,,Use this field to find the visit that occured for the person prior to the given visit. There could be a few days or a few years in between.,"The preceding_visit_id can be used to link a visit immediately preceding the current visit. Note this is not symmetrical, and there is no such thing as a ""following_visit_id"".",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_occurrence_id,Yes,0,,bigint,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,person_id,Yes,0,,bigint,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_concept_id,Yes,0,,integer,0,,"The CONDITION_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_end_date,No,,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATE,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_end_datetime,No,,,datetime,0,,,should not be inferred,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATETIME,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +All other Visits: visit_end_datetime = visit_start_datetime. If this is a one-day visit the end date should match the start date.",No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_OCCURRENCE,VISIT_START_DATE,1,,Yes,1,,Yes,,, +VISIT_OCCURRENCE,visit_end_datetime,No,,,datetime,0,,,"If no time is given for the end date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_OCCURRENCE,VISIT_START_DATETIME,1,,Yes,1,,Yes,,, +VISIT_OCCURRENCE,visit_type_concept_id,Yes,0,,Integer,0,,"Use this field to understand the provenance of the visit record, or where the record comes from.","Populate this field based on the provenance of the visit record, as in whether it came from an EHR record or billing claim.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,provider_id,No,,,integer,0,,There will only be one provider per visit. If multiple providers are associated with a visit that information can be found in the VISIT_DETAIL table.,"If there are multiple providers associated with a visit, you will need to choose which one to put here. The additional providers can be stored in the visit_detail table.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,care_site_id,No,,,integer,0,,This field provides information about the care site where the visit took place.,There should only be one care site associated with a visit.,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,visit_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the kind of visit that took place (inpatient, outpatient, emergency, etc.)","If there is information about the kind of visit in the source data that value should be stored here. If a visit is an amalgamation of visits from the source then use a hierarchy to choose the visit source value, such as IP -> ER-> OP. This should line up with the logic chosen to determine how visits are created.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,VISIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,visit_source_concept_id,No,,,integer,0,,,If the visit source value is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,admitting_source_concept_id,No,,,integer,0,,"Use this field to determine where the patient was admitted from. This concept is part of the visit domain and can indicate if a patient was admitted to the hospital from a long-term care facility, for example.","If available, map the admitted_from_source_value to a standard concept in the visit domain.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,admitting_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was admitted from. Typically this applies only to visits that have a length of stay, like inpatient visits or long-term care visits.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ADMITTING_SOURCE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,discharge_to_concept_id,No,,,integer,0,,"Use this field to determine where the patient was discharged to after a visit. This concept is part of the visit domain and can indicate if a patient was discharged to home or sent to a long-term care facility, for example.","If available, map the discharge_to_source_value to a standard concept in the visit domain.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,discharge_to_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was discharged to after a visit, as in they went home or were moved to long-term care. Typically this applies only to visits that have a length of stay of a day or more.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DISCHARGE_TO_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,preceding_visit_occurrence_id,No,,,integer,0,,Use this field to find the visit that occured for the person prior to the given visit. There could be a few days or a few years in between.,"The preceding_visit_id can be used to link a visit immediately preceding the current visit. Note this is not symmetrical, and there is no such thing as a ""following_visit_id"".",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_occurrence_id,Yes,0,,bigint,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,person_id,Yes,0,,bigint,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_concept_id,Yes,0,,integer,0,,"The CONDITION_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +CONDITION_OCCURRENCE,condition_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +CONDITION_OCCURRENCE,condition_end_date,No,,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATE,1,,Yes,1,,Yes,,, +CONDITION_OCCURRENCE,condition_end_datetime,No,,,datetime,0,,,should not be inferred,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATETIME,1,,Yes,1,,Yes,,, +CONDITION_OCCURRENCE,condition_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, CONDITION_OCCURRENCE,condition_status_concept_id,No,,,integer,0,,,"Presently, there is no designated vocabulary, domain, or class that represents condition status. The following concepts from SNOMED are recommended: Admitting diagnosis: 4203942 Final diagnosis: 4230359 (should also be used for discharge diagnosis -Preliminary diagnosis: 4033240",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,stop_reason,No,,,varchar(20),0,,The Stop Reason indicates why a Condition is no longer valid with respect to the purpose within the source data. Note that a Stop Reason does not necessarily imply that the condition is no longer occurring.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_source_value,No,,,varchar(50),0,,"This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Condition necessary for a given analytic use case. Consider using CONDITION_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network. ",This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,CONDITION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_status_source_value,No,,,varchar(50),0,,,This code is mapped to a Standard Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,CONDITION_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_exposure_id,Yes,0,,bigint,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,person_id,Yes,0,,bigint,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_exposure_start_date,Yes,0,,date,0,,,"Valid entries include a start date of a prescription, the date a prescription was filled, or the date on which a Drug administration procedure was recorded.",No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_exposure_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_exposure_end_date,Yes,0,,date,0,,,"The DRUG_EXPOSURE_END_DATE denotes the day the drug exposure ended for the patient. This could be that the duration of DRUG_SUPPLY was reached (in which case DRUG_EXPOSURE_END_DATETIME = DRUG_EXPOSURE_START_DATETIME + DAYS_SUPPLY -1 day), or because the exposure was stopped (medication changed, medication discontinued, etc.) When the native data suggests a drug exposure has a days supply less than 0, drop the record as unknown if a person has received the drug or not (THEMIS issue #24). If a patient has multiple records on the same day for the same drug or procedures the ETL should not de-dupe them unless there is probable reason to believe the item is a true data duplicate (THEMIS issue #14). Depending on different sources, it could be a known or an inferred date and denotes the last day at which the patient was still exposed to Drug.",No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_exposure_end_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes -DRUG_EXPOSURE,verbatim_end_date,No,,,date,0,,You can use the TYPE_CONCEPT_ID to delineate between prescriptions written vs. prescriptions dispensed vs. medication history vs. patient-reported exposure,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,stop_reason,No,,,varchar(20),0,,," Reasons include regimen completed, changed, removed, etc.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,refills,No,,,integer,0,,"The content of the refills field determines the current number of refills, not the number of remaining refills. For example, for a drug prescription with 2 refills, the content of this field for the 3 Drug Exposure events are null, 1 and 2.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,12,1,,,,,,,No,,,Yes -DRUG_EXPOSURE,quantity,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,1095,1,,,,,,,No,,,Yes -DRUG_EXPOSURE,days_supply,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,365,1,,,,,,,No,,,Yes -DRUG_EXPOSURE,sig,No,,,varchar(MAX),0,,(and printed on the container),,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,route_concept_id,No,,,integer,0,,"Route information can also be inferred from the Drug product itself by determining the Drug Form of the Concept, creating some partial overlap of the same type of information. Therefore, route information should be stored in DRUG_CONCEPT_ID (as a drug with corresponding Dose Form). The ROUTE_CONCEPT_ID could be used for storing more granular forms e.g. 'Intraventricular cardiac'.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Route,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,lot_number,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_source_value,No,,,varchar(50),0,,,"This code is mapped to a Standard Drug concept in the Standardized Vocabularies and the original code is, stored here for reference.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,DRUG_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,route_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ROUTE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,dose_unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_occurrence_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Procedure,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -PROCEDURE_OCCURRENCE,procedure_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -PROCEDURE_OCCURRENCE,procedure_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,modifier_concept_id,No,,,integer,0,,"These concepts are typically distinguished by 'Modifier' concept classes (e.g., 'CPT4 Modifier' as part of the 'CPT4' vocabulary).",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,quantity,No,,,integer,0,,"If the quantity value is omitted, a single procedure is assumed.","If a Procedure has a quantity of '0' in the source, this should default to '1' in the ETL. If there is a record in the source it can be assumed the exposure occurred at least once (THEMIS issue #26).",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_source_value,No,,,varchar(50),0,,,"This code is mapped to a standard procedure Concept in the Standardized Vocabularies and the original code is, stored here for reference. Procedure source codes are typically ICD-9-Proc, CPT-4, HCPCS or OPCS-4 codes.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,PROCEDURE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,modifier_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,MODIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_exposure_id,Yes,0,,bigint,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,person_id,Yes,0,,bigint,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Device,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_exposure_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_exposure_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_exposure_end_date,No,,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATE,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_exposure_end_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,unique_device_id,No,,,varchar(50),0,,,"For medical devices that are regulated by the FDA, a Unique Device Identification (UDI) is provided if available in the data source and is recorded in the UNIQUE_DEVICE_ID field.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,quantity,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DEVICE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Measurement,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -MEASUREMENT,measurement_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_time,No,,,varchar(10),0,,This is present for backwards compatibility and will be deprecated in an upcoming version,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +Preliminary diagnosis: 4033240",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,stop_reason,No,,,varchar(20),0,,The Stop Reason indicates why a Condition is no longer valid with respect to the purpose within the source data. Note that a Stop Reason does not necessarily imply that the condition is no longer occurring.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_source_value,No,,,varchar(50),0,,"This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Condition necessary for a given analytic use case. Consider using CONDITION_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network. ",This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,CONDITION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_status_source_value,No,,,varchar(50),0,,,This code is mapped to a Standard Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,CONDITION_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_exposure_id,Yes,0,,bigint,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,person_id,Yes,0,,bigint,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_exposure_start_date,Yes,0,,date,0,,,"Valid entries include a start date of a prescription, the date a prescription was filled, or the date on which a Drug administration procedure was recorded.",No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +DRUG_EXPOSURE,drug_exposure_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,drug_exposure_end_date,Yes,0,,date,0,,,"The DRUG_EXPOSURE_END_DATE denotes the day the drug exposure ended for the patient. This could be that the duration of DRUG_SUPPLY was reached (in which case DRUG_EXPOSURE_END_DATETIME = DRUG_EXPOSURE_START_DATETIME + DAYS_SUPPLY -1 day), or because the exposure was stopped (medication changed, medication discontinued, etc.) When the native data suggests a drug exposure has a days supply less than 0, drop the record as unknown if a person has received the drug or not (THEMIS issue #24). If a patient has multiple records on the same day for the same drug or procedures the ETL should not de-dupe them unless there is probable reason to believe the item is a true data duplicate (THEMIS issue #14). Depending on different sources, it could be a known or an inferred date and denotes the last day at which the patient was still exposed to Drug.",No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,drug_exposure_end_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,verbatim_end_date,No,,,date,0,,You can use the TYPE_CONCEPT_ID to delineate between prescriptions written vs. prescriptions dispensed vs. medication history vs. patient-reported exposure,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,drug_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,stop_reason,No,,,varchar(20),0,,," Reasons include regimen completed, changed, removed, etc.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,refills,No,,,integer,0,,"The content of the refills field determines the current number of refills, not the number of remaining refills. For example, for a drug prescription with 2 refills, the content of this field for the 3 Drug Exposure events are null, 1 and 2.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,12,1,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,quantity,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,1095,1,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,days_supply,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,365,1,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,sig,No,,,varchar(MAX),0,,(and printed on the container),,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,route_concept_id,No,,,integer,0,,"Route information can also be inferred from the Drug product itself by determining the Drug Form of the Concept, creating some partial overlap of the same type of information. Therefore, route information should be stored in DRUG_CONCEPT_ID (as a drug with corresponding Dose Form). The ROUTE_CONCEPT_ID could be used for storing more granular forms e.g. 'Intraventricular cardiac'.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Route,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,lot_number,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_source_value,No,,,varchar(50),0,,,"This code is mapped to a Standard Drug concept in the Standardized Vocabularies and the original code is, stored here for reference.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,DRUG_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,route_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ROUTE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,dose_unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_occurrence_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Procedure,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +PROCEDURE_OCCURRENCE,procedure_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,modifier_concept_id,No,,,integer,0,,"These concepts are typically distinguished by 'Modifier' concept classes (e.g., 'CPT4 Modifier' as part of the 'CPT4' vocabulary).",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,quantity,No,,,integer,0,,"If the quantity value is omitted, a single procedure is assumed.","If a Procedure has a quantity of '0' in the source, this should default to '1' in the ETL. If there is a record in the source it can be assumed the exposure occurred at least once (THEMIS issue #26).",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_source_value,No,,,varchar(50),0,,,"This code is mapped to a standard procedure Concept in the Standardized Vocabularies and the original code is, stored here for reference. Procedure source codes are typically ICD-9-Proc, CPT-4, HCPCS or OPCS-4 codes.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,PROCEDURE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,modifier_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,MODIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_exposure_id,Yes,0,,bigint,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,person_id,Yes,0,,bigint,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Device,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_exposure_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +DEVICE_EXPOSURE,device_exposure_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DEVICE_EXPOSURE,device_exposure_end_date,No,,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATE,1,,Yes,1,,Yes,,, +DEVICE_EXPOSURE,device_exposure_end_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes,,, +DEVICE_EXPOSURE,device_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,unique_device_id,No,,,varchar(50),0,,,"For medical devices that are regulated by the FDA, a Unique Device Identification (UDI) is provided if available in the data source and is recorded in the UNIQUE_DEVICE_ID field.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,quantity,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DEVICE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Measurement,0,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,Yes,5, +MEASUREMENT,measurement_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_time,No,,,varchar(10),0,,This is present for backwards compatibility and will be deprecated in an upcoming version,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, MEASUREMENT,operator_concept_id,No,,,integer,0,,"The meaning of Concept 4172703 for '=' is identical to omission of a OPERATOR_CONCEPT_ID value. Since the use of this field is rare, it's important when devising analyses to not to forget testing for the content of this field for values different from =.","If there is a negative value coming from the source, set the VALUE_AS_NUMBER to NULL, with the exception of the following Measurements (listed as LOINC codes): 1925-7 Base excess in Arterial blood by calculation 1927-3 Base excess in Venous blood by calculation Operators are <, <=, =, >=, > and these concepts belong to the 'Meas Value Operator' domain. @@ -131,63 +131,63 @@ MEASUREMENT,operator_concept_id,No,,,integer,0,,"The meaning of Concept 4172703 1926-5 Base excess in Capillary blood by calculation 28638-5 Base excess in Arterial cord blood by calculation 28639-3 Base excess in Venous cord blood by calculation -THEMIS issue #16",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,value_as_number,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,value_as_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,unit_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,range_low,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER.,If reference ranges for upper and lower limit of normal as provided (typically by a laboratory) these are stored in the RANGE_HIGH and RANGE_LOW fields. Ranges have the same unit as the VALUE_AS_NUMBER.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,range_high,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,MEASUREMENT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -MEASUREMENT,value_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_end_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATE,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_end_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATETIME,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_type_concept_id,Yes,0,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,care_site_id,No,,,integer,0,,,,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_source_value,No,,,string(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,VISIT_DETAIL_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_source_concept_id,No,,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,admitting_source_value,No,,,Varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ADMITTING_SOURCE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,admitting_source_concept_id,No,,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,discharge_to_source_value,No,,,Varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DISCHARGE_TO_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,discharge_to_concept_id,No,,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,preceding_visit_detail_id,No,,,Integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_parent_id,No,,,Integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_occurrence_id,Yes,0,,Integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -NOTE,note_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -NOTE,note_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_class_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_title,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_text,Yes,0,,varchar(MAX),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,encoding_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,language_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE_NLP,note_nlp_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,note_id,Yes,0,,integer,0,,,,No,,,Yes,0,,NOTE,NOTE_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,section_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,snippet,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,offset,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,lexical_variant,Yes,0,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,note_nlp_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,note_nlp_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,nlp_system,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,nlp_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,nlp_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,No +THEMIS issue #16",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,value_as_number,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,value_as_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,unit_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,range_low,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER.,If reference ranges for upper and lower limit of normal as provided (typically by a laboratory) these are stored in the RANGE_HIGH and RANGE_LOW fields. Ranges have the same unit as the VALUE_AS_NUMBER.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,range_high,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,MEASUREMENT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,value_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,1, +VISIT_DETAIL,visit_detail_start_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +VISIT_DETAIL,visit_detail_end_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATE,1,,Yes,1,,Yes,Yes,1, +VISIT_DETAIL,visit_detail_end_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATETIME,1,,Yes,1,,Yes,,, +VISIT_DETAIL,visit_detail_type_concept_id,Yes,0,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,care_site_id,No,,,integer,0,,,,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_source_value,No,,,string(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,VISIT_DETAIL_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_source_concept_id,No,,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,admitting_source_value,No,,,Varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ADMITTING_SOURCE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,admitting_source_concept_id,No,,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,discharge_to_source_value,No,,,Varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DISCHARGE_TO_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,discharge_to_concept_id,No,,,Integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,preceding_visit_detail_id,No,,,Integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_parent_id,No,,,Integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_occurrence_id,Yes,0,,Integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,Yes,5, +NOTE,note_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +NOTE,note_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_class_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_title,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_text,Yes,0,,varchar(MAX),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,encoding_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,language_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE_NLP,note_nlp_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,note_id,Yes,0,,integer,0,,,,No,,,Yes,0,,NOTE,NOTE_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,section_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,snippet,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,offset,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,lexical_variant,Yes,0,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,note_nlp_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,note_nlp_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,nlp_system,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,nlp_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,nlp_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,No,,, NOTE_NLP,term_exists,No,,,varchar(1),0,,,"Term_exists is defined as a flag that indicates if the patient actually has or had the condition. Any of the following modifiers would make Term_exists false: Negation = true Subject = [anything other than the patient] @@ -195,140 +195,140 @@ Conditional = true/li> Rule_out = true Uncertain = very low certainty or any lower certainties A complete lack of modifiers would make Term_exists true. -",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, NOTE_NLP,term_temporal,No,,,varchar(50),0,,,"Term_temporal is to indicate if a condition is present or just in the past. The following would be past: History = true -Concept_date = anything before the time of the report",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +Concept_date = anything before the time of the report",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, NOTE_NLP,term_modifiers,No,,,varchar(2000),0,,,"For the modifiers that are there, they would have to have these values: Negation = false Subject = patient Conditional = false Rule_out = false -Uncertain = true or high or moderate or even low (could argue about low). Term_modifiers will concatenate all modifiers for different types of entities (conditions, drugs, labs etc) into one string. Lab values will be saved as one of the modifiers. A list of allowable modifiers (e.g., signature for medications) and their possible values will be standardized later.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -OBSERVATION,observation_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -OBSERVATION,observation_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -OBSERVATION,observation_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_as_number,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_as_string,No,,,varchar(60),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_as_concept_id,No,,,Integer,0,,,"Note that the value of VALUE_AS_CONCEPT_ID may be provided through mapping from a source Concept which contains the content of the Observation. In those situations, the CONCEPT_RELATIONSHIP table in addition to the 'Maps to' record contains a second record with the relationship_id set to 'Maps to value'. For example, ICD9CM V17.5 concept_id 44828510 'Family history of asthma' has a 'Maps to' relationship to 4167217 'Family history of clinical finding' as well as a 'Maps to value' record to 317009 'Asthma'.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,qualifier_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,unit_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,OBSERVATION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -OBSERVATION,qualifier_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,QUALIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -SPECIMEN,specimen_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -SPECIMEN,quantity,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -SPECIMEN,unit_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,anatomic_site_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,disease_status_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_source_id,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,SPECIMEN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,anatomic_site_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ANATOMIC_SITE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,disease_status_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DISEASE_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -FACT_RELATIONSHIP,domain_concept_id_1,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,0,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,fact_id_1,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,domain_concept_id_2,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,0,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,fact_id_2,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,relationship_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,0,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,location_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,address_1,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,address_2,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,city,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,state,No,,,varchar(2),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,zip,No,,,varchar(9),0,,,"Zip codes are handled as strings of up to 9 characters length. For US addresses, these represent either a 3-digit abbreviated Zip code as provided by many sources for patient protection reasons, the full 5-digit Zip or the 9-digit (ZIP + 4) codes. Unless for specific reasons analytical methods should expect and utilize only the first 3 digits. For international addresses, different rules apply.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,county,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,location_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,care_site_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,care_site_name,No,,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,place_of_service_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,location_id,No,,,integer,0,,,,No,,,Yes,0,,LOCATION,LOCATION_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,care_site_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,place_of_service_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,provider_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,provider_name,No,,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,npi,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,dea,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,specialty_concept_id,No,,,integer,0,,,"If a Provider has more than one Specialty, the main or most often exerted specialty should be recorded.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,care_site_id,No,,,integer,0,,,,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,year_of_birth,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,gender_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Gender,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,provider_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,specialty_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,SPECIALTY_CONCEPT_ID,,,,,,,,,,,,No,,,No -PROVIDER,specialty_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,gender_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,GENDER_CONCEPT_ID,,,,,,,,,,,,No,,,No -PROVIDER,gender_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PAYER_PLAN_PERIOD,payer_plan_period_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_plan_period_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_plan_period_end_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,Yes,PAYER_PLAN_PERIOD,PAYER_PLAN_PERIOD_START_DATE,1,,No,,,Yes -PAYER_PLAN_PERIOD,payer_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,PAYER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,plan_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,plan_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,PLAN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,plan_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,sponsor_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,sponsor_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,SPONSOR_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,sponsor_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,family_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,0,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,stop_reason_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,stop_reason_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,STOP_REASON_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,stop_reason_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -COST,cost_id,Yes,0,,INTEGER,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,cost_event_id,Yes,0,,INTEGER,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,cost_domain_id,Yes,0,,VARCHAR(20),0,,,,No,,,Yes,0,,DOMAIN,DOMAIN_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,cost_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,currency_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,total_charge,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,total_cost,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,total_paid,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_by_payer,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_by_patient,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_patient_copay,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_patient_coinsurance,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_patient_deductible,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_by_primary,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_ingredient_cost,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,paid_dispensing_fee,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,payer_plan_period_id,No,,,INTEGER,0,,,,No,,,Yes,0,,PAYER_PLAN_PERIOD,PAYER_PLAN_PERIOD_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,amount_allowed,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,revenue_code_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,revenue_code_source_value,No,,,VARCHAR(50),0,,Revenue codes are a method to charge for a class of procedures and conditions in the U.S. hospital system.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,drg_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,drg_source_value,No,,,VARCHAR(3),0,,Diagnosis Related Groups are US codes used to classify hospital cases into one of approximately 500 groups. ,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -DRUG_ERA,drug_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_ERA,drug_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_ERA,drug_era_start_date,Yes,0,,datetime,0,,,The Drug Era Start Date is the start date of the first Drug Exposure for a given ingredient. (NOT RIGHT),No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes +Uncertain = true or high or moderate or even low (could argue about low). Term_modifiers will concatenate all modifiers for different types of entities (conditions, drugs, labs etc) into one string. Lab values will be saved as one of the modifiers. A list of allowable modifiers (e.g., signature for medications) and their possible values will be standardized later.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +OBSERVATION,observation_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,Yes,5, +OBSERVATION,observation_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +OBSERVATION,observation_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_as_number,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_as_string,No,,,varchar(60),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_as_concept_id,No,,,Integer,0,,,"Note that the value of VALUE_AS_CONCEPT_ID may be provided through mapping from a source Concept which contains the content of the Observation. In those situations, the CONCEPT_RELATIONSHIP table in addition to the 'Maps to' record contains a second record with the relationship_id set to 'Maps to value'. For example, ICD9CM V17.5 concept_id 44828510 'Family history of asthma' has a 'Maps to' relationship to 4167217 'Family history of clinical finding' as well as a 'Maps to value' record to 317009 'Asthma'.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,qualifier_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,unit_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,provider_id,No,,,integer,0,,,,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,visit_occurrence_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,visit_detail_id,No,,,integer,0,,,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,OBSERVATION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,qualifier_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,QUALIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +SPECIMEN,specimen_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +SPECIMEN,quantity,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +SPECIMEN,unit_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,anatomic_site_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,disease_status_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_source_id,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,SPECIMEN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,unit_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,anatomic_site_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ANATOMIC_SITE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,disease_status_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DISEASE_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +FACT_RELATIONSHIP,domain_concept_id_1,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,0,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,fact_id_1,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,domain_concept_id_2,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,0,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,fact_id_2,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,relationship_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,0,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,location_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,address_1,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,address_2,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,city,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,state,No,,,varchar(2),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,zip,No,,,varchar(9),0,,,"Zip codes are handled as strings of up to 9 characters length. For US addresses, these represent either a 3-digit abbreviated Zip code as provided by many sources for patient protection reasons, the full 5-digit Zip or the 9-digit (ZIP + 4) codes. Unless for specific reasons analytical methods should expect and utilize only the first 3 digits. For international addresses, different rules apply.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,county,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,location_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,care_site_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,care_site_name,No,,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,place_of_service_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,location_id,No,,,integer,0,,,,No,,,Yes,0,,LOCATION,LOCATION_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,care_site_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,place_of_service_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,provider_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,provider_name,No,,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,npi,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,dea,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,specialty_concept_id,No,,,integer,0,,,"If a Provider has more than one Specialty, the main or most often exerted specialty should be recorded.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,care_site_id,No,,,integer,0,,,,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,year_of_birth,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,gender_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Gender,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,provider_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,specialty_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,SPECIALTY_CONCEPT_ID,,,,,,,,,,,,No,,,No,,, +PROVIDER,specialty_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,gender_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,GENDER_CONCEPT_ID,,,,,,,,,,,,No,,,No,,, +PROVIDER,gender_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PAYER_PLAN_PERIOD,payer_plan_period_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_plan_period_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_plan_period_end_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,Yes,PAYER_PLAN_PERIOD,PAYER_PLAN_PERIOD_START_DATE,1,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,PAYER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,plan_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,plan_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,PLAN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,plan_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,sponsor_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,sponsor_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,SPONSOR_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,sponsor_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,family_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,0,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,stop_reason_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,stop_reason_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,STOP_REASON_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,stop_reason_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +COST,cost_id,Yes,0,,INTEGER,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,cost_event_id,Yes,0,,INTEGER,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,cost_domain_id,Yes,0,,VARCHAR(20),0,,,,No,,,Yes,0,,DOMAIN,DOMAIN_ID,,,,,,,No,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,cost_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,currency_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,total_charge,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,total_cost,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,total_paid,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_by_payer,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_by_patient,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_patient_copay,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_patient_coinsurance,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_patient_deductible,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_by_primary,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_ingredient_cost,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,paid_dispensing_fee,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,payer_plan_period_id,No,,,INTEGER,0,,,,No,,,Yes,0,,PAYER_PLAN_PERIOD,PAYER_PLAN_PERIOD_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,amount_allowed,No,,,FLOAT,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,revenue_code_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,revenue_code_source_value,No,,,VARCHAR(50),0,,Revenue codes are a method to charge for a class of procedures and conditions in the U.S. hospital system.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,drg_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,drg_source_value,No,,,VARCHAR(3),0,,Diagnosis Related Groups are US codes used to classify hospital cases into one of approximately 500 groups. ,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +DRUG_ERA,drug_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,drug_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,drug_era_start_date,Yes,0,,datetime,0,,,The Drug Era Start Date is the start date of the first Drug Exposure for a given ingredient. (NOT RIGHT),No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, DRUG_ERA,drug_era_end_date,Yes,0,,datetime,0,,,"The Drug Era End Date is the end date of the last Drug Exposure. The End Date of each Drug Exposure is either taken from the field drug_exposure_end_date or, as it is typically not available, inferred using the following rules: For pharmacy prescription data, the date when the drug was dispensed plus the number of days of supply are used to extrapolate the End Date for the Drug Exposure. Depending on the country-specific healthcare system, this supply information is either explicitly provided in the day_supply field or inferred from package size or similar information. For Procedure Drugs, usually the drug is administered on a single date (i.e., the administration date). -A standard Persistence Window of 30 days (gap, slack) is permitted between two subsequent such extrapolated DRUG_EXPOSURE records to be considered to be merged into a single Drug Era. (ARENT WE REQUIRING TO USE DRUG_EXPOSURE_END_DATE NOW????)",No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_ERA,DRUG_ERA_START_DATE,1,,No,,,Yes -DRUG_ERA,drug_exposure_count,No,,,integer,0,,,,No,,,No,,,,,,,,,,,,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -DRUG_ERA,gap_days,No,,,integer,0,,,"The Gap Days determine how many total drug-free days are observed between all Drug Exposure events that contribute to a DRUG_ERA record. It is assumed that the drugs are ""not stockpiled"" by the patient, i.e. that if a new drug prescription or refill is observed (a new DRUG_EXPOSURE record is written), the remaining supply from the previous events is abandoned. The difference between Persistence Window and Gap Days is that the former is the maximum drug-free time allowed between two subsequent DRUG_EXPOSURE records, while the latter is the sum of actual drug-free days for the given Drug Era under the above assumption of non-stockpiling.",No,,,No,,,,,,,,,,,,,,Yes,100,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes -DOSE_ERA,dose_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,drug_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,unit_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,dose_value,Yes,0,,float,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes -DOSE_ERA,dose_era_start_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DOSE_ERA,dose_era_end_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -CONDITION_ERA,condition_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_ERA,condition_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_ERA,condition_era_start_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -CONDITION_ERA,condition_era_end_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -CONDITION_ERA,condition_occurrence_count,No,,,integer,0,,,,No,,,No,,,,,,,,,,,,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes \ No newline at end of file +A standard Persistence Window of 30 days (gap, slack) is permitted between two subsequent such extrapolated DRUG_EXPOSURE records to be considered to be merged into a single Drug Era. (ARENT WE REQUIRING TO USE DRUG_EXPOSURE_END_DATE NOW????)",No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_ERA,DRUG_ERA_START_DATE,1,,No,,,Yes,,, +DRUG_ERA,drug_exposure_count,No,,,integer,0,,,,No,,,No,,,,,,,,,,,,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,gap_days,No,,,integer,0,,,"The Gap Days determine how many total drug-free days are observed between all Drug Exposure events that contribute to a DRUG_ERA record. It is assumed that the drugs are ""not stockpiled"" by the patient, i.e. that if a new drug prescription or refill is observed (a new DRUG_EXPOSURE record is written), the remaining supply from the previous events is abandoned. The difference between Persistence Window and Gap Days is that the former is the maximum drug-free time allowed between two subsequent DRUG_EXPOSURE records, while the latter is the sum of actual drug-free days for the given Drug Era under the above assumption of non-stockpiling.",No,,,No,,,,,,,,,,,,,,Yes,100,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,dose_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,drug_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,unit_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,dose_value,Yes,0,,float,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,dose_era_start_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DOSE_ERA,dose_era_end_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +CONDITION_ERA,condition_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_ERA,condition_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,0,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_ERA,condition_era_start_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +CONDITION_ERA,condition_era_end_date,Yes,0,,datetime,0,,,,No,,,No,,,,,,,,,,,,,,Yes,0,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +CONDITION_ERA,condition_occurrence_count,No,,,integer,0,,,,No,,,No,,,,,,,,,,,,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, \ No newline at end of file diff --git a/inst/csv/OMOP_CDMv5.4_Check_Descriptions.csv b/inst/csv/OMOP_CDMv5.4_Check_Descriptions.csv index a8e960fe..6d9760ab 100644 --- a/inst/csv/OMOP_CDMv5.4_Check_Descriptions.csv +++ b/inst/csv/OMOP_CDMv5.4_Check_Descriptions.csv @@ -1,4 +1,5 @@ checkLevel,checkName,checkDescription,kahnContext,kahnCategory,kahnSubcategory,sqlFile,evaluationFilter +TABLE,cdmTable,A yes or no value indicating if @cdmTableName table is present as expected based on the specification. ,Verification,Conformance,Relational,table_cdm_table.sql,cdmTableName!='' TABLE,measurePersonCompleteness,The number and percent of persons in the CDM that do not have at least one record in the @cdmTableName table,Validation,Completeness,,table_person_completeness.sql,measurePersonCompleteness=='Yes' FIELD,cdmField,A yes or no value indicating if @cdmFieldName is present in the @cdmTableName table as expected based on the specification. ,Verification,Conformance,Relational,field_cdm_field.sql,cdmFieldName!='' FIELD,isRequired,The number and percent of records with a NULL value in the @cdmFieldName of the @cdmTableName that is considered not nullable.,Validation,Conformance,Relational,field_is_not_nullable.sql,isRequired=='Yes' @@ -7,7 +8,7 @@ FIELD,isPrimaryKey,The number and percent of records that have a duplicate value FIELD,isForeignKey,The number and percent of records that have a value in the @cdmFieldName field in the @cdmTableName table that does not exist in the @fkTableName table.,Verification,Conformance,Relational,is_foreign_key.sql,isForeignKey=='Yes' FIELD,fkDomain,The number and percent of records that have a value in the @cdmFieldName field in the @cdmTableName table that do not conform to the @fkDomain domain.,Verification,Conformance,Value,field_fk_domain.sql,isForeignKey=='Yes' & fkDomain!= '' FIELD,fkClass,The number and percent of records that have a value in the @cdmFieldName field in the @cdmTableName table that do not conform to the @fkClass class.,Verification,Conformance,Computational,field_fk_class.sql,isForeignKey=='Yes' & fkClass!='' -FIELD,isStandardValidConcept,"The number and percent of records that do not have a standard, valid concept in the @cdmFieldName field in the @cdmTableName table. ",Verification,Conformance,,field_is_standard_valid_concept.sql,isStandardValidConcept=='Yes' +FIELD,isStandardValidConcept,"The number and percent of records that do not have a standard, valid concept in the @cdmFieldName field in the @cdmTableName table. ",Verification,Conformance,Value,field_is_standard_valid_concept.sql,isStandardValidConcept=='Yes' FIELD,measureValueCompleteness,The number and percent of records with a NULL value in the @cdmFieldName of the @cdmTableName.,Verification,Completeness,,field_measure_value_completeness.sql,measureValueCompleteness=='Yes' FIELD,standardConceptRecordCompleteness,The number and percent of records with a value of 0 in the standard concept field @cdmFieldName in the @cdmTableName table.,Verification,Completeness,,field_concept_record_completeness.sql,standardConceptRecordCompleteness=='Yes' FIELD,sourceConceptRecordCompleteness,The number and percent of records with a value of 0 in the source concept field @cdmFieldName in the @cdmTableName table.,Verification,Completeness,,field_concept_record_completeness.sql,sourceConceptRecordCompleteness=='Yes' @@ -16,6 +17,7 @@ FIELD,plausibleValueLow,The number and percent of records with a value in the @c FIELD,plausibleValueHigh,The number and percent of records with a value in the @cdmFieldName field of the @cdmTableName table greater than @plausibleValueHigh.,Verification,Plausibility,Atemporal,field_plausible_value_high.sql,plausibleValueHigh!='' FIELD,plausibleTemporalAfter,The number and percent of records with a value in the @cdmFieldName field of the @cdmTableName that occurs prior to the date in the @plausibleTemporalAfterFieldName field of the @plausibleTemporalAfterTableName table.,Verification,Plausibility,Temporal,field_plausible_temporal_after.sql,plausibleTemporalAfter=='Yes' FIELD,plausibleDuringLife,"If yes, the number and percent of records with a date value in the @cdmFieldName field of the @cdmTableName table that occurs after death.",Verification,Plausibility,Temporal,field_plausible_during_life.sql,plausibleDuringLife=='Yes' +FIELD,withinVisitDates,The number and percent of records not within one week on either side of the corresponding visit occurrence start and end date,Verification,Conformance,,field_within_visit_dates.sql,withinVisitDates=='Yes' CONCEPT,plausibleValueLow,"For the combination of CONCEPT_ID @conceptId (@conceptName) and UNIT_CONCEPT_ID @unitConceptId (@unitConceptName), the number and percent of records that have a value less than @plausibleValueLow.",Verification,Plausibility,Atemporal,concept_plausible_value_low.sql,plausibleValueLow!='' CONCEPT,plausibleValueHigh,"For the combination of CONCEPT_ID @conceptId (@conceptName) and UNIT_CONCEPT_ID @unitConceptId (@unitConceptName), the number and percent of records that have a value higher than @plausibleValueHigh.",Verification,Plausibility,Atemporal,concept_plausible_value_high.sql,plausibleValueHigh!='' CONCEPT,plausibleGender,"For a CONCEPT_ID @conceptId (@conceptName), the number and percent of records associated with patients with an implausible gender (correct gender = @plausibleGender).",Validation,Plausibility,Atemporal,concept_plausible_gender.sql,plausibleGender!='' diff --git a/inst/csv/OMOP_CDMv5.4_Concept_Level.csv b/inst/csv/OMOP_CDMv5.4_Concept_Level.csv index 57cfad09..b0e8ea49 100644 --- a/inst/csv/OMOP_CDMv5.4_Concept_Level.csv +++ b/inst/csv/OMOP_CDMv5.4_Concept_Level.csv @@ -305,7 +305,7 @@ MEASUREMENT,MEASUREMENT_CONCEPT_ID,2212643,Blood count; hemoglobin (Hgb),8713,gr MEASUREMENT,MEASUREMENT_CONCEPT_ID,2212643,Blood count; hemoglobin (Hgb),8837,microgram per deciliter,2,5,,319,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,2212643,Blood count; hemoglobin (Hgb),8840,milligram per deciliter,3,5,,36,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,2212742,"Thromboplastin time, partial (PTT); plasma or whole blood",8554,percent,0,5,,100,5,,,,,,,,,,,,, -PROCEDURE_OCCURRENCE,PROCEDURE_CONCEPT_ID,2617204,"Cervical or vaginal cancer screening, pelvic and clinical breast examination",,,,,,,,Female,5,,,,,,,,,,, +PROCEDURE_OCCURRENCE,PROCEDURE_CONCEPT_ID,2617204,"Cervical or vaginal cancer screening, pelvic and clinical breast examination",,,,,,,,,Female,5,,,,,,,,,, PROCEDURE_OCCURRENCE,PROCEDURE_CONCEPT_ID,2721063,"Annual gynecological examination, new patient",,,,,,,,,Female,5,,,,,,,,,, PROCEDURE_OCCURRENCE,PROCEDURE_CONCEPT_ID,2721064,"Annual gynecological examination, established patient",,,,,,,,,Female,5,,,,,,,,,, PROCEDURE_OCCURRENCE,PROCEDURE_CONCEPT_ID,2780478,"Resection of Prostate, Percutaneous Endoscopic Approach",,,,,,,,,Male,5,,,,,,,,,, @@ -601,7 +601,7 @@ MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Auto MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,8816,million per milliliter,0,5,,1,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,8848,thousand per microliter,0.001,5,,400,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,8961,thousand per cubic millimeter,0.001,5,,400,5,,,,,,,,,,,,, -MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,9254,per liter,0,5,,4E+11,5,,,,,,,,,,,,, +MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,9254,per liter,0,5,,400000000000,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,9435,thousand per liter,0,5,,400000000,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,9436,thousand per milliliter,0,5,,400000,5,,,,,,,,,,,,, MEASUREMENT,MEASUREMENT_CONCEPT_ID,3013429,Basophils [#/volume] in Blood by Automated count,9444,billion per liter,0,5,,400,5,,,,,,,,,,,,, diff --git a/inst/csv/OMOP_CDMv5.4_Field_Level.csv b/inst/csv/OMOP_CDMv5.4_Field_Level.csv index 84260969..d035a3ba 100644 --- a/inst/csv/OMOP_CDMv5.4_Field_Level.csv +++ b/inst/csv/OMOP_CDMv5.4_Field_Level.csv @@ -1,329 +1,329 @@ -cdmTableName,cdmFieldName,isRequired,isRequiredThreshold,isRequiredNotes,cdmDatatype,cdmDatatypeThreshold,cdmDatatypeNotes,userGuidance,etlConventions,isPrimaryKey,isPrimaryKeyThreshold,isPrimaryKeyNotes,isForeignKey,isForeignKeyThreshold,isForeignKeyNotes,fkTableName,fkFieldName,fkDomain,fkDomainThreshold,fkDomainNotes,fkClass,fkClassThreshold,fkClassNotes,isStandardValidConcept,isStandardValidConceptThreshold,isStandardValidConceptNotes,measureValueCompleteness,measureValueCompletenessThreshold,measureValueCompletenessNotes,standardConceptRecordCompleteness,standardConceptRecordCompletenessThreshold,standardConceptRecordCompletenessNotes,sourceConceptRecordCompleteness,sourceConceptRecordCompletenessThreshold,sourceConceptRecordCompletenessNotes,sourceValueCompleteness,sourceValueCompletenessThreshold,sourceValueCompletenessNotes,standardConceptFieldName,plausibleValueLow,plausibleValueLowThreshold,plausibleValueLowNotes,plausibleValueHigh,plausibleValueHighThreshold,plausibleValueHighNotes,plausibleTemporalAfter,plausibleTemporalAfterTableName,plausibleTemporalAfterFieldName,plausibleTemporalAfterThreshold,plausibleTemporalAfterNotes,plausibleDuringLife,plausibleDuringLifeThreshold,plausibleDuringLifeNotes,runForCohort -CARE_SITE,care_site_id,Yes,0,,integer,0,,,Assign an id to each unique combination of location_id and place_of_service_source_value,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,care_site_name,No,,,varchar(255),0,,The name of the care_site as it appears in the source data,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,care_site_source_value,No,,,varchar(50),0,,The identifier of the care_site as it appears in the source data. This could be an identifier separate from the name of the care_site.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,location_id,No,,,integer,0,,The location_id from the LOCATION table representing the physical location of the care_site.,,No,,,Yes,0,,LOCATION,LOCATION_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,place_of_service_concept_id,No,,,integer,0,,"This is a high-level way of characterizing a Care Site. Typically, however, Care Sites can provide care in multiple settings (inpatient, outpatient, etc.) and this granularity should be reflected in the visit.","Choose the concept in the visit domain that best represents the setting in which healthcare is provided in the Care Site. If most visits in a Care Site are Inpatient, then the place_of_service_concept_id should represent Inpatient. If information is present about a unique Care Site (e.g. Pharmacy) then a Care Site record should be created. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=2&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -CARE_SITE,place_of_service_source_value,No,,,varchar(50),0,,,Put the place of service of the care_site as it appears in the source data.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -CDM_SOURCE,cdm_etl_reference,No,,,varchar(255),0,,,Put the link to the CDM version used.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,cdm_holder,Yes,0,,varchar(255),0,,The holder of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,cdm_release_date,Yes,0,,date,0,,The release data of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'2000-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CDM_SOURCE,SOURCE_RELEASE_DATE,0,,,,, -CDM_SOURCE,cdm_source_abbreviation,Yes,0,,varchar(25),0,,The abbreviation of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,cdm_source_name,Yes,0,,varchar(255),0,,The name of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,cdm_version,No,,,varchar(10),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,cdm_version_concept_id,Yes,0,,integer,0,,The Concept Id representing the version of the CDM.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Metadata,0,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,source_description,No,,,varchar(MAX),0,,The description of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,source_documentation_reference,No,,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CDM_SOURCE,source_release_date,Yes,0,,date,0,,The release date of the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'2000-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,,,, -CDM_SOURCE,vocabulary_version,Yes,0,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT,cohort_definition_id,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT,cohort_end_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,,,, -COHORT,cohort_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,,,, -COHORT,subject_id,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,cohort_definition_description,No,,,varchar(MAX),0,,A complete description of the cohort.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,cohort_definition_id,Yes,0,,integer,0,,"This is the identifier given to the cohort, usually by the ATLAS application",,No,,,Yes,0,,COHORT,COHORT_DEFINITION_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,cohort_definition_name,Yes,0,,varchar(255),0,,A short description of the cohort,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,cohort_definition_syntax,No,,,varchar(MAX),0,,Syntax or code to operationalize the Cohort Definition.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,cohort_initiation_date,No,,,date,0,,A date to indicate when the Cohort was initiated in the COHORT table.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,definition_type_concept_id,Yes,0,,integer,0,,Type defining what kind of Cohort Definition the record represents and how the syntax may be executed.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COHORT_DEFINITION,subject_concept_id,Yes,0,,integer,0,,"This field contains a Concept that represents the domain of the subjects that are members of the cohort (e.g., Person, Provider, Visit).",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +cdmTableName,cdmFieldName,isRequired,isRequiredThreshold,isRequiredNotes,cdmDatatype,cdmDatatypeThreshold,cdmDatatypeNotes,userGuidance,etlConventions,isPrimaryKey,isPrimaryKeyThreshold,isPrimaryKeyNotes,isForeignKey,isForeignKeyThreshold,isForeignKeyNotes,fkTableName,fkFieldName,fkDomain,fkDomainThreshold,fkDomainNotes,fkClass,fkClassThreshold,fkClassNotes,isStandardValidConcept,isStandardValidConceptThreshold,isStandardValidConceptNotes,measureValueCompleteness,measureValueCompletenessThreshold,measureValueCompletenessNotes,standardConceptRecordCompleteness,standardConceptRecordCompletenessThreshold,standardConceptRecordCompletenessNotes,sourceConceptRecordCompleteness,sourceConceptRecordCompletenessThreshold,sourceConceptRecordCompletenessNotes,sourceValueCompleteness,sourceValueCompletenessThreshold,sourceValueCompletenessNotes,standardConceptFieldName,plausibleValueLow,plausibleValueLowThreshold,plausibleValueLowNotes,plausibleValueHigh,plausibleValueHighThreshold,plausibleValueHighNotes,plausibleTemporalAfter,plausibleTemporalAfterTableName,plausibleTemporalAfterFieldName,plausibleTemporalAfterThreshold,plausibleTemporalAfterNotes,plausibleDuringLife,plausibleDuringLifeThreshold,plausibleDuringLifeNotes,runForCohort,withinVisitDates,withinVisitDatesThreshold,withinVisitDatesNotes +CARE_SITE,care_site_id,Yes,0,,integer,0,,,Assign an id to each unique combination of location_id and place_of_service_source_value,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,care_site_name,No,,,varchar(255),0,,The name of the care_site as it appears in the source data,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,care_site_source_value,No,,,varchar(50),0,,The identifier of the care_site as it appears in the source data. This could be an identifier separate from the name of the care_site.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,location_id,No,,,integer,0,,The location_id from the LOCATION table representing the physical location of the care_site.,,No,,,Yes,0,,LOCATION,LOCATION_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,place_of_service_concept_id,No,,,integer,0,,"This is a high-level way of characterizing a Care Site. Typically, however, Care Sites can provide care in multiple settings (inpatient, outpatient, etc.) and this granularity should be reflected in the visit.","Choose the concept in the visit domain that best represents the setting in which healthcare is provided in the Care Site. If most visits in a Care Site are Inpatient, then the place_of_service_concept_id should represent Inpatient. If information is present about a unique Care Site (e.g. Pharmacy) then a Care Site record should be created. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=2&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CARE_SITE,place_of_service_source_value,No,,,varchar(50),0,,,Put the place of service of the care_site as it appears in the source data.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +CDM_SOURCE,cdm_etl_reference,No,,,varchar(255),0,,,Put the link to the CDM version used.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,cdm_holder,Yes,0,,varchar(255),0,,The holder of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,cdm_release_date,Yes,0,,date,0,,The release data of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'2000-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CDM_SOURCE,SOURCE_RELEASE_DATE,0,,,,,,,, +CDM_SOURCE,cdm_source_abbreviation,Yes,0,,varchar(25),0,,The abbreviation of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,cdm_source_name,Yes,0,,varchar(255),0,,The name of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,cdm_version,No,,,varchar(10),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,cdm_version_concept_id,Yes,0,,integer,0,,The Concept Id representing the version of the CDM.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Metadata,0,,,,,Yes,0,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,source_description,No,,,varchar(MAX),0,,The description of the CDM instance.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,source_documentation_reference,No,,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CDM_SOURCE,source_release_date,Yes,0,,date,0,,The release date of the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'2000-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,,,,,,, +CDM_SOURCE,vocabulary_version,Yes,0,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT,cohort_definition_id,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT,cohort_end_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,,,,,,, +COHORT,cohort_start_date,Yes,0,,date,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,,,,,,, +COHORT,subject_id,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,cohort_definition_description,No,,,varchar(MAX),0,,A complete description of the cohort.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,cohort_definition_id,Yes,0,,integer,0,,"This is the identifier given to the cohort, usually by the ATLAS application",,No,,,Yes,0,,COHORT,COHORT_DEFINITION_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,cohort_definition_name,Yes,0,,varchar(255),0,,A short description of the cohort,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,cohort_definition_syntax,No,,,varchar(MAX),0,,Syntax or code to operationalize the Cohort Definition.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,cohort_initiation_date,No,,,date,0,,A date to indicate when the Cohort was initiated in the COHORT table.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,definition_type_concept_id,Yes,0,,integer,0,,Type defining what kind of Cohort Definition the record represents and how the syntax may be executed.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COHORT_DEFINITION,subject_concept_id,Yes,0,,integer,0,,"This field contains a Concept that represents the domain of the subjects that are members of the cohort (e.g., Person, Provider, Visit).",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT,concept_class_id,Yes,0,,varchar(20),0,,"The attribute or concept class of the Concept. Examples are 'Clinical Drug', -'Ingredient', 'Clinical Finding' etc.",,No,,,Yes,0,,CONCEPT_CLASS,CONCEPT_CLASS_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +'Ingredient', 'Clinical Finding' etc.",,No,,,Yes,0,,CONCEPT_CLASS,CONCEPT_CLASS_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT,concept_code,Yes,0,,varchar(50),0,,"The concept code represents the identifier of the Concept in the source vocabulary, such as SNOMED-CT concept IDs, RxNorm RXCUIs etc. Note that concept -codes are not unique across vocabularies.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT,concept_id,Yes,0,,integer,0,,A unique identifier for each Concept across all domains.,,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT,concept_name,Yes,0,,varchar(255),0,,"An unambiguous, meaningful and descriptive name for the Concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT,domain_id,Yes,0,,varchar(20),0,,A foreign key to the [DOMAIN](https://ohdsi.github.io/CommonDataModel/cdm531.html#domain) table the Concept belongs to.,,No,,,Yes,0,,DOMAIN,DOMAIN_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +codes are not unique across vocabularies.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT,concept_id,Yes,0,,integer,0,,A unique identifier for each Concept across all domains.,,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT,concept_name,Yes,0,,varchar(255),0,,"An unambiguous, meaningful and descriptive name for the Concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT,domain_id,Yes,0,,varchar(20),0,,A foreign key to the [DOMAIN](https://ohdsi.github.io/CommonDataModel/cdm531.html#domain) table the Concept belongs to.,,No,,,Yes,0,,DOMAIN,DOMAIN_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT,invalid_reason,No,,,varchar(1),0,,"Reason the Concept was invalidated. Possible values are D (deleted), U (replaced with an update) or NULL when -valid_end_date has the default value.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +valid_end_date has the default value.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT,standard_concept,No,,,varchar(1),0,,"This flag determines where a Concept is a Standard Concept, i.e. is used in the data, a Classification Concept, or a non-standard Source Concept. The allowable values are 'S' (Standard Concept) and 'C' (Classification -Concept), otherwise the content is NULL.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +Concept), otherwise the content is NULL.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT,valid_end_date,Yes,0,,date,0,,"The date when the Concept became invalid because it was deleted or superseded (updated) by a new concept. The default value is 31-Dec-2099, meaning, the Concept is valid until it -becomes deprecated.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,Yes,CONCEPT,VALID_START_DATE,0,,,,, +becomes deprecated.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,Yes,CONCEPT,VALID_START_DATE,0,,,,,,,, CONCEPT,valid_start_date,Yes,0,,date,0,,"The date when the Concept was first recorded. The default value is 1-Jan-1970, meaning, the Concept has no -(known) date of inception.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +(known) date of inception.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT,vocabulary_id,Yes,0,,varchar(20),0,,"A foreign key to the [VOCABULARY](https://ohdsi.github.io/CommonDataModel/cdm531.html#vocabulary) table indicating from which source the -Concept has been adapted.",,No,,,Yes,0,,VOCABULARY,VOCABULARY_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +Concept has been adapted.",,No,,,Yes,0,,VOCABULARY,VOCABULARY_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT_ANCESTOR,ancestor_concept_id,Yes,0,,integer,0,,"The Concept Id for the higher-level concept -that forms the ancestor in the relationship.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +that forms the ancestor in the relationship.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT_ANCESTOR,descendant_concept_id,Yes,0,,integer,0,,"The Concept Id for the lower-level concept that forms the descendant in the -relationship.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +relationship.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT_ANCESTOR,max_levels_of_separation,Yes,0,,integer,0,,"The maximum separation in number of levels of hierarchy between ancestor and descendant concepts. This is an attribute -that is used to simplify hierarchic analysis.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +that is used to simplify hierarchic analysis.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT_ANCESTOR,min_levels_of_separation,Yes,0,,integer,0,,"The minimum separation in number of levels of hierarchy between ancestor and descendant concepts. This is an attribute -that is used to simplify hierarchic analysis.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_CLASS,concept_class_concept_id,Yes,0,,integer,0,,A Concept that represents the Concept Class.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_CLASS,concept_class_id,Yes,0,,varchar(20),0,,A unique key for each class.,,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +that is used to simplify hierarchic analysis.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_CLASS,concept_class_concept_id,Yes,0,,integer,0,,A Concept that represents the Concept Class.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_CLASS,concept_class_id,Yes,0,,varchar(20),0,,A unique key for each class.,,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, CONCEPT_CLASS,concept_class_name,Yes,0,,varchar(255),0,,"The name describing the Concept Class, e.g. -Clinical Finding, Ingredient, etc.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_RELATIONSHIP,concept_id_1,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_RELATIONSHIP,concept_id_2,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_RELATIONSHIP,invalid_reason,No,,,varchar(1),0,,"Reason the relationship was invalidated. Possible values are 'D' (deleted), 'U' (updated) or NULL. ",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_RELATIONSHIP,relationship_id,Yes,0,,varchar(20),0,,The relationship between CONCEPT_ID_1 and CONCEPT_ID_2. Please see the [Vocabulary Conventions](https://ohdsi.github.io/CommonDataModel/dataModelConventions.html#concept_relationships). for more information. ,,No,,,Yes,0,,RELATIONSHIP,RELATIONSHIP_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_RELATIONSHIP,valid_end_date,Yes,0,,date,0,,The date when the relationship is invalidated.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,Yes,CONCEPT_RELATIONSHIP,VALID_START_DATE,0,,,,, -CONCEPT_RELATIONSHIP,valid_start_date,Yes,0,,date,0,,The date when the relationship is first recorded.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_SYNONYM,concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_SYNONYM,concept_synonym_name,Yes,0,,varchar(1000),0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONCEPT_SYNONYM,language_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONDITION_ERA,condition_concept_id,Yes,0,,integer,0,,The Concept Id representing the Condition.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +Clinical Finding, Ingredient, etc.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_RELATIONSHIP,concept_id_1,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_RELATIONSHIP,concept_id_2,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_RELATIONSHIP,invalid_reason,No,,,varchar(1),0,,"Reason the relationship was invalidated. Possible values are 'D' (deleted), 'U' (updated) or NULL. ",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_RELATIONSHIP,relationship_id,Yes,0,,varchar(20),0,,The relationship between CONCEPT_ID_1 and CONCEPT_ID_2. Please see the [Vocabulary Conventions](https://ohdsi.github.io/CommonDataModel/dataModelConventions.html#concept_relationships). for more information. ,,No,,,Yes,0,,RELATIONSHIP,RELATIONSHIP_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_RELATIONSHIP,valid_end_date,Yes,0,,date,0,,The date when the relationship is invalidated.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,Yes,CONCEPT_RELATIONSHIP,VALID_START_DATE,0,,,,,,,, +CONCEPT_RELATIONSHIP,valid_start_date,Yes,0,,date,0,,The date when the relationship is first recorded.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_SYNONYM,concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_SYNONYM,concept_synonym_name,Yes,0,,varchar(1000),0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONCEPT_SYNONYM,language_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONDITION_ERA,condition_concept_id,Yes,0,,integer,0,,The Concept Id representing the Condition.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, CONDITION_ERA,condition_era_end_date,Yes,0,,datetime,0,,"The end date for the Condition Era constructed from the individual instances of Condition Occurrences. It is the end date of the final continuously recorded instance of the -Condition.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_ERA,CONDITION_ERA_START_DATE,1,,No,,,Yes -CONDITION_ERA,condition_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +Condition.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_ERA,CONDITION_ERA_START_DATE,1,,No,,,Yes,,, +CONDITION_ERA,condition_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, CONDITION_ERA,condition_era_start_date,Yes,0,,datetime,0,,"The start date for the Condition Era constructed from the individual instances of Condition Occurrences. It is the start date of the very first chronologically recorded instance of -the condition with at least 31 days since any prior record of the same Condition. ",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes +the condition with at least 31 days since any prior record of the same Condition. ",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, CONDITION_ERA,condition_occurrence_count,No,,,integer,0,,"The number of individual Condition Occurrences used to construct the -condition era.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -CONDITION_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_concept_id,Yes,0,,integer,0,,"The CONDITION_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source value which represents a condition","The CONCEPT_ID that the CONDITION_SOURCE_VALUE maps to. Only records whose source values map to concepts with a domain of ""Condition"" should go in this table. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Condition&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_end_date,No,,,date,0,,Use this date to determine the end date of the condition,"Most often data sources do not have the idea of a start date for a condition. Rather, if a source only has one date associated with a condition record it is acceptable to use that date for both the CONDITION_START_DATE and the CONDITION_END_DATE.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATE,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_end_datetime,No,,,datetime,0,,,If a source does not specify datetime the convention is to set the time to midnight (00:00:0000),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATETIME,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_occurrence_id,Yes,0,,integer,0,,The unique key given to a condition record for a person. Refer to the ETL for how duplicate conditions during the same visit were handled.,"Each instance of a condition present in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same condition within the same visit. It is valid to keep these duplicates and assign them individual, unique, CONDITION_OCCURRENCE_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONDITION_OCCURRENCE,condition_source_concept_id,No,,,integer,0,,"This is the concept representing the condition source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Condition necessary for a given analytic use case. Consider using CONDITION_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the CONDITION_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the condition that occurred. For example, this could be an ICD10 or Read code.",This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,CONDITION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_start_date,Yes,0,,date,0,,Use this date to determine the start date of the condition,"Most often data sources do not have the idea of a start date for a condition. Rather, if a source only has one date associated with a condition record it is acceptable to use that date for both the CONDITION_START_DATE and the CONDITION_END_DATE.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_start_datetime,No,,,datetime,0,,,If a source does not specify datetime the convention is to set the time to midnight (00:00:0000),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -CONDITION_OCCURRENCE,condition_status_concept_id,No,,,integer,0,,"This concept represents the point during the visit the diagnosis was given (admitting diagnosis, final diagnosis), whether the diagnosis was determined due to laboratory findings, if the diagnosis was exclusionary, or if it was a preliminary diagnosis, among others. ","Choose the Concept in the Condition Status domain that best represents the point during the visit when the diagnosis was given. These can include admitting diagnosis, principal diagnosis, and secondary diagnosis. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Condition+Status&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition Status,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -CONDITION_OCCURRENCE,condition_status_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the condition status.,This information may be called something different in the source data but the field is meant to contain a value indicating when and how a diagnosis was given to a patient. This source value is mapped to a standard concept which is stored in the CONDITION_STATUS_CONCEPT_ID field.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,CONDITION_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,condition_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Condition record, as in whether the condition was from an EHR system, insurance claim, registry, or other sources.",Choose the CONDITION_TYPE_CONCEPT_ID that best represents the provenance of the record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,person_id,Yes,0,,integer,0,,The PERSON_ID of the PERSON for whom the condition is recorded.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -CONDITION_OCCURRENCE,provider_id,No,,,integer,0,,"The provider associated with condition record, e.g. the provider who made the diagnosis or the provider who recorded the symptom.","The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record, for example the admitting vs attending physician on an EHR record.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,stop_reason,No,,,varchar(20),0,,The Stop Reason indicates why a Condition is no longer valid with respect to the purpose within the source data. Note that a Stop Reason does not necessarily imply that the condition is no longer occurring.,This information is often not populated in source data and it is a valid etl choice to leave it blank if the information does not exist.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the condition occurred. For example, if the person was in the ICU at the time of the diagnosis the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -CONDITION_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,The visit during which the condition occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If a CONDITION_START_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the Visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the CONDITION_OCCURRENCE record.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -COST,amount_allowed,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,cost_domain_id,Yes,0,,varchar(20),0,,,,No,,,Yes,0,,DOMAIN,DOMAIN_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,cost_event_id,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,cost_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,cost_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,currency_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,drg_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,drg_source_value,No,,,varchar(3),0,,Diagnosis Related Groups are US codes used to classify hospital cases into one of approximately 500 groups. ,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_by_patient,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_by_payer,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_by_primary,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_dispensing_fee,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_ingredient_cost,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_patient_coinsurance,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_patient_copay,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,paid_patient_deductible,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,payer_plan_period_id,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,revenue_code_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -COST,revenue_code_source_value,No,,,varchar(50),0,,Revenue codes are a method to charge for a class of procedures and conditions in the U.S. hospital system.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,total_charge,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,total_cost,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -COST,total_paid,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DEATH,cause_concept_id,No,,,integer,0,,"This is the Standard Concept representing the Person's cause of death, if available.","There is no specified domain for this concept, just choose the Standard Concept Id that best represents the person's cause of death.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,Yes -DEATH,cause_source_concept_id,No,,,integer,0,,,If the cause of death was coded using a Vocabulary present in the OMOP Vocabularies put the CONCEPT_ID representing the cause of death here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -DEATH,cause_source_value,No,,,varchar(50),0,,,"If available, put the source code representing the cause of death here. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,CAUSE_SOURCE_CONCEPT_ID,,,,,,,,,,,,,,,Yes -DEATH,death_date,Yes,0,,date,0,,The date the person was deceased.,"If the precise date include day or month is not known or not allowed, December is used as the default month, and the last day of the month the default day.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,,,,Yes -DEATH,death_datetime,No,,,datetime,0,,,If not available set time to midnight (00:00:00),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,,,,Yes -DEATH,death_type_concept_id,No,,,integer,0,,"This is the provenance of the death record, i.e., where it came from. It is possible that an administrative claims database would source death information from a government file so do not assume the Death Type is the same as the Visit Type, etc.",Use the type concept that be reflects the source of the death record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,,,,Yes -DEATH,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,Yes -DEVICE_EXPOSURE,device_concept_id,Yes,0,,integer,0,,"The DEVICE_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source concept id which represents a foreign object or instrument the person was exposed to. ",The CONCEPT_ID that the DEVICE_SOURCE_VALUE maps to. ,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Device,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_exposure_end_date,No,,,date,0,,"The DEVICE_EXPOSURE_END_DATE denotes the day the device exposure ended for the patient, if given.",Put the end date or discontinuation date as it appears from the source data or leave blank if unavailable.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATE,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_exposure_end_datetime,No,,,datetime,0,,,If a source does not specify datetime the convention is to set the time to midnight (00:00:0000),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_exposure_id,Yes,0,,integer,0,,The unique key given to records a person's exposure to a foreign physical object or instrument.,Each instance of an exposure to a foreign object or device present in the source data should be assigned this unique key. ,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DEVICE_EXPOSURE,device_exposure_start_date,Yes,0,,date,0,,Use this date to determine the start date of the device record.,"Valid entries include a start date of a procedure to implant a device, the date of a prescription for a device, or the date of device administration. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_exposure_start_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DEVICE_EXPOSURE,device_source_concept_id,No,,,integer,0,,"This is the concept representing the device source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Device necessary for a given analytic use case. Consider using DEVICE_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the DEVICE_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the device exposure that occurred. For example, this could be an NDC or Gemscript code.",This code is mapped to a Standard Device Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DEVICE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,device_type_concept_id,Yes,0,,integer,0,,"You can use the TYPE_CONCEPT_ID to denote the provenance of the record, as in whether the record is from administrative claims or EHR. ","Choose the drug_type_concept_id that best represents the provenance of the record, for example whether it came from a record of a prescription written or physician administered drug. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DEVICE_EXPOSURE,production_id,No,,,varchar(255),0,,This is the Production Identifier (UDI-PI) portion of the Unique Device Identification.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DEVICE_EXPOSURE,provider_id,No,,,integer,0,,"The Provider associated with device record, e.g. the provider who wrote the prescription or the provider who implanted the device.",The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,quantity,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,unique_device_id,No,,,varchar(255),0,,"This is the Unique Device Identification (UDI-DI) number for devices regulated by the FDA, if given. ","For medical devices that are regulated by the FDA, a Unique Device Identification (UDI) is provided if available in the data source and is recorded in the UNIQUE_DEVICE_ID field.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DEVICE_EXPOSURE,unit_concept_id,No,,,integer,0,,UNIT_SOURCE_VALUES should be mapped to a Standard Concept in the Unit domain that best represents the unit as given in the source data. ,"There is no standardization requirement for units associated with DEVICE_CONCEPT_IDs, however, it is the responsibility of the ETL to choose the most plausible unit. If there is no unit associated with a Device record, set to NULL.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -DEVICE_EXPOSURE,unit_source_concept_id,No,,,integer,0,,"This is the concept representing the UNIT_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Unit necessary for a given analytic use case. Consider using UNIT_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the UNIT_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here. ,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,unit_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the unit of the Device. For example, blood transfusions are considered devices and can be given in mL quantities. ","This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference. Using the blood transfusion example, blood transfusion is represented by the DEVICE_CONCEPT_ID and the unit (mL) would be housed in the UNIT_SOURCE_VALUE and mapped to a standard concept in the unit domain. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,UNIT_CONCEPT_ID,,,,,,,,,,,,,,, -DEVICE_EXPOSURE,visit_detail_id,No,,,integer,0,,The Visit Detail during which the device was prescribed or given.,To populate this field device exposures must be explicitly initiated in the visit detail record.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DEVICE_EXPOSURE,visit_occurrence_id,No,,,integer,0,,The Visit during which the device was prescribed or given.,To populate this field device exposures must be explicitly initiated in the visit.,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOMAIN,domain_concept_id,Yes,0,,integer,0,,A Concept representing the Domain Concept the DOMAIN record belongs to.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DOMAIN,domain_id,Yes,0,,varchar(20),0,,A unique key for each domain.,,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +condition era.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +CONDITION_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_concept_id,Yes,0,,integer,0,,"The CONDITION_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source value which represents a condition","The CONCEPT_ID that the CONDITION_SOURCE_VALUE maps to. Only records whose source values map to concepts with a domain of ""Condition"" should go in this table. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Condition&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_end_date,No,,,date,0,,Use this date to determine the end date of the condition,"Most often data sources do not have the idea of a start date for a condition. Rather, if a source only has one date associated with a condition record it is acceptable to use that date for both the CONDITION_START_DATE and the CONDITION_END_DATE.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATE,1,,Yes,1,,Yes,,, +CONDITION_OCCURRENCE,condition_end_datetime,No,,,datetime,0,,,If a source does not specify datetime the convention is to set the time to midnight (00:00:0000),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,CONDITION_OCCURRENCE,CONDITION_START_DATETIME,1,,Yes,1,,Yes,,, +CONDITION_OCCURRENCE,condition_occurrence_id,Yes,0,,integer,0,,The unique key given to a condition record for a person. Refer to the ETL for how duplicate conditions during the same visit were handled.,"Each instance of a condition present in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same condition within the same visit. It is valid to keep these duplicates and assign them individual, unique, CONDITION_OCCURRENCE_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONDITION_OCCURRENCE,condition_source_concept_id,No,,,integer,0,,"This is the concept representing the condition source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Condition necessary for a given analytic use case. Consider using CONDITION_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the CONDITION_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the condition that occurred. For example, this could be an ICD10 or Read code.",This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,CONDITION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_start_date,Yes,0,,date,0,,Use this date to determine the start date of the condition,"Most often data sources do not have the idea of a start date for a condition. Rather, if a source only has one date associated with a condition record it is acceptable to use that date for both the CONDITION_START_DATE and the CONDITION_END_DATE.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +CONDITION_OCCURRENCE,condition_start_datetime,No,,,datetime,0,,,If a source does not specify datetime the convention is to set the time to midnight (00:00:0000),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +CONDITION_OCCURRENCE,condition_status_concept_id,No,,,integer,0,,"This concept represents the point during the visit the diagnosis was given (admitting diagnosis, final diagnosis), whether the diagnosis was determined due to laboratory findings, if the diagnosis was exclusionary, or if it was a preliminary diagnosis, among others. ","Choose the Concept in the Condition Status domain that best represents the point during the visit when the diagnosis was given. These can include admitting diagnosis, principal diagnosis, and secondary diagnosis. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Condition+Status&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Condition Status,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONDITION_OCCURRENCE,condition_status_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the condition status.,This information may be called something different in the source data but the field is meant to contain a value indicating when and how a diagnosis was given to a patient. This source value is mapped to a standard concept which is stored in the CONDITION_STATUS_CONCEPT_ID field.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,CONDITION_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,condition_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Condition record, as in whether the condition was from an EHR system, insurance claim, registry, or other sources.",Choose the CONDITION_TYPE_CONCEPT_ID that best represents the provenance of the record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,person_id,Yes,0,,integer,0,,The PERSON_ID of the PERSON for whom the condition is recorded.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +CONDITION_OCCURRENCE,provider_id,No,,,integer,0,,"The provider associated with condition record, e.g. the provider who made the diagnosis or the provider who recorded the symptom.","The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record, for example the admitting vs attending physician on an EHR record.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,stop_reason,No,,,varchar(20),0,,The Stop Reason indicates why a Condition is no longer valid with respect to the purpose within the source data. Note that a Stop Reason does not necessarily imply that the condition is no longer occurring.,This information is often not populated in source data and it is a valid etl choice to leave it blank if the information does not exist.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the condition occurred. For example, if the person was in the ICU at the time of the diagnosis the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +CONDITION_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,The visit during which the condition occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If a CONDITION_START_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the Visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the CONDITION_OCCURRENCE record.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +COST,amount_allowed,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,cost_domain_id,Yes,0,,varchar(20),0,,,,No,,,Yes,0,,DOMAIN,DOMAIN_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,cost_event_id,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,cost_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,cost_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,currency_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,drg_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,drg_source_value,No,,,varchar(3),0,,Diagnosis Related Groups are US codes used to classify hospital cases into one of approximately 500 groups. ,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_by_patient,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_by_payer,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_by_primary,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_dispensing_fee,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_ingredient_cost,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_patient_coinsurance,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_patient_copay,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,paid_patient_deductible,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,payer_plan_period_id,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,revenue_code_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +COST,revenue_code_source_value,No,,,varchar(50),0,,Revenue codes are a method to charge for a class of procedures and conditions in the U.S. hospital system.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,total_charge,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,total_cost,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +COST,total_paid,No,,,float,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DEATH,cause_concept_id,No,,,integer,0,,"This is the Standard Concept representing the Person's cause of death, if available.","There is no specified domain for this concept, just choose the Standard Concept Id that best represents the person's cause of death.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,Yes,,, +DEATH,cause_source_concept_id,No,,,integer,0,,,If the cause of death was coded using a Vocabulary present in the OMOP Vocabularies put the CONCEPT_ID representing the cause of death here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEATH,cause_source_value,No,,,varchar(50),0,,,"If available, put the source code representing the cause of death here. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,CAUSE_SOURCE_CONCEPT_ID,,,,,,,,,,,,,,,Yes,,, +DEATH,death_date,Yes,0,,date,0,,The date the person was deceased.,"If the precise date include day or month is not known or not allowed, December is used as the default month, and the last day of the month the default day.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,,,,Yes,,, +DEATH,death_datetime,No,,,datetime,0,,,If not available set time to midnight (00:00:00),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,,,,Yes,,, +DEATH,death_type_concept_id,No,,,integer,0,,"This is the provenance of the death record, i.e., where it came from. It is possible that an administrative claims database would source death information from a government file so do not assume the Death Type is the same as the Visit Type, etc.",Use the type concept that be reflects the source of the death record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,,,,Yes,,, +DEATH,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,Yes,,, +DEVICE_EXPOSURE,device_concept_id,Yes,0,,integer,0,,"The DEVICE_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source concept id which represents a foreign object or instrument the person was exposed to. ",The CONCEPT_ID that the DEVICE_SOURCE_VALUE maps to. ,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Device,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_exposure_end_date,No,,,date,0,,"The DEVICE_EXPOSURE_END_DATE denotes the day the device exposure ended for the patient, if given.",Put the end date or discontinuation date as it appears from the source data or leave blank if unavailable.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATE,1,,Yes,1,,Yes,,, +DEVICE_EXPOSURE,device_exposure_end_datetime,No,,,datetime,0,,,If a source does not specify datetime the convention is to set the time to midnight (00:00:0000),No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DEVICE_EXPOSURE,DEVICE_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes,,, +DEVICE_EXPOSURE,device_exposure_id,Yes,0,,integer,0,,The unique key given to records a person's exposure to a foreign physical object or instrument.,Each instance of an exposure to a foreign object or device present in the source data should be assigned this unique key. ,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DEVICE_EXPOSURE,device_exposure_start_date,Yes,0,,date,0,,Use this date to determine the start date of the device record.,"Valid entries include a start date of a procedure to implant a device, the date of a prescription for a device, or the date of device administration. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +DEVICE_EXPOSURE,device_exposure_start_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DEVICE_EXPOSURE,device_source_concept_id,No,,,integer,0,,"This is the concept representing the device source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Device necessary for a given analytic use case. Consider using DEVICE_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the DEVICE_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the device exposure that occurred. For example, this could be an NDC or Gemscript code.",This code is mapped to a Standard Device Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,DEVICE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,device_type_concept_id,Yes,0,,integer,0,,"You can use the TYPE_CONCEPT_ID to denote the provenance of the record, as in whether the record is from administrative claims or EHR. ","Choose the drug_type_concept_id that best represents the provenance of the record, for example whether it came from a record of a prescription written or physician administered drug. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DEVICE_EXPOSURE,production_id,No,,,varchar(255),0,,This is the Production Identifier (UDI-PI) portion of the Unique Device Identification.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DEVICE_EXPOSURE,provider_id,No,,,integer,0,,"The Provider associated with device record, e.g. the provider who wrote the prescription or the provider who implanted the device.",The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,quantity,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,unique_device_id,No,,,varchar(255),0,,"This is the Unique Device Identification (UDI-DI) number for devices regulated by the FDA, if given. ","For medical devices that are regulated by the FDA, a Unique Device Identification (UDI) is provided if available in the data source and is recorded in the UNIQUE_DEVICE_ID field.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DEVICE_EXPOSURE,unit_concept_id,No,,,integer,0,,UNIT_SOURCE_VALUES should be mapped to a Standard Concept in the Unit domain that best represents the unit as given in the source data. ,"There is no standardization requirement for units associated with DEVICE_CONCEPT_IDs, however, it is the responsibility of the ETL to choose the most plausible unit. If there is no unit associated with a Device record, set to NULL.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DEVICE_EXPOSURE,unit_source_concept_id,No,,,integer,0,,"This is the concept representing the UNIT_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Unit necessary for a given analytic use case. Consider using UNIT_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the UNIT_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here. ,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,unit_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the unit of the Device. For example, blood transfusions are considered devices and can be given in mL quantities. ","This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference. Using the blood transfusion example, blood transfusion is represented by the DEVICE_CONCEPT_ID and the unit (mL) would be housed in the UNIT_SOURCE_VALUE and mapped to a standard concept in the unit domain. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,UNIT_CONCEPT_ID,,,,,,,,,,,,,,,,,, +DEVICE_EXPOSURE,visit_detail_id,No,,,integer,0,,The Visit Detail during which the device was prescribed or given.,To populate this field device exposures must be explicitly initiated in the visit detail record.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DEVICE_EXPOSURE,visit_occurrence_id,No,,,integer,0,,The Visit during which the device was prescribed or given.,To populate this field device exposures must be explicitly initiated in the visit.,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOMAIN,domain_concept_id,Yes,0,,integer,0,,A Concept representing the Domain Concept the DOMAIN record belongs to.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DOMAIN,domain_id,Yes,0,,varchar(20),0,,A unique key for each domain.,,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, DOMAIN,domain_name,Yes,0,,varchar(255),0,,"The name describing the Domain, e.g. Condition, Procedure, Measurement -etc.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DOSE_ERA,dose_era_end_date,Yes,0,,datetime,0,,,The date the Person was no longer exposed to the dosage of the specific drug ingredient. An era is ended if there are 31 days or more between dosage records.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -DOSE_ERA,dose_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,dose_era_start_date,Yes,0,,datetime,0,,"The date the Person started on the specific dosage, with at least 31 days since any prior exposure.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DOSE_ERA,dose_value,Yes,0,,float,0,,The numeric value of the dosage of the drug_ingredient.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes -DOSE_ERA,drug_concept_id,Yes,0,,integer,0,,The Concept Id representing the specific drug ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DOSE_ERA,unit_concept_id,Yes,0,,integer,0,,The Concept Id representing the unit of the specific drug ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_ERA,drug_concept_id,Yes,0,,integer,0,,The Concept Id representing the specific drug ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +etc.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DOSE_ERA,dose_era_end_date,Yes,0,,datetime,0,,,The date the Person was no longer exposed to the dosage of the specific drug ingredient. An era is ended if there are 31 days or more between dosage records.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +DOSE_ERA,dose_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,dose_era_start_date,Yes,0,,datetime,0,,"The date the Person started on the specific dosage, with at least 31 days since any prior exposure.",,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DOSE_ERA,dose_value,Yes,0,,float,0,,The numeric value of the dosage of the drug_ingredient.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,drug_concept_id,Yes,0,,integer,0,,The Concept Id representing the specific drug ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DOSE_ERA,unit_concept_id,Yes,0,,integer,0,,The Concept Id representing the unit of the specific drug ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,drug_concept_id,Yes,0,,integer,0,,The Concept Id representing the specific drug ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,Ingredient,0,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, DRUG_ERA,drug_era_end_date,Yes,0,,datetime,0,,,"The Drug Era End Date is the end date of the last Drug Exposure. The End Date of each Drug Exposure is either taken from the field drug_exposure_end_date or, as it is typically not available, inferred using the following rules: For pharmacy prescription data, the date when the drug was dispensed plus the number of days of supply are used to extrapolate the End Date for the Drug Exposure. Depending on the country-specific healthcare system, this supply information is either explicitly provided in the day_supply field or inferred from package size or similar information. For Procedure Drugs, usually the drug is administered on a single date (i.e., the administration date). -A standard Persistence Window of 30 days (gap, slack) is permitted between two subsequent such extrapolated DRUG_EXPOSURE records to be considered to be merged into a single Drug Era.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_ERA,DRUG_ERA_START_DATE,1,,No,,,Yes -DRUG_ERA,drug_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_ERA,drug_era_start_date,Yes,0,,datetime,0,,,"The Drug Era Start Date is the start date of the first Drug Exposure for a given ingredient, with at least 31 days since the previous exposure. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DRUG_ERA,drug_exposure_count,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -DRUG_ERA,gap_days,No,,,integer,0,,,"The Gap Days determine how many total drug-free days are observed between all Drug Exposure events that contribute to a DRUG_ERA record. It is assumed that the drugs are ""not stockpiled"" by the patient, i.e. that if a new drug prescription or refill is observed (a new DRUG_EXPOSURE record is written), the remaining supply from the previous events is abandoned. The difference between Persistence Window and Gap Days is that the former is the maximum drug-free time allowed between two subsequent DRUG_EXPOSURE records, while the latter is the sum of actual drug-free days for the given Drug Era under the above assumption of non-stockpiling.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes -DRUG_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,days_supply,No,,,integer,0,,,Days supply of the drug. This should be the verbatim days_supply as given on the prescription. If the drug is physician administered use duration end date if given or set to 1 as default if duration is not available.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,365,1,,,,,,,No,,,Yes -DRUG_EXPOSURE,dose_unit_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the dose unit of the drug given.,This information may be called something different in the source data but the field is meant to contain a value indicating the unit of dosage of drug given to the patient. **This is an older column and will be deprecated in an upcoming version.**,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_concept_id,Yes,0,,integer,0,,"The DRUG_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source concept id which represents a drug product or molecule otherwise introduced to the body. The drug concepts can have a varying degree of information about drug strength and dose. This information is relevant in the context of quantity and administration information in the subsequent fields plus strength information from the DRUG_STRENGTH table, provided as part of the standard vocabulary download.","The CONCEPT_ID that the DRUG_SOURCE_VALUE maps to. The concept id should be derived either from mapping from the source concept id or by picking the drug concept representing the most amount of detail you have. Records whose source values map to standard concepts with a domain of Drug should go in this table. When the Drug Source Value of the code cannot be translated into Standard Drug Concept IDs, a Drug exposure entry is stored with only the corresponding SOURCE_CONCEPT_ID and DRUG_SOURCE_VALUE and a DRUG_CONCEPT_ID of 0. The Drug Concept with the most detailed content of information is preferred during the mapping process. These are indicated in the CONCEPT_CLASS_ID field of the Concept and are recorded in the following order of precedence: 'Branded Pack', 'Clinical Pack', 'Branded Drug', 'Clinical Drug', 'Branded Drug Component', 'Clinical Drug Component', 'Branded Drug Form', 'Clinical Drug Form', and only if no other information is available 'Ingredient'. Note: If only the drug class is known, the DRUG_CONCEPT_ID field should contain 0. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Drug&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_exposure_end_date,Yes,0,,date,0,,The DRUG_EXPOSURE_END_DATE denotes the day the drug exposure ended for the patient.,"If this information is not explicitly available in the data, infer the end date using the following methods:

1. Start first with duration or days supply using the calculation drug start date + days supply -1 day. 2. Use quantity divided by daily dose that you may obtain from the sig or a source field (or assumed daily dose of 1) for solid, indivisibile, drug products. If quantity represents ingredient amount, quantity divided by daily dose * concentration (from drug_strength) drug concept id tells you the dose form. 3. If it is an administration record, set drug end date equal to drug start date. If the record is a written prescription then set end date to start date + 29. If the record is a mail-order prescription set end date to start date + 89. The end date must be equal to or greater than the start date. Ibuprofen 20mg/mL oral solution concept tells us this is oral solution. Calculate duration as quantity (200 example) * daily dose (5mL) /concentration (20mg/mL) 200*5/20 = 50 days. [Examples by dose form](https://ohdsi.github.io/CommonDataModel/drug_dose.html)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_exposure_end_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_exposure_id,Yes,0,,integer,0,,The unique key given to records of drug dispensings or administrations for a person. Refer to the ETL for how duplicate drugs during the same visit were handled.,"Each instance of a drug dispensing or administration present in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same drug within the same visit. It is valid to keep these duplicates and assign them individual, unique, DRUG_EXPOSURE_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_EXPOSURE,drug_exposure_start_date,Yes,0,,date,0,,Use this date to determine the start date of the drug record.,"Valid entries include a start date of a prescription, the date a prescription was filled, or the date on which a Drug administration was recorded. It is a valid ETL choice to use the date the drug was ordered as the DRUG_EXPOSURE_START_DATE.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_exposure_start_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -DRUG_EXPOSURE,drug_source_concept_id,No,,,integer,0,,"This is the concept representing the drug source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Drug necessary for a given analytic use case. Consider using DRUG_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the DRUG_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the drug exposure that occurred. For example, this could be an NDC or Gemscript code.",This code is mapped to a Standard Drug Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,DRUG_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,drug_type_concept_id,Yes,0,,integer,0,,"You can use the TYPE_CONCEPT_ID to delineate between prescriptions written vs. prescriptions dispensed vs. medication history vs. patient-reported exposure, etc.","Choose the drug_type_concept_id that best represents the provenance of the record, for example whether it came from a record of a prescription written or physician administered drug. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,lot_number,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,person_id,Yes,0,,integer,0,,The PERSON_ID of the PERSON for whom the drug dispensing or administration is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_EXPOSURE,provider_id,No,,,integer,0,,"The Provider associated with drug record, e.g. the provider who wrote the prescription or the provider who administered the drug.","The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record, for example the ordering vs administering physician on an EHR record.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +A standard Persistence Window of 30 days (gap, slack) is permitted between two subsequent such extrapolated DRUG_EXPOSURE records to be considered to be merged into a single Drug Era.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_ERA,DRUG_ERA_START_DATE,1,,No,,,Yes,,, +DRUG_ERA,drug_era_id,Yes,0,,integer,0,,,,Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,drug_era_start_date,Yes,0,,datetime,0,,,"The Drug Era Start Date is the start date of the first Drug Exposure for a given ingredient, with at least 31 days since the previous exposure. ",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DRUG_ERA,drug_exposure_count,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,gap_days,No,,,integer,0,,,"The Gap Days determine how many total drug-free days are observed between all Drug Exposure events that contribute to a DRUG_ERA record. It is assumed that the drugs are ""not stockpiled"" by the patient, i.e. that if a new drug prescription or refill is observed (a new DRUG_EXPOSURE record is written), the remaining supply from the previous events is abandoned. The difference between Persistence Window and Gap Days is that the former is the maximum drug-free time allowed between two subsequent DRUG_EXPOSURE records, while the latter is the sum of actual drug-free days for the given Drug Era under the above assumption of non-stockpiling.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,,,,,,,,,No,,,Yes,,, +DRUG_ERA,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,days_supply,No,,,integer,0,,,Days supply of the drug. This should be the verbatim days_supply as given on the prescription. If the drug is physician administered use duration end date if given or set to 1 as default if duration is not available.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,365,1,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,dose_unit_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the dose unit of the drug given.,This information may be called something different in the source data but the field is meant to contain a value indicating the unit of dosage of drug given to the patient. **This is an older column and will be deprecated in an upcoming version.**,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_concept_id,Yes,0,,integer,0,,"The DRUG_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source concept id which represents a drug product or molecule otherwise introduced to the body. The drug concepts can have a varying degree of information about drug strength and dose. This information is relevant in the context of quantity and administration information in the subsequent fields plus strength information from the DRUG_STRENGTH table, provided as part of the standard vocabulary download.","The CONCEPT_ID that the DRUG_SOURCE_VALUE maps to. The concept id should be derived either from mapping from the source concept id or by picking the drug concept representing the most amount of detail you have. Records whose source values map to standard concepts with a domain of Drug should go in this table. When the Drug Source Value of the code cannot be translated into Standard Drug Concept IDs, a Drug exposure entry is stored with only the corresponding SOURCE_CONCEPT_ID and DRUG_SOURCE_VALUE and a DRUG_CONCEPT_ID of 0. The Drug Concept with the most detailed content of information is preferred during the mapping process. These are indicated in the CONCEPT_CLASS_ID field of the Concept and are recorded in the following order of precedence: 'Branded Pack', 'Clinical Pack', 'Branded Drug', 'Clinical Drug', 'Branded Drug Component', 'Clinical Drug Component', 'Branded Drug Form', 'Clinical Drug Form', and only if no other information is available 'Ingredient'. Note: If only the drug class is known, the DRUG_CONCEPT_ID field should contain 0. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Drug&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,,,,Yes,0,,Yes,100,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_exposure_end_date,Yes,0,,date,0,,The DRUG_EXPOSURE_END_DATE denotes the day the drug exposure ended for the patient.,"If this information is not explicitly available in the data, infer the end date using the following methods:

1. Start first with duration or days supply using the calculation drug start date + days supply -1 day. 2. Use quantity divided by daily dose that you may obtain from the sig or a source field (or assumed daily dose of 1) for solid, indivisibile, drug products. If quantity represents ingredient amount, quantity divided by daily dose * concentration (from drug_strength) drug concept id tells you the dose form. 3. If it is an administration record, set drug end date equal to drug start date. If the record is a written prescription then set end date to start date + 29. If the record is a mail-order prescription set end date to start date + 89. The end date must be equal to or greater than the start date. Ibuprofen 20mg/mL oral solution concept tells us this is oral solution. Calculate duration as quantity (200 example) * daily dose (5mL) /concentration (20mg/mL) 200*5/20 = 50 days. [Examples by dose form](https://ohdsi.github.io/CommonDataModel/drug_dose.html)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,drug_exposure_end_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATETIME,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,drug_exposure_id,Yes,0,,integer,0,,The unique key given to records of drug dispensings or administrations for a person. Refer to the ETL for how duplicate drugs during the same visit were handled.,"Each instance of a drug dispensing or administration present in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same drug within the same visit. It is valid to keep these duplicates and assign them individual, unique, DRUG_EXPOSURE_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_EXPOSURE,drug_exposure_start_date,Yes,0,,date,0,,Use this date to determine the start date of the drug record.,"Valid entries include a start date of a prescription, the date a prescription was filled, or the date on which a Drug administration was recorded. It is a valid ETL choice to use the date the drug was ordered as the DRUG_EXPOSURE_START_DATE.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +DRUG_EXPOSURE,drug_exposure_start_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,drug_source_concept_id,No,,,integer,0,,"This is the concept representing the drug source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Drug necessary for a given analytic use case. Consider using DRUG_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the DRUG_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,100,,No,,,Yes,10,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the drug exposure that occurred. For example, this could be an NDC or Gemscript code.",This code is mapped to a Standard Drug Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,10,,DRUG_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,drug_type_concept_id,Yes,0,,integer,0,,"You can use the TYPE_CONCEPT_ID to delineate between prescriptions written vs. prescriptions dispensed vs. medication history vs. patient-reported exposure, etc.","Choose the drug_type_concept_id that best represents the provenance of the record, for example whether it came from a record of a prescription written or physician administered drug. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,100,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,lot_number,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,person_id,Yes,0,,integer,0,,The PERSON_ID of the PERSON for whom the drug dispensing or administration is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_EXPOSURE,provider_id,No,,,integer,0,,"The Provider associated with drug record, e.g. the provider who wrote the prescription or the provider who administered the drug.","The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record, for example the ordering vs administering physician on an EHR record.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, DRUG_EXPOSURE,quantity,No,,,float,0,,,"To find the dose form of a drug the RELATIONSHIP table can be used where the relationship_id is 'Has dose form'. If liquid, quantity stands for the total amount dispensed or ordered of ingredient in the units given by the drug_strength table. If the unit from the source data does not align with the unit in the DRUG_STRENGTH table the quantity should be converted to the correct unit given in DRUG_STRENGTH. For clinical drugs with fixed dose forms (tablets etc.) the quantity is the number of units/tablets/capsules prescribed or dispensed (can be partial, but then only 1/2 or 1/3, not 0.01). Clinical drugs with divisible dose forms (injections) the quantity is the amount of ingredient the patient got. For example, if the injection is 2mg/mL but the patient got 80mL then quantity is reported as 160. Quantified clinical drugs with divisible dose forms (prefilled syringes), the quantity is the amount of ingredient similar to clinical drugs. Please see [how to calculate drug dose](https://ohdsi.github.io/CommonDataModel/drug_dose.html) for more information. -",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,1095,1,,,,,,,No,,,Yes -DRUG_EXPOSURE,refills,No,,,integer,0,,This is only filled in when the record is coming from a prescription written this field is meant to represent intended refills at time of the prescription.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,12,1,,,,,,,No,,,Yes -DRUG_EXPOSURE,route_concept_id,No,,,integer,0,,,The standard CONCEPT_ID that the ROUTE_SOURCE_VALUE maps to in the route domain.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Route,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,route_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the drug route.,This information may be called something different in the source data but the field is meant to contain a value indicating when and how a drug was given to a patient. This source value is mapped to a standard concept which is stored in the ROUTE_CONCEPT_ID field.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ROUTE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,sig,No,,,varchar(MAX),0,,This is the verbatim instruction for the drug as written by the provider.,"Put the written out instructions for the drug as it is verbatim in the source, if available.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,stop_reason,No,,,varchar(20),0,,"The reason a person stopped a medication as it is represented in the source. Reasons include regimen completed, changed, removed, etc. This field will be retired in v6.0.",This information is often not populated in source data and it is a valid etl choice to leave it blank if the information does not exist.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,verbatim_end_date,No,,,date,0,,"This is the end date of the drug exposure as it appears in the source data, if it is given",Put the end date or discontinuation date as it appears from the source data or leave blank if unavailable.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes -DRUG_EXPOSURE,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the drug exposure occurred. For example, if the person was in the ICU at the time of the drug administration the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_EXPOSURE,visit_occurrence_id,No,,,integer,0,,"The Visit during which the drug was prescribed, administered or dispensed.",To populate this field drug exposures must be explicitly initiated in the visit.,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -DRUG_STRENGTH,amount_unit_concept_id,No,,,integer,0,,The Concept representing the Unit of measure for the amount of active ingredient contained within the drug product. ,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,amount_value,No,,,float,0,,The numeric value or the amount of active ingredient contained within the drug product.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,box_size,No,,,integer,0,,The number of units of Clinical Branded Drug or Quantified Clinical or Branded Drug contained in a box as dispensed to the patient.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,denominator_unit_concept_id,No,,,integer,0,,The Concept representing the denominator unit for the concentration of active ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,denominator_value,No,,,float,0,,"The amount of total liquid (or other divisible product, such as ointment, gel, spray, etc.).",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,drug_concept_id,Yes,0,,integer,0,,The Concept representing the Branded Drug or Clinical Drug Product.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,ingredient_concept_id,Yes,0,,integer,0,,The Concept representing the active ingredient contained within the drug product.,"Combination Drugs will have more than one record in this table, one for each active Ingredient.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,Ingredient,0,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,invalid_reason,No,,,varchar(1),0,,"Reason the concept was invalidated. Possible values are D (deleted), U (replaced with an update) or NULL when valid_end_date has the default value.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,numerator_unit_concept_id,No,,,integer,0,,The Concept representing the Unit of measure for the concentration of active ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,numerator_value,No,,,float,0,,The concentration of the active ingredient contained within the drug product.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -DRUG_STRENGTH,valid_end_date,Yes,0,,date,0,,The date when then Concept became invalid.,,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,Yes,DRUG_STRENGTH,VALID_START_DATE,0,,,,, +",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,1095,1,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,refills,No,,,integer,0,,This is only filled in when the record is coming from a prescription written this field is meant to represent intended refills at time of the prescription.,,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,0,1,,12,1,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,route_concept_id,No,,,integer,0,,,The standard CONCEPT_ID that the ROUTE_SOURCE_VALUE maps to in the route domain.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Route,0,,,,,Yes,0,,Yes,100,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,route_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the drug route.,This information may be called something different in the source data but the field is meant to contain a value indicating when and how a drug was given to a patient. This source value is mapped to a standard concept which is stored in the ROUTE_CONCEPT_ID field.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,Yes,100,,ROUTE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,sig,No,,,varchar(MAX),0,,This is the verbatim instruction for the drug as written by the provider.,"Put the written out instructions for the drug as it is verbatim in the source, if available.",No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,stop_reason,No,,,varchar(20),0,,"The reason a person stopped a medication as it is represented in the source. Reasons include regimen completed, changed, removed, etc. This field will be retired in v6.0.",This information is often not populated in source data and it is a valid etl choice to leave it blank if the information does not exist.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,verbatim_end_date,No,,,date,0,,"This is the end date of the drug exposure as it appears in the source data, if it is given",Put the end date or discontinuation date as it appears from the source data or leave blank if unavailable.,No,,,No,,,,,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,DRUG_EXPOSURE,DRUG_EXPOSURE_START_DATE,1,,Yes,1,,Yes,,, +DRUG_EXPOSURE,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the drug exposure occurred. For example, if the person was in the ICU at the time of the drug administration the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_EXPOSURE,visit_occurrence_id,No,,,integer,0,,"The Visit during which the drug was prescribed, administered or dispensed.",To populate this field drug exposures must be explicitly initiated in the visit.,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +DRUG_STRENGTH,amount_unit_concept_id,No,,,integer,0,,The Concept representing the Unit of measure for the amount of active ingredient contained within the drug product. ,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,amount_value,No,,,float,0,,The numeric value or the amount of active ingredient contained within the drug product.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,box_size,No,,,integer,0,,The number of units of Clinical Branded Drug or Quantified Clinical or Branded Drug contained in a box as dispensed to the patient.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,denominator_unit_concept_id,No,,,integer,0,,The Concept representing the denominator unit for the concentration of active ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,denominator_value,No,,,float,0,,"The amount of total liquid (or other divisible product, such as ointment, gel, spray, etc.).",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,drug_concept_id,Yes,0,,integer,0,,The Concept representing the Branded Drug or Clinical Drug Product.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Drug,0,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,ingredient_concept_id,Yes,0,,integer,0,,The Concept representing the active ingredient contained within the drug product.,"Combination Drugs will have more than one record in this table, one for each active Ingredient.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,Ingredient,0,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,invalid_reason,No,,,varchar(1),0,,"Reason the concept was invalidated. Possible values are D (deleted), U (replaced with an update) or NULL when valid_end_date has the default value.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,numerator_unit_concept_id,No,,,integer,0,,The Concept representing the Unit of measure for the concentration of active ingredient.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,numerator_value,No,,,float,0,,The concentration of the active ingredient contained within the drug product.,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +DRUG_STRENGTH,valid_end_date,Yes,0,,date,0,,The date when then Concept became invalid.,,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,Yes,DRUG_STRENGTH,VALID_START_DATE,0,,,,,,,, DRUG_STRENGTH,valid_start_date,Yes,0,,date,0,,"The date when the Concept was first recorded. The default value is -1-Jan-1970.",,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_concept_id,Yes,0,,integer,0,,"The EPISODE_CONCEPT_ID represents the kind abstraction related to the disease phase, outcome or treatment.","Choose a concept in the Episode domain that best represents the ongoing disease phase, outcome, or treatment. Please see [article] for cancers and [article] for non-cancers describing how these are defined. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Episode&page=1&pageSize=15&query=)",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Episode,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_end_date,No,,,date,0,,The date when the instance of the Episode is considered to have ended.,Please see [article] for how to define an Episode end date.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,EPISODE,EPISODE_START_DATE,1,,Yes,1,,Yes -EPISODE,episode_end_datetime,No,,,datetime,0,,The date when the instance of the Episode is considered to have ended.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,EPISODE,EPISODE_START_DATETIME,1,,Yes,1,,Yes -EPISODE,episode_id,Yes,0,,bigint,0,,A unique identifier for each Episode.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_number,No,,,integer,0,,"For sequences of episodes, this is used to indicate the order the episodes occurred. For example, lines of treatment could be indicated here. ",Please see [article] for the details of how to count episodes.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_object_concept_id,Yes,0,,integer,0,,"A Standard Concept representing the disease phase, outcome, or other abstraction of which the episode consists. For example, if the EPISODE_CONCEPT_ID is [treatment regimen](https://athena.ohdsi.org/search-terms/terms/32531) then the EPISODE_OBJECT_CONCEPT_ID should contain the chemotherapy regimen concept, like [Afatinib monotherapy](https://athena.ohdsi.org/search-terms/terms/35804392). ",Episode entries from the 'Disease Episode' concept class should have an episode_object_concept_id that comes from the Condition domain. Episode entries from the 'Treatment Episode' concept class should have an episode_object_concept_id that scome from the 'Procedure' domain or 'Regimen' concept class.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Procedure OR Regimen,0,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_parent_id,No,,,bigint,0,,Use this field to find the Episode that subsumes the given Episode record. This is used in the case that an Episode are nested into each other.,"If there are multiple nested levels to how Episodes are represented, the EPISODE_PARENT_ID can be used to record this relationship. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_source_concept_id,No,,,integer,0,,A foreign key to a Episode Concept that refers to the code used in the source.,Given that the Episodes are user-defined it is unlikely that there will be a Source Concept available. If that is the case then set this field to zero. ,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,No -EPISODE,episode_source_value,No,,,varchar(50),0,,The source code for the Episdoe as it appears in the source data. This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,episode_start_date,Yes,0,,date,0,,The date when the Episode beings. ,Please see [article] for how to define an Episode start date.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -EPISODE,episode_start_datetime,No,,,datetime,0,,The date and time when the Episode begins.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -EPISODE,episode_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Episode record, as in whether the episode was from an EHR system, insurance claim, registry, or other sources.",Choose the EPISODE_TYPE_CONCEPT_ID that best represents the provenance of the record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE,person_id,Yes,0,,bigint,0,,The PERSON_ID of the PERSON for whom the episode is recorded.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE_EVENT,episode_event_field_concept_id,Yes,0,,integer,0,,This field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ,Put the CONCEPT_ID that identifies which table and field the EVENT_ID came from. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?vocabulary=CDM&conceptClass=Field&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,Metadata,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE_EVENT,episode_id,Yes,0,,bigint,0,,Use this field to link the EPISODE_EVENT record to its EPISODE.,Put the EPISODE_ID that subsumes the EPISODE_EVENT record here.,No,,,Yes,0,,EPISODE,EPISODE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -EPISODE_EVENT,event_id,Yes,0,,bigint,0,,"This field is the primary key of the linked record in the database. For example, if the Episode Event is a Condition Occurrence, then the CONDITION_OCCURRENCE_ID of the linked record goes in this field. ",Put the primary key of the linked record here. ,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -FACT_RELATIONSHIP,domain_concept_id_1,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,domain_concept_id_2,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,fact_id_1,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,fact_id_2,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -FACT_RELATIONSHIP,relationship_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,address_1,No,,,varchar(50),0,,This is the first line of the address.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,address_2,No,,,varchar(50),0,,This is the second line of the address,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,city,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,country_concept_id,No,,,integer,0,,The Concept Id representing the country. Values should conform to the [Geography](https://athena.ohdsi.org/search-terms/terms?domain=Geography&standardConcept=Standard&page=1&pageSize=15&query=&boosts) domain. ,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Geography,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,,,, -LOCATION,country_source_value,No,,,varchar(80),0,,The name of the country.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -LOCATION,county,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,latitude,No,,,float,0,,,Must be between -90 and 90.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -LOCATION,location_id,Yes,0,,integer,0,,The unique key given to a unique Location.,Each instance of a Location in the source data should be assigned this unique key.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,location_source_value,No,,,varchar(50),0,,,"Put the verbatim value for the location here, as it shows up in the source. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,longitude,No,,,float,0,,,Must be between -180 and 180.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -LOCATION,state,No,,,varchar(2),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -LOCATION,zip,No,,,varchar(9),0,,,"Zip codes are handled as strings of up to 9 characters length. For US addresses, these represent either a 3-digit abbreviated Zip code as provided by many sources for patient protection reasons, the full 5-digit Zip or the 9-digit (ZIP + 4) codes. Unless for specific reasons analytical methods should expect and utilize only the first 3 digits. For international addresses, different rules apply.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -MEASUREMENT,meas_event_field_concept_id,No,,,integer,0,,"If the Measurement record is related to another record in the database, this field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ",Put the CONCEPT_ID that identifies which table and field the MEASUREMENT_EVENT_ID came from.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -MEASUREMENT,measurement_concept_id,Yes,0,,integer,0,,"The MEASUREMENT_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies.","The CONCEPT_ID that the MEASUREMENT_SOURCE_CONCEPT_ID maps to. Only records whose SOURCE_CONCEPT_IDs map to Standard Concepts with a domain of ""Measurement"" should go in this table.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Measurement,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_date,Yes,0,,date,0,,Use this date to determine the date of the measurement.,"If there are multiple dates in the source data associated with a record such as order_date, draw_date, and result_date, choose the one that is closest to the date the sample was drawn from the patient.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -MEASUREMENT,measurement_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,Yes -MEASUREMENT,measurement_event_id,No,,,bigint,0,,"If the Measurement record is related to another record in the database, this field is the primary key of the linked record. ","Put the primary key of the linked record, if applicable, here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -MEASUREMENT,measurement_id,Yes,0,,integer,0,,The unique key given to a Measurement record for a Person. Refer to the ETL for how duplicate Measurements during the same Visit were handled.,"Each instance of a measurement present in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same measurement within the same visit. It is valid to keep these duplicates and assign them individual, unique, MEASUREMENT_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_source_concept_id,No,,,integer,0,,"This is the concept representing the MEASUREMENT_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Measurement necessary for a given analytic use case. Consider using MEASUREMENT_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the MEASUREMENT_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the Measurement that occurred. For example, this could be an ICD10 or Read code.",This code is mapped to a Standard Measurement Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,MEASUREMENT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_time,No,,,varchar(10),0,,,This is present for backwards compatibility and will be deprecated in an upcoming version.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,measurement_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Measurement record, as in whether the measurement was from an EHR system, insurance claim, registry, or other sources.","Choose the MEASUREMENT_TYPE_CONCEPT_ID that best represents the provenance of the record, for example whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,operator_concept_id,No,,,integer,0,,"The meaning of Concept [4172703](https://athena.ohdsi.org/search-terms/terms/4172703) for '=' is identical to omission of a OPERATOR_CONCEPT_ID value. Since the use of this field is rare, it's important when devising analyses to not to forget testing for the content of this field for values different from =.","Operators are <, <=, =, >=, > and these concepts belong to the 'Meas Value Operator' domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Meas+Value+Operator&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Meas Value Operator,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,person_id,Yes,0,,integer,0,,The PERSON_ID of the Person for whom the Measurement is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,provider_id,No,,,integer,0,,"The provider associated with measurement record, e.g. the provider who ordered the test or the provider who recorded the result.",The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record. For example the admitting vs attending physician on an EHR record.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,range_high,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER. These ranges are provided by the source and should remain NULL if not given.,If reference ranges for upper and lower limit of normal as provided (typically by a laboratory) these are stored in the RANGE_HIGH and RANGE_LOW fields. This should be set to NULL if not provided.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,range_low,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER. These ranges are provided by the source and should remain NULL if not given.,If reference ranges for upper and lower limit of normal as provided (typically by a laboratory) these are stored in the RANGE_HIGH and RANGE_LOW fields. This should be set to NULL if not provided.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,unit_concept_id,No,,,integer,0,,"There is currently no recommended unit for individual measurements, i.e. it is not mandatory to represent Hemoglobin a1C measurements as a percentage. UNIT_SOURCE_VALUES should be mapped to a Standard Concept in the Unit domain that best represents the unit as given in the source data.","There is no standardization requirement for units associated with MEASUREMENT_CONCEPT_IDs, however, it is the responsibility of the ETL to choose the most plausible unit.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,unit_source_concept_id,No,,,integer,0,,"""This is the concept representing the UNIT_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Measurement necessary for a given analytic use case. Consider using UNIT_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.""",If the UNIT_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,50,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,unit_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the unit of the Measurement that occurred. ,This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -MEASUREMENT,value_as_concept_id,No,,,integer,0,,If the raw data gives a categorial result for measurements those values are captured and mapped to standard concepts in the 'Meas Value' domain.,"If the raw data provides categorial results as well as continuous results for measurements, it is a valid ETL choice to preserve both values. The continuous value should go in the VALUE_AS_NUMBER field and the categorical value should be mapped to a standard concept in the 'Meas Value' domain and put in the VALUE_AS_CONCEPT_ID field. This is also the destination for the 'Maps to value' relationship.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Meas Value,0,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,value_as_number,No,,,float,0,,"This is the numerical value of the Result of the Measurement, if available. Note that measurements such as blood pressures will be split into their component parts i.e. one record for systolic, one record for diastolic.","If there is a negative value coming from the source, set the VALUE_AS_NUMBER to NULL, with the exception of the following Measurements (listed as LOINC codes):
- [1925-7](https://athena.ohdsi.org/search-terms/terms/3003396) Base excess in Arterial blood by calculation - [1927-3](https://athena.ohdsi.org/search-terms/terms/3002032) Base excess in Venous blood by calculation - [8632-2](https://athena.ohdsi.org/search-terms/terms/3006277) QRS-Axis - [11555-0](https://athena.ohdsi.org/search-terms/terms/3012501) Base excess in Blood by calculation - [1926-5](https://athena.ohdsi.org/search-terms/terms/3003129) Base excess in Capillary blood by calculation - [28638-5](https://athena.ohdsi.org/search-terms/terms/3004959) Base excess in Arterial cord blood by calculation [28639-3](https://athena.ohdsi.org/search-terms/terms/3007435) Base excess in Venous cord blood by calculation",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,value_source_value,No,,,varchar(50),0,,This field houses the verbatim result value of the Measurement from the source data . ,"If both a continuous and categorical result are given in the source data such that both VALUE_AS_NUMBER and VALUE_AS_CONCEPT_ID are both included, store the verbatim value that was mapped to VALUE_AS_CONCEPT_ID here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the Measurement occurred. For example, if the Person was in the ICU at the time the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -MEASUREMENT,visit_occurrence_id,No,,,integer,0,,The visit during which the Measurement occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If a MEASUREMENT_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the measurement record. If a measurement is related to a visit explicitly in the source data, it is possible that the result date of the Measurement falls outside of the bounds of the Visit dates.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -METADATA,metadata_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,metadata_date,No,,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,metadata_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,metadata_id,Yes,0,,integer,0,,The unique key given to a Metadata record.,Attribute value is auto-generated,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,metadata_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,name,Yes,0,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,value_as_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,value_as_number,No,,,float,0,,"This is the numerical value of the result of the Metadata, if applicable and available. It is not expected that all Metadata will have numeric results, rather, this field is here to house values should they exist. ",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -METADATA,value_as_string,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -NOTE,encoding_concept_id,Yes,0,,integer,0,,This is the Concept representing the character encoding type. ,"Put the Concept Id that represents the encoding character type here. Currently the only option is UTF-8 ([32678](https://athena.ohdsi.org/search-terms/terms/32678)). It the note is encoded in any other type, like ASCII then put 0. ",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,language_concept_id,Yes,0,,integer,0,,The language of the note. ,Use Concepts that are descendants of the concept [4182347](https://athena.ohdsi.org/search-terms/terms/4182347) (World Languages).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +1-Jan-1970.",,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_concept_id,Yes,0,,integer,0,,"The EPISODE_CONCEPT_ID represents the kind abstraction related to the disease phase, outcome or treatment.","Choose a concept in the Episode domain that best represents the ongoing disease phase, outcome, or treatment. Please see [article] for cancers and [article] for non-cancers describing how these are defined. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Episode&page=1&pageSize=15&query=)",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Episode,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_end_date,No,,,date,0,,The date when the instance of the Episode is considered to have ended.,Please see [article] for how to define an Episode end date.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,EPISODE,EPISODE_START_DATE,1,,Yes,1,,Yes,,, +EPISODE,episode_end_datetime,No,,,datetime,0,,The date when the instance of the Episode is considered to have ended.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,EPISODE,EPISODE_START_DATETIME,1,,Yes,1,,Yes,,, +EPISODE,episode_id,Yes,0,,bigint,0,,A unique identifier for each Episode.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_number,No,,,integer,0,,"For sequences of episodes, this is used to indicate the order the episodes occurred. For example, lines of treatment could be indicated here. ",Please see [article] for the details of how to count episodes.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_object_concept_id,Yes,0,,integer,0,,"A Standard Concept representing the disease phase, outcome, or other abstraction of which the episode consists. For example, if the EPISODE_CONCEPT_ID is [treatment regimen](https://athena.ohdsi.org/search-terms/terms/32531) then the EPISODE_OBJECT_CONCEPT_ID should contain the chemotherapy regimen concept, like [Afatinib monotherapy](https://athena.ohdsi.org/search-terms/terms/35804392). ",Episode entries from the 'Disease Episode' concept class should have an episode_object_concept_id that comes from the Condition domain. Episode entries from the 'Treatment Episode' concept class should have an episode_object_concept_id that scome from the 'Procedure' domain or 'Regimen' concept class.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Procedure OR Regimen,0,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_parent_id,No,,,bigint,0,,Use this field to find the Episode that subsumes the given Episode record. This is used in the case that an Episode are nested into each other.,"If there are multiple nested levels to how Episodes are represented, the EPISODE_PARENT_ID can be used to record this relationship. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_source_concept_id,No,,,integer,0,,A foreign key to a Episode Concept that refers to the code used in the source.,Given that the Episodes are user-defined it is unlikely that there will be a Source Concept available. If that is the case then set this field to zero. ,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,No,,, +EPISODE,episode_source_value,No,,,varchar(50),0,,The source code for the Episdoe as it appears in the source data. This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,episode_start_date,Yes,0,,date,0,,The date when the Episode beings. ,Please see [article] for how to define an Episode start date.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +EPISODE,episode_start_datetime,No,,,datetime,0,,The date and time when the Episode begins.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +EPISODE,episode_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Episode record, as in whether the episode was from an EHR system, insurance claim, registry, or other sources.",Choose the EPISODE_TYPE_CONCEPT_ID that best represents the provenance of the record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE,person_id,Yes,0,,bigint,0,,The PERSON_ID of the PERSON for whom the episode is recorded.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE_EVENT,episode_event_field_concept_id,Yes,0,,integer,0,,This field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ,Put the CONCEPT_ID that identifies which table and field the EVENT_ID came from. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?vocabulary=CDM&conceptClass=Field&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,Metadata,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE_EVENT,episode_id,Yes,0,,bigint,0,,Use this field to link the EPISODE_EVENT record to its EPISODE.,Put the EPISODE_ID that subsumes the EPISODE_EVENT record here.,No,,,Yes,0,,EPISODE,EPISODE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +EPISODE_EVENT,event_id,Yes,0,,bigint,0,,"This field is the primary key of the linked record in the database. For example, if the Episode Event is a Condition Occurrence, then the CONDITION_OCCURRENCE_ID of the linked record goes in this field. ",Put the primary key of the linked record here. ,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +FACT_RELATIONSHIP,domain_concept_id_1,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,domain_concept_id_2,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,fact_id_1,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,fact_id_2,Yes,0,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +FACT_RELATIONSHIP,relationship_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,address_1,No,,,varchar(50),0,,This is the first line of the address.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,address_2,No,,,varchar(50),0,,This is the second line of the address,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,city,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,country_concept_id,No,,,integer,0,,The Concept Id representing the country. Values should conform to the [Geography](https://athena.ohdsi.org/search-terms/terms?domain=Geography&standardConcept=Standard&page=1&pageSize=15&query=&boosts) domain. ,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Geography,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,,,,,,, +LOCATION,country_source_value,No,,,varchar(80),0,,The name of the country.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +LOCATION,county,No,,,varchar(20),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,latitude,No,,,float,0,,,Must be between -90 and 90.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +LOCATION,location_id,Yes,0,,integer,0,,The unique key given to a unique Location.,Each instance of a Location in the source data should be assigned this unique key.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,location_source_value,No,,,varchar(50),0,,,"Put the verbatim value for the location here, as it shows up in the source. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,longitude,No,,,float,0,,,Must be between -180 and 180.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +LOCATION,state,No,,,varchar(2),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +LOCATION,zip,No,,,varchar(9),0,,,"Zip codes are handled as strings of up to 9 characters length. For US addresses, these represent either a 3-digit abbreviated Zip code as provided by many sources for patient protection reasons, the full 5-digit Zip or the 9-digit (ZIP + 4) codes. Unless for specific reasons analytical methods should expect and utilize only the first 3 digits. For international addresses, different rules apply.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +MEASUREMENT,meas_event_field_concept_id,No,,,integer,0,,"If the Measurement record is related to another record in the database, this field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ",Put the CONCEPT_ID that identifies which table and field the MEASUREMENT_EVENT_ID came from.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +MEASUREMENT,measurement_concept_id,Yes,0,,integer,0,,"The MEASUREMENT_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies.","The CONCEPT_ID that the MEASUREMENT_SOURCE_CONCEPT_ID maps to. Only records whose SOURCE_CONCEPT_IDs map to Standard Concepts with a domain of ""Measurement"" should go in this table.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Measurement,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_date,Yes,0,,date,0,,Use this date to determine the date of the measurement.,"If there are multiple dates in the source data associated with a record such as order_date, draw_date, and result_date, choose the one that is closest to the date the sample was drawn from the patient.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,Yes,5, +MEASUREMENT,measurement_datetime,No,,,datetime,0,,,"This is not required, though it is in v6. If a source does not specify datetime the convention is to set the time to midnight (00:00:0000)",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_event_id,No,,,bigint,0,,"If the Measurement record is related to another record in the database, this field is the primary key of the linked record. ","Put the primary key of the linked record, if applicable, here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +MEASUREMENT,measurement_id,Yes,0,,integer,0,,The unique key given to a Measurement record for a Person. Refer to the ETL for how duplicate Measurements during the same Visit were handled.,"Each instance of a measurement present in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same measurement within the same visit. It is valid to keep these duplicates and assign them individual, unique, MEASUREMENT_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_source_concept_id,No,,,integer,0,,"This is the concept representing the MEASUREMENT_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Measurement necessary for a given analytic use case. Consider using MEASUREMENT_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the MEASUREMENT_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the Measurement that occurred. For example, this could be an ICD10 or Read code.",This code is mapped to a Standard Measurement Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,MEASUREMENT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_time,No,,,varchar(10),0,,,This is present for backwards compatibility and will be deprecated in an upcoming version.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,measurement_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Measurement record, as in whether the measurement was from an EHR system, insurance claim, registry, or other sources.","Choose the MEASUREMENT_TYPE_CONCEPT_ID that best represents the provenance of the record, for example whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,operator_concept_id,No,,,integer,0,,"The meaning of Concept [4172703](https://athena.ohdsi.org/search-terms/terms/4172703) for '=' is identical to omission of a OPERATOR_CONCEPT_ID value. Since the use of this field is rare, it's important when devising analyses to not to forget testing for the content of this field for values different from =.","Operators are <, <=, =, >=, > and these concepts belong to the 'Meas Value Operator' domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Meas+Value+Operator&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Meas Value Operator,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,person_id,Yes,0,,integer,0,,The PERSON_ID of the Person for whom the Measurement is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,provider_id,No,,,integer,0,,"The provider associated with measurement record, e.g. the provider who ordered the test or the provider who recorded the result.",The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record. For example the admitting vs attending physician on an EHR record.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,range_high,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER. These ranges are provided by the source and should remain NULL if not given.,If reference ranges for upper and lower limit of normal as provided (typically by a laboratory) these are stored in the RANGE_HIGH and RANGE_LOW fields. This should be set to NULL if not provided.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,range_low,No,,,float,0,,Ranges have the same unit as the VALUE_AS_NUMBER. These ranges are provided by the source and should remain NULL if not given.,If reference ranges for upper and lower limit of normal as provided (typically by a laboratory) these are stored in the RANGE_HIGH and RANGE_LOW fields. This should be set to NULL if not provided.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,unit_concept_id,No,,,integer,0,,"There is currently no recommended unit for individual measurements, i.e. it is not mandatory to represent Hemoglobin a1C measurements as a percentage. UNIT_SOURCE_VALUES should be mapped to a Standard Concept in the Unit domain that best represents the unit as given in the source data.","There is no standardization requirement for units associated with MEASUREMENT_CONCEPT_IDs, however, it is the responsibility of the ETL to choose the most plausible unit.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,unit_source_concept_id,No,,,integer,0,,"""This is the concept representing the UNIT_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Measurement necessary for a given analytic use case. Consider using UNIT_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.""",If the UNIT_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,50,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,unit_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the unit of the Measurement that occurred. ,This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,value_as_concept_id,No,,,integer,0,,If the raw data gives a categorial result for measurements those values are captured and mapped to standard concepts in the 'Meas Value' domain.,"If the raw data provides categorial results as well as continuous results for measurements, it is a valid ETL choice to preserve both values. The continuous value should go in the VALUE_AS_NUMBER field and the categorical value should be mapped to a standard concept in the 'Meas Value' domain and put in the VALUE_AS_CONCEPT_ID field. This is also the destination for the 'Maps to value' relationship.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Meas Value,0,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,value_as_number,No,,,float,0,,"This is the numerical value of the Result of the Measurement, if available. Note that measurements such as blood pressures will be split into their component parts i.e. one record for systolic, one record for diastolic.","If there is a negative value coming from the source, set the VALUE_AS_NUMBER to NULL, with the exception of the following Measurements (listed as LOINC codes):
- [1925-7](https://athena.ohdsi.org/search-terms/terms/3003396) Base excess in Arterial blood by calculation - [1927-3](https://athena.ohdsi.org/search-terms/terms/3002032) Base excess in Venous blood by calculation - [8632-2](https://athena.ohdsi.org/search-terms/terms/3006277) QRS-Axis - [11555-0](https://athena.ohdsi.org/search-terms/terms/3012501) Base excess in Blood by calculation - [1926-5](https://athena.ohdsi.org/search-terms/terms/3003129) Base excess in Capillary blood by calculation - [28638-5](https://athena.ohdsi.org/search-terms/terms/3004959) Base excess in Arterial cord blood by calculation [28639-3](https://athena.ohdsi.org/search-terms/terms/3007435) Base excess in Venous cord blood by calculation",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,value_source_value,No,,,varchar(50),0,,This field houses the verbatim result value of the Measurement from the source data . ,"If both a continuous and categorical result are given in the source data such that both VALUE_AS_NUMBER and VALUE_AS_CONCEPT_ID are both included, store the verbatim value that was mapped to VALUE_AS_CONCEPT_ID here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the Measurement occurred. For example, if the Person was in the ICU at the time the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +MEASUREMENT,visit_occurrence_id,No,,,integer,0,,The visit during which the Measurement occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If a MEASUREMENT_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the measurement record. If a measurement is related to a visit explicitly in the source data, it is possible that the result date of the Measurement falls outside of the bounds of the Visit dates.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +METADATA,metadata_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,metadata_date,No,,,date,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,metadata_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,metadata_id,Yes,0,,integer,0,,The unique key given to a Metadata record.,Attribute value is auto-generated,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,metadata_type_concept_id,Yes,0,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,name,Yes,0,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,value_as_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,value_as_number,No,,,float,0,,"This is the numerical value of the result of the Metadata, if applicable and available. It is not expected that all Metadata will have numeric results, rather, this field is here to house values should they exist. ",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +METADATA,value_as_string,No,,,varchar(250),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +NOTE,encoding_concept_id,Yes,0,,integer,0,,This is the Concept representing the character encoding type. ,"Put the Concept Id that represents the encoding character type here. Currently the only option is UTF-8 ([32678](https://athena.ohdsi.org/search-terms/terms/32678)). It the note is encoded in any other type, like ASCII then put 0. ",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,language_concept_id,Yes,0,,integer,0,,The language of the note. ,Use Concepts that are descendants of the concept [4182347](https://athena.ohdsi.org/search-terms/terms/4182347) (World Languages).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, NOTE,note_class_concept_id,Yes,0,,integer,0,,"A Standard Concept Id representing the HL7 LOINC -Document Type Vocabulary classification of the note.",Map the note classification to a Standard Concept. For more information see the ETL Conventions in the description of the NOTE table. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&conceptClass=Doc+Kind&conceptClass=Doc+Role&conceptClass=Doc+Setting&conceptClass=Doc+Subject+Matter&conceptClass=Doc+Type+of+Service&domain=Meas+Value&page=1&pageSize=15&query=). This Concept can alternatively be represented by concepts with the relationship 'Kind of (LOINC)' to [706391](https://athena.ohdsi.org/search-terms/terms/706391) (Note).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_date,Yes,0,,date,0,,The date the note was recorded.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -NOTE,note_datetime,No,,,datetime,0,,,If time is not given set the time to midnight.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -NOTE,note_event_field_concept_id,No,,,integer,0,,"If the Note record is related to another record in the database, this field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ",Put the CONCEPT_ID that identifies which table and field the NOTE_EVENT_ID came from.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -NOTE,note_event_id,No,,,bigint,0,,"If the Note record is related to another record in the database, this field is the primary key of the linked record. ","Put the primary key of the linked record, if applicable, here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -NOTE,note_id,Yes,0,,integer,0,,A unique identifier for each note.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_source_value,No,,,varchar(50),0,,,The source value mapped to the NOTE_CLASS_CONCEPT_ID.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_text,Yes,0,,varchar(MAX),0,,The content of the note.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_title,No,,,varchar(250),0,,The title of the note.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,note_type_concept_id,Yes,0,,integer,0,,The provenance of the note. Most likely this will be EHR. ,"Put the source system of the note, as in EHR record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&domain=Type+Concept&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,provider_id,No,,,integer,0,,The Provider who wrote the note.,The ETL may need to make a determination on which provider to put here.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,visit_detail_id,No,,,integer,0,,The Visit Detail during which the note was written.,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE,visit_occurrence_id,No,,,integer,0,,The Visit during which the note was written. ,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -NOTE_NLP,"""offset""",No,,,varchar(50),0,,Character offset of the extracted term in the input note,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -NOTE_NLP,lexical_variant,Yes,0,,varchar(250),0,,Raw text extracted from the NLP tool.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,nlp_date,Yes,0,,date,0,,The date of the note processing.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,nlp_datetime,No,,,datetime,0,,The date and time of the note processing.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,No -NOTE_NLP,nlp_system,No,,,varchar(250),0,,,Name and version of the NLP system that extracted the term. Useful for data provenance.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,note_id,Yes,0,,integer,0,,This is the NOTE_ID for the NOTE record the NLP record is associated to.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -NOTE_NLP,note_nlp_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,note_nlp_id,Yes,0,,integer,0,,A unique identifier for the NLP record.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,note_nlp_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,section_concept_id,No,,,integer,0,,,"The SECTION_CONCEPT_ID should be used to represent the note section contained in the NOTE_NLP record. These concepts can be found as parts of document panels and are based on the type of note written, i.e. a discharge summary. These panels can be found as concepts with the relationship 'Subsumes' to CONCEPT_ID [45875957](https://athena.ohdsi.org/search-terms/terms/45875957).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -NOTE_NLP,snippet,No,,,varchar(250),0,,A small window of text surrounding the term,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +Document Type Vocabulary classification of the note.",Map the note classification to a Standard Concept. For more information see the ETL Conventions in the description of the NOTE table. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&conceptClass=Doc+Kind&conceptClass=Doc+Role&conceptClass=Doc+Setting&conceptClass=Doc+Subject+Matter&conceptClass=Doc+Type+of+Service&domain=Meas+Value&page=1&pageSize=15&query=). This Concept can alternatively be represented by concepts with the relationship 'Kind of (LOINC)' to [706391](https://athena.ohdsi.org/search-terms/terms/706391) (Note).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_date,Yes,0,,date,0,,The date the note was recorded.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,Yes,5, +NOTE,note_datetime,No,,,datetime,0,,,If time is not given set the time to midnight.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +NOTE,note_event_field_concept_id,No,,,integer,0,,"If the Note record is related to another record in the database, this field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ",Put the CONCEPT_ID that identifies which table and field the NOTE_EVENT_ID came from.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +NOTE,note_event_id,No,,,bigint,0,,"If the Note record is related to another record in the database, this field is the primary key of the linked record. ","Put the primary key of the linked record, if applicable, here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +NOTE,note_id,Yes,0,,integer,0,,A unique identifier for each note.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_source_value,No,,,varchar(50),0,,,The source value mapped to the NOTE_CLASS_CONCEPT_ID.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_text,Yes,0,,varchar(MAX),0,,The content of the note.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_title,No,,,varchar(250),0,,The title of the note.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,note_type_concept_id,Yes,0,,integer,0,,The provenance of the note. Most likely this will be EHR. ,"Put the source system of the note, as in EHR record. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&domain=Type+Concept&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,provider_id,No,,,integer,0,,The Provider who wrote the note.,The ETL may need to make a determination on which provider to put here.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,visit_detail_id,No,,,integer,0,,The Visit Detail during which the note was written.,,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE,visit_occurrence_id,No,,,integer,0,,The Visit during which the note was written. ,,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +NOTE_NLP,"""offset""",No,,,varchar(50),0,,Character offset of the extracted term in the input note,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +NOTE_NLP,lexical_variant,Yes,0,,varchar(250),0,,Raw text extracted from the NLP tool.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,nlp_date,Yes,0,,date,0,,The date of the note processing.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,nlp_datetime,No,,,datetime,0,,The date and time of the note processing.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,No,,, +NOTE_NLP,nlp_system,No,,,varchar(250),0,,,Name and version of the NLP system that extracted the term. Useful for data provenance.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,note_id,Yes,0,,integer,0,,This is the NOTE_ID for the NOTE record the NLP record is associated to.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +NOTE_NLP,note_nlp_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,note_nlp_id,Yes,0,,integer,0,,A unique identifier for the NLP record.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,note_nlp_source_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,section_concept_id,No,,,integer,0,,,"The SECTION_CONCEPT_ID should be used to represent the note section contained in the NOTE_NLP record. These concepts can be found as parts of document panels and are based on the type of note written, i.e. a discharge summary. These panels can be found as concepts with the relationship 'Subsumes' to CONCEPT_ID [45875957](https://athena.ohdsi.org/search-terms/terms/45875957).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +NOTE_NLP,snippet,No,,,varchar(250),0,,A small window of text surrounding the term,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, NOTE_NLP,term_exists,No,,,varchar(1),0,,,"Term_exists is defined as a flag that indicates if the patient actually has or had the condition. Any of the following modifiers would make Term_exists false: Negation = true Subject = [anything other than the patient] @@ -331,221 +331,221 @@ Conditional = true/li> Rule_out = true Uncertain = very low certainty or any lower certainties A complete lack of modifiers would make Term_exists true. -",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, NOTE_NLP,term_modifiers,No,,,varchar(2000),0,,,"For the modifiers that are there, they would have to have these values:

- Negation = false - Subject = patient - Conditional = false - Rule_out = false -- Uncertain = true or high or moderate or even low (could argue about low). Term_modifiers will concatenate all modifiers for different types of entities (conditions, drugs, labs etc) into one string. Lab values will be saved as one of the modifiers. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +- Uncertain = true or high or moderate or even low (could argue about low). Term_modifiers will concatenate all modifiers for different types of entities (conditions, drugs, labs etc) into one string. Lab values will be saved as one of the modifiers. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, NOTE_NLP,term_temporal,No,,,varchar(50),0,,,"Term_temporal is to indicate if a condition is present or just in the past. The following would be past:

- History = true -- Concept_date = anything before the time of the report",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -OBSERVATION,obs_event_field_concept_id,No,,,integer,0,,"If the Observation record is related to another record in the database, this field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ",Put the CONCEPT_ID that identifies which table and field the OBSERVATION_EVENT_ID came from.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -OBSERVATION,observation_concept_id,Yes,0,,integer,0,,"The OBSERVATION_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies.","The CONCEPT_ID that the OBSERVATION_SOURCE_CONCEPT_ID maps to. There is no specified domain that the Concepts in this table must adhere to. The only rule is that records with Concepts in the Condition, Procedure, Drug, Measurement, or Device domains MUST go to the corresponding table. ",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_date,Yes,0,,date,0,,"The date of the Observation. Depending on what the Observation represents this could be the date of a lab test, the date of a survey, or the date a patient's family history was taken. ",For some observations the ETL may need to make a choice as to which date to choose.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -OBSERVATION,observation_datetime,No,,,datetime,0,,,If no time is given set to midnight (00:00:00).,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -OBSERVATION,observation_event_id,No,,,bigint,0,,"If the Observation record is related to another record in the database, this field is the primary key of the linked record. ","Put the primary key of the linked record, if applicable, here. See the [ETL Conventions for the OBSERVATION](https://ohdsi.github.io/CommonDataModel/cdm60.html#observation) table for more details.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -OBSERVATION,observation_id,Yes,0,,integer,0,,The unique key given to an Observation record for a Person. Refer to the ETL for how duplicate Observations during the same Visit were handled.,Each instance of an observation present in the source data should be assigned this unique key. ,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_source_concept_id,No,,,integer,0,,"This is the concept representing the OBSERVATION_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Observation necessary for a given analytic use case. Consider using OBSERVATION_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the OBSERVATION_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the Observation that occurred. For example, this could be an ICD10 or Read code.",This code is mapped to a Standard Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,OBSERVATION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -OBSERVATION,observation_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Observation record, as in whether the measurement was from an EHR system, insurance claim, registry, or other sources.","Choose the OBSERVATION_TYPE_CONCEPT_ID that best represents the provenance of the record, for example whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,person_id,Yes,0,,integer,0,,The PERSON_ID of the Person for whom the Observation is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,provider_id,No,,,integer,0,,"The provider associated with the observation record, e.g. the provider who ordered the test or the provider who recorded the result.",The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record. For example the admitting vs attending physician on an EHR record.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,qualifier_concept_id,No,,,integer,0,,"This field contains all attributes specifying the clinical fact further, such as as degrees, severities, drug-drug interaction alerts etc.","Use your best judgement as to what Concepts to use here and if they are necessary to accurately represent the clinical record. There is no restriction on the domain of these Concepts, they just need to be Standard.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,qualifier_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the qualifier of the Observation that occurred. ,This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,QUALIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -OBSERVATION,unit_concept_id,No,,,integer,0,,There is currently no recommended unit for individual observation concepts. UNIT_SOURCE_VALUES should be mapped to a Standard Concept in the Unit domain that best represents the unit as given in the source data.,"There is no standardization requirement for units associated with OBSERVATION_CONCEPT_IDs, however, it is the responsibility of the ETL to choose the most plausible unit.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,unit_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the unit of the Observation that occurred. ,This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_as_concept_id,No,,,Integer,0,,"It is possible that some records destined for the Observation table have two clinical ideas represented in one source code. This is common with ICD10 codes that describe a family history of some Condition, for example. In OMOP the Vocabulary breaks these two clinical ideas into two codes; one becomes the OBSERVATION_CONCEPT_ID and the other becomes the VALUE_AS_CONCEPT_ID. It is important when using the Observation table to keep this possibility in mind and to examine the VALUE_AS_CONCEPT_ID field for relevant information. ","Note that the value of VALUE_AS_CONCEPT_ID may be provided through mapping from a source Concept which contains the content of the Observation. In those situations, the CONCEPT_RELATIONSHIP table in addition to the 'Maps to' record contains a second record with the relationship_id set to 'Maps to value'. For example, ICD10 [Z82.4](https://athena.ohdsi.org/search-terms/terms/45581076) 'Family history of ischaemic heart disease and other diseases of the circulatory system' has a 'Maps to' relationship to [4167217](https://athena.ohdsi.org/search-terms/terms/4167217) 'Family history of clinical finding' as well as a 'Maps to value' record to [134057](https://athena.ohdsi.org/search-terms/terms/134057) 'Disorder of cardiovascular system'.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_as_number,No,,,float,0,,"This is the numerical value of the Result of the Observation, if applicable and available. It is not expected that all Observations will have numeric results, rather, this field is here to house values should they exist. ",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_as_string,No,,,varchar(60),0,,"This is the categorical value of the Result of the Observation, if applicable and available. ",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,value_source_value,No,,,varchar(50),0,,This field houses the verbatim result value of the Observation from the source data. Do not get confused with the Observation_source_value which captures source value of the observation mapped to observation_concept_id. This field is the observation result value from the source.," If the observation_source_value was a question, for example, or an observation that requires a result then this field is the answer/ result from the source data. Store the verbatim value that represents the result of the observation_source_value. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -OBSERVATION,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the Observation occurred. For example, if the Person was in the ICU at the time the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION,visit_occurrence_id,No,,,integer,0,,The visit during which the Observation occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If an OBSERVATION_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the observation record. If an observation is related to a visit explicitly in the source data, it is possible that the result date of the Observation falls outside of the bounds of the Visit dates.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION_PERIOD,observation_period_end_date,Yes,0,,date,0,,Use this date to determine the end date of the period for which we can assume that all events for a Person are recorded.,"It is often the case that the idea of Observation Periods does not exist in source data. In those cases, the observation_period_end_date can be inferred as the last Event date available for the Person. In insurance claim data, the Observation Period can be considered as the time period the Person is enrolled with a payer.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,OBSERVATION_PERIOD,OBSERVATION_PERIOD_START_DATE,1,,Yes,1,,Yes -OBSERVATION_PERIOD,observation_period_id,Yes,0,,integer,0,,A Person can have multiple discrete Observation Periods which are identified by the Observation_Period_Id.,Assign a unique observation_period_id to each discrete Observation Period for a Person.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -OBSERVATION_PERIOD,observation_period_start_date,Yes,0,,date,0,,Use this date to determine the start date of the Observation Period.,"It is often the case that the idea of Observation Periods does not exist in source data. In those cases, the observation_period_start_date can be inferred as the earliest Event date available for the Person. In insurance claim data, the Observation Period can be considered as the time period the Person is enrolled with a payer. If a Person switches plans but stays with the same payer, and therefore capturing of data continues, that change would be captured in [PAYER_PLAN_PERIOD](https://ohdsi.github.io/CommonDataModel/cdm531.html#payer_plan_period).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -OBSERVATION_PERIOD,period_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Observation Period as in whether the period was determined from an insurance enrollment file, EHR healthcare encounters, or other sources.",Choose the observation_period_type_concept_id that best represents how the period was determined. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,,,, -OBSERVATION_PERIOD,person_id,Yes,0,,integer,0,,The Person ID of the PERSON record for which the Observation Period is recorded.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,family_source_value,No,,,varchar(50),0,,The common identifier for all people (often a family) that covered by the same policy.,Often these are the common digits of the enrollment id of the policy members.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,0,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_concept_id,No,,,integer,0,,This field represents the organization who reimburses the provider which administers care to the Person.,"Map the Payer directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. The point is to stratify on this information and identify if Persons have the same payer, though the name of the Payer is not necessary. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Payer&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_plan_period_end_date,Yes,0,,date,0,,End date of Plan coverage.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PAYER_PLAN_PERIOD,PAYER_PLAN_PERIOD_START_DATE,1,,No,,,Yes -PAYER_PLAN_PERIOD,payer_plan_period_id,Yes,0,,integer,0,,"A unique identifier for each unique combination of a Person, Payer, Plan, and Period of time.",,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_plan_period_start_date,Yes,0,,date,0,,Start date of Plan coverage.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -PAYER_PLAN_PERIOD,payer_source_concept_id,No,,,integer,0,,,If the source data codes the Payer in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,payer_source_value,No,,,varchar(50),0,,This is the Payer as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,PAYER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,person_id,Yes,0,,integer,0,,The Person covered by the Plan.,"A single Person can have multiple, overlapping, PAYER_PLAN_PERIOD records",No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,plan_concept_id,No,,,integer,0,,This field represents the specific health benefit Plan the Person is enrolled in.,Map the Plan directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. The point is to stratify on this information and identify if Persons have the same health benefit Plan though the name of the Plan is not necessary. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Plan&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,plan_source_concept_id,No,,,integer,0,,,If the source data codes the Plan in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,plan_source_value,No,,,varchar(50),0,,This is the health benefit Plan of the Person as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,PLAN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,sponsor_concept_id,No,,,integer,0,,"This field represents the sponsor of the Plan who finances the Plan. This includes self-insured, small group health plan and large group health plan.",Map the sponsor directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. The point is to stratify on this information and identify if Persons have the same sponsor though the name of the sponsor is not necessary. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Sponsor&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,sponsor_source_concept_id,No,,,integer,0,,,If the source data codes the sponsor in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,sponsor_source_value,No,,,varchar(50),0,,The Plan sponsor as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,SPONSOR_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,stop_reason_concept_id,No,,,integer,0,,"This field represents the reason the Person left the Plan, if known.",Map the stop reason directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Plan+Stop+Reason&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,stop_reason_source_concept_id,No,,,integer,0,,,If the source data codes the stop reason in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PAYER_PLAN_PERIOD,stop_reason_source_value,No,,,varchar(50),0,,The Plan stop reason as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,STOP_REASON_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PERSON,birth_datetime,No,,,datetime,0,,,"This field is not required but highly encouraged. For data sources that provide the precise datetime of birth, that value should be stored in this field. If birth_datetime is not provided in the source, use the following logic to infer the date: If day_of_birth is null and month_of_birth is not null then use the first of the month in that year. If month_of_birth is null or if day_of_birth AND month_of_birth are both null and the person has records during their year of birth then use the date of the earliest record, otherwise use the 15th of June of that year. If time of birth is not given use midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1850-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,Yes -PERSON,care_site_id,No,,,integer,0,,The Care Site refers to where the Provider typically provides the primary care.,,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,day_of_birth,No,,,integer,0,,,"For data sources that provide the precise date of birth, the day should be extracted and stored in this field.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,31,1,,,,,,,No,,,Yes -PERSON,ethnicity_concept_id,Yes,0,,integer,0,,"This field captures Ethnicity as defined by the Office of Management and Budget (OMB) of the US Government: it distinguishes only between ""Hispanic"" and ""Not Hispanic"". Races and ethnic backgrounds are not stored here.",Only use this field if you have US-based data and a source of this information. Do not attempt to infer Ethnicity from the race or ethnic background of the Person. [Accepted ethnicity concepts](http://athena.ohdsi.org/search-terms/terms?domain=Ethnicity&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,Ethnicity,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,ethnicity_source_concept_id,No,,,integer,0,,"Due to the small number of options, this tends to be zero.","If the source data codes ethnicity in an OMOP supported vocabulary, store the concept_id here.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PERSON,ethnicity_source_value,No,,,varchar(50),0,,This field is used to store the ethnicity of the person from the source data. It is not intended for use in standard analytics but for reference only.,"If the person has an ethnicity other than the OMB standard of ""Hispanic"" or ""Not Hispanic"" store that value from the source data here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,ETHNICITY_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PERSON,gender_concept_id,Yes,0,,integer,0,,This field is meant to capture the biological sex at birth of the Person. This field should not be used to study gender identity issues.,Use the gender or sex value present in the data under the assumption that it is the biological sex at birth. If the source data captures gender identity it should be stored in the [OBSERVATION](https://ohdsi.github.io/CommonDataModel/cdm531.html#observation) table. [Accepted gender concepts](http://athena.ohdsi.org/search-terms/terms?domain=Gender&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,Gender,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,gender_source_concept_id,No,,,integer,0,,"Due to the small number of options, this tends to be zero.","If the source data codes biological sex in a non-standard vocabulary, store the concept_id here.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PERSON,gender_source_value,No,,,varchar(50),0,,This field is used to store the biological sex of the person from the source data. It is not intended for use in standard analytics but for reference only.,Put the biological sex of the person as it appears in the source data.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,GENDER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PERSON,location_id,No,,,integer,0,,The location refers to the physical address of the person. This field should capture the last known location of the person. ,"Put the location_id from the [LOCATION](https://ohdsi.github.io/CommonDataModel/cdm531.html#location) table here that represents the most granular location information for the person. This could represent anything from postal code or parts thereof, state, or county for example. Since many databases contain deidentified data, it is common that the precision of the location is reduced to prevent re-identification. This field should capture the last known location. ",No,,,Yes,0,,LOCATION,LOCATION_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,month_of_birth,No,,,integer,0,,,"For data sources that provide the precise date of birth, the month should be extracted and stored in this field.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,12,1,,,,,,,No,,,Yes -PERSON,person_id,Yes,0,,integer,0,,It is assumed that every person with a different unique identifier is in fact a different person and should be treated independently.,"Any person linkage that needs to occur to uniquely identify Persons ought to be done prior to writing this table. This identifier can be the original id from the source data provided if it is an integer, otherwise it can be an autogenerated number.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,person_source_value,No,,,varchar(50),0,,Use this field to link back to persons in the source data. This is typically used for error checking of ETL logic.,Some use cases require the ability to link back to persons in the source data. This field allows for the storing of the person value as it appears in the source. This field is not required but strongly recommended.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,provider_id,No,,,integer,0,,The Provider refers to the last known primary care provider (General Practitioner).,"Put the provider_id from the [PROVIDER](https://ohdsi.github.io/CommonDataModel/cdm531.html#provider) table of the last known general practitioner of the person. If there are multiple providers, it is up to the ETL to decide which to put here.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,race_concept_id,Yes,0,,integer,0,,This field captures race or ethnic background of the person.,"Only use this field if you have information about race or ethnic background. The Vocabulary contains Concepts about the main races and ethnic backgrounds in a hierarchical system. Due to the imprecise nature of human races and ethnic backgrounds, this is not a perfect system. Mixed races are not supported. If a clear race or ethnic background cannot be established, use Concept_Id 0. [Accepted Race Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Race&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Race,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PERSON,race_source_concept_id,No,,,integer,0,,"Due to the small number of options, this tends to be zero.",If the source data codes race in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PERSON,race_source_value,No,,,varchar(50),0,,This field is used to store the race of the person from the source data. It is not intended for use in standard analytics but for reference only.,Put the race of the person as it appears in the source data.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,RACE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PERSON,year_of_birth,Yes,0,,integer,0,,Compute age using year_of_birth.,"For data sources with date of birth, the year should be extracted. For data sources where the year of birth is not available, the approximate year of birth could be derived based on age group categorization, if available.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1850,1,,YEAR(GETDATE())+1,1,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,modifier_concept_id,No,,,integer,0,,The modifiers are intended to give additional information about the procedure but as of now the vocabulary is under review.,"It is up to the ETL to choose how to map modifiers if they exist in source data. These concepts are typically distinguished by 'Modifier' concept classes (e.g., 'CPT4 Modifier' as part of the 'CPT4' vocabulary). If there is more than one modifier on a record, one should be chosen that pertains to the procedure rather than provider. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?conceptClass=CPT4+Modifier&conceptClass=HCPCS+Modifier&vocabulary=CPT4&vocabulary=HCPCS&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,modifier_source_value,No,,,varchar(50),0,,,The original modifier code from the source is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,MODIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,person_id,Yes,0,,integer,0,,The PERSON_ID of the PERSON for whom the procedure is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_concept_id,Yes,0,,integer,0,,"The PROCEDURE_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source value which represents a procedure","The CONCEPT_ID that the PROCEDURE_SOURCE_VALUE maps to. Only records whose source values map to standard concepts with a domain of ""Procedure"" should go in this table. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Procedure&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Procedure,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_date,Yes,0,,date,0,,Use this date to determine the date the procedure started.,This is meant to be the **start date** of the procedure. It will be renamed in a future version to **PROCEDURE_START_DATE**. ,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -PROCEDURE_OCCURRENCE,procedure_datetime,No,,,datetime,0,,,"If the procedure has a start time in the native date, use this field to house that information. This will be renamed in a future version to **PROCEDURE_START_DATETIME**.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -PROCEDURE_OCCURRENCE,procedure_end_date,No,,,date,0,,Use this field to house the date that the procedure ended. ,This is meant to be the end date of the procedure. It is not required and for most cases will be the same as the PROCEDURE_START_DATE.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PROCEDURE_OCCURRENCE,PROCEDURE_DATE,1,,Yes,1,,Yes -PROCEDURE_OCCURRENCE,procedure_end_datetime,No,,,datetime,0,,Use this field to house the datetime that the procedure ended. ,This is meant to house the end datetime of the procedure and will most often be used in conjunction with the procedure_start_datetime to determine the length of the procedure.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PROCEDURE_OCCURRENCE,PROCEDURE_DATETIME,1,,Yes,1,,Yes -PROCEDURE_OCCURRENCE,procedure_occurrence_id,Yes,0,,integer,0,,The unique key given to a procedure record for a person. Refer to the ETL for how duplicate procedures during the same visit were handled.,"Each instance of a procedure occurrence in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same procedure within the same visit. It is valid to keep these duplicates and assign them individual, unique, PROCEDURE_OCCURRENCE_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_source_concept_id,No,,,integer,0,,"This is the concept representing the procedure source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Procedure necessary for a given analytic use case. Consider using PROCEDURE_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the PROCEDURE_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the procedure that occurred. For example, this could be an CPT4 or OPCS4 code.",Use this value to look up the source concept id and then map the source concept id to a standard concept id.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,PROCEDURE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,procedure_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Procedure record, as in whether the procedure was from an EHR system, insurance claim, registry, or other sources.","Choose the PROCEDURE_TYPE_CONCEPT_ID that best represents the provenance of the record, for example whether it came from an EHR record or billing claim. If a procedure is recorded as an EHR encounter, the PROCEDURE_TYPE_CONCEPT would be 'EHR encounter record'. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,provider_id,No,,,integer,0,,"The provider associated with the procedure record, e.g. the provider who performed the Procedure.","The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record, for example the admitting vs attending physician on an EHR record.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,quantity,No,,,integer,0,,"If the quantity value is omitted, a single procedure is assumed.","If a Procedure has a quantity of '0' in the source, this should default to '1' in the ETL. If there is a record in the source it can be assumed the exposure occurred at least once",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the Procedure occurred. For example, if the Person was in the ICU at the time of the Procedure the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROCEDURE_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,The visit during which the procedure occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If a PROCEDURE_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the Visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the PROCEDURE_OCCURRENCE record.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -PROVIDER,care_site_id,No,,,integer,0,,This is the CARE_SITE_ID for the location that the provider primarily practices in.,"If a Provider has more than one Care Site, the main or most often exerted CARE_SITE_ID should be recorded.",No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,dea,No,,,varchar(20),0,,"This is the identifier issued by the DEA, a US federal agency, that allows a provider to write prescriptions for controlled substances.",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,gender_concept_id,No,,,integer,0,,This field represents the recorded gender of the provider in the source data.,"If given, put a concept from the gender domain representing the recorded gender of the provider. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Gender&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Gender,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,gender_source_concept_id,No,,,integer,0,,This is often zero as many sites use proprietary codes to store provider gender.,If the source data codes provider gender in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,gender_source_value,No,,,varchar(50),0,,This is provider's gender as it appears in the source data.,Put the provider's gender as it appears in the source data. This field is up to the discretion of the ETL-er as to whether this should be the coded value from the source or the text description of the lookup value.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,GENDER_CONCEPT_ID,,,,,,,,,,,,No,,,No -PROVIDER,npi,No,,,varchar(20),0,,This is the National Provider Number issued to health care providers in the US by the Centers for Medicare and Medicaid Services (CMS).,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,provider_id,Yes,0,,integer,0,,It is assumed that every provider with a different unique identifier is in fact a different person and should be treated independently.,"This identifier can be the original id from the source data provided it is an integer, otherwise it can be an autogenerated number.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,provider_name,No,,,varchar(255),0,,,"This field is not necessary as it is not necessary to have the actual identity of the Provider. Rather, the idea is to uniquely and anonymously identify providers of care across the database.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,provider_source_value,No,,,varchar(50),0,,Use this field to link back to providers in the source data. This is typically used for error checking of ETL logic.,Some use cases require the ability to link back to providers in the source data. This field allows for the storing of the provider identifier as it appears in the source.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,specialty_concept_id,No,,,integer,0,,"This field either represents the most common specialty that occurs in the data or the most specific concept that represents all specialties listed, should the provider have more than one. This includes physician specialties such as internal medicine, emergency medicine, etc. and allied health professionals such as nurses, midwives, and pharmacists.","If a Provider has more than one Specialty, there are two options: 1. Choose a concept_id which is a common ancestor to the multiple specialties, or, 2. Choose the specialty that occurs most often for the provider. Concepts in this field should be Standard with a domain of Provider. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Provider&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,specialty_source_concept_id,No,,,integer,0,,This is often zero as many sites use proprietary codes to store physician speciality.,If the source data codes provider specialty in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,No -PROVIDER,specialty_source_value,No,,,varchar(50),0,,"This is the kind of provider or specialty as it appears in the source data. This includes physician specialties such as internal medicine, emergency medicine, etc. and allied health professionals such as nurses, midwives, and pharmacists.",Put the kind of provider as it appears in the source data. This field is up to the discretion of the ETL-er as to whether this should be the coded value from the source or the text description of the lookup value.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,SPECIALTY_CONCEPT_ID,,,,,,,,,,,,No,,,No -PROVIDER,year_of_birth,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +- Concept_date = anything before the time of the report",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +OBSERVATION,obs_event_field_concept_id,No,,,integer,0,,"If the Observation record is related to another record in the database, this field is the CONCEPT_ID that identifies which table the primary key of the linked record came from. ",Put the CONCEPT_ID that identifies which table and field the OBSERVATION_EVENT_ID came from.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +OBSERVATION,observation_concept_id,Yes,0,,integer,0,,"The OBSERVATION_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies.","The CONCEPT_ID that the OBSERVATION_SOURCE_CONCEPT_ID maps to. There is no specified domain that the Concepts in this table must adhere to. The only rule is that records with Concepts in the Condition, Procedure, Drug, Measurement, or Device domains MUST go to the corresponding table. ",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_date,Yes,0,,date,0,,"The date of the Observation. Depending on what the Observation represents this could be the date of a lab test, the date of a survey, or the date a patient's family history was taken. ",For some observations the ETL may need to make a choice as to which date to choose.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,Yes,5, +OBSERVATION,observation_datetime,No,,,datetime,0,,,If no time is given set to midnight (00:00:00).,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +OBSERVATION,observation_event_id,No,,,bigint,0,,"If the Observation record is related to another record in the database, this field is the primary key of the linked record. ","Put the primary key of the linked record, if applicable, here. See the [ETL Conventions for the OBSERVATION](https://ohdsi.github.io/CommonDataModel/cdm60.html#observation) table for more details.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +OBSERVATION,observation_id,Yes,0,,integer,0,,The unique key given to an Observation record for a Person. Refer to the ETL for how duplicate Observations during the same Visit were handled.,Each instance of an observation present in the source data should be assigned this unique key. ,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_source_concept_id,No,,,integer,0,,"This is the concept representing the OBSERVATION_SOURCE_VALUE and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Observation necessary for a given analytic use case. Consider using OBSERVATION_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the OBSERVATION_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the Observation that occurred. For example, this could be an ICD10 or Read code.",This code is mapped to a Standard Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,OBSERVATION_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,observation_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Observation record, as in whether the measurement was from an EHR system, insurance claim, registry, or other sources.","Choose the OBSERVATION_TYPE_CONCEPT_ID that best represents the provenance of the record, for example whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,person_id,Yes,0,,integer,0,,The PERSON_ID of the Person for whom the Observation is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,provider_id,No,,,integer,0,,"The provider associated with the observation record, e.g. the provider who ordered the test or the provider who recorded the result.",The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record. For example the admitting vs attending physician on an EHR record.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,qualifier_concept_id,No,,,integer,0,,"This field contains all attributes specifying the clinical fact further, such as as degrees, severities, drug-drug interaction alerts etc.","Use your best judgement as to what Concepts to use here and if they are necessary to accurately represent the clinical record. There is no restriction on the domain of these Concepts, they just need to be Standard.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,qualifier_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the qualifier of the Observation that occurred. ,This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,QUALIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,unit_concept_id,No,,,integer,0,,There is currently no recommended unit for individual observation concepts. UNIT_SOURCE_VALUES should be mapped to a Standard Concept in the Unit domain that best represents the unit as given in the source data.,"There is no standardization requirement for units associated with OBSERVATION_CONCEPT_IDs, however, it is the responsibility of the ETL to choose the most plausible unit.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Unit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,unit_source_value,No,,,varchar(50),0,,This field houses the verbatim value from the source data representing the unit of the Observation that occurred. ,This code is mapped to a Standard Condition Concept in the Standardized Vocabularies and the original code is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_as_concept_id,No,,,Integer,0,,"It is possible that some records destined for the Observation table have two clinical ideas represented in one source code. This is common with ICD10 codes that describe a family history of some Condition, for example. In OMOP the Vocabulary breaks these two clinical ideas into two codes; one becomes the OBSERVATION_CONCEPT_ID and the other becomes the VALUE_AS_CONCEPT_ID. It is important when using the Observation table to keep this possibility in mind and to examine the VALUE_AS_CONCEPT_ID field for relevant information. ","Note that the value of VALUE_AS_CONCEPT_ID may be provided through mapping from a source Concept which contains the content of the Observation. In those situations, the CONCEPT_RELATIONSHIP table in addition to the 'Maps to' record contains a second record with the relationship_id set to 'Maps to value'. For example, ICD10 [Z82.4](https://athena.ohdsi.org/search-terms/terms/45581076) 'Family history of ischaemic heart disease and other diseases of the circulatory system' has a 'Maps to' relationship to [4167217](https://athena.ohdsi.org/search-terms/terms/4167217) 'Family history of clinical finding' as well as a 'Maps to value' record to [134057](https://athena.ohdsi.org/search-terms/terms/134057) 'Disorder of cardiovascular system'.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_as_number,No,,,float,0,,"This is the numerical value of the Result of the Observation, if applicable and available. It is not expected that all Observations will have numeric results, rather, this field is here to house values should they exist. ",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_as_string,No,,,varchar(60),0,,"This is the categorical value of the Result of the Observation, if applicable and available. ",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,value_source_value,No,,,varchar(50),0,,This field houses the verbatim result value of the Observation from the source data. Do not get confused with the Observation_source_value which captures source value of the observation mapped to observation_concept_id. This field is the observation result value from the source.," If the observation_source_value was a question, for example, or an observation that requires a result then this field is the answer/ result from the source data. Store the verbatim value that represents the result of the observation_source_value. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +OBSERVATION,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the Observation occurred. For example, if the Person was in the ICU at the time the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION,visit_occurrence_id,No,,,integer,0,,The visit during which the Observation occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If an OBSERVATION_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the observation record. If an observation is related to a visit explicitly in the source data, it is possible that the result date of the Observation falls outside of the bounds of the Visit dates.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION_PERIOD,observation_period_end_date,Yes,0,,date,0,,Use this date to determine the end date of the period for which we can assume that all events for a Person are recorded.,"It is often the case that the idea of Observation Periods does not exist in source data. In those cases, the observation_period_end_date can be inferred as the last Event date available for the Person. In insurance claim data, the Observation Period can be considered as the time period the Person is enrolled with a payer.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,OBSERVATION_PERIOD,OBSERVATION_PERIOD_START_DATE,1,,Yes,1,,Yes,,, +OBSERVATION_PERIOD,observation_period_id,Yes,0,,integer,0,,A Person can have multiple discrete Observation Periods which are identified by the Observation_Period_Id.,Assign a unique observation_period_id to each discrete Observation Period for a Person.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +OBSERVATION_PERIOD,observation_period_start_date,Yes,0,,date,0,,Use this date to determine the start date of the Observation Period.,"It is often the case that the idea of Observation Periods does not exist in source data. In those cases, the observation_period_start_date can be inferred as the earliest Event date available for the Person. In insurance claim data, the Observation Period can be considered as the time period the Person is enrolled with a payer. If a Person switches plans but stays with the same payer, and therefore capturing of data continues, that change would be captured in [PAYER_PLAN_PERIOD](https://ohdsi.github.io/CommonDataModel/cdm531.html#payer_plan_period).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +OBSERVATION_PERIOD,period_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Observation Period as in whether the period was determined from an insurance enrollment file, EHR healthcare encounters, or other sources.",Choose the observation_period_type_concept_id that best represents how the period was determined. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,,,,,,, +OBSERVATION_PERIOD,person_id,Yes,0,,integer,0,,The Person ID of the PERSON record for which the Observation Period is recorded.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,family_source_value,No,,,varchar(50),0,,The common identifier for all people (often a family) that covered by the same policy.,Often these are the common digits of the enrollment id of the policy members.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,0,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_concept_id,No,,,integer,0,,This field represents the organization who reimburses the provider which administers care to the Person.,"Map the Payer directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. The point is to stratify on this information and identify if Persons have the same payer, though the name of the Payer is not necessary. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Payer&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_plan_period_end_date,Yes,0,,date,0,,End date of Plan coverage.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PAYER_PLAN_PERIOD,PAYER_PLAN_PERIOD_START_DATE,1,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_plan_period_id,Yes,0,,integer,0,,"A unique identifier for each unique combination of a Person, Payer, Plan, and Period of time.",,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_plan_period_start_date,Yes,0,,date,0,,Start date of Plan coverage.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_source_concept_id,No,,,integer,0,,,If the source data codes the Payer in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,payer_source_value,No,,,varchar(50),0,,This is the Payer as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,PAYER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,person_id,Yes,0,,integer,0,,The Person covered by the Plan.,"A single Person can have multiple, overlapping, PAYER_PLAN_PERIOD records",No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,plan_concept_id,No,,,integer,0,,This field represents the specific health benefit Plan the Person is enrolled in.,Map the Plan directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. The point is to stratify on this information and identify if Persons have the same health benefit Plan though the name of the Plan is not necessary. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Plan&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,plan_source_concept_id,No,,,integer,0,,,If the source data codes the Plan in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,plan_source_value,No,,,varchar(50),0,,This is the health benefit Plan of the Person as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,PLAN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,sponsor_concept_id,No,,,integer,0,,"This field represents the sponsor of the Plan who finances the Plan. This includes self-insured, small group health plan and large group health plan.",Map the sponsor directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. The point is to stratify on this information and identify if Persons have the same sponsor though the name of the sponsor is not necessary. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Sponsor&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,sponsor_source_concept_id,No,,,integer,0,,,If the source data codes the sponsor in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,sponsor_source_value,No,,,varchar(50),0,,The Plan sponsor as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,SPONSOR_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,stop_reason_concept_id,No,,,integer,0,,"This field represents the reason the Person left the Plan, if known.",Map the stop reason directly to a standard CONCEPT_ID. If one does not exists please contact the vocabulary team. There is no global controlled vocabulary available for this information. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Plan+Stop+Reason&standardConcept=Standard&page=1&pageSize=15&query=).,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,stop_reason_source_concept_id,No,,,integer,0,,,If the source data codes the stop reason in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PAYER_PLAN_PERIOD,stop_reason_source_value,No,,,varchar(50),0,,The Plan stop reason as it appears in the source data.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,STOP_REASON_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PERSON,birth_datetime,No,,,datetime,0,,,"This field is not required but highly encouraged. For data sources that provide the precise datetime of birth, that value should be stored in this field. If birth_datetime is not provided in the source, use the following logic to infer the date: If day_of_birth is null and month_of_birth is not null then use the first of the month in that year. If month_of_birth is null or if day_of_birth AND month_of_birth are both null and the person has records during their year of birth then use the date of the earliest record, otherwise use the 15th of June of that year. If time of birth is not given use midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1850-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,,,,,,No,,,Yes,,, +PERSON,care_site_id,No,,,integer,0,,The Care Site refers to where the Provider typically provides the primary care.,,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,day_of_birth,No,,,integer,0,,,"For data sources that provide the precise date of birth, the day should be extracted and stored in this field.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,31,1,,,,,,,No,,,Yes,,, +PERSON,ethnicity_concept_id,Yes,0,,integer,0,,"This field captures Ethnicity as defined by the Office of Management and Budget (OMB) of the US Government: it distinguishes only between ""Hispanic"" and ""Not Hispanic"". Races and ethnic backgrounds are not stored here.",Only use this field if you have US-based data and a source of this information. Do not attempt to infer Ethnicity from the race or ethnic background of the Person. [Accepted ethnicity concepts](http://athena.ohdsi.org/search-terms/terms?domain=Ethnicity&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,Ethnicity,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,ethnicity_source_concept_id,No,,,integer,0,,"Due to the small number of options, this tends to be zero.","If the source data codes ethnicity in an OMOP supported vocabulary, store the concept_id here.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PERSON,ethnicity_source_value,No,,,varchar(50),0,,This field is used to store the ethnicity of the person from the source data. It is not intended for use in standard analytics but for reference only.,"If the person has an ethnicity other than the OMB standard of ""Hispanic"" or ""Not Hispanic"" store that value from the source data here.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,ETHNICITY_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PERSON,gender_concept_id,Yes,0,,integer,0,,This field is meant to capture the biological sex at birth of the Person. This field should not be used to study gender identity issues.,Use the gender or sex value present in the data under the assumption that it is the biological sex at birth. If the source data captures gender identity it should be stored in the [OBSERVATION](https://ohdsi.github.io/CommonDataModel/cdm531.html#observation) table. [Accepted gender concepts](http://athena.ohdsi.org/search-terms/terms?domain=Gender&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,Gender,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,gender_source_concept_id,No,,,integer,0,,"Due to the small number of options, this tends to be zero.","If the source data codes biological sex in a non-standard vocabulary, store the concept_id here.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PERSON,gender_source_value,No,,,varchar(50),0,,This field is used to store the biological sex of the person from the source data. It is not intended for use in standard analytics but for reference only.,Put the biological sex of the person as it appears in the source data.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,GENDER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PERSON,location_id,No,,,integer,0,,The location refers to the physical address of the person. This field should capture the last known location of the person. ,"Put the location_id from the [LOCATION](https://ohdsi.github.io/CommonDataModel/cdm531.html#location) table here that represents the most granular location information for the person. This could represent anything from postal code or parts thereof, state, or county for example. Since many databases contain deidentified data, it is common that the precision of the location is reduced to prevent re-identification. This field should capture the last known location. ",No,,,Yes,0,,LOCATION,LOCATION_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,month_of_birth,No,,,integer,0,,,"For data sources that provide the precise date of birth, the month should be extracted and stored in this field.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,12,1,,,,,,,No,,,Yes,,, +PERSON,person_id,Yes,0,,integer,0,,It is assumed that every person with a different unique identifier is in fact a different person and should be treated independently.,"Any person linkage that needs to occur to uniquely identify Persons ought to be done prior to writing this table. This identifier can be the original id from the source data provided if it is an integer, otherwise it can be an autogenerated number.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,person_source_value,No,,,varchar(50),0,,Use this field to link back to persons in the source data. This is typically used for error checking of ETL logic.,Some use cases require the ability to link back to persons in the source data. This field allows for the storing of the person value as it appears in the source. This field is not required but strongly recommended.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,provider_id,No,,,integer,0,,The Provider refers to the last known primary care provider (General Practitioner).,"Put the provider_id from the [PROVIDER](https://ohdsi.github.io/CommonDataModel/cdm531.html#provider) table of the last known general practitioner of the person. If there are multiple providers, it is up to the ETL to decide which to put here.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,race_concept_id,Yes,0,,integer,0,,This field captures race or ethnic background of the person.,"Only use this field if you have information about race or ethnic background. The Vocabulary contains Concepts about the main races and ethnic backgrounds in a hierarchical system. Due to the imprecise nature of human races and ethnic backgrounds, this is not a perfect system. Mixed races are not supported. If a clear race or ethnic background cannot be established, use Concept_Id 0. [Accepted Race Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Race&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Race,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PERSON,race_source_concept_id,No,,,integer,0,,"Due to the small number of options, this tends to be zero.",If the source data codes race in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PERSON,race_source_value,No,,,varchar(50),0,,This field is used to store the race of the person from the source data. It is not intended for use in standard analytics but for reference only.,Put the race of the person as it appears in the source data.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,RACE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PERSON,year_of_birth,Yes,0,,integer,0,,Compute age using year_of_birth.,"For data sources with date of birth, the year should be extracted. For data sources where the year of birth is not available, the approximate year of birth could be derived based on age group categorization, if available.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1850,1,,YEAR(GETDATE())+1,1,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,modifier_concept_id,No,,,integer,0,,The modifiers are intended to give additional information about the procedure but as of now the vocabulary is under review.,"It is up to the ETL to choose how to map modifiers if they exist in source data. These concepts are typically distinguished by 'Modifier' concept classes (e.g., 'CPT4 Modifier' as part of the 'CPT4' vocabulary). If there is more than one modifier on a record, one should be chosen that pertains to the procedure rather than provider. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?conceptClass=CPT4+Modifier&conceptClass=HCPCS+Modifier&vocabulary=CPT4&vocabulary=HCPCS&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,modifier_source_value,No,,,varchar(50),0,,,The original modifier code from the source is stored here for reference.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,MODIFIER_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,person_id,Yes,0,,integer,0,,The PERSON_ID of the PERSON for whom the procedure is recorded. This may be a system generated code.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_concept_id,Yes,0,,integer,0,,"The PROCEDURE_CONCEPT_ID field is recommended for primary use in analyses, and must be used for network studies. This is the standard concept mapped from the source value which represents a procedure","The CONCEPT_ID that the PROCEDURE_SOURCE_VALUE maps to. Only records whose source values map to standard concepts with a domain of ""Procedure"" should go in this table. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Procedure&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Procedure,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_date,Yes,0,,date,0,,Use this date to determine the date the procedure started.,This is meant to be the **start date** of the procedure. It will be renamed in a future version to **PROCEDURE_START_DATE**. ,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,5, +PROCEDURE_OCCURRENCE,procedure_datetime,No,,,datetime,0,,,"If the procedure has a start time in the native date, use this field to house that information. This will be renamed in a future version to **PROCEDURE_START_DATETIME**.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_end_date,No,,,date,0,,Use this field to house the date that the procedure ended. ,This is meant to be the end date of the procedure. It is not required and for most cases will be the same as the PROCEDURE_START_DATE.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PROCEDURE_OCCURRENCE,PROCEDURE_DATE,1,,Yes,1,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_end_datetime,No,,,datetime,0,,Use this field to house the datetime that the procedure ended. ,This is meant to house the end datetime of the procedure and will most often be used in conjunction with the procedure_start_datetime to determine the length of the procedure.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PROCEDURE_OCCURRENCE,PROCEDURE_DATETIME,1,,Yes,1,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_occurrence_id,Yes,0,,integer,0,,The unique key given to a procedure record for a person. Refer to the ETL for how duplicate procedures during the same visit were handled.,"Each instance of a procedure occurrence in the source data should be assigned this unique key. In some cases, a person can have multiple records of the same procedure within the same visit. It is valid to keep these duplicates and assign them individual, unique, PROCEDURE_OCCURRENCE_IDs, though it is up to the ETL how they should be handled.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_source_concept_id,No,,,integer,0,,"This is the concept representing the procedure source value and may not necessarily be standard. This field is discouraged from use in analysis because it is not required to contain Standard Concepts that are used across the OHDSI community, and should only be used when Standard Concepts do not adequately represent the source detail for the Procedure necessary for a given analytic use case. Consider using PROCEDURE_CONCEPT_ID instead to enable standardized analytics that can be consistent across the network.",If the PROCEDURE_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the procedure that occurred. For example, this could be an CPT4 or OPCS4 code.",Use this value to look up the source concept id and then map the source concept id to a standard concept id.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,PROCEDURE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,procedure_type_concept_id,Yes,0,,integer,0,,"This field can be used to determine the provenance of the Procedure record, as in whether the procedure was from an EHR system, insurance claim, registry, or other sources.","Choose the PROCEDURE_TYPE_CONCEPT_ID that best represents the provenance of the record, for example whether it came from an EHR record or billing claim. If a procedure is recorded as an EHR encounter, the PROCEDURE_TYPE_CONCEPT would be 'EHR encounter record'. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,provider_id,No,,,integer,0,,"The provider associated with the procedure record, e.g. the provider who performed the Procedure.","The ETL may need to make a choice as to which PROVIDER_ID to put here. Based on what is available this may or may not be different than the provider associated with the overall VISIT_OCCURRENCE record, for example the admitting vs attending physician on an EHR record.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,quantity,No,,,integer,0,,"If the quantity value is omitted, a single procedure is assumed.","If a Procedure has a quantity of '0' in the source, this should default to '1' in the ETL. If there is a record in the source it can be assumed the exposure occurred at least once",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,visit_detail_id,No,,,integer,0,,"The VISIT_DETAIL record during which the Procedure occurred. For example, if the Person was in the ICU at the time of the Procedure the VISIT_OCCURRENCE record would reflect the overall hospital stay and the VISIT_DETAIL record would reflect the ICU stay during the hospital visit.",Same rules apply as for the VISIT_OCCURRENCE_ID.,No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROCEDURE_OCCURRENCE,visit_occurrence_id,No,,,integer,0,,The visit during which the procedure occurred.,"Depending on the structure of the source data, this may have to be determined based on dates. If a PROCEDURE_DATE occurs within the start and end date of a Visit it is a valid ETL choice to choose the VISIT_OCCURRENCE_ID from the Visit that subsumes it, even if not explicitly stated in the data. While not required, an attempt should be made to locate the VISIT_OCCURRENCE_ID of the PROCEDURE_OCCURRENCE record.",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +PROVIDER,care_site_id,No,,,integer,0,,This is the CARE_SITE_ID for the location that the provider primarily practices in.,"If a Provider has more than one Care Site, the main or most often exerted CARE_SITE_ID should be recorded.",No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,dea,No,,,varchar(20),0,,"This is the identifier issued by the DEA, a US federal agency, that allows a provider to write prescriptions for controlled substances.",,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,gender_concept_id,No,,,integer,0,,This field represents the recorded gender of the provider in the source data.,"If given, put a concept from the gender domain representing the recorded gender of the provider. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Gender&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Gender,0,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,gender_source_concept_id,No,,,integer,0,,This is often zero as many sites use proprietary codes to store provider gender.,If the source data codes provider gender in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,gender_source_value,No,,,varchar(50),0,,This is provider's gender as it appears in the source data.,Put the provider's gender as it appears in the source data. This field is up to the discretion of the ETL-er as to whether this should be the coded value from the source or the text description of the lookup value.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,GENDER_CONCEPT_ID,,,,,,,,,,,,No,,,No,,, +PROVIDER,npi,No,,,varchar(20),0,,This is the National Provider Number issued to health care providers in the US by the Centers for Medicare and Medicaid Services (CMS).,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,provider_id,Yes,0,,integer,0,,It is assumed that every provider with a different unique identifier is in fact a different person and should be treated independently.,"This identifier can be the original id from the source data provided it is an integer, otherwise it can be an autogenerated number.",Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,provider_name,No,,,varchar(255),0,,,"This field is not necessary as it is not necessary to have the actual identity of the Provider. Rather, the idea is to uniquely and anonymously identify providers of care across the database.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,provider_source_value,No,,,varchar(50),0,,Use this field to link back to providers in the source data. This is typically used for error checking of ETL logic.,Some use cases require the ability to link back to providers in the source data. This field allows for the storing of the provider identifier as it appears in the source.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,specialty_concept_id,No,,,integer,0,,"This field either represents the most common specialty that occurs in the data or the most specific concept that represents all specialties listed, should the provider have more than one. This includes physician specialties such as internal medicine, emergency medicine, etc. and allied health professionals such as nurses, midwives, and pharmacists.","If a Provider has more than one Specialty, there are two options: 1. Choose a concept_id which is a common ancestor to the multiple specialties, or, 2. Choose the specialty that occurs most often for the provider. Concepts in this field should be Standard with a domain of Provider. [Accepted Concepts](http://athena.ohdsi.org/search-terms/terms?domain=Provider&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,100,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,specialty_source_concept_id,No,,,integer,0,,This is often zero as many sites use proprietary codes to store physician speciality.,If the source data codes provider specialty in an OMOP supported vocabulary store the concept_id here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,No,,, +PROVIDER,specialty_source_value,No,,,varchar(50),0,,"This is the kind of provider or specialty as it appears in the source data. This includes physician specialties such as internal medicine, emergency medicine, etc. and allied health professionals such as nurses, midwives, and pharmacists.",Put the kind of provider as it appears in the source data. This field is up to the discretion of the ETL-er as to whether this should be the coded value from the source or the text description of the lookup value.,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,SPECIALTY_CONCEPT_ID,,,,,,,,,,,,No,,,No,,, +PROVIDER,year_of_birth,No,,,integer,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, RELATIONSHIP,defines_ancestry,Yes,0,,varchar(1),0,,"Defines whether a hierarchical relationship contributes to the concept_ancestor table. These are subsets of the hierarchical -relationships. Valid values are 1 or 0.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +relationships. Valid values are 1 or 0.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, RELATIONSHIP,is_hierarchical,Yes,0,,varchar(1),0,,"Defines whether a relationship defines concepts into classes or hierarchies. Values -are 1 for hierarchical relationship or 0 if not.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +are 1 for hierarchical relationship or 0 if not.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, RELATIONSHIP,relationship_concept_id,Yes,0,,integer,0,,"A foreign key that refers to an identifier in the [CONCEPT](https://ohdsi.github.io/CommonDataModel/cdm531.html#concept) table for the unique -relationship concept.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +relationship concept.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, RELATIONSHIP,relationship_id,Yes,0,,varchar(20),0,,"The type of relationship captured by the -relationship record.",,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -RELATIONSHIP,relationship_name,Yes,0,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +relationship record.",,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +RELATIONSHIP,relationship_name,Yes,0,,varchar(255),0,,,,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, RELATIONSHIP,reverse_relationship_id,Yes,0,,varchar(20),0,,"The identifier for the relationship used to define the reverse relationship between two -concepts.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -SOURCE_TO_CONCEPT_MAP,invalid_reason,No,,,varchar(1),0,,"Reason the mapping instance was invalidated. Possible values are D (deleted), U (replaced with an update) or NULL when valid_end_date has the default value.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +concepts.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +SOURCE_TO_CONCEPT_MAP,invalid_reason,No,,,varchar(1),0,,"Reason the mapping instance was invalidated. Possible values are D (deleted), U (replaced with an update) or NULL when valid_end_date has the default value.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, SOURCE_TO_CONCEPT_MAP,source_code,Yes,0,,varchar(50),0,,"The source code being translated -into a Standard Concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +into a Standard Concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, SOURCE_TO_CONCEPT_MAP,source_code_description,No,,,varchar(255),0,,"An optional description for the source code. This is included as a convenience to compare the description of the source code to -the name of the concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +the name of the concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, SOURCE_TO_CONCEPT_MAP,source_concept_id,Yes,0,,integer,0,,"A foreign key to the Source Concept that is being translated -into a Standard Concept.","This is either 0 or should be a number above 2 billion, which are the Concepts reserved for site-specific codes and mappings. ",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No +into a Standard Concept.","This is either 0 or should be a number above 2 billion, which are the Concepts reserved for site-specific codes and mappings. ",No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,100,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,No,,, SOURCE_TO_CONCEPT_MAP,source_vocabulary_id,Yes,0,,varchar(20),0,,"A foreign key to the VOCABULARY table defining the vocabulary of the source code that is being translated to a Standard -Concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +Concept.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, SOURCE_TO_CONCEPT_MAP,target_concept_id,Yes,0,,integer,0,,"The target Concept to which the source code is being -mapped.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,No,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -SOURCE_TO_CONCEPT_MAP,target_vocabulary_id,Yes,0,,varchar(20),0,,The Vocabulary of the target Concept.,,No,,,Yes,0,,VOCABULARY,VOCABULARY_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +mapped.",,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,No,100,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +SOURCE_TO_CONCEPT_MAP,target_vocabulary_id,Yes,0,,varchar(20),0,,The Vocabulary of the target Concept.,,No,,,Yes,0,,VOCABULARY,VOCABULARY_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, SOURCE_TO_CONCEPT_MAP,valid_end_date,Yes,0,,date,0,,"The date when the mapping instance became invalid because it was deleted or superseded (updated) by a new relationship. -Default value is 31-Dec-2099.",,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,Yes,SOURCE_TO_CONCEPT_MAP,VALID_START_DATE,0,,,,, +Default value is 31-Dec-2099.",,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,Yes,SOURCE_TO_CONCEPT_MAP,VALID_START_DATE,0,,,,,,,, SOURCE_TO_CONCEPT_MAP,valid_start_date,Yes,0,,date,0,,"The date when the mapping -instance was first recorded.",,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -SPECIMEN,anatomic_site_concept_id,No,,,integer,0,,This is the site on the body where the specimen is from.,Map the ANATOMIC_SITE_SOURCE_VALUE to a Standard Concept in the Spec Anatomic Site domain. This should be coded at the lowest level of granularity [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&domain=Spec+Anatomic+Site&conceptClass=Body+Structure&page=4&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,anatomic_site_source_value,No,,,varchar(50),0,,,"This is the site on the body where the specimen was taken from, as represented in the source.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,ANATOMIC_SITE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,disease_status_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,disease_status_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,DISEASE_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,person_id,Yes,0,,integer,0,,The person from whom the specimen is collected.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,quantity,No,,,float,0,,The amount of specimen collected from the person.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_concept_id,Yes,0,,integer,0,,,The standard CONCEPT_ID that the SPECIMEN_SOURCE_VALUE maps to in the specimen domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Specimen&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_date,Yes,0,,date,0,,The date the specimen was collected.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -SPECIMEN,specimen_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes -SPECIMEN,specimen_id,Yes,0,,integer,0,,Unique identifier for each specimen.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_source_id,No,,,varchar(50),0,,This is the identifier for the specimen from the source system. ,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,SPECIMEN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -SPECIMEN,specimen_type_concept_id,Yes,0,,integer,0,,,"Put the source of the specimen record, as in an EHR system. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&domain=Type+Concept&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,unit_concept_id,No,,,integer,0,,The unit for the quantity of the specimen.,Map the UNIT_SOURCE_VALUE to a Standard Concept in the Unit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Unit&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -SPECIMEN,unit_source_value,No,,,varchar(50),0,,,"This unit for the quantity of the specimen, as represented in the source.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,admitted_from_concept_id,No,,,Integer,0,,"Use this field to determine where the patient was admitted from. This concept is part of the visit domain and can indicate if a patient was admitted to the hospital from a long-term care facility, for example.","If available, map the admitted_from_source_value to a standard concept in the visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=). If the person was admitted from home, set this to 0.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,admitted_from_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was admitted from. Typically this applies only to visits that have a length of stay, like inpatient visits or long-term care visits.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,care_site_id,No,,,integer,0,,This field provides information about the Care Site where the Visit Detail took place.,There should only be one Care Site associated with a Visit Detail.,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,discharged_to_concept_id,No,,,integer,0,,"Use this field to determine where the patient was discharged to after a visit. This concept is part of the visit domain and can indicate if a patient was transferred to another hospital or sent to a long-term care facility, for example. It is assumed that a person is discharged to home therefore there is not a standard concept id for ""home"". Use concept id = 0 when a person is discharged to home.","If available, map the DISCHARGE_TO_SOURCE_VALUE to a Standard Concept in the Visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,discharged_to_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was discharged to after a visit, as in they went home or were moved to long-term care. Typically this applies only to visits that have a length of stay of a day or more.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,parent_visit_detail_id,No,,,integer,0,,Use this field to find the visit detail that subsumes the given visit detail record. This is used in the case that a visit detail record needs to be nested beyond the VISIT_OCCURRENCE/VISIT_DETAIL relationship.,"If there are multiple nested levels to how Visits are represented in the source, the VISIT_DETAIL_PARENT_ID can be used to record this relationship. ",No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,preceding_visit_detail_id,No,,,integer,0,,Use this field to find the visit detail that occurred for the person prior to the given visit detail record. There could be a few days or a few years in between.,"The PRECEDING_VISIT_DETAIL_ID can be used to link a visit immediately preceding the current Visit Detail. Note this is not symmetrical, and there is no such thing as a ""following_visit_id"".",No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,provider_id,No,,,integer,0,,"There will only be one provider per **visit** record and the ETL document should clearly state how they were chosen (attending, admitting, etc.). This is a typical reason for leveraging the VISIT_DETAIL table as even though each VISIT_DETAIL record can only have one provider, there is no limit to the number of VISIT_DETAIL records that can be associated to a VISIT_OCCURRENCE record.",The additional providers associated to a Visit can be stored in this table where each VISIT_DETAIL record represents a different provider.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_concept_id,Yes,0,,integer,0,,"This field contains a concept id representing the kind of visit detail, like inpatient or outpatient. All concepts in this field should be standard and belong to the Visit domain.","Populate this field based on the kind of visit that took place for the person. For example this could be ""Inpatient Visit"", ""Outpatient Visit"", ""Ambulatory Visit"", etc. This table will contain standard concepts in the Visit domain. These concepts are arranged in a hierarchical structure to facilitate cohort definitions by rolling up to generally familiar Visits adopted in most healthcare systems worldwide. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +instance was first recorded.",,No,,,No,,,,,,,,,,,No,,,No,0,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +SPECIMEN,anatomic_site_concept_id,No,,,integer,0,,This is the site on the body where the specimen is from.,Map the ANATOMIC_SITE_SOURCE_VALUE to a Standard Concept in the Spec Anatomic Site domain. This should be coded at the lowest level of granularity [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&domain=Spec+Anatomic+Site&conceptClass=Body+Structure&page=4&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,anatomic_site_source_value,No,,,varchar(50),0,,,"This is the site on the body where the specimen was taken from, as represented in the source.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,ANATOMIC_SITE_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,disease_status_concept_id,No,,,integer,0,,,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,disease_status_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,DISEASE_STATUS_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,person_id,Yes,0,,integer,0,,The person from whom the specimen is collected.,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,quantity,No,,,float,0,,The amount of specimen collected from the person.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,1,1,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_concept_id,Yes,0,,integer,0,,,The standard CONCEPT_ID that the SPECIMEN_SOURCE_VALUE maps to in the specimen domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Specimen&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_date,Yes,0,,date,0,,The date the specimen was collected.,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +SPECIMEN,specimen_datetime,No,,,datetime,0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,No,,,Yes,,, +SPECIMEN,specimen_id,Yes,0,,integer,0,,Unique identifier for each specimen.,,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_source_id,No,,,varchar(50),0,,This is the identifier for the specimen from the source system. ,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_source_value,No,,,varchar(50),0,,,,No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,SPECIMEN_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,specimen_type_concept_id,Yes,0,,integer,0,,,"Put the source of the specimen record, as in an EHR system. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?standardConcept=Standard&domain=Type+Concept&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,unit_concept_id,No,,,integer,0,,The unit for the quantity of the specimen.,Map the UNIT_SOURCE_VALUE to a Standard Concept in the Unit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Unit&standardConcept=Standard&page=1&pageSize=15&query=),No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +SPECIMEN,unit_source_value,No,,,varchar(50),0,,,"This unit for the quantity of the specimen, as represented in the source.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,UNIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,admitted_from_concept_id,No,,,Integer,0,,"Use this field to determine where the patient was admitted from. This concept is part of the visit domain and can indicate if a patient was admitted to the hospital from a long-term care facility, for example.","If available, map the admitted_from_source_value to a standard concept in the visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=). If the person was admitted from home, set this to 0.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,admitted_from_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was admitted from. Typically this applies only to visits that have a length of stay, like inpatient visits or long-term care visits.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,care_site_id,No,,,integer,0,,This field provides information about the Care Site where the Visit Detail took place.,There should only be one Care Site associated with a Visit Detail.,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,discharged_to_concept_id,No,,,integer,0,,"Use this field to determine where the patient was discharged to after a visit. This concept is part of the visit domain and can indicate if a patient was transferred to another hospital or sent to a long-term care facility, for example. It is assumed that a person is discharged to home therefore there is not a standard concept id for ""home"". Use concept id = 0 when a person is discharged to home.","If available, map the DISCHARGE_TO_SOURCE_VALUE to a Standard Concept in the Visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,discharged_to_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was discharged to after a visit, as in they went home or were moved to long-term care. Typically this applies only to visits that have a length of stay of a day or more.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,parent_visit_detail_id,No,,,integer,0,,Use this field to find the visit detail that subsumes the given visit detail record. This is used in the case that a visit detail record needs to be nested beyond the VISIT_OCCURRENCE/VISIT_DETAIL relationship.,"If there are multiple nested levels to how Visits are represented in the source, the VISIT_DETAIL_PARENT_ID can be used to record this relationship. ",No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,preceding_visit_detail_id,No,,,integer,0,,Use this field to find the visit detail that occurred for the person prior to the given visit detail record. There could be a few days or a few years in between.,"The PRECEDING_VISIT_DETAIL_ID can be used to link a visit immediately preceding the current Visit Detail. Note this is not symmetrical, and there is no such thing as a ""following_visit_id"".",No,,,Yes,0,,VISIT_DETAIL,VISIT_DETAIL_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,provider_id,No,,,integer,0,,"There will only be one provider per **visit** record and the ETL document should clearly state how they were chosen (attending, admitting, etc.). This is a typical reason for leveraging the VISIT_DETAIL table as even though each VISIT_DETAIL record can only have one provider, there is no limit to the number of VISIT_DETAIL records that can be associated to a VISIT_OCCURRENCE record.",The additional providers associated to a Visit can be stored in this table where each VISIT_DETAIL record represents a different provider.,No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_concept_id,Yes,0,,integer,0,,"This field contains a concept id representing the kind of visit detail, like inpatient or outpatient. All concepts in this field should be standard and belong to the Visit domain.","Populate this field based on the kind of visit that took place for the person. For example this could be ""Inpatient Visit"", ""Outpatient Visit"", ""Ambulatory Visit"", etc. This table will contain standard concepts in the Visit domain. These concepts are arranged in a hierarchical structure to facilitate cohort definitions by rolling up to generally familiar Visits adopted in most healthcare systems worldwide. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, VISIT_DETAIL,visit_detail_end_date,Yes,0,,date,0,,"This the end date of the patient-provider interaction. If a Person is still an inpatient in the hospital at the time of the data extract and does not have a visit_end_date, then set the visit_end_date to the date of the data pull.","Visit Detail end dates are mandatory. If end dates are not provided in the source there are three ways in which to derive them:
- Outpatient Visit Detail: visit_detail_end_datetime = visit_detail_start_datetime - Emergency Room Visit Detail: visit_detail_end_datetime = visit_detail_start_datetime - Inpatient Visit Detail: Usually there is information about discharge. If not, you should be able to derive the end date from the sudden decline of activity or from the absence of inpatient procedures/drugs. - Non-hospital institution Visit Details: Particularly for claims data, if end dates are not provided assume the visit is for the duration of month that it occurs.
For Inpatient Visit Details ongoing at the date of ETL, put date of processing the data into visit_detai_end_datetime and visit_detail_type_concept_id with 32220 ""Still patient"" to identify the visit as incomplete. -All other Visits Details: visit_detail_end_datetime = visit_detail_start_datetime. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATE,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_end_datetime,No,,,datetime,0,,"If a Person is still an inpatient in the hospital at the time of the data extract and does not have a visit_end_datetime, then set the visit_end_datetime to the datetime of the data pull.","If no time is given for the end date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATETIME,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_id,Yes,0,,integer,0,,Use this to identify unique interactions between a person and the health care system. This identifier links across the other CDM event tables to associate events with a visit detail.,This should be populated by creating a unique identifier for each unique interaction between a person and the healthcare system where the person receives a medical good or service over a span of time.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_source_concept_id,No,,,Integer,0,,,If the VISIT_DETAIL_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_DETAIL,visit_detail_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the kind of visit detail that took place (inpatient, outpatient, emergency, etc.)","If there is information about the kind of visit detail in the source data that value should be stored here. If a visit is an amalgamation of visits from the source then use a hierarchy to choose the VISIT_DETAIL_SOURCE_VALUE, such as IP -> ER-> OP. This should line up with the logic chosen to determine how visits are created.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,visit_detail_start_date,Yes,0,,date,0,,This is the date of the start of the encounter. This may or may not be equal to the date of the Visit the Visit Detail is associated with.,"When populating VISIT_DETAIL_START_DATE, you should think about the patient experience to make decisions on how to define visits. Most likely this should be the date of the patient-provider interaction.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_start_datetime,No,,,datetime,0,,,"If no time is given for the start date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -VISIT_DETAIL,visit_detail_type_concept_id,Yes,0,,integer,0,,"Use this field to understand the provenance of the visit detail record, or where the record comes from.","Populate this field based on the provenance of the visit detail record, as in whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_DETAIL,visit_occurrence_id,Yes,0,,integer,0,,Use this field to link the VISIT_DETAIL record to its VISIT_OCCURRENCE.,Put the VISIT_OCCURRENCE_ID that subsumes the VISIT_DETAIL record here.,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_OCCURRENCE,admitted_from_concept_id,No,,,integer,0,,"Use this field to determine where the patient was admitted from. This concept is part of the visit domain and can indicate if a patient was admitted to the hospital from a long-term care facility, for example.","If available, map the admitted_from_source_value to a standard concept in the visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=). If a person was admitted from home, set this to 0.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_OCCURRENCE,admitted_from_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was admitted from. Typically this applies only to visits that have a length of stay, like inpatient visits or long-term care visits.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_OCCURRENCE,care_site_id,No,,,integer,0,,This field provides information about the Care Site where the Visit took place.,There should only be one Care Site associated with a Visit.,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,discharged_to_concept_id,No,,,integer,0,,"Use this field to determine where the patient was discharged to after a visit. This concept is part of the visit domain and can indicate if a patient was transferred to another hospital or sent to a long-term care facility, for example. It is assumed that a person is discharged to home therefore there is not a standard concept id for ""home"". Use concept id = 0 when a person is discharged to home.","If available, map the discharged_to_source_value to a standard concept in the visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_OCCURRENCE,discharged_to_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was discharged to after a visit, as in they went home or were moved to long-term care. Typically this applies only to visits that have a length of stay of a day or more.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, -VISIT_OCCURRENCE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,preceding_visit_occurrence_id,No,,,integer,0,,Use this field to find the visit that occurred for the person prior to the given visit. There could be a few days or a few years in between.,"This field can be used to link a visit immediately preceding the current visit. Note this is not symmetrical, and there is no such thing as a ""following_visit_id"".",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,provider_id,No,,,integer,0,,"There will only be one provider per visit record and the ETL document should clearly state how they were chosen (attending, admitting, etc.). If there are multiple providers associated with a visit in the source, this can be reflected in the event tables (CONDITION_OCCURRENCE, PROCEDURE_OCCURRENCE, etc.) or in the VISIT_DETAIL table.","If there are multiple providers associated with a visit, you will need to choose which one to put here. The additional providers can be stored in the [VISIT_DETAIL](https://ohdsi.github.io/CommonDataModel/cdm531.html#visit_detail) table.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,visit_concept_id,Yes,0,,integer,0,,"This field contains a concept id representing the kind of visit, like inpatient or outpatient. All concepts in this field should be standard and belong to the Visit domain.","Populate this field based on the kind of visit that took place for the person. For example this could be ""Inpatient Visit"", ""Outpatient Visit"", ""Ambulatory Visit"", etc. This table will contain standard concepts in the Visit domain. These concepts are arranged in a hierarchical structure to facilitate cohort definitions by rolling up to generally familiar Visits adopted in most healthcare systems worldwide. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes +All other Visits Details: visit_detail_end_datetime = visit_detail_start_datetime. ",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATE,1,,Yes,1,,Yes,Yes,1, +VISIT_DETAIL,visit_detail_end_datetime,No,,,datetime,0,,"If a Person is still an inpatient in the hospital at the time of the data extract and does not have a visit_end_datetime, then set the visit_end_datetime to the datetime of the data pull.","If no time is given for the end date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_DETAIL,VISIT_DETAIL_START_DATETIME,1,,Yes,1,,Yes,,, +VISIT_DETAIL,visit_detail_id,Yes,0,,integer,0,,Use this to identify unique interactions between a person and the health care system. This identifier links across the other CDM event tables to associate events with a visit detail.,This should be populated by creating a unique identifier for each unique interaction between a person and the healthcare system where the person receives a medical good or service over a span of time.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_source_concept_id,No,,,Integer,0,,,If the VISIT_DETAIL_SOURCE_VALUE is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_DETAIL,visit_detail_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the kind of visit detail that took place (inpatient, outpatient, emergency, etc.)","If there is information about the kind of visit detail in the source data that value should be stored here. If a visit is an amalgamation of visits from the source then use a hierarchy to choose the VISIT_DETAIL_SOURCE_VALUE, such as IP -> ER-> OP. This should line up with the logic chosen to determine how visits are created.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,visit_detail_start_date,Yes,0,,date,0,,This is the date of the start of the encounter. This may or may not be equal to the date of the Visit the Visit Detail is associated with.,"When populating VISIT_DETAIL_START_DATE, you should think about the patient experience to make decisions on how to define visits. Most likely this should be the date of the patient-provider interaction.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,Yes,1, +VISIT_DETAIL,visit_detail_start_datetime,No,,,datetime,0,,,"If no time is given for the start date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +VISIT_DETAIL,visit_detail_type_concept_id,Yes,0,,integer,0,,"Use this field to understand the provenance of the visit detail record, or where the record comes from.","Populate this field based on the provenance of the visit detail record, as in whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_DETAIL,visit_occurrence_id,Yes,0,,integer,0,,Use this field to link the VISIT_DETAIL record to its VISIT_OCCURRENCE.,Put the VISIT_OCCURRENCE_ID that subsumes the VISIT_DETAIL record here.,No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_OCCURRENCE,admitted_from_concept_id,No,,,integer,0,,"Use this field to determine where the patient was admitted from. This concept is part of the visit domain and can indicate if a patient was admitted to the hospital from a long-term care facility, for example.","If available, map the admitted_from_source_value to a standard concept in the visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=). If a person was admitted from home, set this to 0.",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_OCCURRENCE,admitted_from_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was admitted from. Typically this applies only to visits that have a length of stay, like inpatient visits or long-term care visits.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_OCCURRENCE,care_site_id,No,,,integer,0,,This field provides information about the Care Site where the Visit took place.,There should only be one Care Site associated with a Visit.,No,,,Yes,0,,CARE_SITE,CARE_SITE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,discharged_to_concept_id,No,,,integer,0,,"Use this field to determine where the patient was discharged to after a visit. This concept is part of the visit domain and can indicate if a patient was transferred to another hospital or sent to a long-term care facility, for example. It is assumed that a person is discharged to home therefore there is not a standard concept id for ""home"". Use concept id = 0 when a person is discharged to home.","If available, map the discharged_to_source_value to a standard concept in the visit domain. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,5,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_OCCURRENCE,discharged_to_source_value,No,,,varchar(50),0,,,"This information may be called something different in the source data but the field is meant to contain a value indicating where a person was discharged to after a visit, as in they went home or were moved to long-term care. Typically this applies only to visits that have a length of stay of a day or more.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, +VISIT_OCCURRENCE,person_id,Yes,0,,integer,0,,,,No,,,Yes,0,,PERSON,PERSON_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,preceding_visit_occurrence_id,No,,,integer,0,,Use this field to find the visit that occurred for the person prior to the given visit. There could be a few days or a few years in between.,"This field can be used to link a visit immediately preceding the current visit. Note this is not symmetrical, and there is no such thing as a ""following_visit_id"".",No,,,Yes,0,,VISIT_OCCURRENCE,VISIT_OCCURRENCE_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,provider_id,No,,,integer,0,,"There will only be one provider per visit record and the ETL document should clearly state how they were chosen (attending, admitting, etc.). If there are multiple providers associated with a visit in the source, this can be reflected in the event tables (CONDITION_OCCURRENCE, PROCEDURE_OCCURRENCE, etc.) or in the VISIT_DETAIL table.","If there are multiple providers associated with a visit, you will need to choose which one to put here. The additional providers can be stored in the [VISIT_DETAIL](https://ohdsi.github.io/CommonDataModel/cdm531.html#visit_detail) table.",No,,,Yes,0,,PROVIDER,PROVIDER_ID,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,visit_concept_id,Yes,0,,integer,0,,"This field contains a concept id representing the kind of visit, like inpatient or outpatient. All concepts in this field should be standard and belong to the Visit domain.","Populate this field based on the kind of visit that took place for the person. For example this could be ""Inpatient Visit"", ""Outpatient Visit"", ""Ambulatory Visit"", etc. This table will contain standard concepts in the Visit domain. These concepts are arranged in a hierarchical structure to facilitate cohort definitions by rolling up to generally familiar Visits adopted in most healthcare systems worldwide. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Visit&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Visit,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, VISIT_OCCURRENCE,visit_end_date,Yes,0,,date,0,,"For inpatient visits the end date is typically the discharge date. If a Person is still an inpatient in the hospital at the time of the data extract and does not have a visit_end_date, then set the visit_end_date to the date of the data pull.","Visit end dates are mandatory. If end dates are not provided in the source there are three ways in which to derive them: - Outpatient Visit: visit_end_datetime = visit_start_datetime - Emergency Room Visit: visit_end_datetime = visit_start_datetime - Inpatient Visit: Usually there is information about discharge. If not, you should be able to derive the end date from the sudden decline of activity or from the absence of inpatient procedures/drugs. - Non-hospital institution Visits: Particularly for claims data, if end dates are not provided assume the visit is for the duration of month that it occurs. For Inpatient Visits ongoing at the date of ETL, put date of processing the data into visit_end_datetime and visit_type_concept_id with 32220 ""Still patient"" to identify the visit as incomplete. -- All other Visits: visit_end_datetime = visit_start_datetime. If this is a one-day visit the end date should match the start date.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_OCCURRENCE,VISIT_START_DATE,1,,Yes,1,,Yes -VISIT_OCCURRENCE,visit_end_datetime,No,,,datetime,0,,"If a Person is still an inpatient in the hospital at the time of the data extract and does not have a visit_end_datetime, then set the visit_end_datetime to the datetime of the data pull.","If no time is given for the end date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_OCCURRENCE,VISIT_START_DATETIME,1,,Yes,1,,Yes -VISIT_OCCURRENCE,visit_occurrence_id,Yes,0,,integer,0,,Use this to identify unique interactions between a person and the health care system. This identifier links across the other CDM event tables to associate events with a visit.,This should be populated by creating a unique identifier for each unique interaction between a person and the healthcare system where the person receives a medical good or service over a span of time.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,visit_source_concept_id,No,,,integer,0,,,If the visit source value is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,visit_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the kind of visit that took place (inpatient, outpatient, emergency, etc.)","If there is information about the kind of visit in the source data that value should be stored here. If a visit is an amalgamation of visits from the source then use a hierarchy to choose the visit source value, such as IP -> ER-> OP. This should line up with the logic chosen to determine how visits are created.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,VISIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes -VISIT_OCCURRENCE,visit_start_date,Yes,0,,date,0,,"For inpatient visits, the start date is typically the admission date. For outpatient visits the start date and end date will be the same.","When populating VISIT_START_DATE, you should think about the patient experience to make decisions on how to define visits. In the case of an inpatient visit this should be the date the patient was admitted to the hospital or institution. In all other cases this should be the date of the patient-provider interaction.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -VISIT_OCCURRENCE,visit_start_datetime,No,,,datetime,0,,,"If no time is given for the start date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes -VISIT_OCCURRENCE,visit_type_concept_id,Yes,0,,Integer,0,,"Use this field to understand the provenance of the visit record, or where the record comes from.","Populate this field based on the provenance of the visit record, as in whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes -VOCABULARY,vocabulary_concept_id,Yes,0,,integer,0,,A Concept that represents the Vocabulary the VOCABULARY record belongs to.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +- All other Visits: visit_end_datetime = visit_start_datetime. If this is a one-day visit the end date should match the start date.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_OCCURRENCE,VISIT_START_DATE,1,,Yes,1,,Yes,,, +VISIT_OCCURRENCE,visit_end_datetime,No,,,datetime,0,,"If a Person is still an inpatient in the hospital at the time of the data extract and does not have a visit_end_datetime, then set the visit_end_datetime to the datetime of the data pull.","If no time is given for the end date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,VISIT_OCCURRENCE,VISIT_START_DATETIME,1,,Yes,1,,Yes,,, +VISIT_OCCURRENCE,visit_occurrence_id,Yes,0,,integer,0,,Use this to identify unique interactions between a person and the health care system. This identifier links across the other CDM event tables to associate events with a visit.,This should be populated by creating a unique identifier for each unique interaction between a person and the healthcare system where the person receives a medical good or service over a span of time.,Yes,0,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,visit_source_concept_id,No,,,integer,0,,,If the visit source value is coded in the source data using an OMOP supported vocabulary put the concept id representing the source value here.,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,Yes,,,No,,,Yes,100,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,visit_source_value,No,,,varchar(50),0,,"This field houses the verbatim value from the source data representing the kind of visit that took place (inpatient, outpatient, emergency, etc.)","If there is information about the kind of visit in the source data that value should be stored here. If a visit is an amalgamation of visits from the source then use a hierarchy to choose the visit source value, such as IP -> ER-> OP. This should line up with the logic chosen to determine how visits are created.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,Yes,100,,VISIT_CONCEPT_ID,,,,,,,,,,,,No,,,Yes,,, +VISIT_OCCURRENCE,visit_start_date,Yes,0,,date,0,,"For inpatient visits, the start date is typically the admission date. For outpatient visits the start date and end date will be the same.","When populating VISIT_START_DATE, you should think about the patient experience to make decisions on how to define visits. In the case of an inpatient visit this should be the date the patient was admitted to the hospital or institution. In all other cases this should be the date of the patient-provider interaction.",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +VISIT_OCCURRENCE,visit_start_datetime,No,,,datetime,0,,,"If no time is given for the start date of a visit, set it to midnight (00:00:0000).",No,,,No,,,,,,,,,,,No,,,Yes,,,No,,,No,,,No,,,,'1950-01-01',1,,"DATEADD(dd,1,GETDATE())",1,,Yes,PERSON,BIRTH_DATETIME,1,,Yes,1,,Yes,,, +VISIT_OCCURRENCE,visit_type_concept_id,Yes,0,,Integer,0,,"Use this field to understand the provenance of the visit record, or where the record comes from.","Populate this field based on the provenance of the visit record, as in whether it came from an EHR record or billing claim. [Accepted Concepts](https://athena.ohdsi.org/search-terms/terms?domain=Type+Concept&standardConcept=Standard&page=1&pageSize=15&query=).",No,,,Yes,0,,CONCEPT,CONCEPT_ID,Type Concept,0,,,,,Yes,0,,Yes,,,Yes,0,,No,,,No,,,,,,,,,,,,,,,No,,,Yes,,, +VOCABULARY,vocabulary_concept_id,Yes,0,,integer,0,,A Concept that represents the Vocabulary the VOCABULARY record belongs to.,,No,,,Yes,0,,CONCEPT,CONCEPT_ID,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, VOCABULARY,vocabulary_id,Yes,0,,varchar(20),0,,"A unique identifier for each Vocabulary, such -as ICD9CM, SNOMED, Visit.",,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +as ICD9CM, SNOMED, Visit.",,Yes,0,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, VOCABULARY,vocabulary_name,Yes,0,,varchar(255),0,,"The name describing the vocabulary, for example, International Classification of Diseases, Ninth Revision, Clinical -Modification, Volume 1 and 2 (NCHS) etc.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +Modification, Volume 1 and 2 (NCHS) etc.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, VOCABULARY,vocabulary_reference,No,,,varchar(255),0,,"External reference to documentation or available download of the about the -vocabulary.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, +vocabulary.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, VOCABULARY,vocabulary_version,No,,,varchar(255),0,,"Version of the Vocabulary as indicated in -the source.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,, \ No newline at end of file +the source.",,No,,,No,,,,,,,,,,,No,,,No,,,No,,,No,,,No,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file diff --git a/inst/shinyApps/www/js/loadResults.js b/inst/shinyApps/www/js/loadResults.js index dc6dc33d..435a0540 100755 --- a/inst/shinyApps/www/js/loadResults.js +++ b/inst/shinyApps/www/js/loadResults.js @@ -81,6 +81,10 @@ function loadResults(results) { '' + d.EXECUTION_TIME + '' + '' + '' + + 'Not applicable reason:' + + '' + d.NOT_APPLICABLE_REASON + '' + + '' + + '' + 'SQL Query:' + '
' + d.QUERY_TEXT + '
' + '' + @@ -145,7 +149,7 @@ function loadResults(results) { "data": null, "defaultContent": '' }, - { data: function (d) { if (d.FAILED == 0) { return "PASS" } else { return "FAIL" } }, title: "STATUS", className: 'dt-body-right' }, + { data: function (d) { if (d.IS_ERROR == 1) { return "ERROR" } else if (d.NOT_APPLICABLE == 1) { return "NOT APPLICABLE" } else if (d.FAILED == 1) { return "FAIL" } else {return "PASS"} }, title: "STATUS", className: 'dt-body-right' }, /*{ data: function (d) { return d.CONTEXT ? d.CONTEXT : "None"; }, title: "CONTEXT" },*/ { data: "CDM_TABLE_NAME", title: "TABLE"}, { data: function (d) { return d.CDM_FIELD_NAME ? d.CDM_FIELD_NAME : "None"; }, title: "FIELD", visible: false }, diff --git a/inst/sql/sql_server/concept_plausible_gender.sql b/inst/sql/sql_server/concept_plausible_gender.sql index 8c559eef..a2ecfea1 100755 --- a/inst/sql/sql_server/concept_plausible_gender.sql +++ b/inst/sql/sql_server/concept_plausible_gender.sql @@ -23,6 +23,7 @@ FROM SELECT COUNT_BIG(*) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable INNER JOIN @cdmDatabaseSchema.person p @@ -33,9 +34,9 @@ FROM ON cdmTable.PERSON_ID = c.SUBJECT_ID AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } - WHERE cdmTable.@cdmFieldName = @conceptId AND p.gender_concept_id <> {@plausibleGender == 'Male'} ? {8507} : {8532} + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/concept_plausible_value_high.sql b/inst/sql/sql_server/concept_plausible_value_high.sql index d5c7ae94..19775e1d 100755 --- a/inst/sql/sql_server/concept_plausible_value_high.sql +++ b/inst/sql/sql_server/concept_plausible_value_high.sql @@ -24,6 +24,7 @@ FROM SELECT COUNT_BIG(*) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT m.* FROM @cdmDatabaseSchema.@cdmTableName m {@cohort}?{ @@ -35,6 +36,7 @@ FROM AND m.unit_concept_id = @unitConceptId AND m.value_as_number IS NOT NULL AND m.value_as_number > @plausibleValueHigh + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/concept_plausible_value_low.sql b/inst/sql/sql_server/concept_plausible_value_low.sql index f7921e4d..c35e9bb9 100755 --- a/inst/sql/sql_server/concept_plausible_value_low.sql +++ b/inst/sql/sql_server/concept_plausible_value_low.sql @@ -23,6 +23,7 @@ FROM SELECT COUNT_BIG(*) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT m.* FROM @cdmDatabaseSchema.@cdmTableName m {@cohort}?{ @@ -34,6 +35,7 @@ FROM AND m.unit_concept_id = @unitConceptId AND m.value_as_number IS NOT NULL AND m.value_as_number < @plausibleValueLow + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_cdm_datatype.sql b/inst/sql/sql_server/field_cdm_datatype.sql index e0a8d2a5..3d4783e3 100755 --- a/inst/sql/sql_server/field_cdm_datatype.sql +++ b/inst/sql/sql_server/field_cdm_datatype.sql @@ -18,9 +18,11 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable WHERE ISNUMERIC(abs(cdmTable.@cdmFieldName)) = 0 AND cdmTable.@cdmFieldName IS NOT NULL + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_concept_record_completeness.sql b/inst/sql/sql_server/field_concept_record_completeness.sql index 2b38f692..5a023c60 100755 --- a/inst/sql/sql_server/field_concept_record_completeness.sql +++ b/inst/sql/sql_server/field_concept_record_completeness.sql @@ -1,7 +1,6 @@ /********* CONCEPT_RECORD_COMPLETENESS -number of 0s / total number of records {@cdmTableName in ('OBSERVATION', 'MEASUREMENT')}?{*for the OBSERVATION.unit_concept_id and MEASUREMENT.unit_concept_id -the numerator and denominator are limited to records where value_as_number IS NOT NULL} +number of 0s / total number of records {@cdmTableName == 'OBSERVATION' | @cdmTableName == 'MEASUREMENT'}?{* for the OBSERVATION.unit_concept_id and MEASUREMENT.unit_concept_id the numerator and denominator are limited to records where value_as_number IS NOT NULL} Parameters used in this template: cdmDatabaseSchema = @cdmDatabaseSchema @@ -20,6 +19,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -27,7 +27,8 @@ FROM ON cdmTable.PERSON_ID = c.SUBJECT_ID AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } - WHERE cdmTable.@cdmFieldName = 0 {@cdmFieldName in ('UNIT_CONCEPT_ID') AND @cdmTableName in ('MEASUREMENT')}?{AND cdmTable.value_as_number IS NOT NULL} + WHERE cdmTable.@cdmFieldName = 0 {@cdmFieldName == 'UNIT_CONCEPT_ID' & (@cdmTableName == 'MEASUREMENT' | @cdmTableName == 'OBSERVATION')}?{AND cdmTable.value_as_number IS NOT NULL} + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( @@ -38,6 +39,6 @@ FROM ON cdmTable.PERSON_ID = c.SUBJECT_ID AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } - {@cdmFieldName in ('UNIT_CONCEPT_ID') AND @cdmTableName in ('MEASUREMENT')}?{WHERE cdmTable.value_as_number IS NOT NULL} + {@cdmFieldName == 'UNIT_CONCEPT_ID' & (@cdmTableName == 'MEASUREMENT' | @cdmTableName == 'OBSERVATION')}?{WHERE cdmTable.value_as_number IS NOT NULL} ) denominator ; diff --git a/inst/sql/sql_server/field_fk_class.sql b/inst/sql/sql_server/field_fk_class.sql index 52b6cce3..ef833778 100755 --- a/inst/sql/sql_server/field_fk_class.sql +++ b/inst/sql/sql_server/field_fk_class.sql @@ -23,6 +23,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable LEFT JOIN @vocabDatabaseSchema.concept co @@ -33,6 +34,7 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } WHERE co.concept_id != 0 AND (co.concept_class_id != '@fkClass') + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_fk_domain.sql b/inst/sql/sql_server/field_fk_domain.sql index 29bebc99..7bc7afcb 100755 --- a/inst/sql/sql_server/field_fk_domain.sql +++ b/inst/sql/sql_server/field_fk_domain.sql @@ -23,6 +23,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable LEFT JOIN @vocabDatabaseSchema.concept co @@ -33,7 +34,7 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } WHERE co.concept_id != 0 AND co.domain_id NOT IN ('@fkDomain') - + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_is_not_nullable.sql b/inst/sql/sql_server/field_is_not_nullable.sql index 88de4848..c126db88 100755 --- a/inst/sql/sql_server/field_is_not_nullable.sql +++ b/inst/sql/sql_server/field_is_not_nullable.sql @@ -22,6 +22,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -30,6 +31,7 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } WHERE cdmTable.@cdmFieldName IS NULL + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_is_primary_key.sql b/inst/sql/sql_server/field_is_primary_key.sql index 29f0a5a1..5965a167 100755 --- a/inst/sql/sql_server/field_is_primary_key.sql +++ b/inst/sql/sql_server/field_is_primary_key.sql @@ -22,6 +22,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -32,7 +33,8 @@ FROM WHERE cdmTable.@cdmFieldName IN ( SELECT @cdmFieldName FROM @cdmDatabaseSchema.@cdmTableName GROUP BY @cdmFieldName - HAVING COUNT_BIG(*) > 1 ) + HAVING COUNT_BIG(*) > 1 ) + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_is_standard_valid_concept.sql b/inst/sql/sql_server/field_is_standard_valid_concept.sql index 13f532a4..f7b4d011 100755 --- a/inst/sql/sql_server/field_is_standard_valid_concept.sql +++ b/inst/sql/sql_server/field_is_standard_valid_concept.sql @@ -22,6 +22,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -30,7 +31,8 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } join @vocabDatabaseSchema.concept co ON cdmTable.@cdmFieldName = co.concept_id - WHERE co.concept_id != 0 AND (co.standard_concept != 'S' OR co.invalid_reason IS NOT NULL ) + WHERE co.concept_id != 0 AND (co.standard_concept != 'S' OR co.invalid_reason IS NOT NULL ) + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_measure_value_completeness.sql b/inst/sql/sql_server/field_measure_value_completeness.sql index 98eadcf3..ed8bfc0b 100755 --- a/inst/sql/sql_server/field_measure_value_completeness.sql +++ b/inst/sql/sql_server/field_measure_value_completeness.sql @@ -21,6 +21,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -29,6 +30,7 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } WHERE cdmTable.@cdmFieldName IS NULL + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_plausible_during_life.sql b/inst/sql/sql_server/field_plausible_during_life.sql index 8322039e..365c5dea 100755 --- a/inst/sql/sql_server/field_plausible_during_life.sql +++ b/inst/sql/sql_server/field_plausible_during_life.sql @@ -21,6 +21,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* from @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -29,7 +30,8 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } join @cdmDatabaseSchema.death de on cdmTable.person_id = de.person_id - where cast(cdmTable.@cdmFieldName as date) > dateadd(day, 60, cast(de.death_date as date)) + where cast(cdmTable.@cdmFieldName as date) > dateadd(day, 60, cast(de.death_date as date)) + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_plausible_temporal_after.sql b/inst/sql/sql_server/field_plausible_temporal_after.sql index 4e9e6b58..2949cf6f 100755 --- a/inst/sql/sql_server/field_plausible_temporal_after.sql +++ b/inst/sql/sql_server/field_plausible_temporal_after.sql @@ -22,6 +22,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cdmDatabaseSchema.@cdmTableName != @cdmDatabaseSchema.@plausibleTemporalAfterTableName}?{ @@ -31,7 +32,13 @@ FROM JOIN @cohortDatabaseSchema.COHORT c ON cdmTable.PERSON_ID = c.SUBJECT_ID AND c.COHORT_DEFINITION_ID = @cohortDefinitionId} - WHERE cast(@plausibleTemporalAfterFieldName as date) > cast(cdmTable.@cdmFieldName as date) + WHERE + {'@plausibleTemporalAfterTableName' == 'PERSON'}?{ + COALESCE(CAST(plausibleTable.@plausibleTemporalAfterFieldName AS DATE),CAST(CONCAT(plausibleTable.YEAR_OF_BIRTH,'-06-01') AS DATE)) + }:{ + CAST(cdmTable.@plausibleTemporalAfterFieldName AS DATE) + } > CAST(cdmTable.@cdmFieldName AS DATE) + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_plausible_value_high.sql b/inst/sql/sql_server/field_plausible_value_high.sql index 05fc48ad..d7e2d73c 100755 --- a/inst/sql/sql_server/field_plausible_value_high.sql +++ b/inst/sql/sql_server/field_plausible_value_high.sql @@ -21,6 +21,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* from @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -33,6 +34,7 @@ FROM }:{ where cdmTable.@cdmFieldName > @plausibleValueHigh } + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_plausible_value_low.sql b/inst/sql/sql_server/field_plausible_value_low.sql index 6b94debd..a42b9c11 100755 --- a/inst/sql/sql_server/field_plausible_value_low.sql +++ b/inst/sql/sql_server/field_plausible_value_low.sql @@ -21,6 +21,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* from @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -33,6 +34,7 @@ FROM }:{ where cdmTable.@cdmFieldName < @plausibleValueLow } + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_source_value_completeness.sql b/inst/sql/sql_server/field_source_value_completeness.sql index 8bc7f5b0..408b7c9e 100755 --- a/inst/sql/sql_server/field_source_value_completeness.sql +++ b/inst/sql/sql_server/field_source_value_completeness.sql @@ -20,6 +20,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT DISTINCT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.@cdmFieldName FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -28,6 +29,7 @@ FROM AND c.COHORT_DEFINITION_ID = @cohortDefinitionId } WHERE cdmTable.@standardConceptFieldName = 0 + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/field_within_visit_dates.sql b/inst/sql/sql_server/field_within_visit_dates.sql new file mode 100644 index 00000000..5d0b7b68 --- /dev/null +++ b/inst/sql/sql_server/field_within_visit_dates.sql @@ -0,0 +1,48 @@ +/********* +FIELD LEVEL check: +WITHIN_VISIT_DATES - find events that occur one week before the corresponding visit_start_date or one week after the corresponding visit_end_date + +Parameters used in this template: +cdmDatabaseSchema = @cdmDatabaseSchema +cdmTableName = @cdmTableName +cdmFieldName = @cdmFieldName +{@cohort & '@runForCohort' == 'Yes'}?{ +cohortDefinitionId = @cohortDefinitionId +cohortDatabaseSchema = @cohortDatabaseSchema +} +**********/ + + +SELECT num_violated_rows, + CASE WHEN denominator.num_rows = 0 THEN 0 ELSE 1.0*num_violated_rows/denominator.num_rows END AS pct_violated_rows, + denominator.num_rows as num_denominator_rows +FROM +( + SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows + FROM + ( + /*violatedRowsBegin*/ + SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* + FROM @cdmDatabaseSchema.@cdmTableName cdmTable + {@cohort & '@runForCohort' == 'Yes'}?{ + JOIN @cohortDatabaseSchema.cohort c + ON cdmTable.person_id = c.subject_id + AND c.cohort_definition_id = @cohortDefinitionId + } + JOIN @cdmDatabaseSchema.visit_occurrence vo + ON cdmTable.visit_occurrence_id = vo.visit_occurrence_id + WHERE cdmTable.@cdmFieldName < dateadd(day, -7, vo.visit_start_date) + OR cdmTable.@cdmFieldName > dateadd(day, 7, vo.visit_end_date) + /*violatedRowsEnd*/ + ) violated_rows +) violated_row_count, +( + SELECT COUNT_BIG(*) AS num_rows + FROM @cdmDatabaseSchema.@cdmTableName cdmTable + {@cohort & '@runForCohort' == 'Yes'}?{ + JOIN @cohortDatabaseSchema.cohort c + ON cdmTable.person_id = c.subject_id + AND c.cohort_definition_id = @cohortDefinitionId + } +) denominator +; \ No newline at end of file diff --git a/inst/sql/sql_server/is_foreign_key.sql b/inst/sql/sql_server/is_foreign_key.sql index 9b4589a2..3234f5f6 100755 --- a/inst/sql/sql_server/is_foreign_key.sql +++ b/inst/sql/sql_server/is_foreign_key.sql @@ -24,6 +24,7 @@ FROM SELECT COUNT_BIG(violated_rows.violating_field) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT '@cdmTableName.@cdmFieldName' AS violating_field, cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -33,7 +34,8 @@ FROM } LEFT JOIN {'@fkTableName' IN ('CONCEPT','DOMAIN')}?{@vocabDatabaseSchema.@fkTableName}:{@cdmDatabaseSchema.@fkTableName} fkTable ON cdmTable.@cdmFieldName = fkTable.@fkFieldName - WHERE fkTable.@fkFieldName IS NULL AND cdmTable.@cdmFieldName IS NOT NULL + WHERE fkTable.@fkFieldName IS NULL AND cdmTable.@cdmFieldName IS NOT NULL + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/result_dataframe_ddl.sql b/inst/sql/sql_server/result_dataframe_ddl.sql index eb341810..f35ceab4 100644 --- a/inst/sql/sql_server/result_dataframe_ddl.sql +++ b/inst/sql/sql_server/result_dataframe_ddl.sql @@ -24,7 +24,11 @@ CREATE TABLE @tableName warning varchar(255), error varchar(8000), checkid varchar(1024), + is_error integer, + not_applicable integer, failed integer, + passed integer, + not_applicable_reason varchar(8000), threshold_value integer, notes_value varchar(8000) ); \ No newline at end of file diff --git a/inst/sql/sql_server/result_table_ddl_concept.sql b/inst/sql/sql_server/result_table_ddl_concept.sql index 2d9b289c..97c7928e 100644 --- a/inst/sql/sql_server/result_table_ddl_concept.sql +++ b/inst/sql/sql_server/result_table_ddl_concept.sql @@ -18,7 +18,11 @@ CREATE TABLE @tableName subcategory varchar(255), context varchar(255), checkid varchar(1024), + is_error integer, + not_applicable integer, failed integer, + passed integer, + not_applicable_reason varchar(8000), threshold_value integer, notes_value varchar(8000), x_row varchar(255), diff --git a/inst/sql/sql_server/result_table_ddl_field.sql b/inst/sql/sql_server/result_table_ddl_field.sql index 9e56d0e9..36971a29 100644 --- a/inst/sql/sql_server/result_table_ddl_field.sql +++ b/inst/sql/sql_server/result_table_ddl_field.sql @@ -19,7 +19,11 @@ CREATE TABLE @tableName subcategory varchar(255), context varchar(255), checkid varchar(1024), + is_error integer, + not_applicable integer, failed integer, + passed integer, + not_applicable_reason varchar(8000), threshold_value integer, notes_value varchar(8000), x_row varchar(255) diff --git a/inst/sql/sql_server/result_table_ddl_table.sql b/inst/sql/sql_server/result_table_ddl_table.sql index fedc728d..c88661fa 100644 --- a/inst/sql/sql_server/result_table_ddl_table.sql +++ b/inst/sql/sql_server/result_table_ddl_table.sql @@ -18,7 +18,11 @@ CREATE TABLE @tableName subcategory varchar(255), context varchar(255), checkid varchar(1024), + is_error integer, + not_applicable integer, failed integer, + passed integer, + not_applicable_reason varchar(8000), threshold_value integer, notes_value varchar(8000), x_row varchar(255) diff --git a/inst/sql/sql_server/table_cdm_table.sql b/inst/sql/sql_server/table_cdm_table.sql new file mode 100644 index 00000000..0fe25fa3 --- /dev/null +++ b/inst/sql/sql_server/table_cdm_table.sql @@ -0,0 +1,29 @@ + +/********* +TABLE LEVEL check: +CDM_TABLE - verify the table exists + +Parameters used in this template: +cdmDatabaseSchema = @cdmDatabaseSchema +cdmTableName = @cdmTableName + +**********/ + + +SELECT num_violated_rows, CASE WHEN denominator.num_rows = 0 THEN 0 ELSE 1.0*num_violated_rows/denominator.num_rows END AS pct_violated_rows, + denominator.num_rows as num_denominator_rows +FROM +( + select num_violated_rows from + ( + select + case when count_big(*) = 0 then 0 + else 0 + end as num_violated_rows + from @cdmDatabaseSchema.@cdmTableName cdmTable + ) violated_rows +) violated_row_count, +( + SELECT 1 as num_rows +) denominator +; \ No newline at end of file diff --git a/inst/sql/sql_server/table_concept_completeness.sql b/inst/sql/sql_server/table_concept_completeness.sql index 5d059b57..e62a4e40 100755 --- a/inst/sql/sql_server/table_concept_completeness.sql +++ b/inst/sql/sql_server/table_concept_completeness.sql @@ -24,6 +24,7 @@ FROM SELECT COUNT_BIG(*) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT cdmTable.* FROM @cdmDatabaseSchema.@cdmTableName cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -33,6 +34,7 @@ FROM } WHERE (cdmTable.@cdmFieldName = 0 OR cdmTable.@cdmFieldName IS NULL) AND (cdmTable.@cdmSourceFieldName = 0 OR cdmTable.@cdmSourceFieldName IS NULL) + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/inst/sql/sql_server/table_person_completeness.sql b/inst/sql/sql_server/table_person_completeness.sql index 2b95f38d..48d8ec00 100755 --- a/inst/sql/sql_server/table_person_completeness.sql +++ b/inst/sql/sql_server/table_person_completeness.sql @@ -21,6 +21,7 @@ FROM SELECT COUNT_BIG(violated_rows.person_id) AS num_violated_rows FROM ( + /*violatedRowsBegin*/ SELECT cdmTable.* FROM @cdmDatabaseSchema.person cdmTable {@cohort & '@runForCohort' == 'Yes'}?{ @@ -31,6 +32,7 @@ FROM LEFT JOIN @cdmDatabaseSchema.@cdmTableName cdmTable2 ON cdmTable.person_id = cdmTable2.person_id WHERE cdmTable2.person_id IS NULL + /*violatedRowsEnd*/ ) violated_rows ) violated_row_count, ( diff --git a/man/executeDqChecks.Rd b/man/executeDqChecks.Rd index f8079c3f..91d0aed5 100644 --- a/man/executeDqChecks.Rd +++ b/man/executeDqChecks.Rd @@ -21,7 +21,8 @@ executeDqChecks( checkNames = c(), cohortDefinitionId = c(), cohortDatabaseSchema = resultsDatabaseSchema, - tablesToExclude = c(), + tablesToExclude = c("CONCEPT", "VOCABULARY", "CONCEPT_ANCESTOR", + "CONCEPT_RELATIONSHIP", "CONCEPT_CLASS", "CONCEPT_SYNONYM", "RELATIONSHIP", "DOMAIN"), cdmVersion = "5.3.1", tableCheckThresholdLoc = "default", fieldCheckThresholdLoc = "default", diff --git a/vignettes/DataQualityDashboard.html b/vignettes/DataQualityDashboard.html index ca31c8f0..ca153725 100644 --- a/vignettes/DataQualityDashboard.html +++ b/vignettes/DataQualityDashboard.html @@ -212,8 +212,8 @@

Getting Started

R Installation

-
install.packages("devtools")
-devtools::install_github("OHDSI/DataQualityDashboard")
+
install.packages("remotes")
+remotes::install_github("OHDSI/DataQualityDashboard")
 

Note

@@ -243,7 +243,6 @@

Executing Data Quality Checks

# where should the logs go? ------------------------------------------------------------------------- outputFolder <- "output" -outputFile <- "results.json" # logging type ------------------------------------------------------------------------------------- verboseMode <- FALSE # set to TRUE if you want to see activity written to the console @@ -266,11 +265,7 @@

Executing Data Quality Checks

# which DQ checks to run? ------------------------------------ -checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Desciptions.csv - -# which CDM tables to exclude? ------------------------------------ - -tablesToExclude <- c() +checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Descriptions.csv # run the job -------------------------------------------------------------------------------------- DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, @@ -284,7 +279,6 @@

Executing Data Quality Checks

verboseMode = verboseMode, writeToTable = writeToTable, checkLevels = checkLevels, - tablesToExclude = tablesToExclude, checkNames = checkNames) # inspect logs ---------------------------------------------------------------------------- @@ -304,9 +298,7 @@

Viewing Results

Launching Dashboard as Shiny App

-
DataQualityDashboard::viewDqDashboard(
-  jsonPath = file.path(getwd(), outputFolder, cdmSourceName, outputFile, cdmSourceName))
-)
+
DataQualityDashboard::viewDqDashboard(jsonFilePath)
 

Launching on a web server

diff --git a/vignettes/DataQualityDashboard.md b/vignettes/DataQualityDashboard.md index aa5b3205..0d153ef1 100644 --- a/vignettes/DataQualityDashboard.md +++ b/vignettes/DataQualityDashboard.md @@ -1,13 +1,13 @@ --- title: "Getting Started" author: "Clair Blacketer" -date: "2021-06-16" +date: "2022-03-31" header-includes: - \usepackage{fancyhdr} - \pagestyle{fancy} - \fancyhead{} - \fancyhead[CO,CE]{Getting Started} - - \fancyfoot[CO,CE]{DataQualityDashboard Package Version 1.0.0} + - \fancyfoot[CO,CE]{DataQualityDashboard Package Version 1.4.0} - \fancyfoot[LE,RO]{\thepage} - \renewcommand{\headrulewidth}{0.4pt} - \renewcommand{\footrulewidth}{0.4pt} @@ -29,8 +29,8 @@ R Installation =============== ```r -install.packages("devtools") -devtools::install_github("OHDSI/DataQualityDashboard") +install.packages("remotes") +remotes::install_github("OHDSI/DataQualityDashboard") ``` Note @@ -62,7 +62,6 @@ sqlOnly <- FALSE # set to TRUE if you just want to get the SQL scripts and not a # where should the logs go? ------------------------------------------------------------------------- outputFolder <- "output" -outputFile <- "results.json" # logging type ------------------------------------------------------------------------------------- verboseMode <- FALSE # set to TRUE if you want to see activity written to the console @@ -85,11 +84,7 @@ checkLevels <- c("TABLE", "FIELD", "CONCEPT") # which DQ checks to run? ------------------------------------ -checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Desciptions.csv - -# which CDM tables to exclude? ------------------------------------ - -tablesToExclude <- c() +checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Descriptions.csv # run the job -------------------------------------------------------------------------------------- DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, @@ -103,7 +98,6 @@ DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, verboseMode = verboseMode, writeToTable = writeToTable, checkLevels = checkLevels, - tablesToExclude = tablesToExclude, checkNames = checkNames) # inspect logs ---------------------------------------------------------------------------- @@ -124,9 +118,7 @@ Viewing Results **Launching Dashboard as Shiny App** ```r -DataQualityDashboard::viewDqDashboard( - jsonPath = file.path(getwd(), outputFolder, cdmSourceName, outputFile, cdmSourceName)) -) +DataQualityDashboard::viewDqDashboard(jsonFilePath) ``` **Launching on a web server** diff --git a/vignettes/DataQualityDashboard.rmd b/vignettes/DataQualityDashboard.rmd index 11f4251d..d8db5828 100644 --- a/vignettes/DataQualityDashboard.rmd +++ b/vignettes/DataQualityDashboard.rmd @@ -29,8 +29,8 @@ R Installation =============== ```r -install.packages("devtools") -devtools::install_github("OHDSI/DataQualityDashboard") +install.packages("remotes") +remotes::install_github("OHDSI/DataQualityDashboard") ``` Note @@ -62,7 +62,6 @@ sqlOnly <- FALSE # set to TRUE if you just want to get the SQL scripts and not a # where should the logs go? ------------------------------------------------------------------------- outputFolder <- "output" -outputFile <- "results.json" # logging type ------------------------------------------------------------------------------------- verboseMode <- FALSE # set to TRUE if you want to see activity written to the console @@ -85,11 +84,7 @@ checkLevels <- c("TABLE", "FIELD", "CONCEPT") # which DQ checks to run? ------------------------------------ -checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Desciptions.csv - -# which CDM tables to exclude? ------------------------------------ - -tablesToExclude <- c() +checkNames <- c() # Names can be found in inst/csv/OMOP_CDM_v5.3.1_Check_Descriptions.csv # run the job -------------------------------------------------------------------------------------- DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, @@ -103,7 +98,6 @@ DataQualityDashboard::executeDqChecks(connectionDetails = connectionDetails, verboseMode = verboseMode, writeToTable = writeToTable, checkLevels = checkLevels, - tablesToExclude = tablesToExclude, checkNames = checkNames) # inspect logs ---------------------------------------------------------------------------- @@ -124,9 +118,7 @@ Viewing Results **Launching Dashboard as Shiny App** ```r -DataQualityDashboard::viewDqDashboard( - jsonPath = file.path(getwd(), outputFolder, cdmSourceName, outputFile, cdmSourceName)) -) +DataQualityDashboard::viewDqDashboard(jsonFilePath) ``` **Launching on a web server** From fa0ee90da6aaf21c69f069dd54291d6981eba097 Mon Sep 17 00:00:00 2001 From: Luis Alberto Alaniz Castillo Date: Sat, 6 Aug 2022 15:44:20 -0600 Subject: [PATCH 4/6] Shyni viewer compatible with version 1 of DQD --- inst/ResultsV2/load_data_10.R | 475 +++++++++++++++++++--------------- inst/ResultsV2/server.r | 387 +++++++++++++++++---------- 2 files changed, 510 insertions(+), 352 deletions(-) diff --git a/inst/ResultsV2/load_data_10.R b/inst/ResultsV2/load_data_10.R index 33999313..f801cbda 100644 --- a/inst/ResultsV2/load_data_10.R +++ b/inst/ResultsV2/load_data_10.R @@ -11,7 +11,10 @@ data <- data.frame(fromJSON(jsonFilePath)) data <- tibble(data) dataT <- select(data, contains("CheckResults")) %>% - rename_(.dots = setNames(names(.), gsub("CheckResults.", "", names(.)))) + rename_(.dots = setNames(names(.), gsub("CheckResults.", "", names(.)))) %>% + rename(any_of(c(N.A. = "NOT_APPLICABLE"))) # any_of(C()) works even if a +# variable does not exists +# https://stackoverflow.com/questions/68965823/rename-only-if-field-exists-otherwise-ignore ################################################ #### TIBBLE OVERVIEW #### @@ -20,7 +23,7 @@ dataT <- select(data, contains("CheckResults")) %>% summaryParts1 <- function(data_tab, variable) { part <- select(data_tab, - c(CATEGORY, CONTEXT, PASSED, FAILED, NOT_APPLICABLE, IS_ERROR)) %>% + c(CATEGORY, CONTEXT, PASSED, FAILED, N.A., IS_ERROR)) %>% mutate(CATEGORY = as.factor(CATEGORY)) %>% mutate(CONTEXT = as.factor(CONTEXT)) %>% group_by(CATEGORY, CONTEXT) %>% @@ -34,10 +37,10 @@ summaryParts1 <- function(data_tab, variable) { mutate(Total = Validation + Verification) } -summaryParts2 <- function(data_tab, variable) { +summaryParts2Sum <- function(data_tab, variable) { part <- select(data_tab, - c(CATEGORY, CONTEXT, PASSED, FAILED, NOT_APPLICABLE, IS_ERROR)) %>% + c(CATEGORY, CONTEXT, FAILED)) %>% mutate(CATEGORY = as.factor(CATEGORY)) %>% mutate(CONTEXT = as.factor(CONTEXT)) %>% group_by(CATEGORY, CONTEXT) %>% @@ -50,84 +53,145 @@ summaryParts2 <- function(data_tab, variable) { ungroup() } -# Checks if a string is in column name -# https://stackoverflow.com/questions/60978376/r-to-identify-whether-column-names-in-a-dataframe-contains-string -checkString <- function(dat, pat) any(grepl(pat, dat$CONTEXT)) +summaryParts2Count <- function(data_tab) { + part <- + select(data_tab, + c(CATEGORY, CONTEXT, FAILED)) %>% + mutate(CATEGORY = as.factor(CATEGORY)) %>% + mutate(CONTEXT = as.factor(CONTEXT)) %>% + group_by(CATEGORY, CONTEXT) %>% + dplyr::summarise("count" := n()) %>% + spread(CONTEXT, count) %>% + ungroup() +} -if (checkString(dataT, "Validation")) { - part1 <- summaryParts1(dataT, PASSED) - - part1 <- dplyr::rename(part1, Validation.Pass = Validation) %>% - dplyr::rename(Verification.Pass = Verification) %>% - dplyr::rename(Total.Pass = Total) - - part2 <- summaryParts1(dataT, FAILED) - - part2 <- dplyr::rename(part2, Validation.Fail = Validation) %>% - dplyr::rename(Verification.Fail = Verification) %>% - dplyr::rename(Total.Fail = Total) - - part3 <- summaryParts1(dataT, NOT_APPLICABLE) - - part3 <- dplyr::rename(part3, Validation.Not_Applicable = Validation) %>% - dplyr::rename(Verification.Not_Applicable = Verification) %>% - dplyr::rename(Total.Not_Applicable = Total) - - part4 <- summaryParts1(dataT, IS_ERROR) - - part4 <- dplyr::rename(part4, Validation.Error = Validation) %>% - dplyr::rename(Verification.Error = Verification) %>% - dplyr::rename(Total.Error = Total) - - data1 <- inner_join(part1, part2, by = "CATEGORY") - data1 <- inner_join(data1, part3, by = "CATEGORY") - data1 <- inner_join(data1, part4, by = "CATEGORY") - - data1 <- - mutate(data1, Validation.PctPass = (Validation.Pass / (Validation.Pass + Validation.Fail)) * - 100) %>% - mutate(Verification.PctPass = (Verification.Pass / (Verification.Pass + Verification.Fail)) * - 100) %>% - mutate(Total.PctPass = (Total.Pass / (Total.Pass + Total.Fail)) * 100) %>% - adorn_totals() - - data1$Validation.PctPass[4] = (data1$Validation.Pass[4] / (data1$Validation.Pass[4] + data1$Validation.Fail[4])) * - 100 - data1$Verification.PctPass[4] = (data1$Verification.Pass[4] / (data1$Verification.Pass[4] + data1$Verification.Fail[4])) * - 100 - data1$Total.PctPass[4] = (data1$Total.Pass[4] / (data1$Total.Pass[4] + data1$Total.Fail[4])) * - 100 -} else{ - part1 <- summaryParts2(dataT, PASSED) - - part1 <- dplyr::rename(part1, Verification.Pass = Verification) - - part2 <- summaryParts2(dataT, FAILED) - - part2 <- dplyr::rename(part2, Verification.Fail = Verification) - - part3 <- summaryParts2(dataT, NOT_APPLICABLE) - - part3 <- dplyr::rename(part3, Verification.Not_Applicable = Verification) - - part4 <- summaryParts2(dataT, IS_ERROR) - - part4 <- dplyr::rename(part4, Verification.Error = Verification) - - - data1 <- inner_join(part1, part2, by = "CATEGORY") - data1 <- inner_join(data1, part3, by = "CATEGORY") - data1 <- inner_join(data1, part4, by = "CATEGORY") - - data1 <- - mutate(data1, Verification.PctPass = (Verification.Pass / (Verification.Pass + Verification.Fail)) * - 100) %>% - adorn_totals() - - data1$Verification.PctPass[3] = (data1$Verification.Pass[3] / (data1$Verification.Pass[3] + data1$Verification.Fail[3])) * - 100 +summaryParts3 <- function(data_tab, variable) { + part <- + select(data_tab, + c(CATEGORY, CONTEXT, PASSED, FAILED, N.A., IS_ERROR)) %>% + mutate(CATEGORY = as.factor(CATEGORY)) %>% + mutate(CONTEXT = as.factor(CONTEXT)) %>% + group_by(CATEGORY, CONTEXT) %>% + dplyr::summarise("sum" := sum({ + { + variable + } + })) %>% + spread(CONTEXT, sum) %>% + ungroup() } +summaryParts4 <- function(data_tab, variable) { + part <- + select(data_tab, + c(CATEGORY, CONTEXT, FAILED)) %>% + mutate(CATEGORY = as.factor(CATEGORY)) %>% + mutate(CONTEXT = as.factor(CONTEXT)) %>% + group_by(CATEGORY, CONTEXT) %>% + dplyr::summarise("sum" := sum({ + { + variable + } + })) %>% + spread(CONTEXT, sum) %>% + ungroup() +} + +# Checks if a string is in column name +# https://stackoverflow.com/questions/60978376/r-to-identify-whether-column-names-in-a-dataframe-contains-string +checkString <- function(dat, pat) + any(grepl(pat, dat$CONTEXT)) + + + + if ("N.A." %in% colnames(dataT)) { + part1 <- summaryParts1(dataT, PASSED) + + part1 <- dplyr::rename(part1, Validation.Pass = Validation) %>% + dplyr::rename(Verification.Pass = Verification) %>% + dplyr::rename(Total.Pass = Total) + + part2 <- summaryParts1(dataT, FAILED) + + part2 <- dplyr::rename(part2, Validation.Fail = Validation) %>% + dplyr::rename(Verification.Fail = Verification) %>% + dplyr::rename(Total.Fail = Total) + + part3 <- summaryParts1(dataT, N.A.) + + part3 <- dplyr::rename(part3, Validation.N.A. = Validation) %>% + dplyr::rename(Verification.N.A. = Verification) %>% + dplyr::rename(Total.N.A. = Total) + + part4 <- summaryParts1(dataT, IS_ERROR) + + part4 <- dplyr::rename(part4, Validation.Error = Validation) %>% + dplyr::rename(Verification.Error = Verification) %>% + dplyr::rename(Total.Error = Total) + + data1 <- inner_join(part1, part2, by = "CATEGORY") + data1 <- inner_join(data1, part3, by = "CATEGORY") + data1 <- inner_join(data1, part4, by = "CATEGORY") + + data1 <- + mutate(data1, Validation.PctPass = (Validation.Pass / (Validation.Pass + Validation.Fail)) * + 100) %>% + mutate(Verification.PctPass = ( + Verification.Pass / (Verification.Pass + Verification.Fail) + ) * + 100) %>% + mutate(Total.PctPass = (Total.Pass / (Total.Pass + Total.Fail)) * 100) %>% + adorn_totals() + + data1$Validation.PctPass[4] = ( + data1$Validation.Pass[4] / (data1$Validation.Pass[4] + data1$Validation.Fail[4])) * + 100 + data1$Verification.PctPass[4] = ( + data1$Verification.Pass[4] / (data1$Verification.Pass[4] + data1$Verification.Fail[4]) + ) * + 100 + data1$Total.PctPass[4] = (data1$Total.Pass[4] / (data1$Total.Pass[4] + data1$Total.Fail[4])) * + 100 + + } else { + part1 <- summaryParts2Sum(dataT, FAILED) + part2 <- summaryParts2Count(dataT) + + part1 <- dplyr::rename(part1, Validation.Fail = Validation) %>% + dplyr::rename(Verification.Fail = Verification) + + part2 <- dplyr::rename(part2, Validation.Total = Validation) %>% + dplyr::rename(Verification.Total = Verification) + + data1 <- inner_join(part1, part2, by = "CATEGORY") + + data1 <- + mutate(data1, + Validation.Pass = (Validation.Total - Validation.Fail)) %>% + mutate(Verification.Pass = (Verification.Total - Verification.Fail)) %>% + mutate(Total.Pass = Verification.Pass + Validation.Pass) %>% + mutate(Total.Fail = Verification.Fail + Validation.Fail) %>% + mutate(Total = Total.Pass + Total.Fail) %>% + mutate(Validation.PctPass = (Validation.Pass / (Validation.Pass + Validation.Fail)) * 100) %>% + mutate(Verification.PctPass = ( + Verification.Pass / (Verification.Pass + Verification.Fail) + ) * 100) %>% + mutate(Total.PctPass = (Total.Pass / (Total.Pass + Total.Fail)) * 100) %>% + select(!c(Validation.Total, Verification.Total, Total)) %>% + adorn_totals() + + data1$Validation.PctPass[4] = ( + data1$Validation.Pass[4] / (data1$Validation.Pass[4] + data1$Validation.Fail[4])) * + 100 + data1$Verification.PctPass[4] = ( + data1$Verification.Pass[4] / (data1$Verification.Pass[4] + data1$Verification.Fail[4]) + ) * + 100 + data1$Total.PctPass[4] = (data1$Total.Pass[4] / (data1$Total.Pass[4] + data1$Total.Fail[4])) * + 100 + + } + ################################################ #### TIBBLE TABLE CENTRIC PIVOT #### ################################################ @@ -136,141 +200,137 @@ getViolatedRowsQuery <- function(queryText) { stringr::str_match(string = queryText, pattern = "(?i)(\\/\\*violatedRowsBegin\\*\\/)(?s)(.*)(\\/\\*violatedRowsEnd\\*\\/)")[3] } -if (checkString(dataT, "Validation")) { - data2 <- mutate(dataT, CATEGORY = factor(CATEGORY)) %>% - mutate(SUBCATEGORY = if_else(SUBCATEGORY == "", "None", SUBCATEGORY)) %>% - mutate(SUBCATEGORY = factor(SUBCATEGORY)) %>% - mutate(CONTEXT = factor(CONTEXT)) %>% - mutate(CHECK_NAME = factor(CHECK_NAME)) %>% - mutate(CHECK_LEVEL = factor(CHECK_LEVEL)) %>% - replace_na( - list( - NUM_VIOLATED_ROWS = 0, - PCT_VIOLATED_ROWS = 0, - FAILED = 0, - IS_ERROR = 0, - NOT_APPLICABLE = 0, - THRESHOLD_VALUE = 0 - ) - ) %>% - replace_na(list(NUM_DENOMINATOR_ROWS = 1, PASSED = 0)) %>% - mutate(CHECKS = 1) %>% - mutate(PCT_PASSED = (PASSED / (PASSED + FAILED)) * 100) %>% - mutate(PCT_VIOLATED_ROWS = NUM_VIOLATED_ROWS / NUM_DENOMINATOR_ROWS * - 100) %>% - mutate(CHECK_STATUS = PASSED + 2 * FAILED + 3 * IS_ERROR + 4 * NOT_APPLICABLE) %>% - mutate(CHECK_LEVEL = recode_factor( - CHECK_LEVEL, - TABLE = "Table", - FIELD = "Field", - CONCEPT = "Concept" - )) %>% - mutate( - CHECK_STATUS = recode( + + if ("N.A." %in% colnames(dataT)) { + data2 <- mutate(dataT, CATEGORY = factor(CATEGORY)) %>% + mutate(SUBCATEGORY = if_else(SUBCATEGORY == "", "None", SUBCATEGORY)) %>% + mutate(SUBCATEGORY = factor(SUBCATEGORY)) %>% + mutate(CONTEXT = factor(CONTEXT)) %>% + mutate(CHECK_NAME = factor(CHECK_NAME)) %>% + mutate(CHECK_LEVEL = factor(CHECK_LEVEL)) %>% + replace_na( + list( + NUM_VIOLATED_ROWS = 0, + PCT_VIOLATED_ROWS = 0, + FAILED = 0, + IS_ERROR = 0, + N.A. = 0, + THRESHOLD_VALUE = 0 + ) + ) %>% + replace_na(list(NUM_DENOMINATOR_ROWS = 1, PASSED = 0)) %>% + mutate(CHECKS = 1) %>% + mutate(PCT_PASSED = (PASSED / (PASSED + FAILED)) * 100) %>% + mutate(PCT_VIOLATED_ROWS = NUM_VIOLATED_ROWS / NUM_DENOMINATOR_ROWS * + 100) %>% + mutate(CHECK_STATUS = PASSED + 2 * FAILED + 3 * IS_ERROR + 4 * N.A.) %>% + mutate(CHECK_LEVEL = recode_factor( + CHECK_LEVEL, + TABLE = "Table", + FIELD = "Field", + CONCEPT = "Concept" + )) %>% + mutate(CHECK_STATUS = recode( CHECK_STATUS, `1` = "Pass", `2` = "Fail", `3` = "Is Error", - `4` = "Not Applicable" - ) - ) %>% - select( - !c( - IS_ERROR, - NOT_APPLICABLE, - PASSED, - EXECUTION_TIME, - SQL_FILE, - CONCEPT_ID, - UNIT_CONCEPT_ID, - CDM_FIELD_NAME - ) - ) %>% - relocate( - CDM_TABLE_NAME, - CHECK_NAME, - checkId, - CHECK_DESCRIPTION, - CHECK_STATUS, - CATEGORY, - SUBCATEGORY, - CONTEXT, - CHECK_LEVEL, - FAILED, - CHECKS, - PCT_PASSED, - NUM_VIOLATED_ROWS, - NUM_DENOMINATOR_ROWS, - PCT_VIOLATED_ROWS, - THRESHOLD_VALUE - ) -} else{ - data2 <- mutate(dataT, CATEGORY = factor(CATEGORY)) %>% - mutate(SUBCATEGORY = if_else(SUBCATEGORY == "", "None", SUBCATEGORY)) %>% - mutate(SUBCATEGORY = factor(SUBCATEGORY)) %>% - mutate(CONTEXT = factor(CONTEXT)) %>% - mutate(CHECK_NAME = factor(CHECK_NAME)) %>% - mutate(CHECK_LEVEL = factor(CHECK_LEVEL)) %>% - replace_na( - list( - NUM_VIOLATED_ROWS = 0, - PCT_VIOLATED_ROWS = 0, - FAILED = 0, - IS_ERROR = 0, - NOT_APPLICABLE = 0, - THRESHOLD_VALUE = 0 + `4` = "N.A." + )) %>% + select( + !c( + IS_ERROR, + N.A., + PASSED, + EXECUTION_TIME, + SQL_FILE, + CONCEPT_ID, + UNIT_CONCEPT_ID, + CDM_FIELD_NAME + ) + ) %>% + relocate( + CDM_TABLE_NAME, + CHECK_NAME, + checkId, + CHECK_DESCRIPTION, + CHECK_STATUS, + CATEGORY, + SUBCATEGORY, + CONTEXT, + CHECK_LEVEL, + FAILED, + CHECKS, + PCT_PASSED, + NUM_VIOLATED_ROWS, + NUM_DENOMINATOR_ROWS, + PCT_VIOLATED_ROWS, + THRESHOLD_VALUE ) - ) %>% - replace_na(list(NUM_DENOMINATOR_ROWS = 1, PASSED = 0)) %>% - mutate(CHECKS = 1) %>% - mutate(PCT_PASSED = (PASSED / (PASSED + FAILED)) * 100) %>% - mutate(PCT_VIOLATED_ROWS = NUM_VIOLATED_ROWS / NUM_DENOMINATOR_ROWS * - 100) %>% - mutate(CHECK_STATUS = PASSED + 2 * FAILED + 3 * IS_ERROR + 4 * NOT_APPLICABLE) %>% - mutate(CHECK_LEVEL = recode_factor( - CHECK_LEVEL, - TABLE = "Table", - FIELD = "Field", - CONCEPT = "Concept" - )) %>% - mutate( - CHECK_STATUS = recode( + } else { + data2 <- mutate(dataT, CATEGORY = factor(CATEGORY)) %>% + mutate(SUBCATEGORY = if_else(SUBCATEGORY == "", "None", SUBCATEGORY)) %>% + mutate(SUBCATEGORY = factor(SUBCATEGORY)) %>% + mutate(CONTEXT = factor(CONTEXT)) %>% + mutate(CHECK_NAME = factor(CHECK_NAME)) %>% + mutate(CHECK_LEVEL = factor(CHECK_LEVEL)) %>% + replace_na( + list( + NUM_VIOLATED_ROWS = 0, + PCT_VIOLATED_ROWS = 0, + FAILED = 0, + IS_ERROR = 0, + N.A. = 0, + THRESHOLD_VALUE = 0 + ) + ) %>% + replace_na(list(NUM_DENOMINATOR_ROWS = 1, PASSED = 0)) %>% + mutate(CHECKS = 1) %>% + mutate(PASSED = (CHECKS - FAILED)) %>% + mutate(PCT_PASSED = (PASSED / CHECKS) * 100) %>% + mutate(PCT_VIOLATED_ROWS = NUM_VIOLATED_ROWS / NUM_DENOMINATOR_ROWS * + 100) %>% + mutate(CHECK_STATUS = PASSED + 2 * FAILED) %>% + mutate(CHECK_LEVEL = recode_factor( + CHECK_LEVEL, + TABLE = "Table", + FIELD = "Field", + CONCEPT = "Concept" + )) %>% + mutate(CHECK_STATUS = recode( CHECK_STATUS, `1` = "Pass", - `2` = "Fail", - `3` = "Is Error", - `4` = "Not Applicable" - ) - ) %>% - select( - !c( - IS_ERROR, - NOT_APPLICABLE, - PASSED, - EXECUTION_TIME, - SQL_FILE, - CDM_FIELD_NAME + `2` = "Fail" + )) %>% + select( + !c( + PASSED, + EXECUTION_TIME, + SQL_FILE, + CONCEPT_ID, + UNIT_CONCEPT_ID, + CDM_FIELD_NAME + ) + ) %>% + relocate( + CDM_TABLE_NAME, + CHECK_NAME, + checkId, + CHECK_DESCRIPTION, + CHECK_STATUS, + CATEGORY, + SUBCATEGORY, + CONTEXT, + CHECK_LEVEL, + FAILED, + CHECKS, + PCT_PASSED, + NUM_VIOLATED_ROWS, + NUM_DENOMINATOR_ROWS, + PCT_VIOLATED_ROWS, + THRESHOLD_VALUE ) - ) %>% - relocate( - CDM_TABLE_NAME, - CHECK_NAME, - checkId, - CHECK_DESCRIPTION, - CHECK_STATUS, - CATEGORY, - SUBCATEGORY, - CONTEXT, - CHECK_LEVEL, - FAILED, - CHECKS, - PCT_PASSED, - NUM_VIOLATED_ROWS, - NUM_DENOMINATOR_ROWS, - PCT_VIOLATED_ROWS, - THRESHOLD_VALUE - ) -} + } DQ_CHECK_SQL <- lapply(dataT$QUERY_TEXT, getViolatedRowsQuery) DQ_CHECK_SQL_1 <- ldply(DQ_CHECK_SQL) @@ -285,7 +345,4 @@ rm("DQ_CHECK_SQL", "DQ_CHECK_SQL_1") data2$FAILED <- as.integer(data2$FAILED) data2$CHECKS <- as.integer(data2$CHECKS) -rm("part1", "part2", "part3", "part4", "data") - #write.csv(data, "data3.csv") - diff --git a/inst/ResultsV2/server.r b/inst/ResultsV2/server.r index 139f50f6..c3cd57fd 100644 --- a/inst/ResultsV2/server.r +++ b/inst/ResultsV2/server.r @@ -4,7 +4,6 @@ library(htmlwidgets) library(htmltools) library(formattable) library(shinyWidgets) -# library(shinythemes) library(dplyr) source("load_data_10.R") @@ -13,144 +12,248 @@ server <- function(input, output) { #### Panel: Overview #### ################################################ if (checkString(dataT, "Validation")) { - output$summary_dt1 <- renderUI({ - reactable( - data1, - striped = TRUE, - highlight = TRUE, - bordered = TRUE, - theme = reactableTheme( - borderColor = "#dfe2e5", - # stripedColor = "#ecf0f1", - highlightColor = "#f0f5f9", - cellPadding = "8px 12px", - ), - rowStyle = function(index) { - if (index == 4) - list(fontWeight = "bold") - }, - columns = list( - CATEGORY = colDef(name = "Category", minWidth = 80), - Validation.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Verification.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Total.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Validation.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Verification.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Total.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Validation.Not_Applicable = colDef( - name = "Not Applicable", - minWidth = 60, - align = "center" - ), - Verification.Not_Applicable = colDef( - name = "Not Applicable", - minWidth = 60, - align = "center" - ), - Total.Not_Applicable = colDef( - name = "Not Applicable", - minWidth = 60, - align = "center" - ), - Validation.Error = colDef( - name = "Error", - minWidth = 60, - align = "center" + if ("N.A." %in% colnames(dataT)) { + output$summary_dt1 <- renderUI({ + reactable( + data1, + striped = TRUE, + highlight = TRUE, + bordered = TRUE, + theme = reactableTheme( + borderColor = "#dfe2e5", + # stripedColor = "#ecf0f1", + highlightColor = "#f0f5f9", + cellPadding = "8px 12px", ), - Verification.Error = colDef( - name = "Error", - minWidth = 60, - align = "center" - ), - Total.Error = colDef( - name = "Error", - minWidth = 60, - align = "center" - ), - Validation.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ), - Verification.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) + rowStyle = function(index) { + if (index == 4) + list(fontWeight = "bold") + }, + columns = list( + CATEGORY = colDef(name = "Category", minWidth = 80), + Validation.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Verification.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Total.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Validation.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Verification.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Total.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Validation.N.A. = colDef( + name = "N.A.", + minWidth = 60, + align = "center" + ), + Verification.N.A. = colDef( + name = "N.A.", + minWidth = 60, + align = "center" + ), + Total.N.A. = colDef( + name = "N.A.", + minWidth = 60, + align = "center" + ), + Validation.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Verification.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Total.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Validation.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Verification.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Total.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ) ), - Total.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ) - ), - columnGroups = list( - colGroup( - name = "Validation", - columns = c( - "Validation.Pass", - "Validation.Fail", - "Validation.Not_Applicable", - "Validation.Error", - "Validation.PctPass" + columnGroups = list( + colGroup( + name = "Validation", + columns = c( + "Validation.Pass", + "Validation.Fail", + "Validation.N.A.", + "Validation.Error", + "Validation.PctPass" + ) + ), + colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.N.A.", + "Verification.Error", + "Verification.PctPass" + ) + ), + colGroup( + name = "Total", + columns = c( + "Total.Pass", + "Total.Fail", + "Total.N.A.", + "Total.Error", + "Total.PctPass" + ) ) + ) + ) + }) + } else { + output$summary_dt1 <- renderUI({ + reactable( + data1, + striped = TRUE, + highlight = TRUE, + bordered = TRUE, + theme = reactableTheme( + borderColor = "#dfe2e5", + # stripedColor = "#ecf0f1", + highlightColor = "#f0f5f9", + cellPadding = "8px 12px", ), - colGroup( - name = "Verification", - columns = c( - "Verification.Pass", - "Verification.Fail", - "Verification.Not_Applicable", - "Verification.Error", - "Verification.PctPass" + rowStyle = function(index) { + if (index == 4) + list(fontWeight = "bold") + }, + columns = list( + CATEGORY = colDef(name = "Category", minWidth = 80), + Validation.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Verification.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Total.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Validation.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Verification.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Total.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Validation.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Verification.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Total.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) ) ), - colGroup( - name = "Total", - columns = c( - "Total.Pass", - "Total.Fail", - "Total.Not_Applicable", - "Total.Error", - "Total.PctPass" + columnGroups = list( + colGroup( + name = "Validation", + columns = c( + "Validation.Pass", + "Validation.Fail", + "Validation.PctPass" + ) + ), + colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.PctPass" + ) + ), + colGroup( + name = "Total", + columns = c( + "Total.Pass", + "Total.Fail", + "Total.PctPass" + ) ) ) ) - ) - }) - } else{ + }) + } + } else { output$summary_dt1 <- renderUI({ reactable( data1, @@ -180,8 +283,8 @@ server <- function(input, output) { align = "center", style = list(color = "red") ), - Verification.Not_Applicable = colDef( - name = "Not Applicable", + Verification.N.A. = colDef( + name = "N.A.", minWidth = 60, align = "center" ), @@ -198,18 +301,16 @@ server <- function(input, output) { colFormat(separators = TRUE, digits = 0) ) ), - columnGroups = list( - colGroup( - name = "Verification", - columns = c( - "Verification.Pass", - "Verification.Fail", - "Verification.Not_Applicable", - "Verification.Error", - "Verification.PctPass" - ) + columnGroups = list(colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.N.A.", + "Verification.Error", + "Verification.PctPass" ) - ) + )) ) }) } From f29f67185368e8125f002cd1c5115d6d0a02933e Mon Sep 17 00:00:00 2001 From: Luis Alberto Alaniz Castillo Date: Sat, 6 Aug 2022 16:01:35 -0600 Subject: [PATCH 5/6] Eliminated 2 superfluous functions from previos version --- inst/ResultsV2/load_data_10.R | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/inst/ResultsV2/load_data_10.R b/inst/ResultsV2/load_data_10.R index f801cbda..93378f7d 100644 --- a/inst/ResultsV2/load_data_10.R +++ b/inst/ResultsV2/load_data_10.R @@ -65,38 +65,6 @@ summaryParts2Count <- function(data_tab) { ungroup() } -summaryParts3 <- function(data_tab, variable) { - part <- - select(data_tab, - c(CATEGORY, CONTEXT, PASSED, FAILED, N.A., IS_ERROR)) %>% - mutate(CATEGORY = as.factor(CATEGORY)) %>% - mutate(CONTEXT = as.factor(CONTEXT)) %>% - group_by(CATEGORY, CONTEXT) %>% - dplyr::summarise("sum" := sum({ - { - variable - } - })) %>% - spread(CONTEXT, sum) %>% - ungroup() -} - -summaryParts4 <- function(data_tab, variable) { - part <- - select(data_tab, - c(CATEGORY, CONTEXT, FAILED)) %>% - mutate(CATEGORY = as.factor(CATEGORY)) %>% - mutate(CONTEXT = as.factor(CONTEXT)) %>% - group_by(CATEGORY, CONTEXT) %>% - dplyr::summarise("sum" := sum({ - { - variable - } - })) %>% - spread(CONTEXT, sum) %>% - ungroup() -} - # Checks if a string is in column name # https://stackoverflow.com/questions/60978376/r-to-identify-whether-column-names-in-a-dataframe-contains-string checkString <- function(dat, pat) From 085056ef6ba2538cd87684535c54a16e9ad3b747 Mon Sep 17 00:00:00 2001 From: Luis Alberto Alaniz Castillo Date: Sat, 6 Aug 2022 16:45:44 -0600 Subject: [PATCH 6/6] Eliminated superfluous conditions from server.r --- inst/ResultsV2/server.r | 433 +++++++++++++++++----------------------- 1 file changed, 185 insertions(+), 248 deletions(-) diff --git a/inst/ResultsV2/server.r b/inst/ResultsV2/server.r index c3cd57fd..e3ea3b85 100644 --- a/inst/ResultsV2/server.r +++ b/inst/ResultsV2/server.r @@ -11,248 +11,144 @@ server <- function(input, output) { ################################################ #### Panel: Overview #### ################################################ - if (checkString(dataT, "Validation")) { - if ("N.A." %in% colnames(dataT)) { - output$summary_dt1 <- renderUI({ - reactable( - data1, - striped = TRUE, - highlight = TRUE, - bordered = TRUE, - theme = reactableTheme( - borderColor = "#dfe2e5", - # stripedColor = "#ecf0f1", - highlightColor = "#f0f5f9", - cellPadding = "8px 12px", + if ("N.A." %in% colnames(dataT)) { + output$summary_dt1 <- renderUI({ + reactable( + data1, + striped = TRUE, + highlight = TRUE, + bordered = TRUE, + theme = reactableTheme( + borderColor = "#dfe2e5", + # stripedColor = "#ecf0f1", + highlightColor = "#f0f5f9", + cellPadding = "8px 12px", + ), + rowStyle = function(index) { + if (index == 4) + list(fontWeight = "bold") + }, + columns = list( + CATEGORY = colDef(name = "Category", minWidth = 80), + Validation.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" ), - rowStyle = function(index) { - if (index == 4) - list(fontWeight = "bold") - }, - columns = list( - CATEGORY = colDef(name = "Category", minWidth = 80), - Validation.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Verification.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Total.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Validation.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Verification.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Total.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Validation.N.A. = colDef( - name = "N.A.", - minWidth = 60, - align = "center" - ), - Verification.N.A. = colDef( - name = "N.A.", - minWidth = 60, - align = "center" - ), - Total.N.A. = colDef( - name = "N.A.", - minWidth = 60, - align = "center" - ), - Validation.Error = colDef( - name = "Error", - minWidth = 60, - align = "center" - ), - Verification.Error = colDef( - name = "Error", - minWidth = 60, - align = "center" - ), - Total.Error = colDef( - name = "Error", - minWidth = 60, - align = "center" - ), - Validation.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ), - Verification.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ), - Total.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ) + Verification.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" ), - columnGroups = list( - colGroup( - name = "Validation", - columns = c( - "Validation.Pass", - "Validation.Fail", - "Validation.N.A.", - "Validation.Error", - "Validation.PctPass" - ) - ), - colGroup( - name = "Verification", - columns = c( - "Verification.Pass", - "Verification.Fail", - "Verification.N.A.", - "Verification.Error", - "Verification.PctPass" - ) - ), - colGroup( - name = "Total", - columns = c( - "Total.Pass", - "Total.Fail", - "Total.N.A.", - "Total.Error", - "Total.PctPass" - ) - ) + Total.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Validation.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Verification.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Total.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), + Validation.N.A. = colDef( + name = "N.A.", + minWidth = 60, + align = "center" + ), + Verification.N.A. = colDef( + name = "N.A.", + minWidth = 60, + align = "center" + ), + Total.N.A. = colDef( + name = "N.A.", + minWidth = 60, + align = "center" + ), + Validation.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Verification.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Total.Error = colDef( + name = "Error", + minWidth = 60, + align = "center" + ), + Validation.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Verification.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) + ), + Total.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) ) - ) - }) - } else { - output$summary_dt1 <- renderUI({ - reactable( - data1, - striped = TRUE, - highlight = TRUE, - bordered = TRUE, - theme = reactableTheme( - borderColor = "#dfe2e5", - # stripedColor = "#ecf0f1", - highlightColor = "#f0f5f9", - cellPadding = "8px 12px", + ), + columnGroups = list( + colGroup( + name = "Validation", + columns = c( + "Validation.Pass", + "Validation.Fail", + "Validation.N.A.", + "Validation.Error", + "Validation.PctPass" + ) ), - rowStyle = function(index) { - if (index == 4) - list(fontWeight = "bold") - }, - columns = list( - CATEGORY = colDef(name = "Category", minWidth = 80), - Validation.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Verification.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Total.Pass = colDef( - name = "Pass", - minWidth = 60, - align = "center" - ), - Validation.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Verification.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Total.Fail = colDef( - name = "Fail", - minWidth = 60, - align = "center", - style = list(color = "red") - ), - Validation.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ), - Verification.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) - ), - Total.PctPass = colDef( - name = "% Pass", - minWidth = 60, - align = "center", - format = - colFormat(separators = TRUE, digits = 0) + colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.N.A.", + "Verification.Error", + "Verification.PctPass" ) ), - columnGroups = list( - colGroup( - name = "Validation", - columns = c( - "Validation.Pass", - "Validation.Fail", - "Validation.PctPass" - ) - ), - colGroup( - name = "Verification", - columns = c( - "Verification.Pass", - "Verification.Fail", - "Verification.PctPass" - ) - ), - colGroup( - name = "Total", - columns = c( - "Total.Pass", - "Total.Fail", - "Total.PctPass" - ) + colGroup( + name = "Total", + columns = c( + "Total.Pass", + "Total.Fail", + "Total.N.A.", + "Total.Error", + "Total.PctPass" ) ) ) - }) - } + ) + }) } else { output$summary_dt1 <- renderUI({ reactable( @@ -272,26 +168,45 @@ server <- function(input, output) { }, columns = list( CATEGORY = colDef(name = "Category", minWidth = 80), + Validation.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), Verification.Pass = colDef( name = "Pass", minWidth = 60, align = "center" ), + Total.Pass = colDef( + name = "Pass", + minWidth = 60, + align = "center" + ), + Validation.Fail = colDef( + name = "Fail", + minWidth = 60, + align = "center", + style = list(color = "red") + ), Verification.Fail = colDef( name = "Fail", minWidth = 60, align = "center", style = list(color = "red") ), - Verification.N.A. = colDef( - name = "N.A.", + Total.Fail = colDef( + name = "Fail", minWidth = 60, - align = "center" + align = "center", + style = list(color = "red") ), - Verification.Error = colDef( - name = "Error", + Validation.PctPass = colDef( + name = "% Pass", minWidth = 60, - align = "center" + align = "center", + format = + colFormat(separators = TRUE, digits = 0) ), Verification.PctPass = colDef( name = "% Pass", @@ -299,18 +214,39 @@ server <- function(input, output) { align = "center", format = colFormat(separators = TRUE, digits = 0) + ), + Total.PctPass = colDef( + name = "% Pass", + minWidth = 60, + align = "center", + format = + colFormat(separators = TRUE, digits = 0) ) ), - columnGroups = list(colGroup( - name = "Verification", - columns = c( - "Verification.Pass", - "Verification.Fail", - "Verification.N.A.", - "Verification.Error", - "Verification.PctPass" + columnGroups = list( + colGroup( + name = "Validation", + columns = c( + "Validation.Pass", + "Validation.Fail", + "Validation.PctPass" + ) + ), + colGroup( + name = "Verification", + columns = c( + "Verification.Pass", + "Verification.Fail", + "Verification.PctPass" + ) + ), + colGroup( + name = "Total", + columns = c("Total.Pass", + "Total.Fail", + "Total.PctPass") ) - )) + ) ) }) } @@ -543,3 +479,4 @@ server <- function(input, output) { getPageAbo() }) } +