# Complete Quarto Workflow for BOIN-ET Reports

    library(boinet)
    library(dplyr)

    # Load additional packages for reporting
    if (requireNamespace("gt", quietly = TRUE)) library(gt)
    if (requireNamespace("ggplot2", quietly = TRUE)) library(ggplot2)

# Overview

This vignette demonstrates how to create complete, reproducible clinical trial reports using the boinet package with Quarto. The workflow covers everything from simulation to final report generation suitable for regulatory submissions, academic publications, and internal documentation.

## Helper Functions for Reports

    # Extract operating characteristics data
    extract_oc_data <- function(boinet_result) {
      dose_levels <- names(boinet_result$n.patient)

      data.frame(
        dose_level = dose_levels,
        toxicity_prob = as.numeric(boinet_result$toxprob),
        efficacy_prob = as.numeric(boinet_result$effprob),
        n_patients = as.numeric(boinet_result$n.patient),
        selection_prob = as.numeric(boinet_result$prop.select),
        stringsAsFactors = FALSE
      )
    }

    # Create summary statistics
    create_summary_stats <- function(boinet_result) {
      oc_data <- extract_oc_data(boinet_result)
      optimal_dose <- oc_data$dose_level[which.max(oc_data$selection_prob)]

      list(
        optimal_dose = optimal_dose,
        max_selection_prob = max(oc_data$selection_prob),
        early_stop_rate = as.numeric(boinet_result$prop.stop),
        avg_duration = as.numeric(boinet_result$duration),
        total_patients = sum(oc_data$n_patients),
        design_type = class(boinet_result)[1]
      )
    }

    # Create formatted text summaries
    create_text_summary <- function(boinet_result) {
      stats <- create_summary_stats(boinet_result)

      sprintf(
        "The %s design selected dose level %s in %.1f%% of trials, with an average trial duration of %.0f days and early stopping rate of %.1f%%.",
        toupper(gsub("\\.", "-", stats$design_type)),
        stats$optimal_dose,
        stats$max_selection_prob,
        stats$avg_duration,
        stats$early_stop_rate
      )
    }

    # Create design parameters table
    create_design_table <- function(result) {
      design_params <- data.frame(
        Parameter = c("Target Toxicity Rate (φ)", "Target Efficacy Rate (δ)",
                      "Lower Toxicity Boundary (λ₁)", "Upper Toxicity Boundary (λ₂)",
                      "Efficacy Boundary (η₁)", "Early Stop Rate (%)",
                      "Average Duration (days)", "Toxicity Assessment Window (days)",
                      "Efficacy Assessment Window (days)", "Accrual Rate (days)"),
        Value = c(result$phi, result$delta, result$lambda1, result$lambda2,
                  result$eta1, result$prop.stop, result$duration,
                  result$tau.T, result$tau.E, result$accrual),
        stringsAsFactors = FALSE
      )

      # Format values
      design_params$Value <- round(as.numeric(design_params$Value), 3)

      if (gt_available) {
        design_params %>%
          gt() %>%
          tab_header(
            title = "TITE-BOIN-ET Design Parameters",
            subtitle = paste("Based on", result$n.sim, "simulated trials")
          ) %>%
          fmt_number(columns = "Value", decimals = 3) %>%
          cols_align(align = "left", columns = "Parameter") %>%
          cols_align(align = "center", columns = "Value")
      } else {
        # Fallback to basic table
        print(design_params)
      }
    }

    # Create operating characteristics table
    create_oc_table <- function(result) {
      dose_levels <- names(result$n.patient)

      oc_data <- data.frame(
        `Dose Level` = dose_levels,
        `True Toxicity Probability` = round(as.numeric(result$toxprob), 3),
        `True Efficacy Probability` = round(as.numeric(result$effprob), 3),
        `Average N Treated` = round(as.numeric(result$n.patient), 1),
        `Selection Probability (%)` = round(as.numeric(result$prop.select), 1),
        check.names = FALSE
      )

      if (gt_available) {
        oc_data %>%
          gt() %>%
          tab_header(
            title = "Operating Characteristics",
            subtitle = "TITE-BOIN-ET Design Simulation Results"
          ) %>%
          fmt_number(columns = c("True Toxicity Probability", "True Efficacy Probability"), decimals = 3) %>%
          fmt_number(columns = "Average N Treated", decimals = 1) %>%
          fmt_number(columns = "Selection Probability (%)", decimals = 1) %>%
          cols_align(align = "center", columns = everything()) %>%
          cols_align(align = "left", columns = "Dose Level") %>%
          tab_style(
            style = cell_fill(color = "lightblue"),
            locations = cells_body(
              rows = `Selection Probability (%)` == max(`Selection Probability (%)`)
            )
          )
      } else {
        # Fallback to basic table
        print(oc_data)
      }
    }

