Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ Imports:
omopgenerics,
here
Config/roxygen2/version: 8.0.0
RoxygenNote: 7.3.3
13 changes: 12 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,27 @@ importFrom(CohortConstructor,requireIsFirstEntry)
importFrom(CohortConstructor,requireSex)
importFrom(CohortConstructor,requireTableIntersect)
importFrom(ParallelLogger,logInfo)
importFrom(PatientProfiles,addConceptIntersectDate)
importFrom(checkmate,assertChoice)
importFrom(checkmate,assertDataFrame)
importFrom(checkmate,assertDirectoryExists)
importFrom(checkmate,assertFileExists)
importFrom(checkmate,assertTRUE)
importFrom(dplyr,collect)
importFrom(dplyr,filter)
importFrom(dplyr,mutate)
importFrom(dplyr,pick)
importFrom(dplyr,pull)
importFrom(dplyr,rowwise)
importFrom(dplyr,select)
importFrom(dplyr,select_if)
importFrom(glue,glue)
importFrom(here,here)
importFrom(omopgenerics,assertList)
importFrom(omopgenerics,assertTable)
importFrom(omopgenerics,importConceptSetExpression)
importFrom(omopgenerics,newCodelist)
importFrom(omopgenerics,settings)
importFrom(omopgenerics,validateCdmArgument)
importFrom(omopgenerics,validateCohortArgument)
importFrom(stringr,str_detect)
importFrom(tidyselect,any_of)
90 changes: 90 additions & 0 deletions R/TNMRules.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#' Documentation of TNM staging rules
#'
#' Internal auxiliary files used to determine cancer stage.
#'
#' @details
#' The package stores three rule sets derived from UICC guidelines for the
#' TNM staging system. The rules stored in these files are differentiated by
#' cancer **site** (bladder, breast, colorectal, lung, oesophageal, prostate,
#' skin), classification **type** (clinical, pathological, base) and
#' classification **edition** (7th, 8th, unspecified). The files are:
#'
#' \enumerate{
#' \item `tnm_concepts.csv`: contains information about the individual TNM
#' components and their concept ids, differentiated by type and edition.
#' There are \eqn{393} total concepts for \eqn{44} unique components:
#' ```
#' TX, T0, Tis, Ta, T1, T1a, T1b, T1c, T1mi, T2, T2a, T2b, T2c, T3, T3a,
#' T3b, T4, T4a, T4b, T4c, T4d, NX, N0, N1, N1a, N1b, N1c, N1mi, N2, N2a,
#' N2b, N2c, N3, N3a, N3b, N3c, M0, M1, M1a, M1b, M1c, M1c1, M1c2, M1d.
#' ```
#' These components have different versions according to:
#' \itemize{
#' \item Edition: \eqn{131} concepts for 7th, \eqn{131} for 8th, \eqn{131}
#' for unspecified;
#' \item Type: \eqn{132} concepts for base, \eqn{132} for clinical, \eqn{129}
#' for pathological (the `M0` component is not valid in the pathological
#' setting, for any of the editions).
#' }
#'
#' \item `tnm_stage_mapping.csv`: contains the rules to determine the cancer
#' stage based on a combination of individual TNM components, differentiated
#' by cancer site, type (clinical, pathological, base) and by edition (7th,
#' 8th, 9th). Each rule refers to a specific source page of the UICC guidelines.
#'
#' The currently available rules support the following concept categories.
#'
#' For `bladder` cancer:
#' \itemize{
#' \item Edition: 7th, 8th, 9th available;
#' \item Type: only "base" is available, for all editions.
#' }
#' For `breast` cancer:
#' \itemize{
#' \item Edition: 7th, 8th, 9th available;
#' \item Type: only "base" is available, for all editions.
#' }
#' For `colorectal` cancer:
#' \itemize{
#' \item Edition: 7th, 8th, 9th available;
#' \item Type: only "base" is available, for all editions.
#' }
#' For `lung` cancer:
#' \itemize{
#' \item Edition: 7th, 8th, 9th available;
#' \item Type: only "base" is available, for all editions.
#' }
#' For `oesophageal` cancer:
#' \itemize{
#' \item For 7th edition, only "base" type is available;
#' \item For 8th edition, only "clinical" and "pathological" types are available but not "base".
#' \item For 9th edition, only "clinical" and "pathological" types are available but not "base".
#' }
#' For `prostate` cancer:
#' \itemize{
#' \item For 7th edition, only "base" type is available;
#' \item For 8th edition, only "clinical" type is available;
#' \item For 9th edition, only "clinical" and "pathological" types are available but not "base".
#' }
#' For `skin` cancer:
#' \itemize{
#' \item For 7th edition, only "pathological" type is available;
#' \item For 8th edition, only "clinical" and "pathological" types are available but not "base".
#' \item For 9th edition, only "clinical" and "pathological" types are available but not "base".
#' }
#'
#' \item `tnm_stage_shortcut_mapping.csv`: contains some more general rules to
#' determine the cancer stage based on a subset of individual TNM components,
#' differentiated by cancer site, type and edition. In fact, there are some
#' special cases in which the value of one or two components
#' is enough to determine the stage, independently of the others.
#' Each rule refers to a specific source page of the UICC guidelines.
#' }
#'
#' These files are meant for internal use and are not intended
#' to be modified by users.
#'
#' @name tnm_rules_docs
#' @source UICC_7th edition.pdf; UICC_8th edition.pdf corroborated by nhs/*.pdf; uicc/UICC_9th edition.pdf
#' @keywords internal
NULL
84 changes: 42 additions & 42 deletions R/addStages.R
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
#' `addStages()` to a cohort
#'
#' It uses a codelist to date intersect with a cancer cohort.
#' It uses a codelist to date intersect with a cancer cohort.
#' Imposes a predefined or custom set of rules to identify
#' summary stages.
#'
#' @param cohort A cohort table with cancer patients from a
#' @param cohort A cohort table with cancer patients from a
#' cdm reference object.
#' @param cdm A cdm reference object.
#' @param cancer In character, the affected site, a choice of:
#' @param cancer In character, the affected site, a choice of:
#' "bladder", "breast", "colorectal", "lung", "melanoma", "oesophagus"
#' and "prostate".
#' @param window to look up stages codes.
#' @param edition A choice of "unspecified", "7th" and "8th".
#' @param type A choice from "base", "clinical" or "pathological".
#' @param order A choice from "first" or "last". If more that one code
#' @param order A choice from "first" or "last". If more than one code
#' intersected, the order defines which code to intersect in the window.
#' @param showTnm If TRUE, the cohort will show the date intersects
#' @param showTnm If TRUE, the cohort will show the date intersects
#' for each matching code. Default FALSE.
#' @importFrom omopgenerics validateCohortArgument validateCdmArgument assertList newCodelist
#' @importFrom omopgenerics validateCohortArgument validateCdmArgument assertList newCodelist
#' @importFrom checkmate assertChoice assertFileExists assertTRUE assertDataFrame
#' @importFrom dplyr filter pull rowwise select_if mutate pick select
#' @importFrom PatientProfiles addConceptIntersectDate
Expand All @@ -35,28 +35,28 @@ addStages <- function(
order = "last",
showTnm = FALSE
) {

# Assert parameters ---------------------------------
cohort |>
omopgenerics::validateCohortArgument()
cdm |>
cdm |>
omopgenerics::validateCdmArgument()
window |>
window |>
omopgenerics::assertList()
edition |>
edition |>
checkmate::assertChoice(
c("unspecified", "7th", "8th")
)
type |>
type |>
checkmate::assertChoice(
c("base", "clinical", "pathological")
)

# Read stages rules data ----------------------------
tnm_files_data <- system.file(
"tnm_files",
package = "oncomop"
) |>
) |>
list.files(
full.names = TRUE
) |>
Expand All @@ -69,17 +69,17 @@ addStages <- function(
.edition = edition,
.type = type
)

