Skip to content

Commit a734373

Browse files
committed
r/Various documentation improvements.
1 parent 0440491 commit a734373

File tree

15 files changed

+219
-196
lines changed

15 files changed

+219
-196
lines changed

r/DESCRIPTION

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ Authors@R: c(person("Manuel", "López-Ibáñez", role = c("aut", "cre"),
1111
Description: Visualization of multi-dimensional data arising in multi-objective optimization, including plots of the empirical attainment function (EAF), M. López-Ibáñez, L. Paquete, and T. Stützle (2010) <doi:10.1007/978-3-642-02538-9_9>, and symmetric Vorob'ev expectation and deviation, M. Binois, D. Ginsbourger, O. Roustant (2015) <doi:10.1016/j.ejor.2014.07.032>, among others.
1212
Depends: R (>= 4.0)
1313
Imports:
14-
moocore,
15-
graphics,
14+
Rdpack,
15+
collapse (>= 2.0.8),
1616
grDevices,
17+
graphics,
1718
matrixStats,
18-
collapse (>= 2.0.8),
19-
Rdpack
19+
moocore
2020
Suggests:
2121
extrafont,
2222
viridisLite,

r/R/eafdiffplot.R

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
#' @param col A character vector of three colors for the magnitude of the
1616
#' differences of 0, 0.5, and 1. Intermediate colors are computed
1717
#' automatically given the value of `intervals`. Alternatively, a function
18-
#' such as [viridisLite::viridis()] that generates a colormap given an integer
19-
#' argument.
18+
#' such as [viridisLite::viridis()] that generates a colormap given an
19+
#' integer argument.
2020
#'
21-
#' @param intervals (`integer(1)`|`character()`) \cr The
22-
#' absolute range of the differences \eqn{[0, 1]} is partitioned into the number
23-
#' of intervals provided. If an integer is provided, then labels for each
24-
#' interval are computed automatically. If a character vector is
25-
#' provided, its length is taken as the number of intervals.
21+
#' @param intervals (`integer(1)`|`character()`)\cr The absolute range of the
22+
#' differences \eqn{[0, 1]} is partitioned into the number of intervals
23+
#' provided. If an integer is provided, then labels for each interval are
24+
#' computed automatically. If a character vector is provided, its length is
25+
#' taken as the number of intervals.
2626
#'
2727
#' @param percentiles The percentiles of the EAF of each side that will be
2828
#' plotted as attainment surfaces. `NA` does not plot any. See
@@ -31,12 +31,12 @@
3131
#' @param full.eaf Whether to plot the EAF of each side instead of the
3232
#' differences between the EAFs.
3333
#'
34-
#' @param type Whether the EAF differences are plotted as points
35-
#' (`"points"`) or whether to color the areas that have at least a
34+
#' @param type (`"points"`|`"area"`)\cr Whether the EAF differences are plotted
35+
#' as points (`"points"`) or whether to color the areas that have at least a
3636
#' certain value (`"area"`).
3737
#'
38-
#' @param legend.pos The position of the legend. See [legend()]. A value of
39-
#' `"none"` hides the legend.
38+
#' @param legend.pos (`character(1)`)\cr The position of the legend. See
39+
#' [legend()]. A value of `"none"` hides the legend.
4040
#'
4141
#' @param title_left,title_right Title for left and right panels, respectively.
4242
#'
@@ -58,28 +58,27 @@
5858
#' [plot.default()].
5959
#'
6060
#' @details
61-
#' This function calculates the differences between the EAFs of two
62-
#' data sets, and plots on the left the differences in favour
63-
#' of the left data set, and on the right the differences in favour of
64-
#' the right data set. By default, it also plots the grand best and worst
65-
#' attainment surfaces, that is, the 0%- and 100%-attainment surfaces
66-
#' over all data. These two surfaces delimit the area where differences
67-
#' may exist. In addition, it also plots the 50%-attainment surface of
68-
#' each data set.
6961
#'
70-
#' With `type = "point"`, only the points where there is a change in
71-
#' the value of the EAF difference are plotted. This means that for areas
72-
#' where the EAF differences stays constant, the region will appear in
73-
#' white even if the value of the differences in that region is
74-
#' large. This explains "white holes" surrounded by black
75-
#' points.
62+
#' This function calculates the differences between the EAFs of two data
63+
#' sets, and plots on the left the differences in favour of the left data
64+
#' set, and on the right the differences in favour of the right data set. By
65+
#' default, it also plots the grand best and worst attainment surfaces, that
66+
#' is, the 0%- and 100%-attainment surfaces over all data. These two surfaces
67+
#' delimit the area where differences may exist. In addition, it also plots
68+
#' the 50%-attainment surface of each data set.
7669
#'
77-
#' With `type = "area"`, the area where the EAF differences has a
78-
#' certain value is plotted. The idea for the algorithm to compute the
79-
#' areas was provided by Carlos M. Fonseca. The implementation uses R
80-
#' polygons, which some PDF viewers may have trouble rendering correctly
81-
#' (See
82-
#' \url{https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-are-there-unwanted-borders}). Plots (should) look correct when printed.
70+
#' With `type = "point"`, only the points where there is a change in the
71+
#' value of the EAF difference are plotted. This means that for areas where
72+
#' the EAF differences stays constant, the region will appear in white even
73+
#' if the value of the differences in that region is large. This explains
74+
#' "white holes" surrounded by black points.
75+
#'
76+
#' With `type = "area"`, the area where the EAF differences has a certain
77+
#' value is plotted. The idea for the algorithm to compute the areas was
78+
#' provided by Carlos M. Fonseca. The implementation uses R polygons, which
79+
#' some PDF viewers may have trouble rendering correctly (See
80+
#' \url{https://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-are-there-unwanted-borders}).
81+
#' Plots (should) look correct when printed.
8382
#'
8483
#' Large differences that appear when using `type = "point"` may
8584
#' seem to disappear when using `type = "area"`. The explanation is
@@ -160,7 +159,7 @@ eafdiffplot <-
160159
# FIXME: check that it is either an integer or a character vector.
161160
if (length(intervals) == 1L) {
162161
intervals <- seq_intervals_labels(
163-
round(seq(0, 1 , length.out = 1 + intervals), 4L), digits = 1L)
162+
round(seq(0, 1, length.out = 1 + intervals), 4L), digits = 1L)
164163
}
165164
if (is.function(col)) { # It is a color-map, like viridis()
166165
col <- col(length(intervals))

r/R/eafplot.R

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
#' attainment surfaces for certain percentiles or as points.
55
#'
66
#' This function can be used to plot random sets of points like those obtained
7-
#' by different runs of biobjective stochastic optimisation algorithms. An EAF
7+
#' by different runs of biobjective stochastic optimisation algorithms \citep{LopPaqStu09emaa}. An EAF
88
#' curve represents the boundary separating points that are known to be
99
#' attainable (that is, dominated in Pareto sense) in at least a fraction
10-
#' (quantile) of the runs from those that are not. The median EAF represents
10+
#' (quantile) of the runs from those that are not \citep{Grunert01}. The median EAF represents
1111
#' the curve where the fraction of attainable points is 50%. In single
1212
#' objective optimisation the function can be used to plot the profile of
13-
#' solution quality over time of a collection of runs of a stochastic optimizer.
13+
#' solution quality over time of a collection of runs of a stochastic optimizer. \citep{LopVerDreDoe2025}.
1414
#'
1515
#' @param x Either a matrix of data values, or a data frame, or a list of
1616
#' data frames of exactly three columns.
@@ -20,18 +20,29 @@ eafplot <- function(x, ...) UseMethod("eafplot")
2020

2121
#' @describeIn eafplot Main function
2222
#'
23-
#' @param groups This may be used to plot profiles of different algorithms on the same plot.
24-
#' @param sets (`numeric()`)\cr Vector indicating which set each point belongs to.
25-
#' @param percentiles (`numeric()`) Vector indicating which percentile should be plot. The
26-
#' default is to plot only the median attainment curve.
27-
#' @param attsurfs TODO
28-
#' @param type (`character(1)`)\cr string giving the type of plot desired. The following values
29-
#' are possible, \samp{points} and \samp{area}.
23+
#' @param sets Vector indicating which set each point belongs to. Will be coerced to a factor.
24+
#'
25+
#' @param groups This may be used to plot data for different algorithms on
26+
#' the same plot. Will be coerced to a factor.
27+
#'
28+
#' @param percentiles (`numeric()`)\cr Vector indicating which percentile
29+
#' should be plot. The default is to plot only the median attainment curve.
30+
#'
31+
#' @param attsurfs TODO
32+
#'
33+
#' @param type (`"point"`|`"area"`)\cr Type of plot.
34+
#'
3035
#' @param xlab,ylab,xlim,ylim,log,col,lty,lwd,pch,cex.pch,las Graphical
3136
#' parameters, see [plot.default()].
32-
#' @param legend.pos the position of the legend, see [legend()]. A value of `"none"` hides the legend.
33-
#' @param legend.txt a character or expression vector to appear in the
34-
#' legend. If `NULL`, appropriate labels will be generated.
37+
#'
38+
#' @param legend.pos (`character(1)`|`list()`|`data.frame()`)\cr Position of
39+
#' the legend. This may be xy coordinates or a keyword ("bottomright",
40+
#' "bottom", "bottomleft", "left", "topleft", "top", "topright", "right",
41+
#' "center"). See Details in [legend()]. A value of "none" hides the legend.
42+
#'
43+
#' @param legend.txt (`expression()`|`character()`)\cr Character or expression
44+
#' vector to appear in the legend. If `NULL`, appropriate labels will be
45+
#' generated.
3546
#'
3647
#' @param extra.points A list of matrices or data.frames with
3748
#' two-columns. Each element of the list defines a set of points, or
@@ -43,18 +54,16 @@ eafplot <- function(x, ...) UseMethod("eafplot")
4354
#' @param extra.legend A character vector providing labels for the
4455
#' groups of points.
4556
#'
46-
#' @param maximise `logical()`|`logical(1)`\cr Whether the objectives must be
57+
#' @param maximise (`logical()`|`logical(1)`)\cr Whether the objectives must be
4758
#' maximised instead of minimised. Either a single logical value that applies
4859
#' to all objectives or a vector of logical values, with one value per
4960
#' objective.
5061
#'
51-
#' @param xaxis.side On which side the x-axis is drawn. Valid values are
52-
#' `"below"` and `"above"`. See [axis()].
62+
#' @param xaxis.side (`"below"`|`"above"`)\cr On which side the x-axis is drawn. See [axis()].
5363
#'
54-
#' @param yaxis.side On which side the y-axis is drawn. Valid values are
55-
#' `"left"` and `"right"`. See [axis()].
64+
#' @param yaxis.side (`"left"`|`"right"`)\cr On which side the y-axis is drawn. See [axis()].
5665
#'
57-
#' @param axes A logical value indicating whether both axes should be drawn
66+
#' @param axes (`logical(1)`)\cr A logical value indicating whether both axes should be drawn
5867
#' on the plot.
5968
#'
6069
#' @param sci.notation Generate prettier labels
@@ -106,11 +115,13 @@ eafplot <- function(x, ...) UseMethod("eafplot")
106115
#' ylab = "Minimum idle time (minutes)", maximise = c(FALSE, TRUE),
107116
#' las = 1, log = "y", main = "SPEA2 (Richmond)",
108117
#' legend.pos = "bottomright")
118+
#'
119+
#' data(tpls50x20_1_MWT, package="moocore")
120+
#' eafplot(tpls50x20_1_MWT[, c(2,3)], sets = tpls50x20_1_MWT[,4L],
121+
#' groups = tpls50x20_1_MWT[["algorithm"]])
109122
#' }
110123
#' @references
111-
#' \insertRef{Grunert01}{moocore}
112-
#'
113-
#' \insertRef{LopPaqStu09emaa}{moocore}
124+
#' \insertAllCited{}
114125
#' @concept eaf
115126
#' @export
116127
eafplot.default <-
@@ -165,13 +176,13 @@ eafplot.default <-
165176
if (is.null(ylab))
166177
ylab <- if (!is.null(colnames(x)[2L])) colnames(x)[2L] else "objective 2"
167178

168-
if (!is.null (attsurfs)) {
169-
# Don't we need to apply maximise?
170-
attsurfs <- lapply(attsurfs, function(x) as.matrix(x[, c(1L,2L), drop=FALSE]))
171-
} else {
179+
if (is.null (attsurfs)) {
172180
attsurfs <- eaf(x, sets, percentiles = percentiles, maximise = maximise, groups = groups)
173181
attsurfs <- eaf_as_list(attsurfs)
174182
# attsurfs <- lapply(attsurfs, matrix_maximise, maximise = maximise)
183+
} else {
184+
# Don't we need to apply maximise?
185+
attsurfs <- lapply(attsurfs, function(x) as.matrix(x[, c(1L,2L), drop=FALSE]))
175186
}
176187

177188
# FIXME: We should take the range from the attsurfs to not make x mandatory.
@@ -415,17 +426,17 @@ plot_eaf_full_area <- function(attsurfs, extreme, maximise, col)
415426
# seq_intervals_labels(seq(0,1, length.out=5), digits = 1)
416427
# "[0.0, 0.2)" "[0.2, 0.4)" "[0.4, 0.6)" "[0.6, 0.8)" "[0.8, 1.0]"
417428
# FIXME: Add examples and tests
418-
seq_intervals_labels <- function(s, first.open = FALSE, last.open = FALSE,
429+
seq_intervals_labels <- function(s, first_open = FALSE, last_open = FALSE,
419430
digits = NULL)
420431
{
421432
# FIXME: This should use:
422433
# levels(cut(0, s, dig.lab=digits, include.lowest=TRUE, right=FALSE))
423434
s <- formatC(s, digits = digits, format = if (is.null(digits)) "g" else "f")
424435
if (length(s) < 2) stop ("sequence must have at least 2 values")
425436
intervals <- paste0("[", s[-length(s)], ", ", s[-1], ")")
426-
if (first.open)
437+
if (first_open)
427438
substr(intervals[1], 0, 1) <- "("
428-
if (!last.open) {
439+
if (!last_open) {
429440
len <- nchar(intervals[length(intervals)])
430441
substr(intervals[length(intervals)], len, len+1) <- "]"
431442
}

r/R/interactive.R

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,15 @@
77
#' [moocore::choose_eafdiff()] may be used in a non-interactive context.
88
#'
99
#' @inheritParams eafdiffplot
10-
# @param data.left,data.right Data frames corresponding to the input data of
11-
# left and right sides, respectively. Each data frame has at least three
12-
# columns, the third one being the set of each point. See also
13-
# [read_datasets()].
14-
#
15-
# @param intervals (`integer(1)`|`character()`) \cr The absolute range of the
16-
# differences \eqn{[0, 1]} is partitioned into the number of intervals
17-
# provided. If an integer is provided, then labels for each interval are
18-
# computed automatically. If a character vector is provided, its length is
19-
# taken as the number of intervals.
2010
#'
2111
#' @param ... Other graphical parameters are passed down to
2212
#' [eafdiffplot()].
2313
#'
24-
#'
25-
#' @return `matrix` where the first 4 columns give the coordinates of two
14+
#' @return `matrix()` where the first 4 columns give the coordinates of two
2615
#' corners of each rectangle and the last column. In both cases, the last
2716
#' column gives the positive differences in favor of the chosen side.
2817
#'
29-
#' @seealso [moocore::read_datasets()], [eafdiffplot()], [moocore::whv_rect()]
18+
#' @seealso [moocore::read_datasets()], [eafdiffplot()], [moocore::whv_rect()]
3019
#'
3120
#' @examples
3221
#'
@@ -56,7 +45,7 @@
5645
#' boxplot(list(A1=whv_A1, A2=whv_A2), main = "Weighted hypervolume")
5746
#' }
5847
#'
59-
#'@references
48+
#' @references
6049
#' \insertAllCited{}
6150
#' @concept eaf
6251
#' @export

r/R/pdf_crop.R

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,35 @@
1818
#' As an alternative, saving the PDF with [grDevices::cairo_pdf()] should
1919
#' already embed the fonts.
2020
#'
21-
#' @param filename Filename of a PDF file to crop. The file will be overwritten.
22-
#' @param mustWork If `TRUE`, then give an error if the file cannot be cropped.
23-
#' @param pdfcrop Path to the `pdfcrop` utility.
24-
#' @param embed_fonts (`logical(1)`) If `TRUE`, use [grDevices::embedFonts()] to embed fonts.
25-
#' @return Nothing
21+
#' @param filename (`character(1)`)\cr Filename of a PDF file to crop. The file will be overwritten.
22+
#'
23+
#' @param mustWork (`logical1`)\cr If `TRUE`, then give an error if the file cannot be cropped.
24+
#'
25+
#' @param pdfcrop (`character(1)`)\cr Path to the `pdfcrop` utility.
26+
#'
27+
#' @param embed_fonts (`logical(1)`)\cr If `TRUE`, use [grDevices::embedFonts()] to embed fonts.
28+
#'
29+
#' @return No return value, called for side effects
2630
#'
2731
#' @seealso [grDevices::embedFonts()] [extrafont::embed_fonts()] [grDevices::cairo_pdf()]
2832
#'
2933
#' @examples
30-
#' \dontrun{
3134
#' extdata_path <- system.file(package = "moocore", "extdata")
3235
#' A1 <- read_datasets(file.path(extdata_path, "wrots_l100w10_dat"))
3336
#' A2 <- read_datasets(file.path(extdata_path, "wrots_l10w100_dat"))
34-
#' pdf(file = "eaf.pdf", onefile = TRUE, width = 5, height = 4)
35-
#' eafplot(list(A1 = A1, A2 = A2), percentiles = 50, sci.notation=TRUE)
37+
#' filename <- tempfile("eafplot", fileext=".pdf")
38+
#' pdf(file = filename, onefile = TRUE, width = 5, height = 4)
39+
#' eafplot(list(A1 = A1, A2 = A2), percentiles = 50, sci.notation = TRUE)
3640
#' dev.off()
37-
#' pdf_crop("eaf.pdf")
38-
#' }
41+
#' try(pdf_crop(filename)) # This may fail if pdfcrop is not installed.
42+
#'
3943
#' @export
4044
pdf_crop <- function(filename, mustWork = FALSE, pdfcrop = Sys.which("pdfcrop"),
4145
embed_fonts = FALSE)
4246
{
4347
if (!file.exists(filename)) {
4448
stop("PDF file", shQuote(filename), "not found")
45-
} else if(!has_file_extension(filename, "pdf")){
49+
} else if (!has_file_extension(filename, "pdf")) {
4650
stop(shQuote(filename), "is not a PDF file")
4751
} else if (is.null(pdfcrop) || pdfcrop == "") {
4852
if (mustWork) {
@@ -52,12 +56,8 @@ pdf_crop <- function(filename, mustWork = FALSE, pdfcrop = Sys.which("pdfcrop"),
5256
}
5357
} else {
5458
system2(pdfcrop, c("--pdfversion 1.5", shQuote(filename), shQuote(filename)),
55-
timeout = 60, stdout = FALSE, stderr = FALSE)
56-
if (embed_fonts) embedFonts(filename)
59+
timeout = 60, stdout = FALSE, stderr = FALSE)
60+
if (embed_fonts)
61+
embedFonts(filename)
5762
}
5863
}
59-
60-
has_file_extension <- function(filename, extension)
61-
{
62-
grepl(paste0('[.]', extension, '$'), filename, ignore.case = TRUE)
63-
}

0 commit comments

Comments
 (0)