Skip to content
Merged

Dev #152

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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ optimizing plotly testing.X
data-raw/catlogo.svg
vignettes/articles/ggpedigree_config.rds
*DESKTOP-16M0RPI's conflicted*
/.claude
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: ggpedigree
Title: Visualizing Pedigrees with 'ggplot2' and 'plotly'
Version: 1.1.1.1
Version: 1.1.1.9
Date/Publication: 2026
Authors@R: c(
person("S. Mason", "Garrison", email= "garrissm@wfu.edu", role = c("aut", "cre", "cph"),
Expand All @@ -25,6 +25,7 @@ Imports:
tidyr
Suggests:
selectr (>= 0.5-1),
svglite,
kinship2,
quadprog,
ggrepel,
Expand Down
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# ggpedigree (development version)
# ==============================

## New features
* Added more flexibility to overlays, including support for shape-mode overlays with custom numeric codes and colors.
* Added a new vignette to explain the clinical preset and its features.

## Bug fixes
* Fixed multi-overlay closure bug where all overlays were filtered on the last column in the list due to R's lazy evaluation of function arguments. Local variable assignment now forces evaluation at the correct loop iteration.
* Fixed `preset` (e.g., `"clinical"`) not being forwarded to `getDefaultPlotConfig()` in `ggPedigree()` and `ggPedigreeInteractive()`, which meant preset-driven settings like `overlay_mode = "shape"` and `overlay_include = TRUE` were silently ignored.

# ggpedigree Version: 1.1.1.1
* Hotpatch to fix plotly vignette selectively failing by using tryCatch to catch the error and print a warning instead of failing the whole vignette build.
* Also increased test coverage of kinship2_pedigree.
Expand Down
95 changes: 92 additions & 3 deletions R/defaultPlotConfig.R
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
#' @param status_color_affected Color for affected individuals.
#' @param status_color_unaffected Color for unaffected individuals.
#' @param overlay_shape Shape used for overlaying points in the plot. Default is 4 (cross).
#' When overlay_mode is "shape", accepts named strings: "cross", "slash", "x".
#' @param overlay_code_affected Code for affected individuals in overlay. Default is 1.
#' @param overlay_code_unaffected Code for unaffected individuals in overlay. Default is 0.
#' @param overlay_label_affected Label for affected individuals in overlay. Default is "Affected".
Expand All @@ -131,6 +132,13 @@
#' @param overlay_alpha_unaffected Alpha for unaffected individuals in overlay. Default is 0.
#' @param overlay_color Color for overlay points. Default is "black".
#' @param overlay_include Whether to include overlay points in the plot. Default is FALSE.
#' @param overlay_mode Character string specifying the overlay rendering mode.
#' "alpha" (default) uses alpha transparency mapping; "shape" draws a shape overlay
#' on matching individuals (e.g., cross for deceased markers).
#' @param overlay_size Numeric. Size of the shape overlay. Default is NULL (inherits from point_size).
#' Only used when overlay_mode is "shape".
#' @param overlay_stroke Stroke width for the shape overlay. Default is 1.5.
#' Only used when overlay_mode is "shape".
#' @param overlay_legend_title Title of the overlay legend. Default is "Overlay".
#' @param overlay_legend_show Whether to show the overlay legend. Default is FALSE.
#' @param focal_fill_include Whether to fill focal individuals. Default is FALSE.
Expand Down Expand Up @@ -186,6 +194,25 @@
#' @param recode_missing_sex Whether to recode missing sex codes in the pedigree. Default is TRUE.
#' @param debug Whether to enable debugging mode.
#' @param add_phantoms Whether to add phantom parents for individuals without parents.
#' @param affected_fill_include Whether to enable affected fill styling. Default is FALSE.
#' @param affected_fill_code_affected Value in the affected fill column that triggers filling. Default is 1.
#' @param affected_fill_code_unaffected Value in the affected fill column for unaffected individuals. Default is 0.
#' @param affected_fill_label_affected Label for affected individuals in fill legend. Default is "Affected".
#' @param affected_fill_label_unaffected Label for unaffected individuals in fill legend. Default is "Unaffected".
#' @param affected_fill_color_affected Color used to fill symbols for affected individuals. Default is "black".
#' @param affected_fill_color_unaffected Color used to fill symbols for unaffected individuals. Default is NA (transparent).

Check notice on line 203 in R/defaultPlotConfig.R

View check run for this annotation

codefactor.io / CodeFactor

R/defaultPlotConfig.R#L203

Lines should not be more than 120 characters. This line is 124 characters. (line_length_linter)
#' @param affected_fill_shape_female Filled shape for affected females. Default is 21 (filled circle).
#' @param affected_fill_shape_male Filled shape for affected males. Default is 22 (filled square).
#' @param affected_fill_shape_unknown Filled shape for affected unknown sex. Default is 23 (filled diamond).
#' @param outline_color_include Whether to enable column-based outline coloring. Default is FALSE.
#' @param outline_color_code_affected Value in the outline color column that triggers colored outlines. Default is 1.
#' @param outline_color_code_unaffected Value in the outline color column for default outlines. Default is 0.
#' @param outline_color_label_affected Label for highlighted outline individuals. Default is "Highlighted".
#' @param outline_color_label_unaffected Label for default outline individuals. Default is "Default".
#' @param outline_color_affected Color used for highlighted outlines. Default is "blue".
#' @param outline_color_unaffected Color used for default (non-highlighted) outlines. Default is "black".
#' @param preset Optional preset name for default styling combinations.
#' Currently supported: "clinical" for standard clinical pedigree styling. Default is "none" (no preset).
#' @param ... Additional arguments for future extensibility.
#' @return A named list of default plotting and layout parameters.
#' @export
Expand Down Expand Up @@ -325,6 +352,9 @@
overlay_alpha_unaffected = 0,
overlay_color = "black",
overlay_include = FALSE,
overlay_mode = "alpha",
overlay_size = NULL,
overlay_stroke = 1.5,
overlay_legend_title = "Overlay",
overlay_legend_show = FALSE,
# ---- Focal Fill Settings ----
Expand Down Expand Up @@ -408,15 +438,37 @@
recode_missing_ids = TRUE,
recode_missing_sex = TRUE,
add_phantoms = FALSE,
# ---- Clinical Pedigree Styling ----
# -- Affected Fill --
affected_fill_include = FALSE,
affected_fill_code_affected = 1,
affected_fill_code_unaffected = 0,
affected_fill_label_affected = "Affected",
affected_fill_label_unaffected = "Unaffected",
affected_fill_color_affected = "black",
affected_fill_color_unaffected = NA,
affected_fill_shape_female = 21,
affected_fill_shape_male = 22,
affected_fill_shape_unknown = 23,
# -- Outline Color --
outline_color_include = FALSE,
outline_color_code_affected = 1,
outline_color_code_unaffected = 0,
outline_color_label_affected = "Highlighted",
outline_color_label_unaffected = "Default",
outline_color_affected = "blue",
outline_color_unaffected = "black",
# -- Preset --
preset = "none",
# ---- Future Extensibility ----
...) {
# Ensure the color palette is a character vector
if (!is.character(color_palette_default) ||
length(color_palette_default) < 3) {

Check notice on line 467 in R/defaultPlotConfig.R

View check run for this annotation

codefactor.io / CodeFactor

R/defaultPlotConfig.R#L467

Indentation should be 8 spaces but is 4 spaces. (indentation_linter)
stop("color_palette_default must be a character vector with at least 3 colors.")
}
if (!is.character(segment_default_color) ||
length(segment_default_color) != 1) {

Check notice on line 471 in R/defaultPlotConfig.R

View check run for this annotation

codefactor.io / CodeFactor

R/defaultPlotConfig.R#L471

Indentation should be 8 spaces but is 4 spaces. (indentation_linter)
stop("segment_default_color must be a single character string.")
}

Expand Down Expand Up @@ -454,7 +506,7 @@
}
color_theme_lower <- stringr::str_to_lower(color_theme)

if (color_theme_lower %in% c(grey_color_names, black_color_names)) {
if (color_theme_lower %in% c(grey_color_names, black_color_names) || identical(preset, "clinical")) {
color_palette_default <- greyscale_palette_default
color_palette_low <- greyscale_low
color_palette_mid <- greyscale_mid
Expand Down Expand Up @@ -625,6 +677,9 @@
overlay_color = overlay_color,
overlay_alpha_affected = overlay_alpha_affected,
overlay_include = overlay_include,
overlay_mode = overlay_mode,
overlay_size = overlay_size,
overlay_stroke = overlay_stroke,
overlay_legend_title = overlay_legend_title,
overlay_legend_show = overlay_legend_show,

Expand Down Expand Up @@ -691,7 +746,29 @@
recode_missing_ids = recode_missing_ids,
recode_missing_sex = recode_missing_sex,
add_phantoms = add_phantoms,
debug = debug
debug = debug,
# ---- Clinical Pedigree Styling ----
# -- Affected Fill --
affected_fill_include = affected_fill_include,
affected_fill_code_affected = affected_fill_code_affected,
affected_fill_code_unaffected = affected_fill_code_unaffected,
affected_fill_label_affected = affected_fill_label_affected,
affected_fill_label_unaffected = affected_fill_label_unaffected,
affected_fill_color_affected = affected_fill_color_affected,
affected_fill_color_unaffected = affected_fill_color_unaffected,
affected_fill_shape_female = affected_fill_shape_female,
affected_fill_shape_male = affected_fill_shape_male,
affected_fill_shape_unknown = affected_fill_shape_unknown,
# -- Outline Color --
outline_color_include = outline_color_include,
outline_color_code_affected = outline_color_code_affected,
outline_color_code_unaffected = outline_color_code_unaffected,
outline_color_label_affected = outline_color_label_affected,
outline_color_label_unaffected = outline_color_label_unaffected,
outline_color_affected = outline_color_affected,
outline_color_unaffected = outline_color_unaffected,
# -- Preset --
preset = preset
)
lc_function_name <- stringr::str_to_lower(function_name)
if (lc_function_name %in% c("ggrelatednessmatrix")) {
Expand All @@ -713,7 +790,7 @@
core_list$return_widget <- FALSE
core_list$return_interactive <- FALSE
} else if (lc_function_name %in%
c("ggphenotypebydegree", "phenotypebydegree")) {

Check notice on line 793 in R/defaultPlotConfig.R

View check run for this annotation

codefactor.io / CodeFactor

R/defaultPlotConfig.R#L793

Indentation should be 15 spaces but is 4 spaces. (indentation_linter)
core_list$point_size <- 1
core_list$plot_title <- "Phenotypic Correlation vs Genetic Relatedness"
core_list$return_static <- FALSE
Expand Down Expand Up @@ -781,6 +858,18 @@
core_list$segment_self_angle <- -75
core_list$segment_self_curvature <- -0.15
}

# Apply clinical preset if specified
if (identical(preset, "clinical")) {
# Clinical defaults: shape by sex, unfilled by default, blue outline for included
core_list$sex_color_include <- FALSE
core_list$sex_shape_include <- TRUE
core_list$outline_include <- TRUE
core_list$outline_color <- core_list$outline_color_unaffected
# Configure overlay for shape mode (e.g., cross for deceased markers)
core_list$overlay_include <- TRUE
core_list$overlay_mode <- "shape"
core_list$overlay_shape <- 4 # Cross shape
core_list$overlay_color <- core_list$color_palette_high
}
core_list
}
9 changes: 7 additions & 2 deletions R/ggPedigreeInteractive.R
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
return_widget = TRUE,
hints = NULL,
code_male = NULL,
sexVar = "sex") {
sexVar = "sex",
affected_fill_column = NULL,
outline_color_column = NULL) {
if (!requireNamespace("plotly", quietly = TRUE)) {
stop("The 'plotly' package is required for interactive plots.")
}
Expand Down Expand Up @@ -98,6 +100,7 @@
default_config <- getDefaultPlotConfig(
function_name = "ggPedigreeInteractive",
personID = personID,
preset = if (is.null(config$preset)) "none" else config$preset,
color_theme = ifelse(is.null(config$color_theme), "color", config$color_theme)
)

Expand Down Expand Up @@ -130,7 +133,9 @@
debug = config$debug,
focal_fill_column = focal_fill_column,
function_name = "ggPedigreeInteractive",
sexVar = sexVar
sexVar = sexVar,
affected_fill_column = affected_fill_column,
outline_color_column = outline_color_column
)