## Mock Data for Demonstration

    # Create mock result for demonstration
    boinet_result <- list(
      toxprob = c("1" = 0.02, "2" = 0.08, "3" = 0.15, "4" = 0.25, "5" = 0.40),
      effprob = c("1" = 0.10, "2" = 0.20, "3" = 0.35, "4" = 0.50, "5" = 0.65),
      n.patient = c("1" = 8.2, "2" = 12.5, "3" = 15.8, "4" = 10.3, "5" = 7.2),
      prop.select = c("1" = 5.2, "2" = 18.7, "3" = 42.1, "4" = 28.3, "5" = 5.7),
      phi = 0.30, delta = 0.60, lambda1 = 0.03, lambda2 = 0.42, eta1 = 0.36,
      tau.T = 28, tau.E = 42, accrual = 7, duration = 156.3, prop.stop = 3.2, n.sim = 1000
    )
    class(boinet_result) <- "tite.boinet"

## Complete Quarto Document Template

Here’s a complete Quarto document template for BOIN-ET analysis that you can save as a separate `.qmd` file:

### Basic Template Structure

    ---
    title: "BOIN-ET Clinical Trial Design Analysis"
    subtitle: "Protocol ABC-2024-001: Novel Kinase Inhibitor"
    author: "Biostatistics Team"
    date: "2025-10-25"
    format:
      html:
        theme: cosmo
        toc: true
        toc-depth: 3
        code-fold: true
        fig-width: 8
        fig-height: 6
      pdf:
        toc: true
        number-sections: true
        fig-width: 7
        fig-height: 5
      docx:
        toc: true
        fig-width: 6.5
        fig-height: 4.5
    execute:
      echo: false
      warning: false
      message: false
    ---

### Example Report Sections

The following demonstrates what would go in your actual Quarto report:

    # Design specifications table
    create_design_table(boinet_result)

TITE-BOIN-ET Design Parameters
Based on 1000 simulated trials
Parameter | Value
--- | ---
Target Toxicity Rate (φ) | 0.300
Target Efficacy Rate (δ) | 0.600
Lower Toxicity Boundary (λ₁) | 0.030
Upper Toxicity Boundary (λ₂) | 0.420
Efficacy Boundary (η₁) | 0.360
Early Stop Rate (%) | 3.200
Average Duration (days) | 156.300
Toxicity Assessment Window (days) | 28.000
Efficacy Assessment Window (days) | 42.000
Accrual Rate (days) | 7.000

    # Operating characteristics table
    create_oc_table(boinet_result)

Operating Characteristics
TITE-BOIN-ET Design Simulation Results
Dose Level | True Toxicity Probability | True Efficacy Probability | Average N Treated | Selection Probability (%)
--- | --- | --- | --- | ---
1 | 0.020 | 0.100 | 8.2 | 5.2
2 | 0.080 | 0.200 | 12.5 | 18.7
3 | 0.150 | 0.350 | 15.8 | 42.1
4 | 0.250 | 0.500 | 10.3 | 28.3
5 | 0.400 | 0.650 | 7.2 | 5.7

    # Extract key statistics for inline reporting
    dose_levels <- names(boinet_result$n.patient)
    selection_probs <- as.numeric(boinet_result$prop.select)
    best_dose_idx <- which.max(selection_probs)
    best_dose <- dose_levels[best_dose_idx]
    max_selection <- max(selection_probs)
    avg_duration <- as.numeric(boinet_result$duration)
    early_stop <- as.numeric(boinet_result$prop.stop)

    cat("Key findings:\n")
    #> Key findings:
    cat("- Optimal dose level:", best_dose, "\n")
    #> - Optimal dose level: 3
    cat("- Selection probability:", round(max_selection, 1), "%\n")
    #> - Selection probability: 42.1 %
    cat("- Average trial duration:", round(avg_duration, 0), "days\n")
    #> - Average trial duration: 156 days
    cat("- Early stopping rate:", round(early_stop, 1), "%\n")
    #> - Early stopping rate: 3.2 %

