From 36e6e22051fc905325e6638c4e18784e4168d8df Mon Sep 17 00:00:00 2001 From: jmw86069 Date: Fri, 8 Nov 2024 15:59:26 -0500 Subject: [PATCH] Added optional plot title; option for single column main and signed counts; nudge_venndir_label() to adjust set label positions. --- DESCRIPTION | 2 +- NAMESPACE | 2 +- NEWS.md | 49 +++ R/Venndir-class.R | 27 +- R/venndir-base-polyclip.R | 38 ++- R/venndir-label-outside-jp.R | 51 +-- R/venndir-labels.R | 40 ++- R/venndir-nudge-label.R | 317 ++++++++++++++---- R/venndir-render-jp.R | 80 ++++- TODO.md | 66 ++++ man/Venndir-class.Rd | 2 + man/draw_gridtext_groups.Rd | 15 +- man/nudge_venndir_label.Rd | 99 +++++- man/plot.JamPolygon.Rd | 2 +- man/render_venndir.Rd | 18 + man/venndir.Rd | 33 ++ .../euler-2-way-venndir.svg | 64 ++-- .../euler-4-way-venndir.svg | 176 +++++----- .../proportional-nested-render-venndir.svg | 64 ++-- .../proportional-nested-venndir.svg | 64 ++-- .../venn-2-way-venndir.svg | 64 ++-- .../venn-3-way-render-venndir.svg | 84 ++--- .../venn-3-way-venndir.svg | 84 ++--- .../venn-4-way-venndir.svg | 200 +++++------ 24 files changed, 1129 insertions(+), 512 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index e534135..4139708 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: venndir Title: Directional Venn diagrams -Version: 0.0.40.900 +Version: 0.0.41.900 Authors@R: c( person(given="James M.", family="Ward", diff --git a/NAMESPACE b/NAMESPACE index d653e6f..caa7243 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method(plot,JamPolygon) export(add_orientation_JamPolygon) export(area_JamPolygon) export(bbox_JamPolygon) @@ -38,7 +39,6 @@ export(nearest_point_JamPolygon) export(nudge_JamPolygon) export(nudge_venndir_label) export(overlaplist2setlist) -export(plot.JamPolygon) export(point_in_JamPolygon) export(polyclip_to_JamPolygon) export(polygon_circles) diff --git a/NEWS.md b/NEWS.md index 97da73a..87800b5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,52 @@ +# venndir 0.0.41.900 + +## overall + +* Add plot titles! +* Arrange signed counts in single column, under main counts. +* Outside Venn labels default slightly toward the top, rather than the sides. +* `nudge_venndir_label()` is convenient for moving inside or outside labels. + +## changes to existing functions + +* `Venndir` S4 object changes. + + * New slot name `"metadata"` to store miscellaneous settings. + All efforts are made to accept older Venndir objects without + this slot available. + +* `venndir()` + + * New argument `main` to draw a plot title. It uses `gridtext` to + enable custom Markdown font options. + When provided, `main` is also stored in `Venndir@metadata$main` + for persistence. + * New argument `template="wide"` is used to arrange count and signed + count labels together: + `"wide"` places them side-by-side, `"tall"` places them in one column. + When provided, `template` is also stored in `Venndir@metadata$template` + for persistence. + * New argument `center` passed to `label_outside_JamPolygon()`. + The default `center=c(0, -0.15)` tends to place labels at the top + rather than the left/right sides by default. + The default use case is improved. + +* `render_venndir()` + + * Now properly converts set names with `"\n"` to use `"
"` as + originally intended, so it "just works". + * New arguments `main` and `template` as above, except that when + no argument is defined, it will use `Venndir@metadata$template` + or `Venndir@metadata$main` if defined. + +* `nudge_venndir_label()` + + * New argument `offset_list` to define a list of offsets to one or more + sets, where set is defined by `names(offset_list)`. + * New arguments `align_x`,`align_y` to apply uniform alignment of labels + to the top/bottom/left/right of a set of labels. Useful to ensure + labels are the same y-position and not slightly different heights. + # venndir 0.0.40.900 * Updated label positioning logic, silenced some unintended verbose output diff --git a/R/Venndir-class.R b/R/Venndir-class.R index 5eceddc..18077d2 100644 --- a/R/Venndir-class.R +++ b/R/Venndir-class.R @@ -21,7 +21,20 @@ check_Venndir <- function # all(c("jp", "jps", "label_df", "setlist") %in% slotNames(object)) is_valid <- (c("jps", "label_df", "setlist") %in% slotNames(object)) # jamba::printDebug("is_valid:", is_valid); - all(is_valid) + + # new practical validation + vnames <- object@jps@polygons$venn_name; + vsets <- unique(unlist(strsplit(vnames, "&"))) + onames <- object@label_df$overlap_set; + osets <- unique(unlist(strsplit(onames, "&"))) + # validate venn contents + is_valid_venn <- ( + all(vsets %in% names(object@setlist)) && + all(osets %in% names(object@setlist)) && + all(length(vnames) == 0 || + object@jps@polygons$venn_name %in% object@label_df$overlap_set) + ) + all(is_valid) && all(is_valid_venn) } #' Venndir class @@ -103,6 +116,8 @@ check_Venndir <- function #' Previously this data could be inferred from `label_df` which was #' tedious, and required column `"item"` which is optional. #' That said, `setlist` can be an empty `list()`. +#' * **metadata**: `list` with optional metadata, intended for future +#' expansion, such as plot title. #' #' @family JamPolygon #' @@ -111,20 +126,22 @@ setClass("Venndir", # jp="JamPolygon", jps="JamPolygon", label_df="data.frame", - setlist="list" + setlist="list", + metadata="list" ), prototype=prototype( jps=NULL, label_df=data.frame(), - setlist=list() + setlist=list(), + metadata=list() ), validity=check_Venndir ); -#' Plot JamPolygon object +#' Plot Venndir object #' -#' Plot JamPolygon object +#' Plot Venndir object #' #' @returns `Venndir` object, invisibly. #' diff --git a/R/venndir-base-polyclip.R b/R/venndir-base-polyclip.R index 2d13343..7352b43 100644 --- a/R/venndir-base-polyclip.R +++ b/R/venndir-base-polyclip.R @@ -47,6 +47,11 @@ #' * _i_tems: "i" only, by default hidden. When enabled, item labels #' defined by `show_items` are spread across the specific Venn overlap #' region. +#' @param main `character` string used as a plot title, default NULL +#' will render no title. When provided, it is rendered using +#' `gridtext::richtext_grob()` which enables some Markdown-style +#' formatting. The title is stored in `venndir@metadata$title` +#' for persistence. #' @param return_items `logical` (default TRUE) indicating whether to #' return items in the overlap data. When `FALSE` item labels also #' cannot be displayed in the figure. @@ -91,6 +96,16 @@ #' * `"box"` adds a dark border around the label region #' @param label_preset `character` deprecated in favor of `show_labels`. #' This argument is passed to `venndir_label_style()`. +#' @param template `character` (default "wide") describing the default +#' layout for counts and signed counts. The value is stored in +#' `venndir@metadata$template` for persistence. +#' * `"wide"` - main counts on the left, right-justified; signed counts +#' on the right, left-justified. +#' This option is preferred for small numbers, and less-crowded diagrams. +#' * `"tall"` - main counts, center-justified; signed counts below main +#' counts, center-justified. +#' This option is recommended for large numbers (where there are 1000 +#' or more items in a single overlap region), or for crowded diagrams. #' @param unicode `logical` (default TRUE) indicating whether to #' display Unicode arrows for signed overlaps. Passed to #' `curate_venn_labels()`. @@ -141,6 +156,16 @@ #' @param r `numeric` radius in units `"mm"` used for rounded #' rectangle corners for labels. Only visible when `label_preset` #' includes a background fill ("lite", "shaded", "fill"), or "box". +#' @param center `numeric` coordinates relative to the plot bounding box, +#' default `c(0, -0.15)` uses a center point in the middle (x=0) +#' and slightly down (y=-0.15) from the plot center. +#' It is used to place labels outside the diagram. +#' In short, labels are placed by drawing a line from this center point, +#' outward through the Venn overlap region to be labeled. The +#' label is positioned outside the polygon region by `segment_distance`. +#' The default `c(0, -0.15)` ensures that labels tend to be at the +#' top of the plot, and not on the left/right side of the plot. +#' This argument is passed along to `label_outside_JamPolygon()`. #' @param segment_distance `numeric` value indicating the distance #' between outside labels and the outer edge of the Venn diaram region. #' Larger values place labels farther away, while also shrinking the @@ -229,6 +254,7 @@ venndir <- function legend_labels=NULL, proportional=FALSE, show_labels="Ncs", + main=NULL, return_items=TRUE, show_items=c(NA, "none", @@ -250,6 +276,8 @@ venndir <- function "lite", "lite_box"), label_preset="none", + template=c("wide", + "tall"), unicode=TRUE, big.mark=",", curate_df=NULL, @@ -263,6 +291,7 @@ venndir <- function sign_count_delim=": ", padding=c(3, 2), r=2, + center=c(0, -0.15), segment_distance=0.1, sep="&", do_plot=TRUE, @@ -282,6 +311,7 @@ venndir <- function overlap_type <- match.arg(overlap_type); item_style <- match.arg(item_style); + template <- match.arg(template); # show_set <- match.arg(show_set); show_set <- "main"; @@ -589,6 +619,7 @@ venndir <- function jp=venn_jps[use_whichset, ], which_jp=seq_along(use_whichset), distance=segment_distance, + center=center, # center_method="label", verbose=verbose, buffer=-0.9, @@ -887,8 +918,9 @@ venndir <- function vo <- new("Venndir", jps=venn_jps, label_df=label_df, - setlist=setlist) - + setlist=setlist, + metadata=list(template=template)) + ## venndir_label_style() # # Todo: use real x_outside @@ -964,7 +996,7 @@ venndir <- function # jps=venn_jps, # label_df=label_df, # setlist=setlist) - + # Optionally plot if (do_plot) { gg <- render_venndir( diff --git a/R/venndir-label-outside-jp.R b/R/venndir-label-outside-jp.R index 06b9c32..172e92f 100644 --- a/R/venndir-label-outside-jp.R +++ b/R/venndir-label-outside-jp.R @@ -118,30 +118,37 @@ label_outside_JamPolygon <- function # get center set.seed(seed); - if (length(center) != 2) { - if ("bbox" %in% center_method || length(which_jp) == 1) { - center <- matrix(ncol=2, - rowMeans(jpbox)) + (rnorm(2) / 1000); - } else if ("label" %in% center_method) { - # use mean of label positions - if (all(c("label_x", "label_y") %in% colnames(jp))) { - center <- cbind( - x=mean(range(jp@polygons$label_x[which_jp], na.rm=TRUE)), - y=mean(range(jp@polygons$label_y[which_jp], na.rm=TRUE))) - } else { - label_xy <- labelr_JamPolygon(jp[which_jp, ]); - # average from range of labels - # center <- cbind( - # x=mean(range(label_xy[,1], na.rm=TRUE)), - # y=mean(range(label_xy[,2], na.rm=TRUE))) - # average from all actual labels - center <- cbind( - x=mean(label_xy[,1], na.rm=TRUE), - y=mean(label_xy[,2], na.rm=TRUE)) - } + # calculate plot center + if ("bbox" %in% center_method || length(which_jp) == 1) { + new_center <- matrix(ncol=2, + rowMeans(jpbox)) + (rnorm(2) / 1000); + } else if ("label" %in% center_method) { + # use mean of label positions + if (all(c("label_x", "label_y") %in% colnames(jp))) { + new_center <- cbind( + x=mean(range(jp@polygons$label_x[which_jp], na.rm=TRUE)), + y=mean(range(jp@polygons$label_y[which_jp], na.rm=TRUE))) + } else { + label_xy <- labelr_JamPolygon(jp[which_jp, ]); + # average from range of labels + # center <- cbind( + # x=mean(range(label_xy[,1], na.rm=TRUE)), + # y=mean(range(label_xy[,2], na.rm=TRUE))) + # average from all actual labels + new_center <- cbind( + x=mean(label_xy[,1], na.rm=TRUE), + y=mean(label_xy[,2], na.rm=TRUE)) + } + } + if (length(center) == 2) { + # relative adjustment + if (TRUE %in% relative) { + center[1] <- diff(jpbox["x", ]) * center[1]; + center[2] <- diff(jpbox["x", ]) * center[2]; } + center <- center + new_center; } else { - center <- matrix(ncol=2, head(center, 2)); + center <- new_center } colnames(center) <- c("x", "y"); # jamba::printDebug("center:");print(center);# debug diff --git a/R/venndir-labels.R b/R/venndir-labels.R index 454c894..9337b7f 100644 --- a/R/venndir-labels.R +++ b/R/venndir-labels.R @@ -26,9 +26,9 @@ #' label_df_rowname, name, childName, gdf_group. #' Importantly, it must be in identical row order as `gdf`. #' @param segment_df `data.frame` with segment coordinates, optional. -#' @param realign `logical` experimental feature indicating whether to -#' realign grouped labels, thus ignoring the hjust/vjust for each -#' label, instead arranging the labels using `groupdf`. +#' @param realign `logical` experimental feature (now default) indicating +#' whether to realign grouped labels, thus ignoring the hjust/vjust +#' for each label, instead arranging the labels using `groupdf`. #' In principle, overlap label (set name) should be top-center, #' and counts should be centered below. When there are main counts #' and signed counts, they should be in two columns, collectively @@ -41,6 +41,11 @@ #' This option is `FALSE` specifically for two-column labels positioned #' around a fixed centerpoint, where one column could be wider than the #' other, and it would otherwise push the other column the other way. +#' @param template `character` string (default "wide") with experimental +#' layout templates for count and signed labels. +#' * `"wide"` - original strategy with signed counts beside main counts. +#' * `"tall"` - new strategy with main counts and signed counts in +#' the same column. #' @param do_draw `logical` indicating whether to draw the finished #' result in the context of the current open graphics device. #' @param verbose `logical` indicating whether to print verbose output. @@ -54,6 +59,8 @@ draw_gridtext_groups <- function segment_df=NULL, realign=TRUE, adjust_center=FALSE, + template=c("wide", + "tall"), adjx_fn=c, adjy_fn=c, do_draw=TRUE, @@ -68,6 +75,7 @@ draw_gridtext_groups <- function } return(gdf); } + template <- match.arg(template); # internal helper function grob_group_roundrect <- function @@ -82,9 +90,11 @@ draw_gridtext_groups <- function adjx_fn=c, adjy_fn=c, adjust_center=FALSE, + template=c("wide", "tall"), verbose=FALSE) { # adjust_centered=FALSE turns off adjustment for adj=0.5 + template <- match.arg(template); # # adapted from gridtext::richtext_grob() internals # if (all(c(1,2,3) %in% k)) { verbose <- TRUE } @@ -155,7 +165,11 @@ draw_gridtext_groups <- function use_vp <- signed_grobs[[1]]$vp } # stack then left-align - gt_signed <- grobs_xalign(xalign="left", + use_xalign <- "center"; + if ("wide" %in% template) { + use_xalign <- "left"; + } + gt_signed <- grobs_xalign(xalign=use_xalign, grobs_stack(signed_grobs, name=paste0(gdfbasename, ".signed"))) } @@ -171,7 +185,7 @@ draw_gridtext_groups <- function # stack then center-align, # or right-align if there are also signed counts use_xalign <- "center" - if (any(is_signed_count)) { + if (any(is_signed_count) && "wide" %in% template) { use_xalign <- "right" } gt_main <- grobs_xalign(xalign=use_xalign, @@ -181,9 +195,18 @@ draw_gridtext_groups <- function ## combine count labels if needed gt_signed_count <- NULL; if (any(is_main_count) && any(is_signed_count)) { - gt_signed_count <- grobs_yalign(yalign="middle", - grobs_tile(list(gt_main, gt_signed), - name=paste0(gdfbasename, ".main_signed"))) + if ("wide" %in% template) { + # use_yalign <- "top"; + use_yalign <- "middle"; + gt_signed_count <- grobs_yalign(yalign=use_yalign, + grobs_tile(list(gt_main, gt_signed), + name=paste0(gdfbasename, ".main_signed"))) + } else if ("tall" %in% template) { + use_xalign <- "center"; + gt_signed_count <- grobs_xalign(xalign=use_xalign, + grobs_stack(list(gt_main, gt_signed), + name=paste0(gdfbasename, ".main_signed"))) + } } else if (any(is_main_count)) { gt_signed_count <- gt_main; } else if (any(is_signed_count)) { @@ -535,6 +558,7 @@ draw_gridtext_groups <- function adjx_fn=adjx_fn, adjy_fn=adjy_fn, adjust_center=adjust_center, + template=template, segment_df=segment_df, verbose=verbose); rr_grobs <- c(rr_grobs, diff --git a/R/venndir-nudge-label.R b/R/venndir-nudge-label.R index 3561c40..cec9065 100644 --- a/R/venndir-nudge-label.R +++ b/R/venndir-nudge-label.R @@ -1,14 +1,61 @@ -#' Nudge venndir label +#' Nudge venndir labels #' -#' Nudge venndir label, work in progress currently +#' Nudge venndir labels +#' +#' Venndir labels are defined for each overlap polygon, with "inner" +#' and "outer" label coordinates for each polygon. +#' The `show_labels` argument to `venndir()` defines which labels +#' are placed inside and outside the Venn diagram polygons. +#' This function is useful to adjust the position of one or more +#' labels. +#' +#' This function does not determine whether labels are displayed inside +#' or outside the Venn polygons. #' #' @family venndir utility #' #' @param venndir_output output from `venndir()` as `Venndir` object. -#' @param set `character` name of the set or overlap to adjust +#' @param set `character` name of the sets or overlaps to adjust. +#' @param x_offset,y_offset `numeric` coordinates to adjust, recycled +#' to the number of entries provided in `set`. +#' @param offset_list `list` (default NULL) used as a shorthand alternative +#' to `set`,`x_offset`,`y_offset`. The format is a `list` with x,y +#' offset values, with list elements named by set. For example: +#' `offset_list = list(setA=c(0, 0.1), set_B=c(-0.1, 0))` +#' @param align_y,align_x `character` string for optional alignment of +#' labels, where all labels in `set` are aligned. +#' * This option is recommended only with `label_location="outside"`, +#' in order to align labels relative to each other. +#' * It is recommeded for example, to make sure two top labels +#' are placed at the same height relative to each other. +#' * All labels in `set` are adjusted as a group, after applying +#' `x_offset`,`y_offset`. +#' * The coordinates of all labels in `set` are used, then the +#' target coordinate is defined by the logic: +#' * `"top","middle","bottom"` - uses the highest, middle, or lowest +#' coordinate among the labels in `set`. +#' * `"left","center","right"` - uses the left-most, center, or +#' right-most coordinate among the labels in `set`. +#' @param unit_type `character` string (default "relative") defining how +#' to interpret the `x_offset`,`y_offset` values. +#' * `"relative"` - interprets the adjustment relative to the plot +#' bounding box, specifically the largest axis span. +#' This option is useful when the plot span is not known. +#' * `"absolute"` - interprets the adjustment with absolute units, +#' which is useful when the plot span is known. +#' @param label_location `character` string (default "outside") indicating +#' which label coordinate to adjust: +#' * `"outside"` - will only adjust the outer label, leaving the inner +#' label position unaffected. +#' * `"inside"` - will only adjust the inner label, leaving the outer +#' label position unaffected. +#' * `"all"` - will adjust both the inner and outer label positions +#' together. +#' @param verbose `logical` indicating whether to print verbose output. +#' @param ... additional arguments are ignored. #' -#' @returns `Venndir` object as output from `venndir()` +#' @returns `Venndir` object after adjusting label coordinates #' #' @examples #' setlist1 <- make_venn_test(100, 3, do_signed=TRUE) @@ -20,53 +67,99 @@ #' main="Default venndir") #' render_venndir(vo1) #' +#' head(vo1@label_df[, c("x", "x_offset", "y", "y_offset")], 3) +#' subset(vo1@label_df, overlap_set %in% "set_A")[, c("x", "x_offset", "y", "y_offset")] +#' #' vo2 <- nudge_venndir_label(vo1, -#' set=c("set_A&set_B&set_C"), -#' x_offset=0.05, -#' y_offset=-0.05) +#' set=c("set_A", "set_B"), +#' x_offset=c(-0.1, 0.1), +#' y_offset=c(0)) #' render_venndir(vo2) #' +#' # alternative with offset_list +#' vo2b <- nudge_venndir_label(vo1, +#' offset_list=list( +#' set_A=c(0.1, 0), +#' set_B=c(0.1, 0), +#' set_C=c(0.4, 0.4))) +#' render_venndir(vo2b) +#' +#' # now align two labels at the top +#' vo2c <- nudge_venndir_label(vo2b, +#' set=c("set_A", "set_B"), +#' align_y="top") +#' render_venndir(vo2c) +#' #' @export nudge_venndir_label <- function (venndir_output, set=NULL, x_offset=0, y_offset=0, + offset_list=NULL, + align_y=c("none", + "top", + "middle", + "bottom"), + align_x=c("none", + "left", + "center", + "right"), unit_type=c("relative", "absolute"), - label_types=c("main", - "signed"), - label_location=c("all", - "inside", - "outside"), - show_label=TRUE, + label_location="outside", verbose=FALSE, ...) { # validate input - label_location <- match.arg(label_location); + if (!inherits(venndir_output, "Venndir")) { + stop("Input must inherit class Venndir.") + } + label_location <- match.arg(label_location, + several.ok=TRUE, + choices=c("outside", "inside", "all")); unit_type <- match.arg(unit_type); + + ## offset_list takes priority + if (length(offset_list) > 0) { + if (verbose) { + jamba::printDebug("nudge_venndir_label(): ", + "Using offset_list to define: ", + c("set", "x_offset", "y_offset.")); + } + set <- names(offset_list); + x_offset <- sapply(offset_list, function(i){ + rep(i, length.out=2)[1] + }) + y_offset <- sapply(offset_list, function(i){ + rep(i, length.out=2)[2] + }) + } + + # confirm set is present in the data + # todo: consider also recognizing setlist_names, if needed if (!any(set %in% venndir_output@label_df$overlap_set)) { - warning(paste0("No values found in label_df$overlap_set using set:", - jamba::cPaste(paste0("'", set, "'")))); + warning(paste0( + "No values found in venndir_output@label_df$overlap_set using set ", + jamba::cPaste(paste0("'", set, "'"), sep=", "))); return(venndir_output); } x_offset <- rep(x_offset, length.out=length(set)); y_offset <- rep(y_offset, length.out=length(set)); - show_label <- rep(show_label, length.out=length(set)); + label_location <- rep(label_location, length.out=length(set)); + names(x_offset) <- set; + names(y_offset) <- set; + names(label_location) <- set; - # adjust by unit_type "relative" by using the bounding box dimensions - if ("Venndir" %in% class(venndir_output)) { - vo <- venndir_output; - } else { - stop("Input must be a Venndir object."); - } + # define units by max range on either axis if ("relative" %in% unit_type) { - unit_scalars <- apply(bbox_JamPolygon(vo@jps), 1, diff) + unit_scalars <- apply(bbox_JamPolygon(venndir_output@jps), 1, diff) + unit_scalars <- rep(max(unit_scalars), length.out=2) x_offset <- x_offset * unit_scalars[1]; y_offset <- y_offset * unit_scalars[2]; } - use_set <- which(set %in% vo@label_df$overlap_set); + + use_set <- which(set %in% venndir_output@label_df$overlap_set); if (verbose) { jamba::printDebug("nudge_venndir_label(): ", "x_offset: ", x_offset); @@ -78,11 +171,11 @@ nudge_venndir_label <- function "use_set: ", use_set); } # create new column if needed - if (!"x_offset" %in% colnames(vo@label_df)) { - vo@label_df$x_offset <- 0; + if (!"x_offset" %in% colnames(venndir_output@label_df)) { + venndir_output@label_df$x_offset <- 0; } - if (!"y_offset" %in% colnames(vo@label_df)) { - vo@label_df$y_offset <- 0; + if (!"y_offset" %in% colnames(venndir_output@label_df)) { + venndir_output@label_df$y_offset <- 0; } # adjust each set x_offset, y_offset @@ -92,39 +185,151 @@ nudge_venndir_label <- function jamba::printDebug("nudge_venndir_label(): ", "iset: ", iset); } - voi <- which(vo@label_df$overlap_set %in% iset & - vo@label_df$type %in% label_types); - if ("all" %in% label_location) { + # define rows matching iset + # 0.0.41.900 - do not subset by label type + voi <- which(venndir_output@label_df$overlap_set %in% iset); + # voi <- which(venndir_output@label_df$overlap_set %in% iset & + # venndir_output@label_df$type %in% label_types); + + if (any(c("inside", "all") %in% label_location)) { # adjust the inside which also adjusts the outside - vo@label_df$x[voi] <- vo@label_df$x[voi] + x_offset[i]; - vo@label_df$y[voi] <- vo@label_df$y[voi] + y_offset[i]; - vo@label_df$show_label[voi] <- show_label[i]; - } else if ("inside" %in% label_location) { - # adjust main label location - vo@label_df$x[voi] <- vo@label_df$x[voi] + x_offset[i]; - vo@label_df$y[voi] <- vo@label_df$y[voi] + y_offset[i]; - vo@label_df$show_label[voi] <- show_label[i]; - # adjust outside location exactly opposite to offset - vo@label_df$x_offset[voi] <- vo@label_df$x_offset[voi] - x_offset[i]; - vo@label_df$y_offset[voi] <- vo@label_df$y_offset[voi] - y_offset[i]; - vo@label_df$show_label[voi] <- show_label[i]; - } else if ("outside" %in% label_location) { + venndir_output@label_df$x[voi] <- venndir_output@label_df$x[voi] + x_offset[iset]; + venndir_output@label_df$y[voi] <- venndir_output@label_df$y[voi] + y_offset[iset]; + # venndir_output@label_df$show_label[voi] <- show_label[iset]; + } + if ("inside" %in% label_location) { + # if only the inside should be adjusted, counteradjust the outside + venndir_output@label_df$x_offset[voi] <- venndir_output@label_df$x_offset[voi] - x_offset[iset]; + venndir_output@label_df$y_offset[voi] <- venndir_output@label_df$y_offset[voi] - y_offset[iset]; + # venndir_output@label_df$show_label[voi] <- show_label[iset]; + } + if ("outside" %in% label_location) { # adjust the outside offset only - vo@label_df$x_offset[voi] <- vo@label_df$x_offset[voi] + x_offset[i]; - vo@label_df$y_offset[voi] <- vo@label_df$y_offset[voi] + y_offset[i]; - vo@label_df$show_label[voi] <- show_label[i]; + venndir_output@label_df$x_offset[voi] <- venndir_output@label_df$x_offset[voi] + x_offset[iset]; + venndir_output@label_df$y_offset[voi] <- venndir_output@label_df$y_offset[voi] + y_offset[iset]; + # venndir_output@label_df$show_label[voi] <- show_label[i]; } if (verbose) { jamba::printDebug("nudge_venndir_label(): ", indent=6, - "voi: ", voi); - jamba::printDebug("nudge_venndir_label(): ", - indent=6, - "applied x_offset: ", x_offset[i], - ", applied y_offset: ", y_offset[i], - ", applied show_label: ", show_label[i]) - print(vo@label_df[voi, , drop=FALSE]) + "adjusted set '", iset, + "', rows: ", voi, + ", x:", x_offset[iset], + ", y:", y_offset[iset]); + if (verbose > 1) { + print(venndir_output@label_df[voi, , drop=FALSE]);# debug + } } } - return(vo); + + # optional align_y + if (!"none" %in% align_y) { + isets <- set[use_set]; + voi <- which(venndir_output@label_df$overlap_set %in% isets); + if (any(c("all", "inside") %in% label_location)) { + if (verbose) { + jamba::printDebug("nudge_venndir_label(): ", + "Aligning inside label y values for ", + jamba::cPaste(isets, sep=", "), + ": ", align_y); + } + y_values <- venndir_output@label_df$y[voi]; + use_y <- ifelse("top" %in% align_y, + max(y_values, na.rm=TRUE), + ifelse("bottom" %in% align_y, + min(y_values, na.rm=TRUE), + mean(y_values, na.rm=TRUE))) + y_diff <- use_y - y_values; + venndir_output <- nudge_venndir_label( + venndir_output=venndir_output, + set=isets, + x_offset=0, + y_offset=y_diff, + unit_type="absolute", + label_location="inside", + align_x="none", + align_y="none") + } + if (any(c("all", "outside") %in% label_location)) { + if (verbose) { + jamba::printDebug("nudge_venndir_label(): ", + "Aligning outside label y values for ", + jamba::cPaste(isets, sep=", "), + ": ", align_y); + } + y_values <- venndir_output@label_df$y[voi] + + venndir_output@label_df$y_offset[voi] + use_y <- ifelse("top" %in% align_y, + max(y_values, na.rm=TRUE), + ifelse("bottom" %in% align_y, + min(y_values, na.rm=TRUE), + mean(y_values, na.rm=TRUE))) + y_diff <- use_y - y_values; + venndir_output <- nudge_venndir_label( + venndir_output=venndir_output, + set=isets, + x_offset=0, + y_offset=y_diff, + unit_type="absolute", + label_location="outside", + align_x="none", + align_y="none") + } + } + # optional align_x + if (!"none" %in% align_x) { + isets <- set[use_set]; + voi <- which(venndir_output@label_df$overlap_set %in% isets); + if (any(c("all", "inside") %in% label_location)) { + if (verbose) { + jamba::printDebug("nudge_venndir_label(): ", + "Aligning inside label x values for ", + jamba::cPaste(isets, sep=", "), + ": ", align_x); + } + x_values <- venndir_output@label_df$x[voi]; + use_x <- ifelse("right" %in% align_x, + max(x_values, na.rm=TRUE), + ifelse("left" %in% align_x, + min(x_values, na.rm=TRUE), + mean(x_values, na.rm=TRUE))) + x_diff <- use_x - x_values; + venndir_output <- nudge_venndir_label( + venndir_output=venndir_output, + set=isets, + x_offset=x_diff, + y_offset=0, + unit_type="absolute", + label_location="inside", + align_x="none", + align_y="none") + } + if (any(c("all", "outside") %in% label_location)) { + if (verbose) { + jamba::printDebug("nudge_venndir_label(): ", + "Aligning outside label x values for ", + jamba::cPaste(isets, sep=", "), + ": ", align_x); + } + x_values <- venndir_output@label_df$x[voi] + + venndir_output@label_df$x_offset[voi] + use_x <- ifelse("right" %in% align_x, + max(x_values, na.rm=TRUE), + ifelse("left" %in% align_x, + min(x_values, na.rm=TRUE), + mean(x_values, na.rm=TRUE))) + x_diff <- use_x - x_values; + venndir_output <- nudge_venndir_label( + venndir_output=venndir_output, + set=isets, + x_offset=x_diff, + y_offset=0, + unit_type="absolute", + label_location="outside", + align_x="none", + align_y="none") + } + } + + return(venndir_output); } diff --git a/R/venndir-render-jp.R b/R/venndir-render-jp.R index dd99683..fcbe221 100644 --- a/R/venndir-render-jp.R +++ b/R/venndir-render-jp.R @@ -41,6 +41,13 @@ #' label components together, therefore drawing fill and border #' around the group instead of each component. In most cases this #' setting should be TRUE. +#' @param template `character` (default "wide") describing the default +#' layout for counts and signed counts. The value is stored in +#' `venndir@metadata$template` for persistence. +#' * `"wide"` - main counts on the left, right-justified; signed counts +#' on the right, left-justified. +#' * `"tall"` - main counts, center-justified; signed counts below main +#' counts, center-justified. #' @param adjust_center `logical` (default TRUE) used when labels are grouped, #' whether the group should be re-centered on the target point. #' Try `adjust_center=FALSE` if wide label groups are adjusted @@ -78,6 +85,7 @@ render_venndir <- function (venndir_output=NULL, expand_fraction=0, font_cex=1, + main=NULL, item_cex=NULL, item_cex_factor=4, plot_warning=TRUE, @@ -107,6 +115,7 @@ render_venndir <- function "gridtext"), item_buffer=-0.15, group_labels=TRUE, + template=NULL, adjust_center=FALSE, draw_legend=TRUE, legend_x="bottomright", @@ -123,10 +132,16 @@ render_venndir <- function if ("list" %in% class(venndir_output) && "vo" %in% names(venndir_output)) { venndir_output <- venndir_output$vo; } + metadata <- list(); if ("Venndir" %in% class(venndir_output)) { venn_jp <- venndir_output@jps; label_df <- venndir_output@label_df; setlist <- venndir_output@setlist; + metadata <- tryCatch({ + venndir_output@metadata + }, error=function(e){ + list() + }) } else { # legacy input if (length(venndir_output) > 0 && is.list(venndir_output)) { @@ -145,11 +160,39 @@ render_venndir <- function venndir_output <- new("Venndir", jps=venn_jp, label_df=label_df, - setlist=list()) + setlist=list(), + metadata=list()) } else { stop("Input must be 'Venndir' or legacy list with 'jp' and 'label_df'") } } + + # validate other options + if (length(template) > 0) { + template <- match.arg(template, + choices=c("tall", "wide")) + } else { + template <- tryCatch({ + metadata$template; + }, error=function(e){ + NULL; + }) + if (length(template) == 0) { + template <- "wide" + } + } + metadata$template <- template; + if (length(main) > 0) { + metadata$main <- main; + # venndir_output@metadata$main <- main; + } else { + main <- tryCatch({ + venndir_output@metadata$main + }, error=function(e){ + NULL; + }) + } + # jamba::printDebug("render_venndir() label_df:");print(label_df);# debug show_items <- head(setdiff(label_df$show_items, c(NA, "none")), 1); if (length(show_items) == 0) { @@ -629,6 +672,13 @@ render_venndir <- function venn_label <- ifelse(!label_df$venn_label %in% c(NA, ""), paste0("**", label_df$venn_label, "**"), "") + # 0.0.41.900 - also convert \n to
+ if (any(grepl("[\n\r]", venn_label))) { + venn_label <- gsub("\n", "
", + gsub("^[\n]+|[\n]+$", "", + gsub("\n\n", "\n", + gsub("[\r\n]+|
", "\n", venn_label)))) + } is_left <- (label_df$type %in% "main") * 1; # enhancement to apply fontsize from venn_spdf to main set labels label_df$overlap_fontsize <- label_df$fontsize; @@ -846,6 +896,30 @@ render_venndir <- function jp_grobList <- list() jp_grobList$jps <- jp_gTree; + ############################################ + # Plot title + if (length(main) > 0 && any(nchar(main) > 0)) { + main <- gsub("\n", "
", main); + main <- jamba::cPaste(main, sep="
\n"); + nlines <- length(strsplit(main, "
")[[1]]) + # + main_grob <- gridtext::richtext_grob( + text=main, + x=0.5, + y=grid::unit(1, "snpc") - grid::unit(0.75, "char"), + default.units="snpc", + gp=grid::gpar( + # col=itemlabels_df$color, + fontsize=16 * font_cex[1]), + r=grid::unit(c(0, 0, 0, 0), "pt"), + padding=grid::unit(c(0, 0, 0, 0), "pt"), + margin=grid::unit(c(0, 0, 0, 0), "pt"), + vp=jp_viewport, + hjust=0.5, + vjust=1); + jp_grobList$main_title <- main_grob; + } + ############################################ # Item labels # draw using text() @@ -1034,6 +1108,7 @@ render_venndir <- function adjx_fn=adjx, adjy_fn=adjy, do_draw=FALSE, + template=template, verbose=verbose) # dgg$g_labels; dgg @@ -1117,7 +1192,8 @@ render_venndir <- function vo_new <- new("Venndir", jps=venn_jp, label_df=label_df, - setlist=setlist) + setlist=setlist, + metadata=metadata) # venndir legender if (TRUE %in% draw_legend) { diff --git a/TODO.md b/TODO.md index 11a4682..75116c1 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,71 @@ # TODO for venndir +## 08nov2024 + +* Based upon some excellent feedback: + + * DONE. Move default labels above, not beside the Venn diagram. + * DONE. Add option for a plot title. + * DONE. Related, make it "easy" to adjust outer labels. + * DONE. Add option for signed counts below main counts in one column. + * Add option to display signed counts in the legend. + * Add option to display percentage in the legend. + +## 01nov2024 + +* Item label enhancements + + * Debug `item_cex` and `item_cex_factor` not being applied as expected. + + * Consider assigning `item_cex` to `label_df` or `jps` for persistence. + * Consider specific logic when `proportional=TRUE` to assume that + all polygons are already proportional to the number of items. + + * Consider option to retain item factor order when provided, + to control the order they are placed. + * Consider some method to adjust the relative "height" of item labels, + for example multi-line labels should take proportionally more height? + * Allow custom `show_labels` so the set names can be displayed outside. + * Store `item_cex` and `item_buffer` somehow for re-use, otherwise + `plot(venndir_out)` does not retain these settings. + * Improve the default adjustment to `item_buffer` based upon number + of items, and relative size of the polygon. With fewer items (2 or 1), + it should more sharply use the center position. + + * Consider option to justify item label based upon its left-right + position in the polygon. Item labels on left edge would be placed so + the left edge of the label aligns with the left edge of the polygon. + It could help reduce labels overlapping the outside of a polygon. + It might make labels more crowded inside the polygon. + * Consider some option to reduce item label overlaps. + * Consider some approach to place count label box inside the polygon, + with item labels around it? Probably not feasible. + + * Useful test case, to reproduce a published figure. + Note that `as_factor()` does not affect item sorting, only the numeric + prefix seems to work. + ``` + as_factor <- function(x){ + factor(x, levels=unique(x)) + } + venndir::venn_meme(x=list( + CLE=as_factor(c("1 CLE:", + "2 IFNa>IFNb", + "3 Anti-malarials effective\ntherapy for skin disease")), + DM=as_factor(c("1 DM:", + "2 IFNb>IFNa", + "\n3 Triggered by immune\nstimulating herbal\nsupplements", + "\n\n\n4 Anti-malarials effective\nin 25%, commonly causes\nmorbilliform rash", + "\n\n\n\n5 Cannabinoid receptor\nagonist proising\ntreatment")), + `CLE&DM`=as_factor(c( + "1 Photosensitivity", + "2 Triggered by viral and\nbacterial infections", + "3 Increased\ntype I IFN"))), + item_cex=c(1.5, 1.5, 1.2), + xyratio=10, + dither_cex=0) + ``` + ## 13sep2024 * Adjust aesthetics based upon feedback. diff --git a/man/Venndir-class.Rd b/man/Venndir-class.Rd index a5ebc62..dd63d46 100644 --- a/man/Venndir-class.Rd +++ b/man/Venndir-class.Rd @@ -86,6 +86,8 @@ and are not yet fully editable. Previously this data could be inferred from \code{label_df} which was tedious, and required column \code{"item"} which is optional. That said, \code{setlist} can be an empty \code{list()}. +\item \strong{metadata}: \code{list} with optional metadata, intended for future +expansion, such as plot title. } } \seealso{ diff --git a/man/draw_gridtext_groups.Rd b/man/draw_gridtext_groups.Rd index 6075568..54c0587 100644 --- a/man/draw_gridtext_groups.Rd +++ b/man/draw_gridtext_groups.Rd @@ -11,6 +11,7 @@ draw_gridtext_groups( segment_df = NULL, realign = TRUE, adjust_center = FALSE, + template = c("wide", "tall"), adjx_fn = c, adjy_fn = c, do_draw = TRUE, @@ -39,9 +40,9 @@ Importantly, it must be in identical row order as \code{gdf}.} \item{segment_df}{\code{data.frame} with segment coordinates, optional.} -\item{realign}{\code{logical} experimental feature indicating whether to -realign grouped labels, thus ignoring the hjust/vjust for each -label, instead arranging the labels using \code{groupdf}. +\item{realign}{\code{logical} experimental feature (now default) indicating +whether to realign grouped labels, thus ignoring the hjust/vjust +for each label, instead arranging the labels using \code{groupdf}. In principle, overlap label (set name) should be top-center, and counts should be centered below. When there are main counts and signed counts, they should be in two columns, collectively @@ -56,6 +57,14 @@ This option is \code{FALSE} specifically for two-column labels positioned around a fixed centerpoint, where one column could be wider than the other, and it would otherwise push the other column the other way.} +\item{template}{\code{character} string (default "wide") with experimental +layout templates for count and signed labels. +\itemize{ +\item \code{"wide"} - original strategy with signed counts beside main counts. +\item \code{"tall"} - new strategy with main counts and signed counts in +the same column. +}} + \item{do_draw}{\code{logical} indicating whether to draw the finished result in the context of the current open graphics device.} diff --git a/man/nudge_venndir_label.Rd b/man/nudge_venndir_label.Rd index bdfd864..e0ed75f 100644 --- a/man/nudge_venndir_label.Rd +++ b/man/nudge_venndir_label.Rd @@ -2,17 +2,18 @@ % Please edit documentation in R/venndir-nudge-label.R \name{nudge_venndir_label} \alias{nudge_venndir_label} -\title{Nudge venndir label} +\title{Nudge venndir labels} \usage{ nudge_venndir_label( venndir_output, set = NULL, x_offset = 0, y_offset = 0, + offset_list = NULL, + align_y = c("none", "top", "middle", "bottom"), + align_x = c("none", "left", "center", "right"), unit_type = c("relative", "absolute"), - label_types = c("main", "signed"), - label_location = c("all", "inside", "outside"), - show_label = TRUE, + label_location = "outside", verbose = FALSE, ... ) @@ -20,13 +21,74 @@ nudge_venndir_label( \arguments{ \item{venndir_output}{output from \code{venndir()} as \code{Venndir} object.} -\item{set}{\code{character} name of the set or overlap to adjust} +\item{set}{\code{character} name of the sets or overlaps to adjust.} + +\item{x_offset, y_offset}{\code{numeric} coordinates to adjust, recycled +to the number of entries provided in \code{set}.} + +\item{offset_list}{\code{list} (default NULL) used as a shorthand alternative +to \code{set},\code{x_offset},\code{y_offset}. The format is a \code{list} with x,y +offset values, with list elements named by set. For example: +\code{offset_list = list(setA=c(0, 0.1), set_B=c(-0.1, 0))}} + +\item{align_y, align_x}{\code{character} string for optional alignment of +labels, where all labels in \code{set} are aligned. +\itemize{ +\item This option is recommended only with \code{label_location="outside"}, +in order to align labels relative to each other. +\item It is recommeded for example, to make sure two top labels +are placed at the same height relative to each other. +\item All labels in \code{set} are adjusted as a group, after applying +\code{x_offset},\code{y_offset}. +\item The coordinates of all labels in \code{set} are used, then the +target coordinate is defined by the logic: +\item \verb{"top","middle","bottom"} - uses the highest, middle, or lowest +coordinate among the labels in \code{set}. +\item \verb{"left","center","right"} - uses the left-most, center, or +right-most coordinate among the labels in \code{set}. +}} + +\item{unit_type}{\code{character} string (default "relative") defining how +to interpret the \code{x_offset},\code{y_offset} values. +\itemize{ +\item \code{"relative"} - interprets the adjustment relative to the plot +bounding box, specifically the largest axis span. +This option is useful when the plot span is not known. +\item \code{"absolute"} - interprets the adjustment with absolute units, +which is useful when the plot span is known. +}} + +\item{label_location}{\code{character} string (default "outside") indicating +which label coordinate to adjust: +\itemize{ +\item \code{"outside"} - will only adjust the outer label, leaving the inner +label position unaffected. +\item \code{"inside"} - will only adjust the inner label, leaving the outer +label position unaffected. +\item \code{"all"} - will adjust both the inner and outer label positions +together. +}} + +\item{verbose}{\code{logical} indicating whether to print verbose output.} + +\item{...}{additional arguments are ignored.} } \value{ -\code{Venndir} object as output from \code{venndir()} +\code{Venndir} object after adjusting label coordinates } \description{ -Nudge venndir label, work in progress currently +Nudge venndir labels +} +\details{ +Venndir labels are defined for each overlap polygon, with "inner" +and "outer" label coordinates for each polygon. +The \code{show_labels} argument to \code{venndir()} defines which labels +are placed inside and outside the Venn diagram polygons. +This function is useful to adjust the position of one or more +labels. + +This function does not determine whether labels are displayed inside +or outside the Venn polygons. } \examples{ setlist1 <- make_venn_test(100, 3, do_signed=TRUE) @@ -38,12 +100,29 @@ vo1 <- venndir(setlist1, main="Default venndir") render_venndir(vo1) +head(vo1@label_df[, c("x", "x_offset", "y", "y_offset")], 3) +subset(vo1@label_df, overlap_set \%in\% "set_A")[, c("x", "x_offset", "y", "y_offset")] + vo2 <- nudge_venndir_label(vo1, - set=c("set_A&set_B&set_C"), - x_offset=0.05, - y_offset=-0.05) + set=c("set_A", "set_B"), + x_offset=c(-0.1, 0.1), + y_offset=c(0)) render_venndir(vo2) +# alternative with offset_list +vo2b <- nudge_venndir_label(vo1, + offset_list=list( + set_A=c(0.1, 0), + set_B=c(0.1, 0), + set_C=c(0.4, 0.4))) +render_venndir(vo2b) + +# now align two labels at the top +vo2c <- nudge_venndir_label(vo2b, + set=c("set_A", "set_B"), + align_y="top") +render_venndir(vo2c) + } \seealso{ Other venndir utility: diff --git a/man/plot.JamPolygon.Rd b/man/plot.JamPolygon.Rd index 3bdd797..9f0acf7 100644 --- a/man/plot.JamPolygon.Rd +++ b/man/plot.JamPolygon.Rd @@ -4,7 +4,7 @@ \alias{plot.JamPolygon} \title{Plot JamPolygon object} \usage{ -plot.JamPolygon( +\method{plot}{JamPolygon}( x, y, xlim = NULL, diff --git a/man/render_venndir.Rd b/man/render_venndir.Rd index 0cca964..af8a2da 100644 --- a/man/render_venndir.Rd +++ b/man/render_venndir.Rd @@ -8,6 +8,7 @@ render_venndir( venndir_output = NULL, expand_fraction = 0, font_cex = 1, + main = NULL, item_cex = NULL, item_cex_factor = 4, plot_warning = TRUE, @@ -25,6 +26,7 @@ render_venndir( item_style = c("default", "text", "gridtext"), item_buffer = -0.15, group_labels = TRUE, + template = NULL, adjust_center = FALSE, draw_legend = TRUE, legend_x = "bottomright", @@ -49,6 +51,12 @@ to be slighly smaller.} \item{font_cex}{\code{numeric} scalar to adjust font sizes.} +\item{main}{\code{character} string used as a plot title, default NULL +will render no title. When provided, it is rendered using +\code{gridtext::richtext_grob()} which enables some Markdown-style +formatting. The title is stored in \code{venndir@metadata$title} +for persistence.} + \item{item_cex}{\code{numeric} scalar applied to item labels in each overlap in order. When \code{length(item_cex) == 1} it is applied uniformly across all overlaps, otherwise it is recycled to the total @@ -167,6 +175,16 @@ label components together, therefore drawing fill and border around the group instead of each component. In most cases this setting should be TRUE.} +\item{template}{\code{character} (default "wide") describing the default +layout for counts and signed counts. The value is stored in +\code{venndir@metadata$template} for persistence. +\itemize{ +\item \code{"wide"} - main counts on the left, right-justified; signed counts +on the right, left-justified. +\item \code{"tall"} - main counts, center-justified; signed counts below main +counts, center-justified. +}} + \item{adjust_center}{\code{logical} (default TRUE) used when labels are grouped, whether the group should be re-centered on the target point. Try \code{adjust_center=FALSE} if wide label groups are adjusted diff --git a/man/venndir.Rd b/man/venndir.Rd index 507373d..9713cda 100644 --- a/man/venndir.Rd +++ b/man/venndir.Rd @@ -13,6 +13,7 @@ venndir( legend_labels = NULL, proportional = FALSE, show_labels = "Ncs", + main = NULL, return_items = TRUE, show_items = c(NA, "none", "sign item", "sign", "item"), max_items = 3000, @@ -24,6 +25,7 @@ venndir( alpha_by_counts = FALSE, label_style = c("basic", "fill", "shaded", "shaded_box", "lite", "lite_box"), label_preset = "none", + template = c("wide", "tall"), unicode = TRUE, big.mark = ",", curate_df = NULL, @@ -35,6 +37,7 @@ venndir( sign_count_delim = ": ", padding = c(3, 2), r = 2, + center = c(0, -0.15), segment_distance = 0.1, sep = "&", do_plot = TRUE, @@ -116,6 +119,12 @@ defined by \code{show_items} are spread across the specific Venn overlap region. }} +\item{main}{\code{character} string used as a plot title, default NULL +will render no title. When provided, it is rendered using +\code{gridtext::richtext_grob()} which enables some Markdown-style +formatting. The title is stored in \code{venndir@metadata$title} +for persistence.} + \item{return_items}{\code{logical} (default TRUE) indicating whether to return items in the overlap data. When \code{FALSE} item labels also cannot be displayed in the figure. @@ -177,6 +186,19 @@ There are pre-defined label styles. \item{label_preset}{\code{character} deprecated in favor of \code{show_labels}. This argument is passed to \code{venndir_label_style()}.} +\item{template}{\code{character} (default "wide") describing the default +layout for counts and signed counts. The value is stored in +\code{venndir@metadata$template} for persistence. +\itemize{ +\item \code{"wide"} - main counts on the left, right-justified; signed counts +on the right, left-justified. +This option is preferred for small numbers, and less-crowded diagrams. +\item \code{"tall"} - main counts, center-justified; signed counts below main +counts, center-justified. +This option is recommended for large numbers (where there are 1000 +or more items in a single overlap region), or for crowded diagrams. +}} + \item{unicode}{\code{logical} (default TRUE) indicating whether to display Unicode arrows for signed overlaps. Passed to \code{curate_venn_labels()}. @@ -242,6 +264,17 @@ for overlap count, and signed overlap count labels, in order.} rectangle corners for labels. Only visible when \code{label_preset} includes a background fill ("lite", "shaded", "fill"), or "box".} +\item{center}{\code{numeric} coordinates relative to the plot bounding box, +default \code{c(0, -0.15)} uses a center point in the middle (x=0) +and slightly down (y=-0.15) from the plot center. +It is used to place labels outside the diagram. +In short, labels are placed by drawing a line from this center point, +outward through the Venn overlap region to be labeled. The +label is positioned outside the polygon region by \code{segment_distance}. +The default \code{c(0, -0.15)} ensures that labels tend to be at the +top of the plot, and not on the left/right side of the plot. +This argument is passed along to \code{label_outside_JamPolygon()}.} + \item{segment_distance}{\code{numeric} value indicating the distance between outside labels and the outer edge of the Venn diaram region. Larger values place labels farther away, while also shrinking the diff --git a/tests/testthat/_snaps/proportional-figure/euler-2-way-venndir.svg b/tests/testthat/_snaps/proportional-figure/euler-2-way-venndir.svg index cd7862c..28c6fee 100644 --- a/tests/testthat/_snaps/proportional-figure/euler-2-way-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/euler-2-way-venndir.svg @@ -18,38 +18,38 @@ - - - - - - - - - - - - - - - - - - -25 -↑:12 -↓:13 -set_A -7 -↑↑:4 -↓↓:2 -X:1 -9 -↑:5 -↓:4 -set_B - - + + + + + + + + + + + + + + + + + + +25 +↑:12 +↓:13 +set_A +7 +↑↑:4 +↓↓:2 +X:1 +9 +↑:5 +↓:4 +set_B + + diff --git a/tests/testthat/_snaps/proportional-figure/euler-4-way-venndir.svg b/tests/testthat/_snaps/proportional-figure/euler-4-way-venndir.svg index 7d9dd0e..23372a3 100644 --- a/tests/testthat/_snaps/proportional-figure/euler-4-way-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/euler-4-way-venndir.svg @@ -18,94 +18,94 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -18 -↑:9 -↓:9 -set_A -4 -↑↑:2 -↓↓:1 -X:1 -1 -X:1 -1 -↑↑↑:1 -8 -↑↑:2 -↓↓:2 -X:4 -8 -↑:5 -↓:3 -set_B -2 -↑↑:1 -↓↓:1 -6 -↑:1 -↓:5 -set_C -1 -↑:1 -set_D - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +18 +↑:9 +↓:9 +set_A +4 +↑↑:2 +↓↓:1 +X:1 +1 +X:1 +1 +↑↑↑:1 +8 +↑↑:2 +↓↓:2 +X:4 +8 +↑:5 +↓:3 +set_B +2 +↑↑:1 +↓↓:1 +6 +↑:1 +↓:5 +set_C +1 +↑:1 +set_D + + + + diff --git a/tests/testthat/_snaps/proportional-figure/proportional-nested-render-venndir.svg b/tests/testthat/_snaps/proportional-figure/proportional-nested-render-venndir.svg index d81dc36..4e31b35 100644 --- a/tests/testthat/_snaps/proportional-figure/proportional-nested-render-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/proportional-nested-render-venndir.svg @@ -18,38 +18,38 @@ - - - - - - - - - - - - - - - - - - - - - - - -16 -set_A -8 -set_C -2 -set_B - - - + + + + + + + + + + + + + + + + + + + + + + + +16 +set_A +8 +set_C +2 +set_B + + + diff --git a/tests/testthat/_snaps/proportional-figure/proportional-nested-venndir.svg b/tests/testthat/_snaps/proportional-figure/proportional-nested-venndir.svg index d81dc36..4e31b35 100644 --- a/tests/testthat/_snaps/proportional-figure/proportional-nested-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/proportional-nested-venndir.svg @@ -18,38 +18,38 @@ - - - - - - - - - - - - - - - - - - - - - - - -16 -set_A -8 -set_C -2 -set_B - - - + + + + + + + + + + + + + + + + + + + + + + + +16 +set_A +8 +set_C +2 +set_B + + + diff --git a/tests/testthat/_snaps/proportional-figure/venn-2-way-venndir.svg b/tests/testthat/_snaps/proportional-figure/venn-2-way-venndir.svg index 8bf6038..f83ca82 100644 --- a/tests/testthat/_snaps/proportional-figure/venn-2-way-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/venn-2-way-venndir.svg @@ -18,38 +18,38 @@ - - - - - - - - - - - - - - - - - - -set_A -25 -↑:12 -↓:13 -7 -↑↑:4 -↓↓:2 -X:1 -9 -↑:5 -↓:4 -set_B - - + + + + + + + + + + + + + + + + + + +set_A +25 +↑:12 +↓:13 +7 +↑↑:4 +↓↓:2 +X:1 +9 +↑:5 +↓:4 +set_B + + diff --git a/tests/testthat/_snaps/proportional-figure/venn-3-way-render-venndir.svg b/tests/testthat/_snaps/proportional-figure/venn-3-way-render-venndir.svg index a2d48ed..0003069 100644 --- a/tests/testthat/_snaps/proportional-figure/venn-3-way-render-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/venn-3-way-render-venndir.svg @@ -18,48 +18,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -set_A -16 -8 -2 -set_B -set_C - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +set_A +16 +8 +2 +set_B +set_C + + + diff --git a/tests/testthat/_snaps/proportional-figure/venn-3-way-venndir.svg b/tests/testthat/_snaps/proportional-figure/venn-3-way-venndir.svg index a2d48ed..0003069 100644 --- a/tests/testthat/_snaps/proportional-figure/venn-3-way-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/venn-3-way-venndir.svg @@ -18,48 +18,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -set_A -16 -8 -2 -set_B -set_C - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +set_A +16 +8 +2 +set_B +set_C + + + diff --git a/tests/testthat/_snaps/proportional-figure/venn-4-way-venndir.svg b/tests/testthat/_snaps/proportional-figure/venn-4-way-venndir.svg index 7a8268e..521c262 100644 --- a/tests/testthat/_snaps/proportional-figure/venn-4-way-venndir.svg +++ b/tests/testthat/_snaps/proportional-figure/venn-4-way-venndir.svg @@ -18,106 +18,106 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -set_A -18 -↑:9 -↓:9 -4 -↑↑:2 -↓↓:1 -X:1 -1 -X:1 -1 -↑↑↑:1 -8 -↑↑:2 -↓↓:2 -X:4 -set_B -8 -↑:5 -↓:3 -2 -↑↑:1 -↓↓:1 -6 -↑:1 -↓:5 -set_C -set_D -1 -↑:1 - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +set_A +18 +↑:9 +↓:9 +4 +↑↑:2 +↓↓:1 +X:1 +1 +X:1 +1 +↑↑↑:1 +8 +↑↑:2 +↓↓:2 +X:4 +set_B +8 +↑:5 +↓:3 +2 +↑↑:1 +↓↓:1 +6 +↑:1 +↓:5 +set_C +set_D +1 +↑:1 + + + +