diff --git a/.Rbuildignore b/.Rbuildignore index 31494e8..f529ba5 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -7,3 +7,4 @@ ^_pkgdown\.yml$ ^docs$ ^pkgdown$ +^data-raw$ diff --git a/DESCRIPTION b/DESCRIPTION index 663ecb1..083bbdd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: visualizeR Type: Package Title: What a color! What a viz! -Version: 0.2.9000 +Version: 0.3.9000 Authors@R: c( person( 'Noblet', 'Guillaume', @@ -24,6 +24,6 @@ Imports: grDevices, glue, scales, - ggblanket (>= 1.5.0) -Suggests: knitr, sf + ggblanket (== 1.6.1) +Suggests: knitr, sf, tmap VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 40ea8e2..6b1f9a3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1 +1 @@ -exportPattern("^[[:alpha:]]+") +exportPattern("^[^\\.]") diff --git a/NEWS.md b/NEWS.md index b1a9f74..fa45d9e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# visualizeR 0.3.9000 + +* Breaking changes: update to `ggblanket` v1.6.1. +* Add plotting functions for indicator maps. + + # visualizeR 0.2.9000 * Breaking changes: almost all functions got refinements, and there are new functions, typically `hbar()` becomes `bar_reach()` and `point_reach()` is added. diff --git a/R/bar.R b/R/bar.R index 6f7e77e..094b97a 100644 --- a/R/bar.R +++ b/R/bar.R @@ -21,7 +21,6 @@ #' @param title_size The size of the title text. Defaults to 14. #' @param legend_position Position of the legend; Default to "right". Can take "right", "left", "top", "bottom" or "none". #' @param legend_rev Reverse the color in the guide? Default to TRUE. -#' @param void Boolean to remove all elements from the plot. Default to FALSE. #' @param ... Other arguments to be passed to "ggblanket::gg_col" #' #' @description `ggblanket` as internals for deciding whether the bar chart is horizontally readable. @@ -29,7 +28,7 @@ #' @return A bar chart #' #' @export -bar_reach <- function(df, x, y, group = NULL, percent = TRUE, palette = "main", reverse = FALSE, family = "Leelawadee", alpha = 1, width = 0.5, x_title = NULL, y_title = NULL, group_title = NULL, position = "dodge", title = NULL, subtitle = NULL, caption = NULL, text_size = 10, title_size = 14, legend_position = "right", legend_rev = TRUE, void = FALSE, ...){ +bar_reach <- function(df, x, y, group = NULL, percent = TRUE, palette = "main", reverse = FALSE, family = "Leelawadee", alpha = 1, width = 0.5, x_title = NULL, y_title = NULL, group_title = NULL, position = "dodge", title = NULL, subtitle = NULL, caption = NULL, text_size = 10, title_size = 14, legend_position = "right", legend_rev = TRUE, ...){ pal <- pal_reach(palette) @@ -64,9 +63,8 @@ bar_reach <- function(df, x, y, group = NULL, percent = TRUE, palette = "main", title_size = title_size, plot_background_pal = "#FFFFFF", panel_background_pal = "#FFFFFF", - legend_reverse = legend_rev, - void = FALSE - ), + legend_reverse = legend_rev + ), ... ) diff --git a/R/data.R b/R/data.R new file mode 100644 index 0000000..8101ff4 --- /dev/null +++ b/R/data.R @@ -0,0 +1,93 @@ +#' Haïti admin 1 centroids shapefile. +#' +#' A multipoint shapefile of Haiti's admin 1. +#' +#' @format A sf multipoint object with 10 features and 9 fields: +#' \describe{ +#' \item{ADM1_PC}{Admin 1 postal code.} +#' \item{ADM1_EN}{Full name in English.} +#' \item{ADM1_FR}{Full name in French.} +#' \item{ADM1_HT}{Full name in Haitian Creole.} +#' \item{ADM0_EN}{Country name in English.} +#' \item{ADM0_FR}{Country name in French.} +#' \item{ADM0_HT}{Country name in Haitian Creole.} +#' \item{ADM0_PC}{Country postal code.} +#' \item{ADM1_FR_UPPER}{Admin 1 French name - uppercase.} +#' \item{geometry}{Multipoint geometry.} +#' } +"centroid_admin1" + + +#' Indicator admin 1 polygons shapefile. +#' +#' A multipolygon shapefile of Haiti's admin 1 with an indicator column 'opn_dfc'. +#' +#' @format A sf multipoint object with 10 features and 10 fields: +#' \describe{ +#' \item{ADM1_PC}{Admin 1 postal code.} +#' \item{admin1}{Admin 1 unique id.} +#' \item{opn_dfc}{Proportion of HHs that reported open defecation as sanitation facility.} +#' \item{ADM1_EN}{Full name in English.} +#' \item{ADM1_FR}{Full name in French.} +#' \item{ADM1_HT}{Full name in Haitian Creole.} +#' \item{ADM0_EN}{Country name in English.} +#' \item{ADM0_FR}{Country name in French.} +#' \item{ADM0_HT}{Country name in Haitian Creole.} +#' \item{ADM0_PC}{Country postal code.} +#' \item{geometry}{Multipolygon geometry.} +#' } +"indicator_admin1" + + +#' Haïti admin 1 lines shapefile. +#' +#' A multiline shapefile of Haiti's admin 1. +#' +#' @format A sf multiline object with 10 features and 8 fields: +#' \describe{ +#' \item{ADM1_EN}{Full name in English.} +#' \item{ADM1_FR}{Full name in French.} +#' \item{ADM1_HT}{Full name in Haitian Creole.} +#' \item{ADM0_EN}{Country name in English.} +#' \item{ADM0_FR}{Country name in French.} +#' \item{ADM0_HT}{Country name in Haitian Creole.} +#' \item{ADM0_PCODE}{Country postal code.} +#' \item{geometry}{Multiline geometry.} +#' } +"line_admin1" + + +#' Haïti border. +#' +#' A multiline shapefile of Haiti's border. +#' +#' @format A sf multiline objet with 1 feature and 6 fields: +#' \describe{ +#' \item{fid_1}{fid_1} +#' \item{uno}{uno} +#' \item{count}{count} +#' \item{x_coord}{x_coord} +#' \item{y_coord}{y_coord} +#' \item{area}{area} +#' \item{geometry}{Multiline geometry.} +#' } +"border_admin0" + + +#' Haïti frontier with Dominican Republic. +#' +#' A multiline shapefile of Haiti's frontier with Dominican Republic. +#' +#' @format A sf multipoint objet with 4 features and 8 fields: +#' \describe{ +#' \item{fid_1}{fid_1} +#' \item{objectid}{objectid} +#' \item{id}{id} +#' \item{fromnode}{fromnode} +#' \item{tonode}{tonode} +#' \item{leftpolygo}{leftpolygo} +#' \item{rightpolygo}{rightpolygo} +#' \item{shape_leng}{shape_leng} +#' \item{geometry}{Multiline geometry.} +#' } +"frontier_admin0" diff --git a/R/map.R b/R/map.R new file mode 100644 index 0000000..3e9ac1b --- /dev/null +++ b/R/map.R @@ -0,0 +1,354 @@ + + +#' Wrapper around `tmap::tm_polygons()` with sane defaults for plotting indicator values +#' +#' @param poly Multipolygon shape defined by sf package. +#' @param col Numeric attribute to map. +#' @param buffer A buffer, either one value or a vector of 4 values (left, bottom, right, top). +#' @param n The desire number of classes. +#' @param style Method to process the color scale for continuous numerical variables. See `classInt::classIntervals()` for details. +#' @param palette Vector of fill colors as hexadecimal values. For REACH color palettes, it is possible to use `pal_reach()`. For now,'palette' must be changed manually, accordingly to the number of drawn classes. +#' @param as_count Boolean. When col is a numeric variable, should it be processed as a count variable? For instance, 0, 1-10, 11-20. +#' @param color_na Fill color for missing data. +#' @param text_na Legend text for missing data. +#' @param legend_title Legend title. +#' @param legend_text_separator Text separator for classes. E.g. " to " will give 0, 1 to 10, 11 to 20. +#' @param border_alpha Transparency of the border. +#' @param border_col Color of the border. +#' @param lwd Linewidth of the border. +#' @param ... Other arguments to pass to `tmap::tm_polygons()`. +#' +#' @return A tmap layer. +#' @export +#' +add_indicator_layer <- function( + poly, + col, + buffer = NULL, + n = 5, + style = "pretty", + palette = pal_reach("red_5"), + as_count = TRUE, + color_na = cols_reach("white"), + text_na = "Missing data", + legend_title = "Proportion (%)", + legend_text_separator = " - ", + border_alpha = 1, + border_col = cols_reach("lt_grey_1"), + lwd = 1, + ...){ + + #------ Checks and make valid + + rlang::check_installed("tmap", reason = "Package \"tmap\" needed for `add_indicator_layer()` to work. Please install it.") + + poly <- sf::st_make_valid(poly) + + #------ Other checks + + col_name <- rlang::as_name(rlang::enquo(col)) + if_not_in_stop(poly, col_name, "poly", "col") + + if (!is.numeric(poly[[col_name]])) rlang::abort(glue::glue("{col_name} is not numeric.")) + + + #------ Prepare data + + if(!is.null(buffer)){ buffer <- buffer_bbox(poly, buffer) } else { buffer <- NULL } + + + #------ Polygon layer + + layer <- tmap::tm_shape( + poly, + bbox = buffer + ) + + tmap::tm_polygons( + col = col_name, + n = n, + style = style, + palette = palette, + as.count = as_count, + colorNA = color_na, + textNA = text_na, + title = legend_title, + legend.format = list(text.separator = legend_text_separator), + borderl.col = border_col, + border.alpha = border_alpha, + lwd = lwd, + ... + ) + + return(layer) + +} + + + + +#' Add admin boundaries (lines) and the legend +#' +#' @param lines List of multiline shape defined by sf package. +#' @param colors Vector of hexadecimal codes. Same order as lines. +#' @param labels Vector of labels in the legend. Same order as lines. +#' @param lwds Vector of line widths. Same order as lines. +#' @param title Legend title. +#' @param buffer A buffer, either one value or a vector of 4 values (left, bottom, right, top). +#' @param ... Other arguments to pass to each shape in `tmap::tm_lines()`. +#' +#' @return A tmap layer. +#' @export +#' +add_admin_boundaries <- function(lines, colors, labels, lwds, title = "", buffer = NULL, ...){ + + + #------ Package check + + rlang::check_installed("tmap", reason = "Package \"tmap\" needed for `add_admin_boundaries()` to work. Please install it.") + + + #------ Check that the length of vectors is identical between arguments + + if(!inherits(lines, "list")) rlang::abort("Please provide a list for lines.") + + ll <- list(lines, colors, labels, lwds) + if (!all(sapply(ll,length) == length(ll[[1]]))) rlang::abort("lines, colors, labels, lwds do not all have the same length.") + + + #------ Make valid + + lines <- lapply(lines, \(x) sf::st_make_valid(x)) + + + #------ Prepare legend + legend_lines <- tmap::tm_add_legend("line", + title = title, + col = colors, + lwd = lwds, + labels = labels) + + + #------ Let's go with all line shapes + + if(!is.null(buffer)){ buffer <- buffer_bbox(lines[[1]], buffer) } else { buffer <- NULL } + + + layers <- tmap::tm_shape(lines[[1]], bbox = buffer) + + tmap::tm_lines(lwd = lwds[[1]], col = colors[[1]], ...) + + if (length(lines) == 1) { + + layers <- layers + legend_lines + + return(layers) + + } else { + + for(i in 2:length(lines)){ + + layers <- layers + tmap::tm_shape(shp = lines[[i]]) + tmap::tm_lines(lwd = lwds[[i]], col = colors[[i]], ...) + } + + layers <- layers + legend_lines + + return(layers) + + } +} + + + + +#' Basic defaults based on `tmap::tm_layout()` +#' +#' @param title Map title. +#' @param legend_position Legend position. Not above the map is a good start. +#' @param frame Boolean. Legend frame? +#' @param legend_frame Legend frame color. +#' @param legend_text_size Legend text size in 'pt'. +#' @param legend_title_size Legend title size in 'pt'. +#' @param title_size Title text size in 'pt'. +#' @param title_fontface Title fontface. Bold if you wanna exemplify a lot what it is about. +#' @param title_color Title font color. +#' @param fontfamily Overall fontfamily. Leelawadee is your precious. +#' @param ... Other arguments to pass to `tmap::tm_layout()`. +#' +#' @return A tmap layer. +#' @export +#' +add_layout <- function( + title = NULL, + legend_position = c(0.02, 0.5), + frame = FALSE, + legend_frame = cols_reach("main_grey"), + legend_text_size = 0.6, + legend_title_size = 0.8, + title_size = 0.9, + title_fontface = "bold", + title_color = cols_reach("main_grey"), + # check.and.fix = TRUE, + fontfamily = "Leelawadee", + ...){ + + layout <- tmap::tm_layout( + title = title, + legend.position = legend_position, + legend.frame = legend_frame, + frame = FALSE, + legend.text.size = legend_text_size, + legend.title.size = legend_title_size, + title.size = title_size, + title.fontface = title_fontface, + title.color = title_color, + fontfamily = fontfamily, + ...) + + return(layout) + + } + + + + +#' Wrapper around `tmap::tm_text()` with sane defaults for plotting admin labels. +#' +#' @param point Multipoint shape defined by sf package. +#' @param text Text labels column. +#' @param size Relative size of the text labels. +#' @param fontface Fontface. +#' @param fontfamily Fontfamily. Leelawadee is your precious. +#' @param shadow Boolean. Add a shadow around text labels. Issue opened on Github to request. +#' @param auto_placement Logical that determines whether the labels are placed automatically. +#' @param remove_overlap Logical that determines whether the overlapping labels are removed. +#' @param ... Other arguments to pass to `tmap::tm_text()`. +#' +#' @return A tmap layer. +#' @export +#' +add_admin_labels <- function(point, + text, + size = 0.5, + fontface = "bold", + fontfamily = "Leelawadee", + shadow = TRUE, + auto_placement = FALSE, + remove_overlap = FALSE, + ...){ + + + #------ Restrictive sf checks (might not be necessary depending on the desired behaviour) + + rlang::check_installed("tmap", reason = "Package \"tmap\" needed for `add_indicator_layer()` to work. Please install it.") + + point <- sf::st_make_valid(point) + + #------ Other checks + + text_name <- rlang::as_name(rlang::enquo(text)) + if_not_in_stop(point, text_name, "point", "text") + + #------ Point text layer + + layer <- tmap::tm_shape(point) + + tmap::tm_text(text = text_name, + size = size, + fontface = fontface, + fontfamily = fontfamily, + shadow = shadow, + auto.placement = auto_placement, + remove.overlap = remove_overlap, + ...) + + return(layer) + +} + + + + +#' Add a compass +#' +#' @param text_size Relative font size. +#' @param position Position of the compass. Vector of two values, specifying the x and y coordinates. +#' @param color_dark Color of the dark parts of the compass. +#' @param text_color color of the text. +#' @param type Compass type, one of: "arrow", "4star", "8star", "radar", "rose". +#' @param ... Other arguments to pass to `tmap::tm_compass()`. +#' +#' @return A tmap layer. +#' @export +#' +add_compass <- function(text_size = 0.6, + position = c("right", 0.8), + color_dark = cols_reach("black"), + text_color = cols_reach("black"), + type = "4star", + ...){ + + compass <- tmap::tm_compass( + text.size = text_size, + position = position, + color.dark = color_dark, + type = type, + text.color = text_color + ) + + return(compass) + +} + + + + +#' Add a scale bar +#' +#' @param text_size Relative font size. +#' @param position Position of the compass. Vector of two values, specifying the x and y coordinates. +#' @param color_dark Color of the dark parts of the compass. +#' @param breaks Breaks of the scale bar. If not specified, breaks will be automatically be chosen given the prefered width of the scale bar. Example: c(0, 50, 100). +#' @param ... Other arguments to pass to `tmap::tm_compass()`. +#' +#' @return A tmap layer. +#' @export +#' +add_scale_bar <- function(text_size = 0.6, + position = c("left", 0.01), + color_dark = cols_reach("black"), + breaks = c(0, 50, 100), + ...){ + + scale_bar <- tmap::tm_scale_bar( + text.size = text_size, + position = position, + color.dark = color_dark, + breaks = breaks, + ... + ) + + return(scale_bar) + +} + + + + +#' Do you want to credit someone or some institution? +#' +#' @param text Text. +#' @param size Relative text size. +#' @param bg_color Background color. +#' @param position Position. Vector of two coordinates. Usually somewhere down. +#' @param ... Other arguments to pass to `tmap::tm_credits()`. +#' +#' @return A tmap layer. +#' @export +#' +add_credits <- function(text, size = 0.4, bg_color = NA, position = c(0.75, 0.02), ...){ + + tmap::tm_credits(text, + size = size, + bg.color = bg_color, + position = position, + ...) +} + diff --git a/R/point.R b/R/point.R index ed7c973..7e7b551 100644 --- a/R/point.R +++ b/R/point.R @@ -18,7 +18,6 @@ #' @param text_size The size of all text other than the title, subtitle and caption. Defaults to 10. #' @param title_size The size of the title text. Defaults to 14. #' @param legend_position Position of the legend; Default to "right". Can take "right", "left", "top", "bottom" or "none". -#' @param void Boolean to remove all elements from the plot. Default to FALSE. #' @param ... Other arguments to be passed to "ggblanket::gg_col" #' #' @description `ggblanket` as internals for deciding whether the bar chart is horizontally readable. @@ -26,7 +25,7 @@ #' @return A bar chart #' #' @export -point_reach <- function(df, x, y, group = NULL, palette = "main", reverse = FALSE, family = "Leelawadee", alpha = 1, size = 1.5, x_title = NULL, y_title = NULL, group_title = NULL, title = NULL, subtitle = NULL, caption = NULL, text_size = 10, title_size = 14, legend_position = "right", void = FALSE, ...){ +point_reach <- function(df, x, y, group = NULL, palette = "main", reverse = FALSE, family = "Leelawadee", alpha = 1, size = 1.5, x_title = NULL, y_title = NULL, group_title = NULL, title = NULL, subtitle = NULL, caption = NULL, text_size = 10, title_size = 14, legend_position = "right", ...){ pal <- pal_reach(palette) @@ -56,8 +55,7 @@ point_reach <- function(df, x, y, group = NULL, palette = "main", reverse = FALS text_size = text_size, title_size = title_size, plot_background_pal = "#FFFFFF", - panel_background_pal = "#FFFFFF", - void = FALSE + panel_background_pal = "#FFFFFF" ), ... ) diff --git a/R/theme_reach.R b/R/theme_reach.R index 755800c..fe5601b 100644 --- a/R/theme_reach.R +++ b/R/theme_reach.R @@ -11,7 +11,6 @@ #' @param legend_position Position of the legend; Default to "right". Can take "right", "left", "top", "bottom" or "none". #' @param legend_direction Direction of the legend. Default to "vertical". Can take "vertical" or "horizontal". #' @param legend_reverse Reverse the color in the guide? Default to TRUE. -#' @param void Boolean to remove all elements from the plot. Default to FALSE. #' @param ... Additional arguments passed to `ggblanket::gg_theme()`. #' #' @@ -29,7 +28,6 @@ theme_reach <- function( title_size = 14, plot_background_pal = "#FFFFFF", panel_background_pal = "#FFFFFF", - void = FALSE, legend_position = "right", legend_direction = "vertical", legend_reverse = TRUE, @@ -42,9 +40,7 @@ theme_reach <- function( text_size = text_size, title_size = title_size, plot_background_pal = plot_background_pal, - panel_background_pal = panel_background_pal, - void = void - ) + panel_background_pal = panel_background_pal) # Default legend to right position diff --git a/README.Rmd b/README.Rmd index 62c10c6..ae39c52 100644 --- a/README.Rmd +++ b/README.Rmd @@ -50,8 +50,7 @@ Roadmap is as follows: Please, do not hesitate to pull request any new viz or colors or color palettes, or to email request any change (guillaume.noblet@reach-initiative.org or gnoblet@zaclys.net). - -## Example 1: extracting colors +## Colors Color palettes for REACH, AGORA and IMPACT are available. Functions to access colors and palettes are `cols_initiative()` or `pal_initiative()`. For now, the initiative with the most colors and color palettes is REACH. Feel free to pull requests new AGORA and IMPACT colors. @@ -67,7 +66,10 @@ pal_reach(palette = "main", reversed = TRUE, color_ramp_palette = FALSE) # Get all color palettes names pal_reach(show_palettes = T) ``` -## Example 2: Bar chart, already REACH themed + +## Charts + +### Example 1: Bar chart, already REACH themed ```{r example-bar-chart, eval = TRUE} library(visualizeR) @@ -88,7 +90,7 @@ bar_reach(df, mean_bl, island, species, percent = FALSE, x_title = "Mean of bill bar_reach(df, mean_bl, island, species, percent = FALSE, palette = "artichoke_3", legend_rev = TRUE) ``` -## Example 3: Point chart, already REACH themed +### Example 2: Point chart, already REACH themed At this stage, `point_reach()` only supports categorical grouping colors with the `group` arg. @@ -104,3 +106,42 @@ point_reach(penguins, bill_length_mm, flipper_length_mm, island, alpha = 0.6, si point_reach(penguins, bill_length_mm, flipper_length_mm, island, palette = "artichoke_3") ``` +## Maps + +```{r example-map} + +# Add indicator layer +# - based on "pretty" classes and title "Proportion (%)" +# - buffer to add a 10% around the bounding box +map <- add_indicator_layer( + indicator_admin1, + opn_dfc, + buffer = 0.1) + + # Layout - some defaults - add the map title + add_layout("% of HH that reported open defecation as sanitation facility") + + # Admin boundaries as list of shape files (lines) and colors, line widths and labels as vectors + add_admin_boundaries( + lines = list(line_admin1, border_admin0, frontier_admin0), + colors = cols_reach("main_lt_grey", "dk_grey", "black"), + lwds = c(0.5, 2, 3), + labels = c("Department", "Country", "Dominican Rep. frontier"), + title = "Administrative boundaries") + + # Add text labels - centered on admin 1 centroids + add_admin_labels(centroid_admin1, ADM1_FR_UPPER) + + # Add a compass + add_compass() + + # Add a scale bar + add_scale_bar() + + # Add credits + add_credits("Admin. boundaries. : CNIGS \nCoord. system: GCS WGS 1984") +``` + +```{r map-save, eval = TRUE, include = FALSE, echo = TRUE} +tmap::tmap_save(map, + "man/figures/README-example-map.png", + height = 4.5, + width = 6 + ) +``` + +![Once exported with `tmap::tmap_save()`.](man/figures/README-example-map.png) diff --git a/README.md b/README.md index 331fdc7..2fec6ca 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Please, do not hesitate to pull request any new viz or colors or color palettes, or to email request any change ( or ). -## Example 1: extracting colors +## Colors Color palettes for REACH, AGORA and IMPACT are available. Functions to access colors and palettes are `cols_initiative()` or @@ -73,7 +73,9 @@ pal_reach(show_palettes = T) #> [33] "blue_4" "blue_5" "blue_6" "blue_7" ``` -## Example 2: Bar chart, already REACH themed +## Charts + +### Example 1: Bar chart, already REACH themed ``` r library(visualizeR) @@ -101,7 +103,7 @@ bar_reach(df, mean_bl, island, species, percent = FALSE, palette = "artichoke_3" -## Example 3: Point chart, already REACH themed +### Example 2: Point chart, already REACH themed At this stage, `point_reach()` only supports categorical grouping colors with the `group` arg. @@ -129,3 +131,36 @@ point_reach(penguins, bill_length_mm, flipper_length_mm, island, palette = "arti ``` + +## Maps + +``` r + +# Add indicator layer +# - based on "pretty" classes and title "Proportion (%)" +# - buffer to add a 10% around the bounding box +map <- add_indicator_layer( + indicator_admin1, + opn_dfc, + buffer = 0.1) + + # Layout - some defaults - add the map title + add_layout("% of HH that reported open defecation as sanitation facility") + + # Admin boundaries as list of shape files (lines) and colors, line widths and labels as vectors + add_admin_boundaries( + lines = list(line_admin1, border_admin0, frontier_admin0), + colors = cols_reach("main_lt_grey", "dk_grey", "black"), + lwds = c(0.5, 2, 3), + labels = c("Department", "Country", "Dominican Rep. frontier"), + title = "Administrative boundaries") + + # Add text labels - centered on admin 1 centroids + add_admin_labels(centroid_admin1, ADM1_FR_UPPER) + + # Add a compass + add_compass() + + # Add a scale bar + add_scale_bar() + + # Add credits + add_credits("Admin. boundaries. : CNIGS \nCoord. system: GCS WGS 1984") +``` + +![Once exported with +`tmap::tmap_save()`.](man/figures/README-example-map.png) diff --git a/data-raw/border_admin0.dbf b/data-raw/border_admin0.dbf new file mode 100644 index 0000000..2cdd77c Binary files /dev/null and b/data-raw/border_admin0.dbf differ diff --git a/data-raw/border_admin0.prj b/data-raw/border_admin0.prj new file mode 100644 index 0000000..f8e4548 --- /dev/null +++ b/data-raw/border_admin0.prj @@ -0,0 +1 @@ +PROJCS["WGS_1984_UTM_Zone_18N",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-75.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["m",1.0]] \ No newline at end of file diff --git a/data-raw/border_admin0.shp b/data-raw/border_admin0.shp new file mode 100644 index 0000000..559c58d Binary files /dev/null and b/data-raw/border_admin0.shp differ diff --git a/data-raw/border_admin0.shx b/data-raw/border_admin0.shx new file mode 100644 index 0000000..f4d8240 Binary files /dev/null and b/data-raw/border_admin0.shx differ diff --git a/data-raw/centroid_admin1.dbf b/data-raw/centroid_admin1.dbf new file mode 100644 index 0000000..f17bfb9 Binary files /dev/null and b/data-raw/centroid_admin1.dbf differ diff --git a/data-raw/centroid_admin1.prj b/data-raw/centroid_admin1.prj new file mode 100644 index 0000000..79392c5 --- /dev/null +++ b/data-raw/centroid_admin1.prj @@ -0,0 +1 @@ +GEOGCS["GCS_unknown",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/data-raw/centroid_admin1.shp b/data-raw/centroid_admin1.shp new file mode 100644 index 0000000..67811d2 Binary files /dev/null and b/data-raw/centroid_admin1.shp differ diff --git a/data-raw/centroid_admin1.shx b/data-raw/centroid_admin1.shx new file mode 100644 index 0000000..f6ca9fc Binary files /dev/null and b/data-raw/centroid_admin1.shx differ diff --git a/data-raw/frontier_admin0.dbf b/data-raw/frontier_admin0.dbf new file mode 100644 index 0000000..20c39d2 Binary files /dev/null and b/data-raw/frontier_admin0.dbf differ diff --git a/data-raw/frontier_admin0.prj b/data-raw/frontier_admin0.prj new file mode 100644 index 0000000..f45cbad --- /dev/null +++ b/data-raw/frontier_admin0.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/data-raw/frontier_admin0.shp b/data-raw/frontier_admin0.shp new file mode 100644 index 0000000..6a7c832 Binary files /dev/null and b/data-raw/frontier_admin0.shp differ diff --git a/data-raw/frontier_admin0.shx b/data-raw/frontier_admin0.shx new file mode 100644 index 0000000..aeb62b0 Binary files /dev/null and b/data-raw/frontier_admin0.shx differ diff --git a/data-raw/indicator_admin1.dbf b/data-raw/indicator_admin1.dbf new file mode 100644 index 0000000..9dd16e2 Binary files /dev/null and b/data-raw/indicator_admin1.dbf differ diff --git a/data-raw/indicator_admin1.prj b/data-raw/indicator_admin1.prj new file mode 100644 index 0000000..f45cbad --- /dev/null +++ b/data-raw/indicator_admin1.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/data-raw/indicator_admin1.shp b/data-raw/indicator_admin1.shp new file mode 100644 index 0000000..cd956a4 Binary files /dev/null and b/data-raw/indicator_admin1.shp differ diff --git a/data-raw/indicator_admin1.shx b/data-raw/indicator_admin1.shx new file mode 100644 index 0000000..114b1d3 Binary files /dev/null and b/data-raw/indicator_admin1.shx differ diff --git a/data-raw/line_admin1.dbf b/data-raw/line_admin1.dbf new file mode 100644 index 0000000..27046d0 Binary files /dev/null and b/data-raw/line_admin1.dbf differ diff --git a/data-raw/line_admin1.prj b/data-raw/line_admin1.prj new file mode 100644 index 0000000..f45cbad --- /dev/null +++ b/data-raw/line_admin1.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/data-raw/line_admin1.shp b/data-raw/line_admin1.shp new file mode 100644 index 0000000..5a39a4b Binary files /dev/null and b/data-raw/line_admin1.shp differ diff --git a/data-raw/line_admin1.shx b/data-raw/line_admin1.shx new file mode 100644 index 0000000..e078d09 Binary files /dev/null and b/data-raw/line_admin1.shx differ diff --git a/data-raw/shapefiles.R b/data-raw/shapefiles.R new file mode 100644 index 0000000..13db57a --- /dev/null +++ b/data-raw/shapefiles.R @@ -0,0 +1,21 @@ + +#------ Border - admin 0 +border_admin0 <- sf::st_read("data-raw/border_admin0.shp") +usethis::use_data(border_admin0, overwrite = TRUE) + +#------ Frontier - admin 0 +frontier_admin0 <- sf::st_read("data-raw/frontier_admin0.shp") +usethis::use_data(frontier_admin0, overwrite = TRUE) + +#------ Line - admin 1 +line_admin1 <- sf::st_read("data-raw/line_admin1.shp") +usethis::use_data(line_admin1, overwrite = TRUE) + +#------ Centroid - admin 1 +centroid_admin1 <- sf::st_read("data-raw/centroid_admin1.shp") |> + dplyr::rename(ADM1_FR_UPPER = ADM1_FR_) +usethis::use_data(centroid_admin1, overwrite = TRUE) + +#------ Indicator polygon - admin 1 +indicator_admin1 <- sf::st_read("data-raw/indicator_admin1.shp") +usethis::use_data(indicator_admin1, overwrite = TRUE) diff --git a/data/border_admin0.rda b/data/border_admin0.rda new file mode 100644 index 0000000..a6400e1 Binary files /dev/null and b/data/border_admin0.rda differ diff --git a/data/centroid_admin1.rda b/data/centroid_admin1.rda new file mode 100644 index 0000000..f144be5 Binary files /dev/null and b/data/centroid_admin1.rda differ diff --git a/data/frontier_admin0.rda b/data/frontier_admin0.rda new file mode 100644 index 0000000..b57263a Binary files /dev/null and b/data/frontier_admin0.rda differ diff --git a/data/indicator_admin1.rda b/data/indicator_admin1.rda new file mode 100644 index 0000000..f1a1a63 Binary files /dev/null and b/data/indicator_admin1.rda differ diff --git a/data/line_admin1.rda b/data/line_admin1.rda new file mode 100644 index 0000000..9393fdd Binary files /dev/null and b/data/line_admin1.rda differ diff --git a/docs/404.html b/docs/404.html index 85d1af1..c75726d 100644 --- a/docs/404.html +++ b/docs/404.html @@ -16,7 +16,7 @@ - + GNU General Public License • visualizeRGNU General Public License • visualizeR @@ -10,7 +10,7 @@ visualizeR - 0.2.9000 + 0.3.9000 + + + + + +
+
+
+ +
+

Add admin boundaries (lines) and the legend

+
+ +
+

Usage

+
add_admin_boundaries(
+  lines,
+  colors,
+  labels,
+  lwds,
+  title = "",
+  buffer = NULL,
+  ...
+)
+
+ +
+

Arguments

+
lines
+

List of multiline shape defined by sf package.

+ + +
colors
+

Vector of hexadecimal codes. Same order as lines.

+ + +
labels
+

Vector of labels in the legend. Same order as lines.

+ + +
lwds
+

Vector of line widths. Same order as lines.

+ + +
title
+

Legend title.

+ + +
buffer
+

A buffer, either one value or a vector of 4 values (left, bottom, right, top).

+ + +
...
+

Other arguments to pass to each shape in `tmap::tm_lines()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/add_admin_labels.html b/docs/reference/add_admin_labels.html new file mode 100644 index 0000000..29ba3b6 --- /dev/null +++ b/docs/reference/add_admin_labels.html @@ -0,0 +1,131 @@ + +Wrapper around `tmap::tm_text()` with sane defaults for plotting admin labels. — add_admin_labels • visualizeR + Skip to contents + + +
+
+
+ +
+

Wrapper around `tmap::tm_text()` with sane defaults for plotting admin labels.

+
+ +
+

Usage

+
add_admin_labels(
+  point,
+  text,
+  size = 0.5,
+  fontface = "bold",
+  fontfamily = "Leelawadee",
+  shadow = TRUE,
+  auto_placement = FALSE,
+  remove_overlap = FALSE,
+  ...
+)
+
+ +
+

Arguments

+
point
+

Multipoint shape defined by sf package.

+ + +
text
+

Text labels column.

+ + +
size
+

Relative size of the text labels.

+ + +
fontface
+

Fontface.

+ + +
fontfamily
+

Fontfamily. Leelawadee is your precious.

+ + +
shadow
+

Boolean. Add a shadow around text labels. Issue opened on Github to request.

+ + +
auto_placement
+

Logical that determines whether the labels are placed automatically.

+ + +
remove_overlap
+

Logical that determines whether the overlapping labels are removed.

+ + +
...
+

Other arguments to pass to `tmap::tm_text()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/add_compass.html b/docs/reference/add_compass.html new file mode 100644 index 0000000..5a2a84e --- /dev/null +++ b/docs/reference/add_compass.html @@ -0,0 +1,116 @@ + +Add a compass — add_compass • visualizeR + Skip to contents + + +
+
+
+ +
+

Add a compass

+
+ +
+

Usage

+
add_compass(
+  text_size = 0.6,
+  position = c("right", 0.8),
+  color_dark = cols_reach("black"),
+  text_color = cols_reach("black"),
+  type = "4star",
+  ...
+)
+
+ +
+

Arguments

+
text_size
+

Relative font size.

+ + +
position
+

Position of the compass. Vector of two values, specifying the x and y coordinates.

+ + +
color_dark
+

Color of the dark parts of the compass.

+ + +
text_color
+

color of the text.

+ + +
type
+

Compass type, one of: "arrow", "4star", "8star", "radar", "rose".

+ + +
...
+

Other arguments to pass to `tmap::tm_compass()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/add_credits.html b/docs/reference/add_credits.html new file mode 100644 index 0000000..8404da4 --- /dev/null +++ b/docs/reference/add_credits.html @@ -0,0 +1,105 @@ + +Do you want to credit someone or some institution? — add_credits • visualizeR + Skip to contents + + +
+
+
+ +
+

Do you want to credit someone or some institution?

+
+ +
+

Usage

+
add_credits(text, size = 0.4, bg_color = NA, position = c(0.75, 0.02), ...)
+
+ +
+

Arguments

+
text
+

Text.

+ + +
size
+

Relative text size.

+ + +
bg_color
+

Background color.

+ + +
position
+

Position. Vector of two coordinates. Usually somewhere down.

+ + +
...
+

Other arguments to pass to `tmap::tm_credits()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/add_indicator_layer.html b/docs/reference/add_indicator_layer.html new file mode 100644 index 0000000..c5bd750 --- /dev/null +++ b/docs/reference/add_indicator_layer.html @@ -0,0 +1,161 @@ + +Wrapper around `tmap::tm_polygons()` with sane defaults for plotting indicator values — add_indicator_layer • visualizeR + Skip to contents + + +
+
+
+ +
+

Wrapper around `tmap::tm_polygons()` with sane defaults for plotting indicator values

+
+ +
+

Usage

+
add_indicator_layer(
+  poly,
+  col,
+  buffer = NULL,
+  n = 5,
+  style = "pretty",
+  palette = pal_reach("red_5"),
+  as_count = TRUE,
+  color_na = cols_reach("white"),
+  text_na = "Missing data",
+  legend_title = "Proportion (%)",
+  legend_text_separator = " - ",
+  border_alpha = 1,
+  border_col = cols_reach("lt_grey_1"),
+  lwd = 1,
+  ...
+)
+
+ +
+

Arguments

+
poly
+

Multipolygon shape defined by sf package.

+ + +
col
+

Numeric attribute to map.

+ + +
buffer
+

A buffer, either one value or a vector of 4 values (left, bottom, right, top).

+ + +
n
+

The desire number of classes.

+ + +
style
+

Method to process the color scale for continuous numerical variables. See `classInt::classIntervals()` for details.

+ + +
palette
+

Vector of fill colors as hexadecimal values. For REACH color palettes, it is possible to use `pal_reach()`. For now,'palette' must be changed manually, accordingly to the number of drawn classes.

+ + +
as_count
+

Boolean. When col is a numeric variable, should it be processed as a count variable? For instance, 0, 1-10, 11-20.

+ + +
color_na
+

Fill color for missing data.

+ + +
text_na
+

Legend text for missing data.

+ + +
legend_title
+

Legend title.

+ + +
legend_text_separator
+

Text separator for classes. E.g. " to " will give 0, 1 to 10, 11 to 20.

+ + +
border_alpha
+

Transparency of the border.

+ + +
border_col
+

Color of the border.

+ + +
lwd
+

Linewidth of the border.

+ + +
...
+

Other arguments to pass to `tmap::tm_polygons()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/add_layout.html b/docs/reference/add_layout.html new file mode 100644 index 0000000..eda0726 --- /dev/null +++ b/docs/reference/add_layout.html @@ -0,0 +1,141 @@ + +Basic defaults based on `tmap::tm_layout()` — add_layout • visualizeR + Skip to contents + + +
+
+
+ +
+

Basic defaults based on `tmap::tm_layout()`

+
+ +
+

Usage

+
add_layout(
+  title = NULL,
+  legend_position = c(0.02, 0.5),
+  frame = FALSE,
+  legend_frame = cols_reach("main_grey"),
+  legend_text_size = 0.6,
+  legend_title_size = 0.8,
+  title_size = 0.9,
+  title_fontface = "bold",
+  title_color = cols_reach("main_grey"),
+  fontfamily = "Leelawadee",
+  ...
+)
+
+ +
+

Arguments

+
title
+

Map title.

+ + +
legend_position
+

Legend position. Not above the map is a good start.

+ + +
frame
+

Boolean. Legend frame?

+ + +
legend_frame
+

Legend frame color.

+ + +
legend_text_size
+

Legend text size in 'pt'.

+ + +
legend_title_size
+

Legend title size in 'pt'.

+ + +
title_size
+

Title text size in 'pt'.

+ + +
title_fontface
+

Title fontface. Bold if you wanna exemplify a lot what it is about.

+ + +
title_color
+

Title font color.

+ + +
fontfamily
+

Overall fontfamily. Leelawadee is your precious.

+ + +
...
+

Other arguments to pass to `tmap::tm_layout()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/add_scale_bar.html b/docs/reference/add_scale_bar.html new file mode 100644 index 0000000..c9a18ac --- /dev/null +++ b/docs/reference/add_scale_bar.html @@ -0,0 +1,111 @@ + +Add a scale bar — add_scale_bar • visualizeR + Skip to contents + + +
+
+
+ +
+

Add a scale bar

+
+ +
+

Usage

+
add_scale_bar(
+  text_size = 0.6,
+  position = c("left", 0.01),
+  color_dark = cols_reach("black"),
+  breaks = c(0, 50, 100),
+  ...
+)
+
+ +
+

Arguments

+
text_size
+

Relative font size.

+ + +
position
+

Position of the compass. Vector of two values, specifying the x and y coordinates.

+ + +
color_dark
+

Color of the dark parts of the compass.

+ + +
breaks
+

Breaks of the scale bar. If not specified, breaks will be automatically be chosen given the prefered width of the scale bar. Example: c(0, 50, 100).

+ + +
...
+

Other arguments to pass to `tmap::tm_compass()`.

+ +
+
+

Value

+ + +

A tmap layer.

+
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/bar_reach.html b/docs/reference/bar_reach.html index 1c49a7e..4227377 100644 --- a/docs/reference/bar_reach.html +++ b/docs/reference/bar_reach.html @@ -1,5 +1,5 @@ -Simple bar chart — bar_reach • visualizeRSimple bar chart — bar_reach • visualizeR @@ -10,7 +10,7 @@ visualizeR - 0.2.9000 + 0.3.9000 + + + + + +
+
+
+ +
+

A multiline shapefile of Haiti's border.

+
+ +
+

Usage

+
border_admin0
+
+ +
+

Format

+

A sf multiline objet with 1 feature and 6 fields:

fid_1
+

fid_1

+ +
uno
+

uno

+ +
count
+

count

+ +
x_coord
+

x_coord

+ +
y_coord
+

y_coord

+ +
area
+

area

+ +
geometry
+

Multiline geometry.

+ + +
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/buffer_bbox.html b/docs/reference/buffer_bbox.html index 730871e..d009941 100644 --- a/docs/reference/buffer_bbox.html +++ b/docs/reference/buffer_bbox.html @@ -1,5 +1,5 @@ -Bbbox buffer — buffer_bbox • visualizeRBbbox buffer — buffer_bbox • visualizeR @@ -10,7 +10,7 @@ visualizeR - 0.2.9000 + 0.3.9000 + + + + + +
+
+
+ +
+

A multipoint shapefile of Haiti's admin 1.

+
+ +
+

Usage

+
centroid_admin1
+
+ +
+

Format

+

A sf multipoint object with 10 features and 9 fields:

ADM1_PC
+

Admin 1 postal code.

+ +
ADM1_EN
+

Full name in English.

+ +
ADM1_FR
+

Full name in French.

+ +
ADM1_HT
+

Full name in Haitian Creole.

+ +
ADM0_EN
+

Country name in English.

+ +
ADM0_FR
+

Country name in French.

+ +
ADM0_HT
+

Country name in Haitian Creole.

+ +
ADM0_PC
+

Country postal code.

+ +
ADM1_FR_UPPER
+

Admin 1 French name - uppercase.

+ +
geometry
+

Multipoint geometry.

+ + +
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/cols_agora.html b/docs/reference/cols_agora.html index 4f59629..a6d9609 100644 --- a/docs/reference/cols_agora.html +++ b/docs/reference/cols_agora.html @@ -1,5 +1,5 @@ -Function to extract AGORA colors as hex codes — cols_agora • visualizeRFunction to extract AGORA colors as hex codes — cols_agora • visualizeR @@ -10,7 +10,7 @@ visualizeR - 0.2.9000 + 0.3.9000 + + + + + +
+
+
+ +
+

A multiline shapefile of Haiti's frontier with Dominican Republic.

+
+ +
+

Usage

+
frontier_admin0
+
+ +
+

Format

+

A sf multipoint objet with 4 features and 8 fields:

fid_1
+

fid_1

+ +
objectid
+

objectid

+ +
id
+

id

+ +
fromnode
+

fromnode

+ +
tonode
+

tonode

+ +
leftpolygo
+

leftpolygo

+ +
rightpolygo
+

rightpolygo

+ +
shape_leng
+

shape_leng

+ +
geometry
+

Multiline geometry.

+ + +
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/if_not_in_stop.html b/docs/reference/if_not_in_stop.html index c7ad676..b9bd9ec 100644 --- a/docs/reference/if_not_in_stop.html +++ b/docs/reference/if_not_in_stop.html @@ -1,5 +1,5 @@ -Stop statement "If not in colnames" with colnames — if_not_in_stop • visualizeRStop statement "If not in colnames" with colnames — if_not_in_stop • visualizeR @@ -10,7 +10,7 @@ visualizeR - 0.2.9000 + 0.3.9000 + + + + + +
+
+
+ +
+

A multipolygon shapefile of Haiti's admin 1 with an indicator column 'opn_dfc'.

+
+ +
+

Usage

+
indicator_admin1
+
+ +
+

Format

+

A sf multipoint object with 10 features and 10 fields:

ADM1_PC
+

Admin 1 postal code.

+ +
admin1
+

Admin 1 unique id.

+ +
opn_dfc
+

Proportion of HHs that reported open defecation as sanitation facility.

+ +
ADM1_EN
+

Full name in English.

+ +
ADM1_FR
+

Full name in French.

+ +
ADM1_HT
+

Full name in Haitian Creole.

+ +
ADM0_EN
+

Country name in English.

+ +
ADM0_FR
+

Country name in French.

+ +
ADM0_HT
+

Country name in Haitian Creole.

+ +
ADM0_PC
+

Country postal code.

+ +
geometry
+

Multipolygon geometry.

+ + +
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/line_admin1.html b/docs/reference/line_admin1.html new file mode 100644 index 0000000..1c91548 --- /dev/null +++ b/docs/reference/line_admin1.html @@ -0,0 +1,105 @@ + +Haïti admin 1 lines shapefile. — line_admin1 • visualizeR + Skip to contents + + +
+
+
+ +
+

A multiline shapefile of Haiti's admin 1.

+
+ +
+

Usage

+
line_admin1
+
+ +
+

Format

+

A sf multiline object with 10 features and 8 fields:

ADM1_EN
+

Full name in English.

+ +
ADM1_FR
+

Full name in French.

+ +
ADM1_HT
+

Full name in Haitian Creole.

+ +
ADM0_EN
+

Country name in English.

+ +
ADM0_FR
+

Country name in French.

+ +
ADM0_HT
+

Country name in Haitian Creole.

+ +
ADM0_PCODE
+

Country postal code.

+ +
geometry
+

Multiline geometry.

+ + +
+ +
+ + +
+ + + +
+ + + + + + + diff --git a/docs/reference/pal_agora.html b/docs/reference/pal_agora.html index 0904e81..5720399 100644 --- a/docs/reference/pal_agora.html +++ b/docs/reference/pal_agora.html @@ -1,5 +1,5 @@ -Return function to interpolate an AGORA color palette — pal_agora • visualizeRReturn function to interpolate an AGORA color palette — pal_agora • visualizeR @@ -10,7 +10,7 @@ visualizeR - 0.2.9000 + 0.3.9000