## Dose Selection Visualization

    if (ggplot2_available) {
      # Create data frame for plotting
      plot_data <- data.frame(
        dose_level = names(boinet_result$n.patient),
        selection_prob = as.numeric(boinet_result$prop.select)
      )

      plot_data %>%
        ggplot(aes(x = dose_level, y = selection_prob)) +
        geom_col(fill = "steelblue", alpha = 0.7) +
        geom_text(aes(label = paste0(round(selection_prob, 1), "%")),
                  vjust = -0.3) +
        labs(
          x = "Dose Level",
          y = "Selection Probability (%)",
          title = "TITE-BOIN-ET Dose Selection Performance"
        ) +
        theme_minimal()
    } else {
      cat("ggplot2 package not available for visualization.\n")
    }

Dose selection probabilities

## Risk-Benefit Analysis

    if (ggplot2_available) {
      # Create risk-benefit plot data
      rb_data <- data.frame(
        dose_level = names(boinet_result$n.patient),
        toxicity_prob = as.numeric(boinet_result$toxprob),
        efficacy_prob = as.numeric(boinet_result$effprob),
        selection_prob = as.numeric(boinet_result$prop.select)
      )

      rb_data %>%
        ggplot(aes(x = toxicity_prob, y = efficacy_prob)) +
        geom_point(aes(size = selection_prob), alpha = 0.7, color = "darkred") +
        geom_text(aes(label = dose_level), vjust = -1.5) +
        scale_size_continuous(name = "Selection\nProbability (%)", range = c(3, 12)) +
        labs(
          x = "True Toxicity Probability",
          y = "True Efficacy Probability",
          title = "Risk-Benefit Profile"
        ) +
        theme_minimal()
    } else {
      cat("ggplot2 package not available for risk-benefit visualization.\n")
    }

Efficacy-toxicity profile

## Parameterized Reports

Quarto supports parameterized reports where you can pass values to customize the analysis.

### Setting Up Parameters

Step 1: Add parameters to your YAML header:

    ---
    title: "BOIN-ET Analysis Report"
    params:
      target_tox: 0.30
      target_eff: 0.60
      protocol_id: "ABC-001"
      compound_name: "XYZ-123"
    ---

Step 2: Use parameters in your analysis code (in a real parameterized document):

    # Access parameters like this:
    # target_toxicity <- params$target_tox
    # protocol_name <- params$protocol_id

Step 3: Render with custom parameters:

    # quarto::quarto_render(
    #   "your_template.qmd",
    #   execute_params = list(
    #     target_tox = 0.25,
    #     target_eff = 0.65,
    #     protocol_id = "XYZ-002",
    #     compound_name = "New Drug"
    #   )
    # )

    # Demonstration of the concept using mock parameters
    mock_params <- list(
      target_tox = 0.30,
      target_eff = 0.60,
      protocol_id = "ABC-001",
      compound_name = "XYZ-123"
    )

    cat("Parameterized report demonstration:\n")
    #> Parameterized report demonstration:
    cat("Protocol:", mock_params$protocol_id, "\n")
    #> Protocol: ABC-001
    cat("Compound:", mock_params$compound_name, "\n")
    #> Compound: XYZ-123
    cat("Target toxicity:", mock_params$target_tox, "\n")
    #> Target toxicity: 0.3
    cat("Target efficacy:", mock_params$target_eff, "\n")
    #> Target efficacy: 0.6

    # This shows how you could customize analysis based on parameters
    cat("\nCustomized analysis settings:\n")
    #>
    #> Customized analysis settings:
    if (mock_params$target_tox < 0.25) {
      cat("- Conservative toxicity approach\n")
    } else if (mock_params$target_tox > 0.35) {
      cat("- Aggressive toxicity approach\n")
    } else {
      cat("- Standard toxicity approach\n")
    }
    #> - Standard toxicity approach