# Extract ruleset -----------------------------------
ruleset <- tnm_files_data$tnm_stage_mapping |>
ruleset <- tnm_files_data$tnm_stage_mapping |>
extractStageRuleset(
.cancer = cancer,
.edition = edition,
.type = "base"
)
)

# .addColumnRules() ---------------------------------
# General function to analyse if it can be reused for
# General function to analyse if it can be reused for
# subtypes and progression
cancer_stage_cohort <- cohort |>
.addColumnRules(
Expand All @@ -93,10 +93,10 @@ addStages <- function(
nameStyle = "{concept_name}",
name = NULL,
ruleset = ruleset
)
)

if (isFALSE(showTnm)) {
cancer_stage_cohort |>
cancer_stage_cohort |>
dplyr::select(
cohort_definition_id,
subject_id,
Expand All @@ -110,13 +110,13 @@ addStages <- function(
}

readStagesRDS <- function(tnm_files) {
tnm_files |>
checkmate::assertFileExists() |>
basename() |>
tnm_files |>
checkmate::assertFileExists() |>
basename() |>
identical(
c( "tnm_concepts.rds",
"tnm_stage_mapping.rds",
"tnm_stage_shortcut_mapping.rds")) |>
"tnm_stage_shortcut_mapping.rds")) |>
checkmate::assertTRUE()
setNames(
lapply(tnm_files, readRDS),
Expand All @@ -131,16 +131,16 @@ extractStageRuleset <- function(
.type
) {
checkmate::assertDataFrame(tnm_stage_mapping)
tnm_stage_mapping |>
tnm_stage_mapping |>
dplyr::filter(
edition == .edition
) |>
) |>
dplyr::filter(
site == .cancer
) |>
) |>
dplyr::filter(
stage_grouping_scope == .type
) |>
) |>
dplyr::select(
rule_id, T, N, M, uicc_stage
)
Expand All @@ -157,10 +157,10 @@ createTNMCodelist <- function(
.data$classification_version == .edition,
.data$type == .type,
) |>
dplyr::filter(
dplyr::filter(
!is.na(.data$concept_id)
)
tnm_codelist <- tnm_stages_concept |>
)
tnm_codelist <- tnm_stages_concept |>
dplyr::pull(
concept_id
) |> lapply(
Expand All @@ -169,7 +169,7 @@ createTNMCodelist <- function(
}
) |> setNames(
tnm_stages_concept$component_tnm
) |>
) |>
omopgenerics::newCodelist()
return(tnm_codelist)
}
Expand All @@ -188,7 +188,7 @@ createTNMCodelist <- function(
ruleset
) {
omopgenerics::validateCohortArgument(cohort)
cohort |>
cohort |>
PatientProfiles::addConceptIntersectDate(
conceptSet,
indexDate = "cohort_start_date",
Expand All @@ -199,7 +199,7 @@ createTNMCodelist <- function(
inObservation = TRUE,
nameStyle = "{concept_name}",
name = NULL
) |>
) |>
.mapRules(ruleset)
}