## 2. Identify data columns for tooltips ----------------------------------
Expand Down Expand Up @@ -304,7 +309,7 @@
#' "spousehint", "parent_fam", "nid", "x_order",
#' "y_order", "y_fam", "zygosity", "extra", and "x_fam".
#' @return The optimized ggplot object with rounded coordinates and reduced data frame.
#' @keywords internal

Check notice on line 312 in R/ggPedigreeInteractive.R

View check run for this annotation

codefactor.io / CodeFactor

R/ggPedigreeInteractive.R#L312

Indentation should be 2 spaces but is 37 spaces. (indentation_linter)


optimizeStaticPedigree <- function(p, config = list(), variable_drop = c(
Expand Down
30 changes: 27 additions & 3 deletions R/ggpedigree.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
#' @param hints Data frame with hints for layout adjustments. Default: NULL.
#' @param interactive Logical. If TRUE, generates an interactive plot using `plotly`. Default: FALSE.
#' @param overlay_column Character string specifying the column name for overlay alpha values.
#' For a single overlay, this is the simplest interface. For multiple overlays, use
#' the \code{overlays} parameter instead.
#' @param overlays A list of overlay specifications for adding multiple independent overlay
#' layers. Each element should be a list with at minimum a \code{column} entry, plus optional
#' entries: \code{code_affected}, \code{shape}, \code{color}, \code{size}, \code{stroke},
#' \code{mode}. Unspecified entries inherit from the \code{overlay_*} config defaults.
#' When \code{overlays} is provided, \code{overlay_column} is ignored.
#' Example: \code{overlays = list(list(column = "DECES", shape = "cross"),
#' list(column = "PROBAND", shape = 8, color = "red"))}
#' @param tooltip_columns Character vector of column names to show when hovering.
#' Defaults to c("personID", "sex"). Additional columns present in `ped`
#' can be supplied – they will be added to the Plotly tooltip text.
Expand All @@ -29,6 +38,12 @@
#' @param code_male Integer or string. Value identifying males in the sex column. (typically 0 or 1) Default: 1
#' @param sexVar Character string specifying the column name for sex. Defaults to "sex".
#' @param focal_fill_column Character string specifying the column name for focal fill color.
#' @param affected_fill_column Character string specifying the column name for conditional
#' affected fill. When provided, individuals matching the `affected_fill_code_affected` config
#' will have their symbols filled. Default is NULL.
#' @param outline_color_column Character string specifying the column name for outline
#' color control. When provided, individuals matching `outline_color_code_affected` config
#' will have colored outlines (e.g., blue for included). Default is NULL.
#' @param config A list of configuration options for customizing the plot.
#' See getDefaultPlotConfig for details of each option. The list can include:
#' \describe{
Expand Down Expand Up @@ -79,13 +94,16 @@
focal_fill_column = NULL,
tooltip_columns = NULL,
overlay_column = NULL,
overlays = NULL,
return_widget = FALSE,
config = list(),
debug = FALSE,
hints = NULL,
interactive = FALSE,
code_male = NULL,
sexVar = "sex") {
sexVar = "sex",
affected_fill_column = NULL,
outline_color_column = NULL) {
if (!inherits(ped, "data.frame")) {
if (rlang::inherits_any(ped, c("ped", "pedigree", "kinship2.pedigree"))) {
# Convert ped object to data.frame
Expand All @@ -103,7 +121,7 @@
}

if (interactive == TRUE &&
requireNamespace("plotly", quietly = TRUE)) {

Check notice on line 124 in R/ggpedigree.R

View check run for this annotation

codefactor.io / CodeFactor

R/ggpedigree.R#L124

Indentation should be 8 spaces but is 4 spaces. (indentation_linter)
# Call the interactive function with the provided arguments

ggPedigreeInteractive(
Expand All @@ -125,11 +143,13 @@
return_widget = return_widget,
tooltip_columns = tooltip_columns,
code_male = code_male,
sexVar = sexVar
sexVar = sexVar,
affected_fill_column = affected_fill_column,
outline_color_column = outline_color_column
)
} else {
if (interactive == TRUE &&
!requireNamespace("plotly", quietly = TRUE)) {

Check notice on line 152 in R/ggpedigree.R

View check run for this annotation

codefactor.io / CodeFactor

R/ggpedigree.R#L152

Indentation should be 10 spaces but is 6 spaces. (indentation_linter)
message("The 'plotly' package is required for interactive plots.")
}

Expand All @@ -137,6 +157,7 @@
default_config <- getDefaultPlotConfig(
function_name = "ggpedigree",
personID = personID,
preset = if (is.null(config$preset)) "none" else config$preset,
color_theme = ifelse(is.null(config$color_theme), "color", config$color_theme)
)

Expand Down Expand Up @@ -166,13 +187,16 @@
matID = matID,
patID = patID,
overlay_column = overlay_column,
overlays = overlays,
twinID = twinID,
status_column = status_column,
focal_fill_column = focal_fill_column,
config = config,
debug = debug,
hints = hints,
sexVar = sexVar
sexVar = sexVar,
affected_fill_column = affected_fill_column,
outline_color_column = outline_color_column
)
}
}
Expand Down
Loading
Loading