## Batch Report Generation

    # Demonstrate the concept with executable code
    scenarios <- list(
      conservative = list(phi = 0.25, delta = 0.50, name = "Conservative"),
      standard = list(phi = 0.30, delta = 0.60, name = "Standard"),
      aggressive = list(phi = 0.35, delta = 0.70, name = "Aggressive")
    )

    # Function to create scenario-specific summaries
    create_scenario_summary <- function(scenario) {
      sprintf(
        "Scenario: %s (φ=%.2f, δ=%.2f)",
        scenario$name, scenario$phi, scenario$delta
      )
    }

    # Generate summaries for all scenarios
    scenario_summaries <- lapply(scenarios, create_scenario_summary)
    cat("Available scenarios:\n")
    #> Available scenarios:
    for(summary in scenario_summaries) {
      cat("-", summary, "\n")
    }
    #> - Scenario: Conservative (φ=0.25, δ=0.50)
    #> - Scenario: Standard (φ=0.30, δ=0.60)
    #> - Scenario: Aggressive (φ=0.35, δ=0.70)

For batch processing, you would typically:

1. Create a parameterized template
2. Define scenarios with different parameters
3. Use `quarto::quarto_render()` with different `execute_params` for each scenario

## Conditional Content

Show different content based on results:

    # Extract results for conditional logic
    oc_data <- extract_oc_data(boinet_result)
    max_selection_prob <- max(oc_data$selection_prob)
    optimal_dose <- oc_data$dose_level[which.max(oc_data$selection_prob)]

    # Conditional content based on results
    if (max_selection_prob > 40) {
      recommendation <- "Strong evidence for optimal dose identification"
      confidence_level <- "High"
    } else if (max_selection_prob > 25) {
      recommendation <- "Moderate evidence for dose selection"
      confidence_level <- "Moderate"
    } else {
      recommendation <- "Weak evidence - consider design modifications"
      confidence_level <- "Low"
    }

    cat("Recommendation Confidence:", confidence_level, "\n")
    #> Recommendation Confidence: High
    cat("Analysis Conclusion:", recommendation, "\n")
    #> Analysis Conclusion: Strong evidence for optimal dose identification
    cat(sprintf("The optimal dose level %s was selected in %.1f%% of simulations.\n",
                optimal_dose, max_selection_prob))
    #> The optimal dose level 3 was selected in 42.1% of simulations.

## Best Practices for Quarto Reports

### 1. Document Structure

Use meaningful YAML headers with appropriate output formats for your audience.

### 2. Chunk Management

- Use descriptive chunk labels
- Set `cache: true` for expensive computations
- Use `echo: false` to hide code in final reports
- Use `eval: false` for demonstration code

### 3. Reproducible Workflows

    # Include session information
    cat("R version:", R.version.string, "\n")
    #> R version: R version 4.5.1 (2025-06-13 ucrt)
    cat("boinet version:", as.character(packageVersion("boinet")), "\n")
    #> boinet version: 1.5.0

    if (gt_available) {
      cat("gt version:", as.character(packageVersion("gt")), "\n")
    }
    #> gt version: 1.1.0

    if (ggplot2_available) {
      cat("ggplot2 version:", as.character(packageVersion("ggplot2")), "\n")
    }
    #> ggplot2 version: 4.0.0

    # Document analysis timestamp
    cat("Analysis completed:", format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "\n")
    #> Analysis completed: 2025-10-25 23:01:14

### 4. Output Formatting

Consider your target audience and output format when designing tables and figures.

## Template Library

### Clinical Protocol Report Template

    # Function to create standardized clinical report content
    create_clinical_report_content <- function(boinet_result, protocol_info) {

      # Extract key information
      oc_data <- extract_oc_data(boinet_result)
      stats <- create_summary_stats(boinet_result)

      # Create content structure
      content <- list(
        title = sprintf("Protocol %s: %s Analysis",
                       protocol_info$id, protocol_info$compound),
        summary = create_text_summary(boinet_result),
        key_findings = list(
          optimal_dose = stats$optimal_dose,
          selection_prob = round(stats$max_selection_prob, 1),
          duration = round(stats$avg_duration, 0),
          early_stop = round(stats$early_stop_rate, 1)
        ),
        oc_data = oc_data
      )

      return(content)
    }

    # Example usage
    protocol_info <- list(id = "XYZ-2024-001", compound = "Novel Kinase Inhibitor")
    demo_result <- boinet_result
    report_content <- create_clinical_report_content(demo_result, protocol_info)

    cat("Report title:", report_content$title, "\n")
    #> Report title: Protocol XYZ-2024-001: Novel Kinase Inhibitor Analysis
    cat("Summary:", report_content$summary, "\n")
    #> Summary: The TITE-BOINET design selected dose level 3 in 42.1% of trials, with an average trial duration of 156 days and early stopping rate of 3.2%.