Expand All @@ -210,29 +210,29 @@ createTNMCodelist <- function(
omopgenerics::validateCohortArgument(cohort)
checkmate::assertDataFrame(ruleset)
cohort |>
dplyr::collect() |>
dplyr::collect() |>
dplyr::rowwise() |>
dplyr::select_if(~ !all(is.na(.))) |>
dplyr::select_if(~ !all(is.na(.))) |>
dplyr::mutate(
cancer_stage = {
rowStages <- dplyr::pick(tidyselect::any_of(tolower(unique(c(ruleset$T, ruleset$N, ruleset$M))))) |>
rowStages <- dplyr::pick(tidyselect::any_of(tolower(unique(c(ruleset$T, ruleset$N, ruleset$M))))) |>
dplyr::select_if(~ !any(is.na(.)))
stageCombination <- names(rowStages)
rowStageT <- stageCombination[names(rowStages) |> stringr::str_detect("t")]
rowStageN <- stageCombination[names(rowStages) |> stringr::str_detect("n")]
rowStageM <- stageCombination[names(rowStages) |> stringr::str_detect("m")]
stage <- ruleset |>
stage <- ruleset |>
dplyr::select(
T, N, M, uicc_stage
) |>
) |>
dplyr::filter(
tolower(T) == rowStageT,
tolower(N) == rowStageN,
tolower(M) == rowStageM,
) |>
) |>
dplyr::pull(uicc_stage)
}
)
)
}

filterStageConcepts <- function(
Expand Down
32 changes: 22 additions & 10 deletions man/addStages.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading