Skip to contents

Creates RECIST v1.1 compliant waterfall and spider plots for tumor response analysis. Implements full RECIST v1.1 protocol including target lesion summation, new lesion detection, non-target progression assessment, and response confirmation requirements. REGULATORY-READY: Suitable for clinical trial endpoints and regulatory submissions.

Usage

waterfallrecist(
  data,
  patientID,
  lesionID,
  visitTime,
  lesionType = NULL,
  location = NULL,
  diameter,
  isNewLesion = NULL,
  baselineTimepoint = 0,
  confirmationInterval = 4,
  maxTargetLesions = 5,
  maxLesionsPerOrgan = 2,
  showWaterfallPlot = TRUE,
  showSpiderPlot = TRUE,
  showLesionTable = TRUE,
  showTargetSumTable = TRUE,
  showBestResponseTable = TRUE,
  showRecistComplianceReport = TRUE,
  colorScheme = "recist"
)

Arguments

data

The data as a data frame with LESION-LEVEL observations (one row per lesion per timepoint).

patientID

Variable containing patient identifiers. Each patient can have multiple lesions tracked across timepoints.

lesionID

Unique lesion identifier within each patient (e.g., L1, L2, Liver_1, Lung_2). Used to track individual lesions across timepoints.

visitTime

Time point of measurement (e.g., weeks from baseline, days from treatment start). Baseline should be time = 0. Used for tracking lesion progression over time.

lesionType

Lesion classification: Target, NonTarget, or New. Target lesions (max 5 total, max 2 per organ) are measured and summed. NonTarget lesions are assessed qualitatively (present/absent/progressed).

location

Anatomic site of lesion (e.g., Liver, Lung, Lymph_Node). Used to enforce RECIST rule: max 2 target lesions per organ.

diameter

Longest diameter of target lesions in millimeters (≥10mm for non-lymph nodes, ≥15mm for lymph nodes). For non-target lesions, can be NA (qualitative assessment only).

isNewLesion

Binary indicator (0 = baseline/existing, 1 = new lesion appearing after baseline). ANY new lesion automatically triggers Progressive Disease (PD) per RECIST v1.1.

baselineTimepoint

Value of visitTime representing baseline (default = 0). All lesions at this timepoint establish the baseline sum.

confirmationInterval

Minimum time interval (weeks) for response confirmation per RECIST v1.1. CR and PR must be confirmed by repeat assessment ≥4 weeks after initial documentation.

maxTargetLesions

Maximum number of target lesions per patient (RECIST v1.1 default = 5).

maxLesionsPerOrgan

Maximum target lesions per organ (RECIST v1.1 default = 2).

showWaterfallPlot

Display waterfall plot showing best confirmed response for each patient.

showSpiderPlot

Display spider plot showing target lesion sum trajectories over time.

showLesionTable

Display detailed lesion-level measurements across all timepoints.

showTargetSumTable

Display target lesion sums and percent changes per visit.

showBestResponseTable

Display best overall response with confirmation status per patient.

showRecistComplianceReport

Display audit report verifying RECIST v1.1 compliance (target lesion limits, confirmation, new lesions).

colorScheme

Color scheme for plots.

Value

A results object containing:

results$lesionTablea table
results$targetSumTablea table
results$bestResponseTablea table
results$recistSummary$orrConfirmeda table
results$recistSummary$dcrConfirmeda table
results$recistSummary$responseDistributiona table
results$complianceReporta html
results$waterfallPlotan image
results$spiderPlotan image

Tables can be converted to data frames with asDF or as.data.frame. For example:

results$lesionTable$asDF

as.data.frame(results$lesionTable)

Examples

# \donttest{
# Example: Lesion-level data for RECIST v1.1
data_recist <- data.frame(
    PatientID = rep(paste0("PT", 1:3), each = 6),
    VisitTime = rep(c(0, 4, 8, 12, 16, 20), 3),
    LesionID = paste0("L", rep(1:2, each = 3, times = 3)),
    LesionType = rep(c("Target", "Target"), each = 3, times = 3),
    Location = rep(c("Liver", "Lung"), each = 3, times = 3),
    Diameter = c(
        # Patient 1
        35, 28, 20,  # Lesion 1
        42, 38, 30,  # Lesion 2
        # Patient 2
        50, 45, 48,  # Lesion 1
        30, 28, 32,  # Lesion 2
        # Patient 3
        45, 30, 25,  # Lesion 1
        38, 25, 20   # Lesion 2
    ),
    IsNewLesion = rep(0, 18)
)

waterfallrecist(
    data = data_recist,
    patientID = "PatientID",
    lesionID = "LesionID",
    visitTime = "VisitTime",
    lesionType = "LesionType",
    location = "Location",
    diameter = "Diameter",
    isNewLesion = "IsNewLesion"
)
#> Error in item$visible && !is(item, "Image"): invalid 'x' type in 'x && y'
# }