### Regulatory Submission Template

    # Function to create regulatory-style formatting
    create_regulatory_content <- function(boinet_result, submission_info) {

      stats <- create_summary_stats(boinet_result)

      # Regulatory-style summary
      reg_summary <- sprintf(
        "Study %s evaluated %d dose levels using a %s design. The recommended Phase II dose is %s, selected in %s%% of %d simulated trials.",
        submission_info$study_id,
        length(names(boinet_result$n.patient)),
        toupper(gsub("\\.", "-", stats$design_type)),
        stats$optimal_dose,
        format(stats$max_selection_prob, digits = 3),
        boinet_result$n.sim
      )

      return(list(
        summary = reg_summary,
        table_title = sprintf("Table %s: Operating Characteristics", submission_info$table_number),
        stats = stats
      ))
    }

    # Example usage
    submission_info <- list(study_id = "ABC-123-001", table_number = "14.2.1")
    demo_result <- boinet_result
    reg_content <- create_regulatory_content(demo_result, submission_info)

    cat("Regulatory summary:", reg_content$summary, "\n")
    #> Regulatory summary: Study ABC-123-001 evaluated 5 dose levels using a TITE-BOINET design. The recommended Phase II dose is 3, selected in 42.1% of 1000 simulated trials.

## Troubleshooting Common Issues

### Package Availability Issues

    # Check required packages
    required_packages <- c("boinet", "dplyr")
    optional_packages <- c("gt", "ggplot2", "knitr", "rmarkdown")

    check_package_status <- function(packages, required = TRUE) {
      status <- sapply(packages, function(pkg) {
        requireNamespace(pkg, quietly = TRUE)
      })

      missing <- names(status)[!status]
      if (length(missing) > 0) {
        cat(ifelse(required, "Missing required", "Missing optional"), "packages:",
            paste(missing, collapse = ", "), "\n")
        cat("Install with: install.packages(c('", paste(missing, collapse = "', '"), "'))\n")
      } else {
        cat("All", ifelse(required, "required", "optional"), "packages available\n")
      }
    }

    check_package_status(required_packages, TRUE)
    #> All required packages available
    check_package_status(optional_packages, FALSE)
    #> All optional packages available

    # Check Quarto availability
    if (quarto_available) {
      cat("✓ Quarto CLI available\n")
    } else {
      cat("⚠ Quarto CLI not found. Install from: https://quarto.org\n")
    }
    #> ✓ Quarto CLI available

### Memory and Performance Issues

    # Tips for handling large simulations
    check_result_size <- function(result) {
      size_mb <- object.size(result) / (1024^2)
      cat(sprintf("Result object size: %.1f MB\n", size_mb))

      if (size_mb > 50) {
        cat("⚠ Large result object detected. Consider:\n")
        cat("  - Using cache: true in chunks\n")
        cat("  - Reducing n.sim for development\n")
        cat("  - Extracting only needed data\n")
      } else {
        cat("✓ Result size is manageable\n")
      }
    }

    # Use the demo result we created earlier
    demo_result <- boinet_result
    check_result_size(demo_result)
    #> Result object size: 0.0 MB
    #> ✓ Result size is manageable

    # Memory-efficient data extraction
    extract_minimal_data <- function(result) {
      list(
        oc_summary = data.frame(
          dose = names(result$n.patient),
          selection_prob = as.numeric(result$prop.select),
          stringsAsFactors = FALSE
        ),
        key_stats = list(
          optimal_dose = names(result$prop.select)[which.max(result$prop.select)],
          duration = result$duration,
          early_stop = result$prop.stop
        )
      )
    }

    minimal_data <- extract_minimal_data(demo_result)
    cat("Minimal data extracted successfully\n")
    #> Minimal data extracted successfully

## Conclusion

The boinet package provides comprehensive support for Quarto-based reporting workflows, enabling:

- Reproducible analysis with parameterized reports
- Professional formatting suitable for various audiences
- Flexible output in multiple formats (HTML, PDF, Word)
- Interactive elements for enhanced user experience
- Standardized templates for consistent reporting

This workflow ensures that BOIN-ET analysis results can be effectively communicated to clinical teams, regulatory agencies, and academic audiences while maintaining full reproducibility and professional presentation standards.

For basic result formatting, see the `result-formatting` vignette. For publication-ready tables, see the `gt-integration` vignette.