├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── DESCRIPTION ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── createPDF.R ├── hidden_createPDF.R ├── sysdata.rda ├── uniqIDHierarchy.R ├── uniqIDMaker.R ├── uniqID_maker_addin.R └── zzz.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── baRcodeR.Rproj ├── codecov.yml ├── cran-comments.md ├── inst ├── WORDLIST └── rstudio │ └── addins.dcf ├── man ├── cheatsheet.Rd ├── create_PDF.Rd ├── custom_create_PDF.Rd ├── figures │ ├── Flowchart.png │ ├── example.png │ └── example_file.pdf ├── make_labels.Rd ├── uniqID_hier_maker.Rd └── uniqID_maker.Rd ├── tests ├── testthat.R └── testthat │ ├── apps │ └── make_labels │ │ ├── app.R │ │ └── tests │ │ ├── hier_labels-current │ │ ├── 001.json │ │ ├── 001.png │ │ ├── 002.json │ │ └── 002.png │ │ ├── hier_labels-expected │ │ ├── 001.json │ │ ├── 001.png │ │ ├── 002.json │ │ └── 002.png │ │ ├── hier_labels.R │ │ ├── labels-current │ │ ├── 001.json │ │ └── 001.png │ │ ├── labels-expected │ │ ├── 001.json │ │ └── 001.png │ │ ├── labels.R │ │ ├── test_bar-current │ │ ├── 001.json │ │ ├── 002.json │ │ ├── 003.json │ │ └── 004.json │ │ ├── test_bar-expected │ │ ├── 001.json │ │ ├── 002.json │ │ ├── 003.json │ │ └── 004.json │ │ ├── test_bar.R │ │ └── test_labels.csv │ ├── test-interactive.R │ ├── test-label_generation.R │ ├── test-pdf_creation.R │ ├── test-test-addin.R │ └── test_warnings.R └── vignettes ├── .gitignore ├── Using-baRcodeR.Rmd ├── add-in-screenshot.png ├── tab-1-screenshot-2.png ├── tab-1-screenshot.png ├── tab-2-screenshot.png ├── tab-3-screenshot-2.png ├── tab-3-screenshot.png └── use-addin.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CRAN-RELEASE$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^cran-comments\.md$ 5 | ^\.travis\.yml$ 6 | ^codecov\.yml$ 7 | ^CODE_OF_CONDUCT\.md$ 8 | ^_pkgdown\.yml$ 9 | ^docs$ 10 | ^pkgdown$ 11 | ^README\.Rmd$ 12 | ^doc$ 13 | ^Meta$ 14 | ^LICENSE\.md$ 15 | paper_figure2.* 16 | paper_figure1.* 17 | ^CRAN-SUBMISSION$ 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .lintr 5 | inst/doc 6 | doc 7 | Meta 8 | docs/ 9 | /doc/ 10 | /Meta/ 11 | CRAN-SUBMISSION -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: r 4 | 5 | r: 6 | - oldrel 7 | - release 8 | - devel 9 | cache: packages 10 | 11 | r_github_packages: 12 | - r-lib/covr 13 | 14 | after_success: 15 | - Rscript -e 'covr::codecov(line_exclusions = "R/uniqID_maker_addin.R")' 16 | 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (https://www.contributor-covenant.org), version 1.0.0, available at 25 | https://contributor-covenant.org/version/1/0/0/. 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: baRcodeR 2 | Title: Label Creation for Tracking and Collecting Data from 3 | Biological Samples 4 | Version: 0.1.8 5 | Authors@R: 6 | c(person(given = "Yihan", 7 | family = "Wu", 8 | role = c("aut"), 9 | email = "yihan.wu@queensu.ca", 10 | comment = c(ORCID = "0000-0002-1202-4208")), 11 | person(given = "Robert", 12 | family = "Colautti", 13 | role = c("aut", "cre"), 14 | email = "robert.colautti@queensu.ca", 15 | comment = c(ORCID = "0000-0003-4213-0711")), 16 | person(given = "Emily", 17 | family = "Bao", 18 | role = "ctb", 19 | email = "13syeb@queensu.ca"), 20 | person(given = "Lluís", 21 | family = "Revilla Sancho", 22 | role = c("rev"), 23 | email = "lluis.revilla@gmail.com", 24 | comment = c(ORCID = "0000-0001-9747-2570")), 25 | person(given = "Rayna", 26 | family = "Harris", 27 | role = c("rev"), 28 | email = "rmharris@ucdavis.edu")) 29 | Description: Tools to generate unique identifier codes and 30 | printable barcoded labels for the management of biological samples. 31 | The creation of unique ID codes and printable PDF files can be 32 | initiated by standard commands, user prompts, or through a GUI addin 33 | for R Studio. Biologically informative codes can be included for 34 | hierarchically structured sampling designs. 35 | License: GPL-3 36 | URL: https://docs.ropensci.org/baRcodeR/ (website) https://github.com/ropensci/baRcodeR/ 37 | BugReports: https://github.com/ropensci/baRcodeR/issues 38 | Depends: 39 | qrcode (>= 0.2.2), 40 | R (>= 4.3.2) 41 | Imports: 42 | DT (>= 0.31), 43 | grDevices, 44 | grid, 45 | miniUI (>= 0.1.1), 46 | rstudioapi, 47 | shiny (>= 0.13) 48 | Suggests: 49 | covr, 50 | knitr, 51 | rmarkdown, 52 | shinytest, 53 | testthat (>= 2.1.0) 54 | VignetteBuilder: 55 | knitr 56 | Encoding: UTF-8 57 | Language: en-CA 58 | RoxygenNote: 7.2.3 59 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(cheatsheet) 4 | export(code_128_make) 5 | export(code_128_make2) 6 | export(create_PDF) 7 | export(custom_create_PDF) 8 | export(make_labels) 9 | export(qrcode_make) 10 | export(uniqID_hier_maker) 11 | export(uniqID_maker) 12 | import(qrcode) 13 | import(rstudioapi) 14 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # baRcodeR 0.1.8 2 | 3 | Thanks to cfmw for suggesting a change to allow underscores in QR codes, and for real-world testing. 4 | 5 | Thanks to lavaman13 and wolass for requesting a different layout for the QR Code labels that allows text above or below the barcode. This is now implemented with the `type="matrix2"` argument in `create_PDF()` 6 | 7 | # baRcodeR 0.1.7 8 | 9 | Thanks to rwalke for adding "Linear2" to the option list (Linear, Matrix). This will produce Code 128 extended linear barcodes, allowing for particular 1-D barcode patterns that are distinct from "Linear" 10 | 11 | Thanks to Theirry() for pointing out that we need to change qrcode::qr_code() from (deprecated) qrcode_gen 12 | 13 | 14 | # baRcodeR 0.1.6 15 | 16 | At the request of a COVID-2019 research group, we have added an option to allow non-encoded text to appear with linear & 2D barcodes. These have been added to custom_create_PDF(): 17 | 18 | * alt_text -- adds human-readable text that is NOT encoded in the digital barcode 19 | * denote -- characters used to denote non-encoded text 20 | 21 | These are considered advanced features that should be used cautiously, and therefore they are not made available through the Addins GUI. 22 | 23 | # baRcodeR 0.1.5 24 | 25 | Bugs: 26 | 27 | - fixed errors in tests due to r-devel switching to using stringsAsFactor = FALSE as default 28 | - fixed broken link in readme 29 | 30 | 31 | # baRcodeR 0.1.4 32 | 33 | Bugs and Improvements: 34 | 35 | - tests have been added for user prompts and the RStudio addin with shinytest 36 | - vignettes describing how to use the add-in and the command line are now organized separately from the restructured README 37 | - `custom_create_PDF()` page generation should now be faster (helpful when making sheets for hundreds of labels) 38 | - the command prompts have been restructured for a more menu-like selection for yes/no questions. 39 | - other minor changes in addition to the major ones outlined above as suggested by reviews at rOpenSci documented [here](https://github.com/ropensci/software-review/issues/338) 40 | - the baRcodeR package is now a part of [rOpenSci](https://ropensci.org/) and the documentation is online (here)[https://docs.ropensci.org/baRcodeR/] 41 | 42 | # baRcodeR 0.1.3 43 | 44 | Bugs and Improvements: 45 | 46 | - major bug fix for linear barcodes that occasionally created unscannable barcodes. 47 | - added documentation on how to create alternative formatting of labels (e.g. spaces, line breaks) 48 | - added padding for labels which were single character or blank 49 | - 2-page cheatsheet now available as addin 50 | 51 | # baRcodeR 0.1.2 52 | 53 | New Feature: 54 | 55 | - In response to a user request, there is now an option to print linear (code 128 set B) barcodes. 56 | 57 | # baRcodeR 0.1.1 58 | 59 | Bugs and Improvements: 60 | 61 | - create_PDF() function will replace all underscores in text with dashes. Underscores are not specified in the encoding dictionary of `qcrode` and will throw errors. 62 | - x_space and y_space parameters are now limited between 0 and 1 for easier use. These parameters are used to position text on the printed labels. 63 | - Font size is no longer limited and is now measured as points. Font size is automatically reduced if text code is too long for the printed labels. 64 | 65 | New Features: 66 | 67 | - label_width and label_height parameters specify the width and height of the label to enable alleys (i.e. gaps) between physical labels. 68 | 69 | 70 | ----------------- 71 | 72 | 73 | # baRcodeR 0.1.0 74 | 75 | This is the first official release of the package. -------------------------------------------------------------------------------- /R/createPDF.R: -------------------------------------------------------------------------------- 1 | #' Make barcodes and print labels 2 | #' 3 | #' Input vector or data.frame of ID codes to produce a PDF of QR codes which can 4 | #' be printed. This is a wrapper function for \code{\link{custom_create_PDF}}. 5 | #' See details of \code{\link{custom_create_PDF}} on how to format text labels 6 | #' if needed. 7 | #' 8 | #' The default PDF setup is for ULINE 1.75" * 0.5" WEATHER RESISTANT LABEL for laser 9 | #' printer; item # S-19297 (uline.ca). The page format can be modified using 10 | #' the \code{...} (advanced arguments) for other label types. 11 | #' 12 | #' @return a PDF file containing QR-coded labels, saved to the default directory. 13 | #' 14 | #' 15 | #' @inheritParams custom_create_PDF 16 | #' @param ... advanced arguments to modify the PDF layout. See 17 | #' \code{\link{custom_create_PDF}} for arguments. The advanced options can be 18 | #' accessed interactively with \code{user = TRUE} and then entering TRUE when prompted to 19 | #' modify advanced options. 20 | #' @export 21 | #' @examples 22 | #' ## data frame 23 | #' example_vector <- as.data.frame(c("ao1", "a02", "a03")) 24 | #' 25 | #' \dontrun{ 26 | #' ## run with default options 27 | #' ## pdf file will be "example.pdf" saved into a temp directory 28 | #' 29 | #' temp_file <- tempfile() 30 | #' 31 | #' create_PDF(Labels = example_vector, name = temp_file) 32 | #' 33 | #' ## view example output from temp folder 34 | #' system2("open", paste0(temp_file, ".pdf")) 35 | #' } 36 | #' 37 | #' ## run interactively. Overrides default pdf options 38 | #' if(interactive()){ 39 | #' create_PDF(user = TRUE, Labels = example_vector) 40 | #' } 41 | #' 42 | #' \dontrun{ 43 | #' ## run using a data frame, automatically choosing the "label" column 44 | #' example_df <- data.frame("level1" = c("a1", "a2"), "label" = c("a1-b1", 45 | #' "a1-b2"), "level2" = c("b1", "b1")) 46 | #' create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), "example_2")) 47 | #' } 48 | #' 49 | #' \dontrun{ 50 | #' ## run using an unnamed data frame 51 | #' example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 52 | #' ## specify column from data frame 53 | #' create_PDF(user = FALSE, Labels = example_df[,2], name = file.path(tempdir(), "example_3")) 54 | #' } 55 | #' \dontrun{ 56 | #' ## create linear (code128) label rather than matrix (2D/QR) labels 57 | #' example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 58 | #' ## specify column from data frame 59 | #' create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), 60 | #' "example_4", type = "linear")) 61 | #' } 62 | #' @seealso \code{\link{custom_create_PDF}} 63 | 64 | 65 | create_PDF <- function(user = FALSE, 66 | Labels = NULL, 67 | name ="LabelsOut", 68 | type = "matrix", 69 | ErrCorr = "H", 70 | Fsz = 12, ...) { 71 | custom_create_PDF(user, Labels, name, type, ErrCorr, Fsz, ...) 72 | } 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /R/hidden_createPDF.R: -------------------------------------------------------------------------------- 1 | #' Make barcodes and print labels 2 | #' 3 | #' Input a vector or data frame of ID codes to produce a PDF of barcode labels 4 | #' that can then be printed. The PDF setup is for the ULINE 1.75" * 0.5" WEATHER 5 | #' RESISTANT LABEL for laser printer; item # S-19297 (uline.ca). See details for 6 | #' how to format text labels properly. 7 | #' 8 | #' \code{qrcode_make} is the helper function for generating a QR code matrix. 9 | #' \code{code_128_make} is the helper function for generating a linear barcode 10 | #' according to code 128 set B. \code{code_128_make2} is the extended helper function for generating a linear barcode 11 | #' according to code 128 set B, all Latin-1 characters, set C and partially A. \code{custom_create_PDF} is the main function 12 | #' which sets page layout, and creates the PDF file. 13 | #' 14 | #' 15 | #' Correction levels for QR codes refer to the level of damage a label can 16 | #' tolerate before the label become unreadable by a scanner (L = Low (7\%), M = 17 | #' Medium (15\%), Q = Quantile (25\%), H = High (30\%)). So a label with L 18 | #' correction can lose up to at most 7% of the code before it is unreadable 19 | #' while a H label can lose up to 30% of the code. This also means that L codes 20 | #' can be printed at smaller sizes compared to H codes. 21 | #' 22 | #' The escape characters \code{\\n} and \code{\\s} (and the hex equivalents 23 | #' \code{\\x0A} and \code{\\x20} can be used to format text labels. Tab character 24 | #' \code{\\t} (\code{\\x09}) does not work for QR codes and should be replaced by 25 | #' a number of space characters. See the package vignette for examples. 26 | #' 27 | #' If \code{ECol} or \code{ERow} is greater than \code{numcol} and \code{numrow}, 28 | #' the labels will be printed starting on the second page. 29 | #' 30 | #' @return a PDF file containing QR-coded labels, saved to the default 31 | #' directory. 32 | #' 33 | #' @param user logical. Run function using interactive mode (prompts user for 34 | #' parameter values) Default is \code{FALSE} 35 | #' @param Labels vector or data frame object containing label names (i.e. unique 36 | #' ID codes) with either UTF-8 or ASCII encoding. 37 | #' @param alt_text vector containing alternative names that are printed along with 38 | #' Labels BUT ARE NOT ENCODED in the barcode image. Use with caution! 39 | #' @param replace_label logical. Replace label text with \code{alt_text}. 40 | #' Generated barcode will contain more information than text label. Use with 41 | #' caution! 42 | #' @param denote character (prefix) or vector of length 2 (prefix, suffix). 43 | #' Denotes alt_text that is not encoded in the barcode image. 44 | #' Default is brackets before and after (). 45 | #' @param name character. Name of the PDF output file. Default is 46 | #' \code{"LabelsOut"}. A file named \code{name.pdf} will be saved to the 47 | #' working directory by default. Use \code{"dirname/name"} to produce a file 48 | #' called \code{name.pdf} in the \code{dirname} directory. 49 | #' @param type character. Choice of \code{"linear"} for code 128, \code{"linear2"} 50 | #' for extended code 128, \code{"matrix"} for QR code (i.e. 2D barcode) with 51 | #' text to the right, or \code{"matrix2"} for QR code with text above or below, 52 | #' depending on \code{y_space} value (0 = below, 1 = above). 53 | #' @param ErrCorr error correction value for matrix labels only. Level of damage 54 | #' from low to high: \code{"L"}, \code{"M"}, \code{"Q"}, \code{"H"}. Default 55 | #' is \code{"H"}. See details for explanation of values. 56 | #' @param Fsz numerical. Sets font size in points. Longer ID codes may be shrunk 57 | #' to fit if truncation is not used for matrix labels. Default font size is 58 | #' \code{5}. ID codes are also shrunk automatically to fit on the label if 59 | #' actual size is bigger than label dimensions. 60 | #' @param Across logical. When \code{TRUE}, print labels across rows, left to 61 | #' right. When \code{FALSE}, print labels down columns, top to bottom. Default 62 | #' is \code{TRUE}. 63 | #' @param ERows number of rows to skip. Default is \code{0}. Example: setting 64 | #' ERows to 6 will begin printing at row 7. ERows and ECols are useful for 65 | #' printing on partially-used label sheets. 66 | #' @param ECols number of columns to skip. Default is \code{0}. Example: setting 67 | #' ECols to 2 will put the first label at column 3. ERows and ECols are useful 68 | #' for printing on partially-used label sheets. 69 | #' @param trunc logical. Text is broken into multiple lines for longer ID codes, 70 | #' to prevent printing off of the label area. Default is \code{TRUE}. If 71 | #' \code{trunc = FALSE}, and text is larger than the physical label, the text will 72 | #' be shrunk down automatically. 73 | #' @param numrow numerical. Number of rows per page. Default is \code{20}. 74 | #' @param numcol numerical. Number of columns per page. Default is \code{4}. 75 | #' @param page_width numerical. Width of page (in inches). Default is set to 76 | #' \code{8.5}. 77 | #' @param page_height numerical. Height of page (in inches). Default is set to 78 | #' \code{11}. 79 | #' @param width_margin numerical. The width margin of the page (in inches). 80 | #' Default is \code{0.25}. 81 | #' @param height_margin numerical. The height margin of the page (in inches). 82 | #' Default is \code{0.5}. 83 | #' @param label_width numerical. The width of label (in inches). Will be 84 | #' calculated as \code{(page_width - 2 * width_margin)/numcol} if 85 | #' \code{label_width} is set as \code{NULL}. 86 | #' @param label_height numerical. The height of the label (in inches). Will be 87 | #' calculated as \code{(page_height - 2 * height_margin)/numrow} if 88 | #' \code{label_height} is set as \code{NULL}. 89 | #' @param x_space numerical. A value between \code{0} and \code{1}. This sets 90 | #' the distance between the QR code and text of each label. Only applies when 91 | #' \code{type = "matrix"}. Default is \code{0}. 92 | #' @param y_space numerical. The height position of the text on the physical 93 | #' label as a proportion of the label height. Only applies when \code{type = 94 | #' "matrix"} or \code{"matrix2"}. A value between \code{0} and \code{1}. 95 | #' Default is \code{0.5}. 96 | #' 97 | #' 98 | #' @examples 99 | #' 100 | #' ## this is the same examples used with create_PDF 101 | #' ## data frame 102 | #' example_vector <- as.data.frame(c("ao1", "a02", "a03")) 103 | #' 104 | #' \dontrun{ 105 | #' ## run with default options 106 | #' ## pdf file will be "example.pdf" saved into a temp directory 107 | #' temp_file <- tempfile() 108 | #' 109 | #' custom_create_PDF(Labels = example_vector, name = temp_file) 110 | #' 111 | #' ## view example output from temp folder 112 | #' system2("open", paste0(temp_file, ".pdf")) 113 | #' } 114 | #' 115 | #' ## run interactively. Overrides default pdf options 116 | #' if(interactive()){ 117 | #' custom_create_PDF(user = TRUE, Labels = example_vector) 118 | #' } 119 | #' 120 | #' \dontrun{ 121 | #' ## run using a data frame, automatically choosing the "label" column 122 | #' example_df <- data.frame("level1" = c("a1", "a2"), "label" = c("a1-b1", 123 | #' "a1-b2"), "level2" = c("b1", "b1")) 124 | #' 125 | #' custom_create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), 126 | #' "example_2")) 127 | #' } 128 | #' \dontrun{ 129 | #' ## run using an unnamed data frame 130 | #' example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 131 | #' ## specify column from data frame 132 | #' custom_create_PDF(user = FALSE, Labels = example_df[,2], name = file.path(tempdir(), "example_3")) 133 | #' } 134 | #' \dontrun{ 135 | #' ## create linear (code128) label rather than matrix (2D/QR) labels 136 | #' example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 137 | #' ## specify column from data frame 138 | #' custom_create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), 139 | #' "example_4", type = "linear")) 140 | #' } 141 | #' \dontrun{ 142 | #' ## Include text for the user that is NOT encoded into the barcode image 143 | #' ## Excluded text is denoted with brackets by default 144 | #' example_df <- data.frame(ID = floor(runif(3) * 10000), name = c("A", "B", "C"), 145 | #' dob = c("1/1/2020", "12/6/2001", "2/8/1986")) 146 | #' 147 | #' ## linear (1d) barcodes with custom denote parameter 148 | #' custom_create_PDF(Labels = example_df$ID, alt_text = paste(example_df$name, 149 | #' example_df$dob), type = "linear", denote=".") 150 | #' } 151 | #' @seealso \code{\link{create_PDF}} 152 | #' @export 153 | #' @import qrcode 154 | 155 | custom_create_PDF <- function(user = FALSE, 156 | Labels = NULL, 157 | name = "LabelsOut", 158 | type = "matrix", 159 | ErrCorr = "H", 160 | Fsz = 12, 161 | Across = TRUE, 162 | ERows = 0, 163 | ECols = 0, 164 | trunc = TRUE, 165 | numrow = 20, 166 | numcol = 4, 167 | page_width = 8.5, 168 | page_height = 11, 169 | width_margin = 0.25, 170 | height_margin = 0.5, 171 | label_width = NA, 172 | label_height = NA, 173 | x_space = 0, 174 | y_space = 0.5, 175 | alt_text = NULL, 176 | replace_label = FALSE, 177 | denote = c("\n(",")") 178 | 179 | ){ 180 | if (length(Labels) == 0) stop("Labels do not exist. Please pass in Labels") 181 | # what to do depending on class of Label input 182 | if(class(Labels)[1] %in% c("character", "integer", "numeric", "factor")){ 183 | # treat as vector 184 | Labels <- Labels 185 | } else if (class(Labels)[1] == "data.frame") { 186 | if (any(tolower(names(Labels)) == "label")){ 187 | Labels <- Labels[, "label"] 188 | } else { 189 | warning("Cannot find a label column. Using first column as label input.") 190 | Labels <- Labels[, 1] 191 | } 192 | } else { 193 | stop("Label input not a vector or a data frame. Please check your input.") 194 | } 195 | if (all(vapply(c( 196 | numcol, numrow, 197 | Fsz, ERows, ECols, 198 | trunc, page_width, page_height, 199 | height_margin, width_margin, 200 | x_space, y_space), is.numeric, logical(1L))) != TRUE) { 201 | stop("One or more numerical parameters are not numeric") 202 | } 203 | labelLength <- max(nchar(paste(Labels))) 204 | if (x_space > 1 | x_space < 0) stop("ERROR: x_space value out of bounds. Must be between 0 and 1") 205 | if (y_space < 0 | y_space > 1) stop("ERROR: y_space value out of bounds. Must be between 0 and 1") 206 | 207 | if (length(alt_text) > 0) { 208 | if(length(alt_text) != length(Labels)) { 209 | stop("Length of alt-text and Labels not equal.") 210 | } 211 | if (length(denote) == 1) { 212 | if (denote[1] %in% c("", NULL, NA, F)) { 213 | warning("alt-text is not encoded in barcode. Nothing shows the end-user which text is encoded. Use with caution! see ?custom_create_pdf") 214 | } else { 215 | warning(paste("alt_text is not encoded in barcode. Non-encoded text begins with",denote[1])) 216 | alt_text <- paste0(denote[1],alt_text) 217 | } 218 | } 219 | if (length(denote) > 1) { 220 | warning(paste("alt_text is not encoded in barcode. Non-encoded text is denoted with",denote[1],denote[2])) 221 | alt_text <- paste0(denote[1],alt_text,denote[2]) 222 | } 223 | alt_text <- as.factor(alt_text) 224 | } 225 | 226 | # clean up any open graphical devices if function fails 227 | on.exit(grDevices::graphics.off()) 228 | # if user prompt has been set to true 229 | if (user == TRUE){ 230 | 231 | ## ask for name 232 | name <- string_input("Please enter name for PDF output file: ") 233 | ## Set font size 234 | Fsz <- numeric_input("Please enter a font size: ", integer = FALSE) 235 | ## Error correction 236 | 237 | ErrCorr <- switch( 238 | fake_menu( 239 | c("L (up to 7% damage)", "M (up to 15% damage)", 240 | "Q (up to 25% damage)", "H (up to 30% damage)"), 241 | "Select an error correction level. "), 242 | "L", "M", "Q", "H") 243 | 244 | # check errCorr input 245 | Advanced <- switch( 246 | fake_menu(c("Yes", "No"), 247 | "Edit advanced parameters?"), 248 | TRUE, FALSE) 249 | 250 | if (Advanced) { 251 | type <- switch( 252 | fake_menu(c("Matrix - text beside", "Matrix - text above", 253 | "Linear", "Linear2"), 254 | "Type of Barcode: "), 255 | "matrix", "matrix2", "linear", "linear2" 256 | ) 257 | 258 | ## Set to TRUE to print labels across rows instead of down columns 259 | Across <- switch(fake_menu(c("Yes", "No"), 260 | "Print labels across?"), 261 | TRUE, FALSE) 262 | 263 | # Split text into rows (prevents text cutoff with narrow labels) 264 | trunc<- switch(fake_menu(c("Yes", "No"), 265 | "Truncate longer labels into multiple lines if necessary?"), 266 | TRUE, FALSE) 267 | 268 | ERows <- numeric_input("Number of rows to skip? (enter 0 for default): ") 269 | 270 | ECols <- numeric_input("Number of cols to skip? (enter 0 for default): ") 271 | 272 | numrow <- numeric_input("Number of rows per page: ") 273 | 274 | numcol <- numeric_input("Number of col per page: ") 275 | 276 | height_margin <- numeric_input( 277 | "Please enter the height margin of page (in inches): ", integer = FALSE) 278 | 279 | width_margin <- numeric_input( 280 | "Please enter the width margin of page (in inches): ", integer = FALSE) 281 | 282 | label_width <- numeric_input( 283 | "Please enter the width of the label (in inches): ", integer = FALSE) 284 | 285 | label_height <- numeric_input( 286 | "Please enter the height of the label (in inches): ", integer = FALSE) 287 | 288 | if(type == "matrix"){ 289 | space <- switch( 290 | numeric_input("Change distances between QR code and text label?\n 1: Yes \n 2: No"), 291 | TRUE, FALSE) 292 | } 293 | 294 | x_space <- 0 295 | y_space <- 0.5 296 | if (space){ 297 | x_space <- numeric_input("Please enter a number between 0 and 1 for \n 298 | horizontal distance between QR code and label: ", 299 | integer = FALSE) 300 | while(x_space > 1 ){ 301 | noquote(print("Invalid input")) 302 | x_space <- numeric_input("Please enter a number between 0 and 1: ", integer = FALSE) 303 | } 304 | 305 | y_space <- numeric_input("Please enter a distance between 0 and 1 for \n 306 | vertical distance from bottom: ", integer = FALSE) 307 | 308 | while(y_space > 1){ 309 | noquote(print("Invalid input")) 310 | numeric_input("Please enter a distance between 0 and 1: ", integer = FALSE) 311 | } 312 | } 313 | } ## end of advanced options loop 314 | 315 | } 316 | 317 | width_margin <- page_width - width_margin * 2 318 | height_margin <- page_height - height_margin * 2 319 | 320 | if(!is.numeric(label_width)){label_width <- width_margin/numcol} 321 | if(!is.numeric(label_height)){label_height <- height_margin/numrow} 322 | 323 | if((type == "linear" | type == "linear2") & label_width / labelLength < 0.03) 324 | warning("Linear barcodes created will have bar width smaller than 0.03 inches. \n Increase label width to make them readable by all scanners.") 325 | 326 | column_space <- (width_margin - label_width * numcol)/(numcol - 1) 327 | row_space <- (height_margin - label_height * numrow)/(numrow - 1) 328 | 329 | # Viewport Setup 330 | ## grid for page, the layout is set up so last row and column do not include the spacers for the other columns 331 | barcode_layout <- grid::grid.layout(numrow, 332 | numcol, 333 | widths = grid::unit(c(rep(label_width + column_space, numcol-1), label_width), "in"), 334 | heights = grid::unit(c(rep(label_height + row_space, numrow-1), label_height), "in") 335 | ) 336 | 337 | ## change viewport and barcode generator depending on qr or 1d barcodes 338 | if(type == "linear"){ 339 | code_vp <- grid::viewport(x=grid::unit(0.05, "npc"), 340 | y=grid::unit(0.8, "npc"), 341 | width = grid::unit(0.9 *label_width, "in"), 342 | height = grid::unit(0.8 * label_height, "in"), 343 | just=c("left", "top")) 344 | 345 | text_height <- ifelse(Fsz / 72 > label_height * 0.3, label_height * 0.3, Fsz/72) 346 | 347 | label_vp <- grid::viewport(x=grid::unit(0.5, "npc"), 348 | y = grid::unit(1, "npc"), 349 | width = grid::unit(1, "npc"), 350 | height = grid::unit(text_height, "in"), 351 | just = c("centre", "top")) 352 | 353 | Fsz <- ifelse(Fsz / 72 > label_height * 0.3, label_height * 72 * 0.3 , Fsz) 354 | 355 | label_plots <- sapply(as.character(Labels), code_128_make , USE.NAMES = TRUE, simplify = FALSE) 356 | } else if (type == "linear2"){ 357 | code_vp <- grid::viewport(x=grid::unit(0.05, "npc"), 358 | y=grid::unit(0.8, "npc"), 359 | width = grid::unit(0.9 *label_width, "in"), 360 | height = grid::unit(0.8 * label_height, "in"), 361 | just=c("left", "top")) 362 | 363 | text_height <- ifelse(Fsz / 72 > label_height * 0.3, label_height * 0.3, Fsz/72) 364 | 365 | label_vp <- grid::viewport(x=grid::unit(0.5, "npc"), 366 | y = grid::unit(1, "npc"), 367 | width = grid::unit(1, "npc"), 368 | height = grid::unit(text_height, "in"), 369 | just = c("centre", "top")) 370 | 371 | Fsz <- ifelse(Fsz / 72 > label_height * 0.3, label_height * 72 * 0.3 , Fsz) 372 | 373 | label_plots <- sapply(as.character(Labels), code_128_make2 , USE.NAMES = TRUE, simplify = FALSE) 374 | } else if (type =="matrix"){ 375 | ## vp for the qrcode within the grid layout 376 | code_vp <- grid::viewport(x=grid::unit(0.05, "npc"), 377 | y=grid::unit(0.8, "npc"), 378 | width = grid::unit(0.3 *label_width, "in"), 379 | height = grid::unit(0.6 * label_height, "in"), 380 | just=c("left", "top")) 381 | 382 | ## vp for the text label within the grid layout, scaling the x_space by 0.6 makes sure it will not overlap with the qrcode 383 | label_vp <- grid::viewport(x=grid::unit((0.4 + 0.6*x_space)*label_width, "in"), 384 | y=grid::unit(y_space, "npc"), 385 | width = grid::unit(0.4, "npc"), 386 | height = grid::unit(0.8, "npc"), 387 | just=c("left", "center")) 388 | 389 | # generate qr, most time intensive part 390 | label_plots <- sapply(as.character(Labels), qrcode_make, ErrCorr = ErrCorr, USE.NAMES = TRUE, simplify = FALSE) 391 | } else if (type =="matrix2"){ 392 | ## vp for the qrcode within the grid layout 393 | code_vp <- grid::viewport(x=grid::unit(0.05, "npc"), 394 | y=grid::unit(0, "npc"), 395 | width = grid::unit(0.3 * label_width, "in"), 396 | height = grid::unit(0.6 * label_height, "in"), 397 | just=c("center", "bottom")) 398 | 399 | ## vp for the text label within the grid layout, scaling the x_space by 0.6 makes sure it will not overlap with the qrcode 400 | label_vp <- grid::viewport(x=grid::unit(0.05, "npc"), 401 | y=grid::unit(y_space, "npc"), 402 | width = grid::unit(0.4, "npc"), 403 | height = grid::unit(0.8, "npc"), 404 | just=c("center", "center")) 405 | 406 | # generate qr, most time intensive part 407 | label_plots <- sapply(as.character(Labels), qrcode_make, ErrCorr = ErrCorr, USE.NAMES = TRUE, simplify = FALSE) 408 | } else {stop("Barcode type must be linear, linear2, matrix or matrix2")} 409 | 410 | # since main text label is taken from label_plots, set names of vector 411 | # then null-out alt text 412 | if(replace_label){ 413 | names(label_plots) <- alt_text 414 | alt_text <- NULL 415 | } 416 | # generate label positions 417 | 418 | if(Across){ 419 | # across = TRUE 420 | positions <- expand.grid(x = 1:numcol, y = 1:numrow) 421 | } else { 422 | # across = FALSE 423 | positions <- expand.grid(y = 1:numrow, x = 1:numcol) 424 | } 425 | 426 | # make df of position for each label 427 | # this extra 5 is so that even if starting position is last cell, there are enough positions generated, hopefully 428 | duplication <- ceiling(length(Labels) / nrow(positions)) + 5 429 | 430 | label_positions <- do.call("rbind", replicate(duplication, positions, simplify = FALSE)) 431 | 432 | # condition here for col/row skipping 433 | starting_pos_index <- min(which(label_positions$x == ECols + 1 & label_positions$y == ERows + 1)) 434 | if(ECols > numcol | ERows > numrow){ 435 | warning("Number of rows/columns to skip greater than number of rows/columns on page. Labels will start in top left corner.") 436 | starting_pos_index <- 1 437 | } 438 | label_positions <- label_positions[seq(starting_pos_index, starting_pos_index + length(Labels)),] 439 | 440 | # File Creation 441 | 442 | oname <- paste0(name, ".pdf") 443 | grDevices::pdf(oname, 444 | width = page_width, 445 | height = page_height, 446 | onefile = TRUE, 447 | family = "Courier") # Standard North American 8.5 x 11 448 | 449 | bc_vp = grid::viewport(layout = barcode_layout) 450 | grid::pushViewport(bc_vp) 451 | 452 | for (i in seq(1,length(label_plots))){ 453 | 454 | # Split label to count characters 455 | Xsplt <- names(label_plots[i]) 456 | Xalt <- paste(alt_text[i]) 457 | lab_pos <- label_positions[i,] 458 | 459 | if(all(i != 1 & lab_pos == c(1, 1))){ 460 | grid::grid.newpage() 461 | 462 | grid::pushViewport( 463 | grid::viewport(width = grid::unit(page_width, "in"), 464 | height = grid::unit(page_height, "in")) 465 | ) 466 | # barcode_layout=grid.layout(numrow, numcol, widths = widths, heights = heights) 467 | grid::pushViewport(bc_vp) 468 | } 469 | 470 | if(trunc == TRUE){ 471 | if(nchar(Xsplt) > 15){ 472 | Xsplt <- paste0(substring(Xsplt, seq(1, nchar(Xsplt), 15), seq(15, nchar(Xsplt)+15-1, 15)), collapse = "\n") 473 | } 474 | } 475 | 476 | # Add alt_text 477 | if (length(alt_text) > 0) { 478 | Xsplt <- paste0(Xsplt,Xalt) 479 | } 480 | 481 | grid::pushViewport(grid::viewport(layout.pos.row=lab_pos$y, layout.pos.col=lab_pos$x)) 482 | # grid::grid.rect() 483 | grid::pushViewport(code_vp) 484 | grid::grid.draw(label_plots[[i]]) 485 | grid::popViewport() 486 | grid::pushViewport(label_vp) 487 | 488 | if(type =="linear" | type == "linear2"){ 489 | grid::grid.rect(gp = grid::gpar(col = NA, fill = "white")) 490 | } 491 | 492 | 493 | 494 | grid::grid.text(label = Xsplt, gp = grid::gpar(fontsize = Fsz, lineheight = 0.8)) 495 | 496 | grid::popViewport(2) 497 | 498 | } 499 | 500 | } #end custom_create_PDF() 501 | 502 | #' @rdname custom_create_PDF 503 | #' @export 504 | 505 | qrcode_make<-function(Labels, ErrCorr){ 506 | # Create text label 507 | Xtxt<-gsub("_", "_", Labels) # gsub changed from "_","-" to test with new qrcode generator 508 | if(nchar(Xtxt) <= 1){ 509 | Xtxt <- paste0("\\s\\s", Xtxt) 510 | warning("Label is single character or blank. Padding with empty spaces.") 511 | } 512 | # Create qrcode 513 | Xpng <- grid::rasterGrob( 514 | abs(qrcode::qr_code(paste0(Xtxt), 515 | ecl = ErrCorr) - 1), 516 | interpolate = FALSE) 517 | return(Xpng) 518 | } 519 | 520 | #' @rdname custom_create_PDF 521 | #' @export 522 | code_128_make <- function(Labels){ 523 | ## labels is a character string 524 | ## read in dict 525 | Barcodes <- barcodes128 526 | ## double check Labels 527 | Labels <- as.character(Labels) 528 | Labels <- iconv(Labels, from = "utf-8", to = "ascii", sub = "-") 529 | start_code <- 209 530 | lab_chars <- unlist(strsplit(Labels, split = "")) 531 | lab_values <- sapply(lab_chars, function(x) utf8ToInt(x)) 532 | # ascii to code 128 is just a difference of 32, this line keeps clarity 533 | code_values <- lab_values - 32 534 | # 104 is the start value for start code b, hardcoded right now 535 | check_sum <- 104 + sum(code_values * seq(1,length(code_values))) 536 | check_character <- check_sum %% 103 537 | Binary_code <- sapply(lab_values, 538 | function(x, Barcodes) Barcodes$Barcode[x == Barcodes$ASCII], 539 | Barcodes = Barcodes) 540 | ## create quiet zone 541 | quiet_zone <- paste(c(1:(10)*0),collapse="") 542 | ## paste together in order: quiet zone, start code binary, binary label, checksum character 543 | ## stop code, and quiet zone. Barcode for checksum is extracted based on position in Barcodes. 544 | binary_label <- paste(quiet_zone, 545 | Barcodes$Barcode[Barcodes$ASCII == start_code], 546 | paste(Binary_code, collapse=""), 547 | Barcodes$Barcode[check_character + 1], 548 | "1100011101011", 549 | quiet_zone, 550 | collapse = "", sep ="") 551 | ## split binary apart for 552 | bar_values <- as.numeric(unlist(strsplit(binary_label, split = ""))) 553 | barcode_bars <- grid::rasterGrob(t(!as.matrix(bar_values)), width = 1, height = 1, interpolate = FALSE) 554 | return(barcode_bars) 555 | } 556 | 557 | #' @rdname custom_create_PDF 558 | #' @export 559 | code_128_make2 <- function(Labels) { 560 | ## labels is a character string 561 | ## read in dict 562 | Barcodes <- barcodes128 563 | ## double check Labels 564 | Labels <- enc2utf8(as.character(Labels)) 565 | Labels <- iconv(Labels, 566 | from = "utf-8", 567 | to = "latin1", 568 | sub = "-") 569 | # start_code <- 209 570 | lab_chars <- enc2utf8(unlist(strsplit(Labels, split = ""))) 571 | 572 | is_number <- lab_chars %in% seq(0, 9) 573 | len1 <- length(lab_chars) 574 | tail <- seq(len1, 1) 575 | 576 | count_number <- 0 577 | count_not_number <- 0 578 | 579 | block_number <- rep(0L, len1) 580 | block_not_number <- rep(0L, len1) 581 | 582 | 583 | for (i in seq(len1, 1)) { 584 | if (is_number[i]) { 585 | count_number <- count_number + 1 586 | count_not_number <- 0L 587 | } else { 588 | count_number <- 0L 589 | count_not_number <- count_not_number + 1 590 | } 591 | block_number[i] <- count_number 592 | block_not_number[i] <- count_not_number 593 | } 594 | # print(rbind(lab_chars, is_number, block_number, block_not_number, tail)) 595 | 596 | lab_values2 <- c() 597 | code_values2 <- c() 598 | last_code_B <- NULL 599 | 600 | i <- 1 601 | repeat { 602 | if (block_number[i] == 2L & len1 == 2L | 603 | block_number[i] > 3 & i == 1L | 604 | block_number[i] > 3 & tail[i] == block_number[i] | 605 | block_number[i] > 5) { 606 | 607 | res <- block_number[i] %% 2L 608 | pairs <- block_number[i] %/% 2L 609 | if (i==1L) { 610 | if(res == 1L) { 611 | # Start code 128B 612 | lab_values2 <- c(lab_values2, 209) 613 | code_values2 <- c(code_values2, 104) 614 | last_code_B <- TRUE 615 | } else { 616 | # Start code 128C 617 | lab_values2 <- c(lab_values2, 210) 618 | code_values2 <- c(code_values2, 105) 619 | last_code_B <- FALSE 620 | } 621 | } 622 | 623 | if (res == 1L) { 624 | 625 | utf_int1 <- utf8ToInt(lab_chars[[i]]) 626 | 627 | if (31 < utf_int1 & utf_int1 < 160){ 628 | 629 | lab_values2 <- c(lab_values2, utf_int1) 630 | code_values2 <- c(code_values2, utf_int1 - 32) 631 | 632 | } else { 633 | 634 | if (utf_int1 < 32) { 635 | # Shift A 636 | lab_values2 <- c(lab_values2, 203) 637 | code_values2 <- c(code_values2, 98) 638 | lab_values2 <- c(lab_values2, utf_int1 + 64 + 32) 639 | code_values2 <- c(code_values2, utf_int1 + 64) 640 | 641 | } else { 642 | # FNC4 643 | lab_values2 <- c(lab_values2, 205) 644 | code_values2 <- c(code_values2, 100) 645 | lab_values2 <- c(lab_values2, utf_int1 - 128) 646 | code_values2 <- c(code_values2, utf_int1 -128 - 32) 647 | } 648 | } 649 | 650 | } 651 | if (i > 1L | res == 1L) { 652 | # Code 128C 653 | lab_values2 <- c(lab_values2, 204) 654 | code_values2 <- c(code_values2, 99) 655 | last_code_B <- FALSE 656 | } 657 | 658 | for (j in seq(1, pairs)){ 659 | pair1 <- as.integer(paste0(lab_chars[i+2*j-2+res],lab_chars[i+2*j-1+res])) 660 | lab_values2 <- c(lab_values2, pair1 + ifelse(pair1 < 95, 32, 105)) 661 | code_values2 <- c(code_values2, pair1) 662 | 663 | } 664 | 665 | } else { 666 | if (i==1L) { 667 | # Start code 128B 668 | lab_values2 <- c(lab_values2, 209) 669 | code_values2 <- c(code_values2, 104) 670 | last_code_B <- TRUE 671 | } else { 672 | if (!last_code_B) { 673 | # Code 128B 674 | lab_values2 <- c(lab_values2, 205) 675 | code_values2 <- c(code_values2, 100) 676 | last_code_B <- TRUE 677 | } 678 | } 679 | for (j in seq(1, max(block_number[i],block_not_number[i]))){ 680 | 681 | utf_int1 <- utf8ToInt(lab_chars[[i+j-1]]) 682 | 683 | if (31 < utf_int1 & utf_int1 < 160){ 684 | 685 | lab_values2 <- c(lab_values2, utf_int1) 686 | code_values2 <- c(code_values2, utf_int1 - 32) 687 | 688 | } else { 689 | 690 | if (utf_int1 < 32) { 691 | # Shift A 692 | lab_values2 <- c(lab_values2, 203) 693 | code_values2 <- c(code_values2, 98) 694 | lab_values2 <- c(lab_values2, utf_int1 + 64 + 32) 695 | code_values2 <- c(code_values2, utf_int1 + 64) 696 | 697 | } else { 698 | # FNC4 699 | lab_values2 <- c(lab_values2, 205) 700 | code_values2 <- c(code_values2, 100) 701 | lab_values2 <- c(lab_values2, utf_int1 - 128) 702 | code_values2 <- c(code_values2, utf_int1 -128 - 32) 703 | } 704 | } 705 | } 706 | } 707 | # print(i) 708 | i <- i + max(block_number[i],block_not_number[i]) 709 | if (i > len1) { 710 | break 711 | } 712 | } 713 | 714 | # print(rbind(lab_values2, code_values2)) 715 | 716 | 717 | # lab_values <- sapply(lab_chars, function(x) utf8ToInt(x)) 718 | # ascii to code 128 is just a difference of 32, this line keeps clarity 719 | # code_values <- lab_values - 32 720 | # 104 is the start value for start code b, hardcoded right now 721 | # check_sum <- 104 + sum(code_values * seq(1, length(code_values))) 722 | check_sum <- sum(code_values2 * c(1,seq(1, length(code_values2)-1))) 723 | 724 | check_character <- check_sum %% 103 725 | Binary_code <- sapply(lab_values2, 726 | function(x, Barcodes) 727 | Barcodes$Barcode[x == Barcodes$ASCII], 728 | Barcodes = Barcodes) 729 | ## create quiet zone 730 | quiet_zone <- paste(c(1:(10) * 0), collapse = "") 731 | ## paste together in order: quiet zone, start code binary, binary label, checksum character 732 | ## stop code, and quiet zone. Barcode for checksum is extracted based on position in Barcodes. 733 | binary_label <- paste( 734 | quiet_zone, 735 | #Barcodes$Barcode[Barcodes$ASCII == start_code], 736 | paste(Binary_code, collapse = ""), 737 | Barcodes$Barcode[check_character + 1], 738 | "1100011101011", 739 | quiet_zone, 740 | collapse = "", 741 | sep = "" 742 | ) 743 | ## split binary apart for 744 | bar_values <- 745 | as.numeric(unlist(strsplit(binary_label, split = ""))) 746 | barcode_bars <- 747 | grid::rasterGrob( 748 | t(!as.matrix(bar_values)), 749 | width = 1, 750 | height = 1, 751 | interpolate = FALSE 752 | ) 753 | return(barcode_bars) 754 | } 755 | 756 | 757 | -------------------------------------------------------------------------------- /R/sysdata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/R/sysdata.rda -------------------------------------------------------------------------------- /R/uniqIDHierarchy.R: -------------------------------------------------------------------------------- 1 | #' Make hierarchical ID codes 2 | #' 3 | #' Generate hierarchical ID codes for barcode labels. 4 | #' Hierarchical codes have a nested structure: e.g. Y subsamples from 5 | #' each of X individuals. Use \code{\link{uniqID_maker}} 6 | #' for sequential single-level labels. Can be run in interactive mode, 7 | #' prompting user for input. The data.frame can be saved as CSV for 8 | #' (i) the \code{\link{create_PDF}} function to generate printable 9 | #' QR-coded labels; and (ii) to downstream data collection using spreadsheet, 10 | #' relational database, etc. 11 | #' 12 | #' @param user logical. Run function using interactive mode (prompts user for 13 | #' parameter values). Default is \code{FALSE} 14 | #' @param hierarchy list. A list with each element consisting of three members 15 | #' a vector of three elements (string, beginning value, end value). See examples. 16 | #' Used only when \code{user=FALSE}) 17 | #' @param end character. A string to be appended to the end of each label. 18 | #' @param digits numerical. Default is \code{2}. Number of digits to be printed, 19 | #' adding leading 0s as needed. This will apply to all levels when \code{user=FALSE}. 20 | #' When the max number of digits in the ID code is greater than number of digits 21 | #' defined in \code{digits}, then \code{digits} is automatically increased 22 | #' to avoid errors. 23 | #' @export 24 | #' @return data.frame of text labels in the first column, with additional columns 25 | #' for each level in the hierarchy list, as defined by the user. 26 | #' 27 | #' @seealso \code{\link{uniqID_maker}} 28 | #' @examples 29 | #' if(interactive()){ 30 | #' ## for interactive mode 31 | #' uniqID_hier_maker(user = TRUE) 32 | #' } 33 | #' 34 | #' ## how to make hierarchy list 35 | #' 36 | #' ## create vectors for each level in the order string_prefix, beginning_value, 37 | #' ## end_value and combine in list 38 | #' 39 | #' a <- c("a", 3, 6) 40 | #' b <- c("b", 1, 3) 41 | #' c <- list(a, b) 42 | #' Labels <- uniqID_hier_maker(hierarchy = c) 43 | #' Labels 44 | #' 45 | #' ## add string at end of each label 46 | #' Labels <- uniqID_hier_maker(hierarchy = c, end = "end") 47 | #' Labels 48 | #' 49 | 50 | 51 | uniqID_hier_maker <- function(user = FALSE, hierarchy, end = NULL, digits = 2){ 52 | # user interaction code 53 | if(user == TRUE){ 54 | hlevels <- numeric_input("What is the number of levels in hierarchy: ") 55 | 56 | strEnd <- switch(fake_menu(c("Yes", "No"), "String at end of label? "), TRUE, FALSE) 57 | 58 | if(strEnd){ 59 | end <- string_input("Please enter ending string: ") 60 | } else { 61 | end <- "" 62 | } 63 | 64 | digits <- numeric_input("Number of digits to print: ") 65 | 66 | # possible inputs 67 | 68 | hierarchy <- vector("list", hlevels) 69 | 70 | for(i in seq(1,hlevels)){ 71 | str <- string_input(paste0("Please enter string for level ",i,": ")) 72 | 73 | startNum <- numeric_input(paste0("Enter the starting number for level ",i,": ")) 74 | 75 | endNum <- numeric_input(paste0("Enter the ending number for level ",i,": ")) 76 | 77 | maxNum <- max(startNum,endNum) 78 | hierarchy[[i]]<-c(str, startNum, endNum) 79 | } 80 | } 81 | # end user input 82 | # hierarchy format check 83 | if (is.list(hierarchy) == FALSE) stop("Hierarchy is not in list format. See ?uniqID_hier_maker") 84 | if (length(unique(vapply(hierarchy, length, integer(1)))) != 1) stop("Hierarchy entries are not of equal length.") 85 | if (any(vapply(hierarchy, length, integer(1)) != 3)) 86 | stop("Each level in hierarchy should have a string, a beginning value and an end value.") 87 | if (length(hierarchy) == 1) 88 | stop("Input list has only one level. Did you forget a level or are you sure you are not looking for uniqIDMaker()?") 89 | # loop through hierarchy to generate text 90 | for(i in seq(1,length(hierarchy))){ 91 | str <- hierarchy[[i]][1] 92 | startNum <- suppressWarnings(as.numeric(hierarchy[[i]][2])) 93 | endNum <- suppressWarnings(as.numeric(hierarchy[[i]][3])) 94 | if (is.na(startNum) == TRUE){ 95 | stop(paste0("Invalid starting number on level ", i, ". Please doublecheck your input")) 96 | } 97 | if (is.na(endNum) == TRUE){ 98 | stop(paste0("Invalid ending number on level ", i, ". Please doublecheck your input")) 99 | } 100 | maxNum <- max(startNum, endNum) 101 | digitsMax <- max(digits, nchar(paste(maxNum))) 102 | if (digitsMax > digits){ 103 | warning("Digits specified less than max level number. Increasing number of digits for level") 104 | digits <- digitsMax 105 | } 106 | lvlRange <- c(startNum:endNum) 107 | line <- paste0(str, "%0", digits, "d") 108 | Labels <- sprintf(line, rep(lvlRange)) 109 | if (i > 1) { 110 | ## replicate previous labels by number of elements in present level 111 | temp_barcode <- rep(barcodes, each = length(startNum:endNum)) 112 | ## rep present level elements so the length matches that of temp_barcode 113 | temp_label <- rep(Labels, length.out = length(temp_barcode)) 114 | ## paste everything together 115 | Labels <- paste(temp_barcode, temp_label, sep = "-") 116 | 117 | } 118 | barcodes <- Labels 119 | } # end hierarchy making loop 120 | # makes columns out of hierarchy levels 121 | label_df <- cbind(barcodes, data.frame(t(sapply(strsplit(barcodes, "-"),c)), stringsAsFactors = FALSE)) 122 | df_names <- sapply(hierarchy, function(x) x[1]) 123 | names(label_df) <- c("label", df_names) 124 | # dont forget to add the string at the end 125 | label_df$label <- paste0(label_df$label, end) 126 | return(label_df) 127 | } 128 | 129 | -------------------------------------------------------------------------------- /R/uniqIDMaker.R: -------------------------------------------------------------------------------- 1 | #' Generate a list of ID codes 2 | #' 3 | #' Create ID codes consisting of a text string and unique numbers (string001, string002, ...). 4 | #' Can be run in interactive mode, prompting user for input. The data.frame 5 | #' output can be saved as CSV for (i) the \code{\link{create_PDF}} function 6 | #' to generate printable QR-coded labels; and (ii) to downstream data 7 | #' collection software (spreadsheets, relational databases, etc.) 8 | #' 9 | #' When the function is called with \code{user = TRUE}, a sequence of 10 | #' numbers is generated between the starting and ending number provided by the 11 | #' user. When \code{user = FALSE}, a vector of custom numbers can be provided. 12 | #' See example below. 13 | #' 14 | #' @return data.frame with text labels in the first column, along with string 15 | #' and numeric values in two additional columns. 16 | #' @param user logical. Run function using interactive mode (prompts user for 17 | #' parameter values). Default is \code{FALSE} 18 | #' @param string character. Text string for label. Default \code{null}. 19 | #' @param level integer vector. Defines the numerical values to be appended 20 | #' to the character string. Can be any sequence of numbers (see examples). 21 | #' @param digits numerical. Default is \code{2}. Number of digits to be printed, 22 | #' adding leading 0s as needed. This will apply to all levels when \code{user=FALSE}. 23 | #' When the numeric value of the label has a greater number of digits than 24 | #' \code{digits}, \code{digits} is automatically increased for the entire level. 25 | #' Default is \code{3}. 26 | #' @param ending_string a character string or vector of strings to attach to the label. 27 | #' If a vector is used, all combinations of that vector with a unique label will be produced. 28 | #' 29 | #' @seealso \code{\link{uniqID_hier_maker}} 30 | #' @export 31 | #' @examples 32 | #' 33 | #' 34 | #' ## sequential string of numbers in label 35 | #' Labels <- uniqID_maker(string = "string", level = c(1:5), digits = 2) 36 | #' Labels 37 | #' 38 | #' ## can also use nonsequential strings in input for levels 39 | #' level <- c(1:5, 8:10, 999:1000) 40 | #' Labels <- uniqID_maker(string = "string", level = level, digits = 4) 41 | #' Labels 42 | #' 43 | #' 44 | #' ## Using the ending_string to produce labels with unique endings 45 | #' ## this is different from hierarchical labels with two levels as there 46 | #' ## is no numbering, just the text string 47 | #' 48 | #' 49 | #' Labels <- uniqID_maker(string = "string", level = c(1:5), digits = 2, ending_string = "A") 50 | #' Labels 51 | #' 52 | #' Labels <- uniqID_maker(string = "string", level = c(1:5), 53 | #' digits = 2, ending_string = c("A", "B")) 54 | #' Labels 55 | #' 56 | #' 57 | #' if(interactive()){ 58 | #' ## function using user prompt does not use any of the other parameters 59 | #' Labels <- uniqID_maker(user = TRUE) 60 | #' Labels 61 | #' } 62 | 63 | 64 | 65 | uniqID_maker <- function(user = FALSE, string = NULL, level, digits = 3, ending_string = NULL){ 66 | if (user == TRUE) { 67 | ## asks for string 68 | string <- string_input("Please enter string for level: ") 69 | ## first value of level 70 | startNum <- numeric_input("Please enter the starting number for level (integer): ") 71 | ## ending value of level 72 | endNum <- numeric_input("Enter the ending number for level: ") 73 | ## finds greatest value 74 | maxNum <- max(startNum,endNum) 75 | ## checks what is number of digits in max value 76 | digitsMax <- nchar(paste(maxNum)) 77 | ## asks for how many digits to print 78 | digits <- numeric_input("Number of digits to print for level: ") 79 | level <-c(startNum:endNum) 80 | 81 | } 82 | if (is.numeric(level) == FALSE) stop("Level is not a string of numbers") 83 | if (is.numeric(digits) == FALSE) stop("Digits is not a numerical value") 84 | ## if the number to digits to print is less than the digits in max value, increase digits 85 | if (nchar(paste(max(level))) > digits){ 86 | warning("Digits specified less than max number. Increasing number of digits.") 87 | digits <- nchar(paste(max(level))) 88 | } 89 | 90 | if(!is.null(ending_string)){ 91 | line <- paste0(string, "%0", digits, "d") 92 | label <- sprintf(line, rep(level)) 93 | ind_string <- rep(string, length(rep(level))) 94 | ind_number <- sprintf(paste0("%0", digits, "d"), rep(level)) 95 | suffix_strings <- expand.grid(label, ending_string)$Var2 96 | label <- paste(label, suffix_strings, sep = "-") 97 | label_df <- data.frame(label, ind_string, ind_number, end_string = as.character(suffix_strings), stringsAsFactors = FALSE) 98 | } else { 99 | line <- paste0(string, "%0", digits, "d") 100 | label <- sprintf(line, rep(level)) 101 | ind_string <- rep(string, length(rep(level))) 102 | ind_number <- sprintf(paste0("%0", digits, "d"), rep(level)) 103 | label_df <- data.frame(label, ind_string, ind_number, stringsAsFactors = FALSE) 104 | } 105 | 106 | 107 | return(label_df) 108 | 109 | } 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /R/uniqID_maker_addin.R: -------------------------------------------------------------------------------- 1 | #' @title baRcodeR GUI 2 | #' 3 | #' @description This addin will allow you to interactive create ID codes and generate PDF files 4 | #' of QR codes. 5 | #' 6 | #' @return Opens RStudio addin gadget window for making labels and barcodes in a GUI 7 | #' @export 8 | #' @import qrcode 9 | #' @examples 10 | #' if(interactive()){ 11 | #' library(baRcodeR) 12 | #' make_labels() 13 | #' } 14 | 15 | 16 | make_labels<-function() { 17 | # user interface 18 | # base::library(qrcode) 19 | add_in <- make_labels_internals() 20 | # Run the application 21 | # shinyApp(ui = ui, server = server) 22 | viewer <- shiny::dialogViewer("baRcodeR", width = 800, height = 1000) 23 | shiny::runGadget(add_in, viewer = viewer) 24 | 25 | } 26 | 27 | make_labels_internals <- function(){ 28 | ui<-miniUI::miniPage( 29 | miniUI::gadgetTitleBar("baRcodeR"), 30 | miniUI::miniTabstripPanel(id = "addin_tabs", selected = NULL, between = NULL, 31 | # simple label tab 32 | miniUI::miniTabPanel(id = "simple_labs", 33 | title = "Simple ID Code Generation", 34 | value = "simple_labs", 35 | icon = shiny::icon("bars"), 36 | miniUI::miniContentPanel( 37 | shiny::fillRow( 38 | shiny::fillCol(shiny::tagList(# user input elements 39 | shiny::tags$h1("Simple ID Codes", id = "title"), 40 | shiny::textInput("prefix", 41 | "ID String", 42 | value = "", 43 | width=NULL, 44 | placeholder="Type in ... ..."), 45 | shiny::numericInput("start_number", 46 | "From (integer)", 47 | value = NULL, 48 | min = 1, 49 | max = Inf, 50 | width=NULL), 51 | shiny::numericInput("end_number", 52 | "To (integer)", 53 | value = NULL, 54 | min = 1, 55 | max = Inf, 56 | width=NULL), 57 | shiny::numericInput("digits", 58 | "digits", 59 | value = 3, 60 | min = 1, 61 | max = Inf, 62 | width=NULL), 63 | # textOutput("check"), 64 | shiny::actionButton("make", "Create Label.csv"), 65 | shiny::p("Note: Generated label csv will be in working directory. Go to 'Barcode Creation' tab to upload text labels and create barcodes. "))), 66 | shiny::fillRow(shiny::tagList(# output code snippet for reproducibility 67 | shiny::tags$h3("Reproducible code"), 68 | shiny::verbatimTextOutput("label_code"), 69 | # output showing label preview 70 | shiny::tags$h3("Preview"), 71 | DT::DTOutput("label_df"))) 72 | ) 73 | 74 | )), 75 | # hierarchy label tab 76 | miniUI::miniTabPanel(id = "hier_labs", 77 | title = "Hierarchical ID Code Generation", 78 | value = "hier_labs", 79 | icon = shiny::icon("sitemap"), 80 | miniUI::miniContentPanel( 81 | shiny::fillRow( 82 | shiny::fillCol(shiny::tagList( 83 | # ui elements 84 | shiny::tags$h1("Hierarchical ID Codes", id = "title"), 85 | shiny::numericInput("hier_digits", 86 | "digits", 87 | value = 2, 88 | min = 1, max = Inf, width=NULL), 89 | shiny::textInput("hier_prefix", 90 | "ID String", 91 | value = "", 92 | width=NULL, 93 | placeholder="Type in ... ..."), 94 | shiny::numericInput("hier_start_number", 95 | "From (integer)", 96 | value = NULL, 97 | min = 1, max = Inf, width=NULL), 98 | shiny::numericInput("hier_end_number", 99 | "To (integer)", 100 | value = NULL, 101 | min = 1, max = Inf, width=NULL), 102 | shiny::actionButton('insertBtn', 'Add level'), 103 | shiny::actionButton('removeBtn', 'Remove level'), 104 | # shiny::actionButton("hier_label_preview", "Preview Labels"), 105 | shiny::actionButton("hier_label_make", "Create Labels.csv"), 106 | shiny::p("Note: Generated label csv will be in working directory. Go to 'Barcode Creation' tab to upload text labels and create barcodes.") 107 | )), 108 | shiny::fillCol(shiny::tagList( 109 | # code snippet 110 | shiny::tags$h3("Reproducible Code"), 111 | shiny::verbatimTextOutput("hier_code"), 112 | # output elements 113 | shiny::tags$h3("Hierarchy"), 114 | # output hierarchy as df 115 | shiny::verbatimTextOutput("list_check"), 116 | shiny::tags$h3("Label Preview"), 117 | # label preview 118 | DT::DTOutput("hier_label_df") 119 | )) 120 | ) 121 | 122 | )), 123 | # tab for pdf output 124 | miniUI::miniTabPanel(id = "bar_gen", title = "Barcode Creation", value= "bar_gen", icon = shiny::icon("qrcode"), 125 | miniUI::miniContentPanel( 126 | shiny::fillRow( 127 | shiny::fillCol( 128 | shiny::tagList( 129 | shiny::fileInput("labels", 130 | "1. Choose a text file of ID codes.", 131 | multiple=FALSE, 132 | accept = c("text/csv", "text/comma-separated-values,text/plain", ".csv")), 133 | shiny::checkboxInput("header", "Header in file?", value=TRUE), 134 | shiny::tags$h3("2. (Optional) Modify PDF from default values"), 135 | shiny::textInput("filename", 136 | "PDF file name", 137 | value = "LabelsOut"), 138 | shiny::selectInput(inputId = "err_corr", 139 | label = "Error Correction", 140 | choices = c("L (up to 7% damage)"="L", 141 | "M (up to 15% damage)"= "M", 142 | "Q (up to 25% damage)" = "Q", 143 | "H (up to 30% damage)" = "H"), 144 | multiple=FALSE), 145 | shiny::selectInput("type", 146 | "Barcode Type", 147 | choices = list("QR code (right-text)" = "matrix", 148 | "QR code (inline-text)" = "matrix2", 149 | "Linear 1" = "linear", 150 | "Linear 2" = "linear2"), 151 | multiple = FALSE), 152 | shiny::numericInput("font_size", 153 | "Font Size", 154 | value = 12, min = 2, max = 100), 155 | shiny::radioButtons("across", 156 | "Print across?", 157 | choices = c(Yes = TRUE, No = FALSE), 158 | selected = TRUE), 159 | shiny::numericInput("erow", 160 | "# of rows to skip", 161 | value = 0, min = 0, max = 20, width=NULL), 162 | shiny::numericInput("ecol", 163 | "# of columns to skip", 164 | value = 0, min = 0, max = 20, width=NULL), 165 | shiny::checkboxInput("trunc", 166 | "Truncate label text?", 167 | value=FALSE), 168 | shiny::numericInput("numrow", 169 | "Number of label rows on sheet", 170 | value = 20, min = 1, max = 100, width=NULL, step = 1), 171 | shiny::numericInput("numcol", 172 | "Number of label columns on sheet", 173 | value = 4, min = 1, max = 100, width=NULL, step = 1), 174 | shiny::numericInput("page_width", 175 | "Page Width (in)", 176 | value = 8.5, min = 1, max = 20, width=NULL, 177 | step = 0.5), 178 | shiny::numericInput("page_height", 179 | "Page Height (in)", 180 | value = 11, 181 | min = 1, max = 20, width=NULL, step = 0.5), 182 | shiny::numericInput("width_margin", 183 | "Width margin of page (in)", 184 | value = 0.25, 185 | min = 0, max = 20, width=NULL, step = 0.05), 186 | shiny::numericInput("height_margin", 187 | "Height margin of page (in)", 188 | value = 0.5, min = 0, max = 20, width=NULL, step = 0.05), 189 | shiny::numericInput("label_width", 190 | "Width of label (in)", 191 | value = NA, min=0, max=100), 192 | shiny::numericInput("label_height", 193 | "Height of label (in)", 194 | value = NA, min=0, max=100), 195 | shiny::numericInput("x_space", 196 | "Horizontal space between barcode and text", 197 | value = 0, min = 0, max = 1), 198 | shiny::numericInput("y_space", 199 | "Vertical location of text on label", 200 | value = 0.5, min = 0, max = 1) 201 | ) 202 | ), 203 | shiny::fillCol( 204 | shiny::tagList(shiny::tags$h3("3. Click 'Import ID Code File' to import and check format of file."), 205 | shiny::actionButton("label_check", "Import ID Code File"), 206 | # output elements 207 | shiny::tags$h3("Preview"), 208 | shiny::plotOutput("label_preview", height = "auto", width = "auto"), 209 | # label preview datatable 210 | DT::DTOutput("check_make_labels"), 211 | # code snippet 212 | shiny::tags$h3("Reproducible Code"), 213 | shiny::verbatimTextOutput("PDF_code_render"), 214 | shiny::tags$h3("4. Click 'Make PDF'"), 215 | shiny::tags$body("Wait for 'Done' to show up before opening PDF file"), 216 | shiny::actionButton("make_pdf", "Make PDF"), 217 | # status of pdf making 218 | shiny::textOutput("PDF_status")) 219 | ) 220 | ) 221 | 222 | ) 223 | ) 224 | ## content panel end 225 | ) 226 | ) 227 | # Define server logic required to draw a histogram 228 | server <- function(input, output, session) { 229 | # simple label serverside 230 | output$check <- shiny::renderText({paste0(input$prefix, input$start_number, input$end_number)}) 231 | # making simple labels 232 | Labels <- shiny::reactive({ 233 | shiny::validate( 234 | shiny::need(input$prefix != "", "Please enter a prefix"), 235 | shiny::need(input$start_number != "", "Please enter a starting value"), 236 | shiny::need(input$end_number != "", "Please enter an ending value"), 237 | shiny::need(input$digits != "", "Please enter the number of digits") 238 | ) 239 | baRcodeR::uniqID_maker(user=FALSE, 240 | string = input$prefix, 241 | level = seq(input$start_number, input$end_number), 242 | digits = input$digits) 243 | }) 244 | # preview of simple labels 245 | output$label_df<-DT::renderDataTable(Labels()) 246 | # writing simple labels 247 | shiny::observeEvent(input$make, { 248 | fileName<-sprintf("Labels_%s.csv", Sys.Date()) 249 | utils::write.csv(Labels(), file = file.path(getwd(), fileName), row.names=FALSE) 250 | 251 | }) 252 | output$label_code<-shiny::renderPrint( 253 | noquote(paste0( 254 | "uniqID_maker(user = FALSE, string = \'", input$prefix, 255 | "\', ", "level = c(", input$start_number, ",", input$end_number, 256 | "), digits = ", input$digits, ")"))) 257 | 258 | # pdf making server side 259 | # check label file 260 | Labels_pdf<-shiny::eventReactive(input$label_check, { 261 | shiny::req(input$labels) 262 | Labels<-utils::read.csv(input$labels$datapath, header=input$header, stringsAsFactors = FALSE) 263 | Labels 264 | }) 265 | # preview label file 266 | output$check_make_labels<-DT::renderDataTable(Labels_pdf(), 267 | server = FALSE, 268 | selection = list(mode = "single", target = "column", selected = 1)) 269 | 270 | output$label_preview <- shiny::renderImage({ 271 | if(input$type == "matrix") { 272 | code_vp <- grid::viewport( 273 | x=grid::unit(0.05, "npc"), 274 | y=grid::unit(0.8, "npc"), 275 | width = grid::unit(0.3 * (input$page_width - 2 * input$width_margin)/input$numcol, "in"), 276 | height = grid::unit(0.6 * (input$page_height - 2 * input$height_margin)/input$numrow, "in"), 277 | just=c("left", "top")) 278 | 279 | label_vp <- grid::viewport( 280 | x=grid::unit((0.4 + 0.6 * input$x_space)* (input$page_width - 2 * input$width_margin)/input$numcol, "in"), 281 | y=grid::unit(input$y_space, "npc"), width = grid::unit(0.4, "npc"), 282 | height = grid::unit(0.8, "npc"), 283 | just=c("left", "center")) 284 | 285 | label_plot <- qrcode_make(Labels = Labels_pdf()[1, input$check_make_labels_columns_selected], 286 | ErrCorr = input$err_corr) 287 | 288 | }else if(input$type == "matrix2") { 289 | code_vp <- grid::viewport( 290 | x=grid::unit(0.05, "npc"), 291 | y=grid::unit(0, "npc"), 292 | width = grid::unit(0.3 * (input$page_width - 2 * input$width_margin)/input$numcol, "in"), 293 | height = grid::unit(0.6 * (input$page_height - 2 * input$height_margin)/input$numrow, "in"), 294 | just=c("center", "bottom")) 295 | 296 | label_vp <- grid::viewport( 297 | x=grid::unit(0.05, "npc"), 298 | y=grid::unit(input$y_space, "npc"), 299 | width = grid::unit(0.4, "npc"), 300 | height = grid::unit(0.8, "npc"), 301 | just=c("center", "center")) 302 | 303 | label_plot <- qrcode_make(Labels = Labels_pdf()[1, input$check_make_labels_columns_selected], 304 | ErrCorr = input$err_corr) 305 | 306 | } else { 307 | code_vp <- grid::viewport(x=grid::unit(0.05, "npc"), 308 | y=grid::unit(0.8, "npc"), 309 | width = grid::unit(0.9 * (input$page_width - 2 * input$width_margin)/input$numcol, "in"), 310 | height = grid::unit(0.8 * (input$page_height - 2 * input$height_margin)/input$numrow, "in"), 311 | just=c("left", "top")) 312 | # text_height <- ifelse(input$Fsz / 72 > (input$page_height - 2 * input$height_margin)/input$numrow * 0.3, (input$page_height - 2 * input$height_margin)/input$numrow * 0.3, input$Fsz/72) 313 | 314 | label_vp <- grid::viewport( 315 | x=grid::unit(0.5, "npc"), 316 | y = grid::unit(1, "npc"), 317 | width = grid::unit(1, "npc"), 318 | height = grid::unit((input$page_height - 2 * input$height_margin)/input$numrow * 0.3, "in"), 319 | just = c("centre", "top")) 320 | 321 | label_plot <- code_128_make(Labels = Labels_pdf()[1, input$check_make_labels_columns_selected]) 322 | } 323 | outputfile <- tempfile(fileext=".png") 324 | grDevices::png(outputfile, 325 | width = (input$page_width - 2 * input$width_margin)/input$numcol, 326 | (input$page_height - 2 * input$height_margin)/input$numrow, 327 | units = "in", res=100) 328 | # grid::grid.rect() 329 | grid::pushViewport(code_vp) 330 | grid::grid.draw(label_plot) 331 | grid::popViewport() 332 | grid::pushViewport(label_vp) 333 | grid::grid.text(label = Labels_pdf()[1, input$check_make_labels_columns_selected], 334 | gp = grid::gpar(fontsize = input$font_size, lineheight = 0.8)) 335 | grDevices::dev.off() 336 | list(src = outputfile, 337 | width = 80 * (input$page_width - 2 * input$width_margin)/input$numcol, 338 | height = 80 * (input$page_height - 2 * input$height_margin)/input$numrow, 339 | alt = "Label Preview") 340 | }, deleteFile = TRUE 341 | ) 342 | # text indicator that pdf finished making 343 | PDF_done<-shiny::eventReactive(input$make_pdf, { 344 | baRcodeR::custom_create_PDF( 345 | user=FALSE, 346 | Labels = Labels_pdf()[, input$check_make_labels_columns_selected], 347 | name = input$filename, 348 | type = input$type, 349 | ErrCorr = input$err_corr, 350 | Fsz = input$font_size, 351 | Across = input$across, 352 | ERows = input$erow, 353 | ECols = input$ecol, 354 | trunc = input$trunc, 355 | numrow = input$numrow, 356 | numcol = input$numcol, 357 | page_width = input$page_width, 358 | page_height = input$page_height, 359 | height_margin = input$height_margin, 360 | width_margin = input$width_margin, 361 | label_width = input$label_width, 362 | label_height = input$label_height, 363 | x_space = input$x_space, 364 | y_space = input$y_space) 365 | status<-"Done" 366 | status 367 | }) 368 | PDF_code_snippet<-shiny::reactive({ 369 | noquote( 370 | paste0("custom_create_PDF(user=FALSE, Labels = label_csv[,",input$check_make_labels_columns_selected, 371 | "], name = \'", input$filename, "\', 372 | type = \'", input$type, 373 | "\', ErrCorr = \'", input$err_corr, 374 | "\', Fsz = ", input$font_size, 375 | ", Across = ", input$across, 376 | ", ERows = ", input$erow, 377 | ", ECols = ", input$ecol, 378 | ", trunc = ", input$trunc, 379 | ", numrow = ", input$numrow, 380 | ", numcol = ", input$numcol, 381 | ", page_width = ", input$page_width, 382 | ", page_height = ", input$page_height, 383 | ", width_margin = ", input$width_margin, 384 | ", height_margin = ", input$height_margin, 385 | ", label_width = ", input$label_width, 386 | ", label_height = ", input$label_height, 387 | ", x_space = ", input$x_space, 388 | ", y_space = ", input$y_space, ")")) 389 | }) 390 | csv_code_snippet<-shiny::reactive({noquote( 391 | paste0( 392 | "label_csv <- read.csv( \'", input$labels$name, 393 | "\', header = ", input$header, 394 | ", stringsAsFactors = FALSE)"))}) 395 | output$PDF_code_render<-shiny::renderText({ 396 | paste(csv_code_snippet(), PDF_code_snippet(), sep = "\n") 397 | }) 398 | # label preview 399 | 400 | 401 | # rendering of pdf indicator 402 | output$PDF_status<-shiny::renderPrint({print(PDF_done())}) 403 | # server-side for hierarchical values 404 | # set reactiveValues to store the level inputs 405 | values<-shiny::reactiveValues() 406 | # set up data frame within reactiveValue function 407 | values$df<-data.frame(Prefix = character(0), start=integer(), end=integer(), stringsAsFactors = FALSE) 408 | # delete row from the df if button is pressed. 409 | shiny::observeEvent(input$removeBtn, { 410 | shiny::isolate(values$df<-values$df[-(nrow(values$df)),]) 411 | }) 412 | # add level to df 413 | shiny::observeEvent(input$insertBtn, { 414 | # level_name<-input$insertBtn 415 | shiny::validate( 416 | shiny::need(input$hier_prefix != "", "Please enter a prefix"), 417 | shiny::need(input$hier_start_number != "", "Please enter a starting value"), 418 | shiny::need(input$hier_end_number != "", "Please enter an ending value"), 419 | shiny::need(input$hier_digits != "", "Please enter the number of digits") 420 | ) 421 | shiny::isolate(values$df[nrow(values$df) + 1,]<-c(input$hier_prefix, input$hier_start_number, input$hier_end_number)) 422 | shiny::updateTextInput(session = session, 423 | "hier_prefix", 424 | "Label String", 425 | value = character(0)) 426 | shiny::updateNumericInput(session = session, 427 | "hier_start_number", 428 | "From (integer)", 429 | value = numeric(0), 430 | min = 1, max = Inf) 431 | shiny::updateNumericInput(session = session, 432 | "hier_end_number", 433 | "To (integer)", 434 | value = numeric(0), 435 | min = 1, max = Inf) 436 | }) 437 | # make hierarchical labels 438 | hier_label_df<-shiny::reactive({ 439 | # shiny::validate( 440 | # shiny::need(input$hier_prefix != "", "Please enter a prefix"), 441 | # shiny::need(input$hier_start_number != "", "Please enter a starting value"), 442 | # shiny::need(input$hier_end_number != "", "Please enter an ending value"), 443 | # shiny::need(input$hier_digits != "", "Please enter the number of digits") 444 | # ) 445 | shiny::validate( 446 | shiny::need(nrow(values$df) > 1, "Please add a level") 447 | ) 448 | hierarchy <- split(values$df, seq(nrow(values$df))) 449 | hier_Labels <- baRcodeR::uniqID_hier_maker(user=FALSE, hierarchy = hierarchy, end = NULL, digits = input$hier_digits) 450 | hier_Labels 451 | }) 452 | hier_code_snippet_obj<-shiny::reactive({ 453 | begin_string<-noquote(strsplit(paste(split(values$df, seq(nrow(values$df))), collapse=', '), ' ')[[1]]) 454 | replace_string<-gsub(pattern = "list\\(", replacement = "c\\(", begin_string) 455 | replace_string<-paste(replace_string, sep="", collapse="") 456 | noquote(paste0( 457 | "uniqID_hier_maker(user = FALSE, hierarchy = list(", replace_string, 458 | "), end = NULL, digits = ", input$hier_digits, ")")) 459 | 460 | }) 461 | output$hier_code<-shiny::renderText(hier_code_snippet_obj()) 462 | # rough df of the level df 463 | output$list_check<-shiny::renderPrint(values$df) 464 | # preview of hierarchical labels 465 | output$hier_label_df<-DT::renderDataTable(hier_label_df()) 466 | # make the csv file 467 | shiny::observeEvent(input$hier_label_make, { 468 | fileName<-sprintf("Labels_%s.csv", Sys.Date()) 469 | utils::write.csv(hier_label_df(), file = file.path(getwd(), fileName), row.names=FALSE) 470 | }) 471 | 472 | # Listen for the 'done' event. This event will be fired when a user 473 | # is finished interacting with your application, and clicks the 'done' 474 | # button. 475 | shiny::observeEvent(input$done, { 476 | 477 | # Here is where your Shiny application might now go an affect the 478 | # contents of a document open in RStudio, using the `rstudioapi` package. 479 | # 480 | # At the end, your application should call 'stopApp()' here, to ensure that 481 | # the gadget is closed after 'done' is clicked. 482 | shiny::stopApp() 483 | }) 484 | } 485 | shiny::shinyApp(ui = ui, server = server) 486 | } 487 | 488 | #' @title baRcodeR Cheatsheet 489 | #' 490 | #' @description This addin links to a downloadable PDF version of the baRcodeR cheatsheet. 491 | #' 492 | #' @return Opens webpage of PDF 493 | #' @import rstudioapi 494 | #' @export 495 | #' @examples 496 | #' if(interactive()){ 497 | #' baRcodeR::cheatsheet() 498 | #' } 499 | 500 | cheatsheet <- function(){ 501 | rstudioapi::sendToConsole("browseURL('https://ndownloader.figshare.com/files/14087612')") 502 | } -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onAttach <- function(libname, pkgname){ 2 | options(baRcodeR.connection = stdin()) 3 | } 4 | 5 | fake_menu <- function(choices, prompt_string){ 6 | attempt <- 1 7 | attempts_allowed <- 3 8 | # real menu doesn't work with std in 9 | choice_string <- paste(1:length(choices), ":", choices, collapse = "\n") 10 | repeat { 11 | choice <- numeric_input(paste0(prompt_string, "\n", choice_string)) 12 | if (choice == 0 | choice > length(choices)){ 13 | cat(paste0("Invalid input. Integer must be between 1 and ", length(choices))) 14 | } 15 | attempt <- attempt + 1 16 | if(attempt > attempts_allowed){ 17 | stop("Invalid input. Please try again.") 18 | } 19 | if (choice <= length(choices) & choice != 0){ 20 | break 21 | } 22 | } 23 | return(choice) 24 | } 25 | 26 | 27 | numeric_input <- function(prompt_string, attempts_allowed = 3, integer = TRUE){ 28 | attempt <- 1 29 | repeat { 30 | cat(prompt_string) 31 | startNum <- suppressWarnings(abs(as.numeric(readLines(con = getOption("baRcodeR.connection"), n = 1)))) 32 | if(integer){ 33 | startNum <- as.integer(startNum) 34 | } 35 | attempt <- attempt + 1 36 | # exit if input is number 37 | if (!is.na(startNum)) { 38 | break 39 | } 40 | # exit if too many attempts 41 | if(attempt > attempts_allowed){ 42 | stop("Invalid input. Please try again.") 43 | } else { 44 | cat("Invalid input. Please enter a number") 45 | } 46 | } 47 | ifelse(!is.na(startNum), return(startNum)) 48 | 49 | } 50 | 51 | 52 | string_input <- function(prompt_string){ 53 | cat(prompt_string) 54 | return(readLines(con = getOption("baRcodeR.connection"), n = 1)) 55 | } 56 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | # baRcodeR 8 | 9 | 10 | 11 | [![Status](https://www.r-pkg.org/badges/version/baRcodeR)](https://CRAN.R-project.org/package=baRcodeR) 12 | [![Downloads](https://cranlogs.r-pkg.org/badges/grand-total/baRcodeR)](https://CRAN.R-project.org/package=baRcodeR) 13 | [![Codecov test 14 | coverage](https://codecov.io/gh/ropensci/baRcodeR/branch/master/graph/badge.svg)](https://app.codecov.io/gh/ropensci/baRcodeR?branch=master) 15 | [![Project Status: Active – The project has reached a stable, usable 16 | state and is being actively 17 | developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 18 | [![CRAN 19 | checks](https://github.com/r-hub/cchecksbadges/blob/gh-pages/summary/baRcodeR.svg)](https://github.com/r-hub/cchecksbadges/blob/gh-pages/summary/baRcodeR.svg) 20 | [![rOpenSci 21 | peer-review](https://badges.ropensci.org/338_status.svg)](https://github.com/ropensci/software-review/issues/338) 22 | 23 | 24 | baRcodeR generates labels for more repeatable workflows with biological samples 25 | 26 | ## Installation 27 | 28 | You can install the released version of baRcodeR from [CRAN](https://CRAN.R-project.org) with: 29 | 30 | ``` 31 | install.packages("baRcodeR") 32 | ``` 33 | 34 | And the development version from [GitHub](https://github.com/) with: 35 | 36 | ``` 37 | # install.packages("devtools") 38 | devtools::install_github("ropensci/baRcodeR", build_vignettes = T) 39 | # for windows users to build vignettes 40 | # install_github("ropensci/baRcodeR", build_opts = c("--no-resave-data", "--no-manual"), build_vignettes = TRUE) 41 | ``` 42 | 43 | > NOTE: Restarting RStudio is necessary for the addin for baRcodeR to appear. 44 | 45 | ## Quick Start 46 | 47 | Text identifiers can be created in a sequential or hierarchical pattern. 48 | 49 | ```{r} 50 | library(baRcodeR) 51 | 52 | example_labels <- uniqID_maker(user = FALSE, string = "Example", level = 1:80) 53 | head(example_labels) 54 | ``` 55 | 56 | Then the text identifiers can be printed out with a laser printer on sticker sheets. 57 | 58 | 59 | ```{r include = F, eval = F} 60 | # generate the image shown in vignettes as png rather than pdf so it shows up in markdown 61 | # pdf_file_name <- "man/figures/example_file" 62 | # create_PDF(Labels = example_labels, name = pdf_file_name) 63 | # pdf_file <- magick::image_read_pdf("man/figures/example_file.pdf") 64 | # magick::image_write(pdf_file, path = "man/figures/example.png", format = "png") 65 | ``` 66 | 67 | 68 | ```{r eval = F} 69 | pdf_file_name <- tempfile() 70 | create_PDF(Labels = example_labels, name = pdf_file_name) 71 | ``` 72 | 73 | ```{r echo = F} 74 | knitr::include_graphics("man/figures/example.png") 75 | ``` 76 | 77 | 78 | Th particular layout above defaults to ULINE 1.75" * 0.5" labels but other layouts can be specified through parameters in the `custom_create_PDF` function. 79 | 80 | 81 | ## Introduction 82 | 83 | `baRcodeR` is a R package for generating unique identifier strings and printable 2D (QR) barcodes, with the aim of improving repeatability of labelling, tracking and curating data from biological samples. Specifically, users can: 84 | 85 | * generate simple ID codes (Ex001, Ex002, Ex003 ...), 86 | * generate hierarchical (i.e. nested) ID codes (A01-B01, A01-B02, A02-B01, A02-B02, A03-B01 ...), 87 | * generate printable PDF files of paired ID codes and QR barcodes with default spacing for ULINE 1.75" * 0.5" WEATHER RESISTANT LABEL for laser printer; item # S-19297 (uline.ca) 88 | * customize the PDF layout for any type of printable format (e.g, vinyl stickers, waterproof paper) 89 | * generate reproducible code for archival purposes (e.g. in publications or online repositories) 90 | * create CSV files to link unique IDs and sampling hierarchy with downstream data collection workflows. For example, the PyTrackDat pipeline can be used to set up a web-based data collection platform: https://github.com/pytrackdat/pytrackdat 91 | 92 | Creating unique, scannable barcodes generally involves two steps: 93 | 94 | 1. Generate unique ID codes with `uniqID_maker()` or `uniqID_hier_maker()` 95 | 2. Create a PDF file containing unique ID codes coupled with 2D barcode using `create_PDF()` 96 | 97 | If you already have ID codes saved in a CSV file, the csv can be read into a `data.frame()` in R. The `label` column, if it exists will be used as input to generate barcodes. Otherwise, the first column in the data frame will be used. 98 | 99 | > NOTE: When printing from pdf, ensure that 'anti-aliasing' or 'smoothing' options are turned OFF, and that you are not using 'fit to page' or similar options that will re-scale the output. 100 | 101 | ![Flowchart of major functions](man/figures/Flowchart.png) 102 | 103 | ### Cheat Sheet 104 | 105 | A 2-page, quick-reference guide is available via [Figshare](https://dx.doi.org/10.6084/m9.figshare.7043309) 106 | 107 | ## Usage with RStudio addin 108 | 109 | Please load the vignette "Use Addin". 110 | 111 | ```{r eval = F} 112 | library(baRcodeR) 113 | vignette("use-addin") 114 | ``` 115 | 116 | 117 | ## Usage from the console 118 | 119 | Please load the vignette "Using-baRcodeR" for console use. 120 | 121 | ```{r eval = F} 122 | vignette("Using-baRcodeR") 123 | ``` 124 | # Contribution 125 | 126 | Please note that the 'baRcodeR' project is released with a 127 | [Contributor Code of Conduct](https://github.com/ropensci/baRcodeR/blob/master/CODE_OF_CONDUCT.md). 128 | By contributing to this project, you agree to abide by its terms. 129 | 130 | Please document issues with a description, a minimal reproducible example, and the `sessionInfo()`. 131 | 132 | ```{r} 133 | sessionInfo() 134 | ``` 135 | 136 | # See also: 137 | 138 | - [zintr](https://github.com/carlganz/zintr)is an R interface to the C zint library. Use zintr if you want to create single barcode images. zintr does not include functions for (i) automating the creation of biologically-relevant, unique ID codes or (ii) customizable layouts for printing multiple barcodes. 139 | 140 | - [zint](https://zint.org.uk/) is a C library that generates a variety of different barcodes. Just like zintr, zint produces single barcode images. 141 | 142 | [![ropensci_footer](https://ropensci.org/public_images/ropensci_footer.png)](https://ropensci.org) 143 | 144 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # baRcodeR 5 | 6 | 7 | 8 | [![Status](https://www.r-pkg.org/badges/version/baRcodeR)](https://CRAN.R-project.org/package=baRcodeR) 9 | [![Downloads](https://cranlogs.r-pkg.org/badges/grand-total/baRcodeR)](https://CRAN.R-project.org/package=baRcodeR) 10 | [![Codecov test 11 | coverage](https://codecov.io/gh/ropensci/baRcodeR/branch/master/graph/badge.svg)](https://app.codecov.io/gh/ropensci/baRcodeR?branch=master) 12 | [![Project Status: Active – The project has reached a stable, usable 13 | state and is being actively 14 | developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 15 | [![CRAN 16 | checks](https://github.com/r-hub/cchecksbadges/blob/gh-pages/summary/baRcodeR.svg)](https://github.com/r-hub/cchecksbadges/blob/gh-pages/summary/baRcodeR.svg) 17 | [![rOpenSci 18 | peer-review](https://badges.ropensci.org/338_status.svg)](https://github.com/ropensci/software-review/issues/338) 19 | 20 | 21 | baRcodeR generates labels for more repeatable workflows with biological 22 | samples 23 | 24 | ## Installation 25 | 26 | You can install the released version of baRcodeR from 27 | [CRAN](https://CRAN.R-project.org) with: 28 | 29 | install.packages("baRcodeR") 30 | 31 | And the development version from [GitHub](https://github.com/) with: 32 | 33 | # install.packages("devtools") 34 | devtools::install_github("ropensci/baRcodeR", build_vignettes = T) 35 | # for windows users to build vignettes 36 | # install_github("ropensci/baRcodeR", build_opts = c("--no-resave-data", "--no-manual"), build_vignettes = TRUE) 37 | 38 | > NOTE: Restarting RStudio is necessary for the addin for baRcodeR to 39 | > appear. 40 | 41 | ## Quick Start 42 | 43 | Text identifiers can be created in a sequential or hierarchical pattern. 44 | 45 | ``` r 46 | library(baRcodeR) 47 | ``` 48 | 49 | ## Loading required package: qrcode 50 | 51 | ``` r 52 | example_labels <- uniqID_maker(user = FALSE, string = "Example", level = 1:80) 53 | head(example_labels) 54 | ``` 55 | 56 | ## label ind_string ind_number 57 | ## 1 Example001 Example 001 58 | ## 2 Example002 Example 002 59 | ## 3 Example003 Example 003 60 | ## 4 Example004 Example 004 61 | ## 5 Example005 Example 005 62 | ## 6 Example006 Example 006 63 | 64 | Then the text identifiers can be printed out with a laser printer on 65 | sticker sheets. 66 | 67 | ``` r 68 | pdf_file_name <- tempfile() 69 | create_PDF(Labels = example_labels, name = pdf_file_name) 70 | ``` 71 | 72 | ![](man/figures/example.png) 73 | 74 | Th particular layout above defaults to ULINE 1.75” \* 0.5” labels but 75 | other layouts can be specified through parameters in the 76 | `custom_create_PDF` function. 77 | 78 | ## Introduction 79 | 80 | `baRcodeR` is a R package for generating unique identifier strings and 81 | printable 2D (QR) barcodes, with the aim of improving repeatability of 82 | labelling, tracking and curating data from biological samples. 83 | Specifically, users can: 84 | 85 | - generate simple ID codes (Ex001, Ex002, Ex003 …), 86 | - generate hierarchical (i.e. nested) ID codes (A01-B01, A01-B02, 87 | A02-B01, A02-B02, A03-B01 …), 88 | - generate printable PDF files of paired ID codes and QR barcodes with 89 | default spacing for ULINE 1.75” \* 0.5” WEATHER RESISTANT LABEL for 90 | laser printer; item # S-19297 (uline.ca) 91 | - customize the PDF layout for any type of printable format (e.g, 92 | vinyl stickers, waterproof paper) 93 | - generate reproducible code for archival purposes (e.g. in 94 | publications or online repositories) 95 | - create CSV files to link unique IDs and sampling hierarchy with 96 | downstream data collection workflows. For example, the PyTrackDat 97 | pipeline can be used to set up a web-based data collection platform: 98 | 99 | 100 | Creating unique, scannable barcodes generally involves two steps: 101 | 102 | 1. Generate unique ID codes with `uniqID_maker()` or 103 | `uniqID_hier_maker()` 104 | 2. Create a PDF file containing unique ID codes coupled with 2D barcode 105 | using `create_PDF()` 106 | 107 | If you already have ID codes saved in a CSV file, the csv can be read 108 | into a `data.frame()` in R. The `label` column, if it exists will be 109 | used as input to generate barcodes. Otherwise, the first column in the 110 | data frame will be used. 111 | 112 | > NOTE: When printing from pdf, ensure that ‘anti-aliasing’ or 113 | > ‘smoothing’ options are turned OFF, and that you are not using ‘fit to 114 | > page’ or similar options that will re-scale the output. 115 | 116 | ![Flowchart of major functions](man/figures/Flowchart.png) 117 | 118 | ### Cheat Sheet 119 | 120 | A 2-page, quick-reference guide is available via 121 | [Figshare](https://dx.doi.org/10.6084/m9.figshare.7043309) 122 | 123 | ## Usage with RStudio addin 124 | 125 | Please load the vignette “Use Addin”. 126 | 127 | ``` r 128 | library(baRcodeR) 129 | vignette("use-addin") 130 | ``` 131 | 132 | ## Usage from the console 133 | 134 | Please load the vignette “Using-baRcodeR” for console use. 135 | 136 | ``` r 137 | vignette("Using-baRcodeR") 138 | ``` 139 | 140 | # Contribution 141 | 142 | Please note that the ‘baRcodeR’ project is released with a [Contributor 143 | Code of 144 | Conduct](https://github.com/ropensci/baRcodeR/blob/master/CODE_OF_CONDUCT.md). 145 | By contributing to this project, you agree to abide by its terms. 146 | 147 | Please document issues with a description, a minimal reproducible 148 | example, and the `sessionInfo()`. 149 | 150 | ``` r 151 | sessionInfo() 152 | ``` 153 | 154 | ## R version 4.1.3 (2022-03-10) 155 | ## Platform: x86_64-w64-mingw32/x64 (64-bit) 156 | ## Running under: Windows 10 x64 (build 22000) 157 | ## 158 | ## Matrix products: default 159 | ## 160 | ## locale: 161 | ## [1] LC_COLLATE=English_Canada.1252 LC_CTYPE=English_Canada.1252 162 | ## [3] LC_MONETARY=English_Canada.1252 LC_NUMERIC=C 163 | ## [5] LC_TIME=English_Canada.1252 164 | ## 165 | ## attached base packages: 166 | ## [1] stats graphics grDevices utils datasets methods base 167 | ## 168 | ## other attached packages: 169 | ## [1] baRcodeR_0.1.7 qrcode_0.1.4 170 | ## 171 | ## loaded via a namespace (and not attached): 172 | ## [1] png_0.1-7 assertthat_0.2.1 digest_0.6.29 R.methodsS3_1.8.1 173 | ## [5] magrittr_2.0.2 evaluate_0.15 highr_0.9 rlang_1.0.2 174 | ## [9] stringi_1.7.6 cli_3.2.0 rstudioapi_0.13 R.oo_1.24.0 175 | ## [13] R.utils_2.11.0 rmarkdown_2.13 tools_4.1.3 stringr_1.4.0 176 | ## [17] xfun_0.30 yaml_2.3.5 fastmap_1.1.0 compiler_4.1.3 177 | ## [21] htmltools_0.5.2 knitr_1.38 178 | 179 | # See also: 180 | 181 | - [zintr](https://github.com/carlganz/zintr)is an R interface to the C 182 | zint library. Use zintr if you want to create single barcode images. 183 | zintr does not include functions for (i) automating the creation of 184 | biologically-relevant, unique ID codes or (ii) customizable layouts 185 | for printing multiple barcodes. 186 | 187 | - [zint](https://zint.org.uk/) is a C library that generates a variety 188 | of different barcodes. Just like zintr, zint produces single barcode 189 | images. 190 | 191 | [![ropensci_footer](https://ropensci.org/public_images/ropensci_footer.png)](https://ropensci.org) 192 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | destination: docs 2 | 3 | url: https://docs.ropensci.org/baRcodeR -------------------------------------------------------------------------------- /baRcodeR.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | PackageRoxygenize: rd,collate,namespace,vignette 19 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## baRcodeR 0.1.8 2 | 3 | * `create_PDF()` now allows underscores in QR code. Previously these were switched to dashes. 4 | * Add a new option (`matrix2`) that places labels above or below, depending on `y_space` parameter 5 | 6 | ## baRcodeR 0.1.7 - added code 128 extended 7 | 8 | * Added missing slash to web link; sorry for the confusion 9 | * "Linear2" added to option list (Linear, Matrix) to produce Code 128 extended linear barcodes. This allows more special characters for linear (1D) barcodes 10 | * Changed qrcode::qr_code() from (depricated) qrcode_gen 11 | 12 | ## baRcodeR 0.1.6 - new parameters 13 | 14 | At the request of a COVID-2019 research group, we have added an option to allow non-encoded text to appear with linear & 2D barcodes: 15 | 16 | * alt_text -- adds human-readable text that is NOT encoded in the digital barcode 17 | * denote -- characters used to denote non-encoded text 18 | 19 | ## baRcodeR 0.1.5 R CMD check results 20 | 21 | This is a minor update to make sure tests pass on r-devel and fix a broken link. 22 | 23 | 24 | ## Test environments 25 | 26 | * local Windows 10 install, R 3.6.1, r-devel 27 | * win-builder (devel and release) 28 | * Ubuntu 16.04 (on travis-ci), R-oldrel, R-release, R-devel 29 | * R-hub 30 | * Windows Server 2008 R2 SP1, R-devel, 32/64 bit 31 | * Ubuntu Linux 16.04 LTS, R-release, GCC 32 | * Fedora Linux, R-devel, clang, gfortran 33 | 34 | 35 | ## Amendment to previous rejected submission 36 | 37 | We have removed the license file from the description file and the package file itself as suggested by Uwe Ligges. 38 | 39 | 40 | 41 | ## baRcodeR 0.1.4 R CMD check results 42 | 43 | There were no ERRORS or WARNINGS. 1 NOTE regarding change of package maintainer from Robert Colautti to Yihan Wu. 44 | 45 | This is our third submission. From our last submission, we made 46 | 47 | 1. changes to clarify documentation 48 | 49 | 2. modify command line prompts with menu-like choices 50 | 51 | 3. added a vignette tutorial to show how to use the package with the RStudio addin and removed similar content from the package README 52 | 53 | 4. corrected error in current CRAN version of package relating to R-devel changes 54 | 55 | ### April 26, 2019 56 | 57 | This is our second submission. From first submission on September 10, 2018, we made three changes: 58 | 59 | 1. We have changed the example for create_PDF() to write to tempdir() as suggested by Uwe Liggs. 60 | 61 | 2. We renamed functions containing label_ to uniqID_ to clarify that the functions generate unique identifiers, in contrast to create_PDF, which generates labels for printing. We found this was already a source of confusions among early testers. 62 | 63 | 3. We fixed a minor bug in the preview of one of the Addins tabs and we clarified explanations in the vignette and documentation. 64 | 65 | ### Oct 4, 2018 66 | 67 | additional changes advised by Swetlana Herbrandt 68 | 69 | 1. Removed 'Open-Source R Tools for' in the title 70 | 2. Replaced T and F with TRUE and FALSE throughout 71 | 3. Repaced \dontrun{} with if(interactive()){} or \donttest{} 72 | 73 | ### Oct 12, 2018 74 | 75 | A few changes from Oct 4 were not included in the last upload. 76 | Additionally, fixed a minor text errors: 77 | 1. 'collection' occurred twice in DESCRIPTION 78 | 2. 'unique' was mis-spelled in documentation of uniqID_maker 79 | 80 | ### Nov 29, 2018 81 | 82 | Bug fixes and minor features added, as outlined in NEWS.md 83 | 84 | ### Jan 10, 2019 85 | 86 | - Added the ability to create linear (1D) barcodes using the type='linear' parameter in create_pdf() 87 | - fixed a few minor spelling/grammar changes 88 | 89 | ### April 26, 2019 90 | 91 | Bug fix for linear barcodes and minor changes outlined in NEWS.md (ver. 0.1.3) 92 | 93 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | 2D 2 | addin 3 | Addins 4 | barcode 5 | Barcode 6 | barcoded 7 | BaRcodeR 8 | barcodes 9 | cheatsheet 10 | Cheatsheet 11 | Codecov 12 | csv 13 | downloadable 14 | ECols 15 | ERows 16 | Figshare 17 | hier 18 | IDcode 19 | IDcodes 20 | popup 21 | pre 22 | PyTrackDat 23 | repeatability 24 | RStudio 25 | scannable 26 | Screenshot 27 | uline 28 | ULINE 29 | uniqID 30 | unscannable 31 | workflows 32 | zint 33 | zintr 34 | -------------------------------------------------------------------------------- /inst/rstudio/addins.dcf: -------------------------------------------------------------------------------- 1 | Name: baRcodeR GUI 2 | Description: Generate unique ID codes with printable linear and 2D barcodes. 3 | Binding: make_labels 4 | Interactive: true 5 | 6 | Name: baRcodeR Cheatsheet 7 | Description: Link to downloadable PDF version of package cheatsheet. 8 | Binding: cheatsheet 9 | Interactive: false -------------------------------------------------------------------------------- /man/cheatsheet.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/uniqID_maker_addin.R 3 | \name{cheatsheet} 4 | \alias{cheatsheet} 5 | \title{baRcodeR Cheatsheet} 6 | \usage{ 7 | cheatsheet() 8 | } 9 | \value{ 10 | Opens webpage of PDF 11 | } 12 | \description{ 13 | This addin links to a downloadable PDF version of the baRcodeR cheatsheet. 14 | } 15 | \examples{ 16 | if(interactive()){ 17 | baRcodeR::cheatsheet() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /man/create_PDF.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/createPDF.R 3 | \name{create_PDF} 4 | \alias{create_PDF} 5 | \title{Make barcodes and print labels} 6 | \usage{ 7 | create_PDF( 8 | user = FALSE, 9 | Labels = NULL, 10 | name = "LabelsOut", 11 | type = "matrix", 12 | ErrCorr = "H", 13 | Fsz = 12, 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{user}{logical. Run function using interactive mode (prompts user for 19 | parameter values) Default is \code{FALSE}} 20 | 21 | \item{Labels}{vector or data frame object containing label names (i.e. unique 22 | ID codes) with either UTF-8 or ASCII encoding.} 23 | 24 | \item{name}{character. Name of the PDF output file. Default is 25 | \code{"LabelsOut"}. A file named \code{name.pdf} will be saved to the 26 | working directory by default. Use \code{"dirname/name"} to produce a file 27 | called \code{name.pdf} in the \code{dirname} directory.} 28 | 29 | \item{type}{character. Choice of \code{"linear"} for code 128, \code{"linear2"} 30 | for extended code 128, \code{"matrix"} for QR code (i.e. 2D barcode) with 31 | text to the right, or \code{"matrix2"} for QR code with text above or below, 32 | depending on \code{y_space} value (0 = below, 1 = above).} 33 | 34 | \item{ErrCorr}{error correction value for matrix labels only. Level of damage 35 | from low to high: \code{"L"}, \code{"M"}, \code{"Q"}, \code{"H"}. Default 36 | is \code{"H"}. See details for explanation of values.} 37 | 38 | \item{Fsz}{numerical. Sets font size in points. Longer ID codes may be shrunk 39 | to fit if truncation is not used for matrix labels. Default font size is 40 | \code{5}. ID codes are also shrunk automatically to fit on the label if 41 | actual size is bigger than label dimensions.} 42 | 43 | \item{...}{advanced arguments to modify the PDF layout. See 44 | \code{\link{custom_create_PDF}} for arguments. The advanced options can be 45 | accessed interactively with \code{user = TRUE} and then entering TRUE when prompted to 46 | modify advanced options.} 47 | } 48 | \value{ 49 | a PDF file containing QR-coded labels, saved to the default directory. 50 | } 51 | \description{ 52 | Input vector or data.frame of ID codes to produce a PDF of QR codes which can 53 | be printed. This is a wrapper function for \code{\link{custom_create_PDF}}. 54 | See details of \code{\link{custom_create_PDF}} on how to format text labels 55 | if needed. 56 | } 57 | \details{ 58 | The default PDF setup is for ULINE 1.75" * 0.5" WEATHER RESISTANT LABEL for laser 59 | printer; item # S-19297 (uline.ca). The page format can be modified using 60 | the \code{...} (advanced arguments) for other label types. 61 | } 62 | \examples{ 63 | ## data frame 64 | example_vector <- as.data.frame(c("ao1", "a02", "a03")) 65 | 66 | \dontrun{ 67 | ## run with default options 68 | ## pdf file will be "example.pdf" saved into a temp directory 69 | 70 | temp_file <- tempfile() 71 | 72 | create_PDF(Labels = example_vector, name = temp_file) 73 | 74 | ## view example output from temp folder 75 | system2("open", paste0(temp_file, ".pdf")) 76 | } 77 | 78 | ## run interactively. Overrides default pdf options 79 | if(interactive()){ 80 | create_PDF(user = TRUE, Labels = example_vector) 81 | } 82 | 83 | \dontrun{ 84 | ## run using a data frame, automatically choosing the "label" column 85 | example_df <- data.frame("level1" = c("a1", "a2"), "label" = c("a1-b1", 86 | "a1-b2"), "level2" = c("b1", "b1")) 87 | create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), "example_2")) 88 | } 89 | 90 | \dontrun{ 91 | ## run using an unnamed data frame 92 | example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 93 | ## specify column from data frame 94 | create_PDF(user = FALSE, Labels = example_df[,2], name = file.path(tempdir(), "example_3")) 95 | } 96 | \dontrun{ 97 | ## create linear (code128) label rather than matrix (2D/QR) labels 98 | example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 99 | ## specify column from data frame 100 | create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), 101 | "example_4", type = "linear")) 102 | } 103 | } 104 | \seealso{ 105 | \code{\link{custom_create_PDF}} 106 | } 107 | -------------------------------------------------------------------------------- /man/custom_create_PDF.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hidden_createPDF.R 3 | \name{custom_create_PDF} 4 | \alias{custom_create_PDF} 5 | \alias{qrcode_make} 6 | \alias{code_128_make} 7 | \alias{code_128_make2} 8 | \title{Make barcodes and print labels} 9 | \usage{ 10 | custom_create_PDF( 11 | user = FALSE, 12 | Labels = NULL, 13 | name = "LabelsOut", 14 | type = "matrix", 15 | ErrCorr = "H", 16 | Fsz = 12, 17 | Across = TRUE, 18 | ERows = 0, 19 | ECols = 0, 20 | trunc = TRUE, 21 | numrow = 20, 22 | numcol = 4, 23 | page_width = 8.5, 24 | page_height = 11, 25 | width_margin = 0.25, 26 | height_margin = 0.5, 27 | label_width = NA, 28 | label_height = NA, 29 | x_space = 0, 30 | y_space = 0.5, 31 | alt_text = NULL, 32 | replace_label = FALSE, 33 | denote = c("\\n(", ")") 34 | ) 35 | 36 | qrcode_make(Labels, ErrCorr) 37 | 38 | code_128_make(Labels) 39 | 40 | code_128_make2(Labels) 41 | } 42 | \arguments{ 43 | \item{user}{logical. Run function using interactive mode (prompts user for 44 | parameter values) Default is \code{FALSE}} 45 | 46 | \item{Labels}{vector or data frame object containing label names (i.e. unique 47 | ID codes) with either UTF-8 or ASCII encoding.} 48 | 49 | \item{name}{character. Name of the PDF output file. Default is 50 | \code{"LabelsOut"}. A file named \code{name.pdf} will be saved to the 51 | working directory by default. Use \code{"dirname/name"} to produce a file 52 | called \code{name.pdf} in the \code{dirname} directory.} 53 | 54 | \item{type}{character. Choice of \code{"linear"} for code 128, \code{"linear2"} 55 | for extended code 128, \code{"matrix"} for QR code (i.e. 2D barcode) with 56 | text to the right, or \code{"matrix2"} for QR code with text above or below, 57 | depending on \code{y_space} value (0 = below, 1 = above).} 58 | 59 | \item{ErrCorr}{error correction value for matrix labels only. Level of damage 60 | from low to high: \code{"L"}, \code{"M"}, \code{"Q"}, \code{"H"}. Default 61 | is \code{"H"}. See details for explanation of values.} 62 | 63 | \item{Fsz}{numerical. Sets font size in points. Longer ID codes may be shrunk 64 | to fit if truncation is not used for matrix labels. Default font size is 65 | \code{5}. ID codes are also shrunk automatically to fit on the label if 66 | actual size is bigger than label dimensions.} 67 | 68 | \item{Across}{logical. When \code{TRUE}, print labels across rows, left to 69 | right. When \code{FALSE}, print labels down columns, top to bottom. Default 70 | is \code{TRUE}.} 71 | 72 | \item{ERows}{number of rows to skip. Default is \code{0}. Example: setting 73 | ERows to 6 will begin printing at row 7. ERows and ECols are useful for 74 | printing on partially-used label sheets.} 75 | 76 | \item{ECols}{number of columns to skip. Default is \code{0}. Example: setting 77 | ECols to 2 will put the first label at column 3. ERows and ECols are useful 78 | for printing on partially-used label sheets.} 79 | 80 | \item{trunc}{logical. Text is broken into multiple lines for longer ID codes, 81 | to prevent printing off of the label area. Default is \code{TRUE}. If 82 | \code{trunc = FALSE}, and text is larger than the physical label, the text will 83 | be shrunk down automatically.} 84 | 85 | \item{numrow}{numerical. Number of rows per page. Default is \code{20}.} 86 | 87 | \item{numcol}{numerical. Number of columns per page. Default is \code{4}.} 88 | 89 | \item{page_width}{numerical. Width of page (in inches). Default is set to 90 | \code{8.5}.} 91 | 92 | \item{page_height}{numerical. Height of page (in inches). Default is set to 93 | \code{11}.} 94 | 95 | \item{width_margin}{numerical. The width margin of the page (in inches). 96 | Default is \code{0.25}.} 97 | 98 | \item{height_margin}{numerical. The height margin of the page (in inches). 99 | Default is \code{0.5}.} 100 | 101 | \item{label_width}{numerical. The width of label (in inches). Will be 102 | calculated as \code{(page_width - 2 * width_margin)/numcol} if 103 | \code{label_width} is set as \code{NULL}.} 104 | 105 | \item{label_height}{numerical. The height of the label (in inches). Will be 106 | calculated as \code{(page_height - 2 * height_margin)/numrow} if 107 | \code{label_height} is set as \code{NULL}.} 108 | 109 | \item{x_space}{numerical. A value between \code{0} and \code{1}. This sets 110 | the distance between the QR code and text of each label. Only applies when 111 | \code{type = "matrix"}. Default is \code{0}.} 112 | 113 | \item{y_space}{numerical. The height position of the text on the physical 114 | label as a proportion of the label height. Only applies when \code{type = 115 | "matrix"} or \code{"matrix2"}. A value between \code{0} and \code{1}. 116 | Default is \code{0.5}.} 117 | 118 | \item{alt_text}{vector containing alternative names that are printed along with 119 | Labels BUT ARE NOT ENCODED in the barcode image. Use with caution!} 120 | 121 | \item{replace_label}{logical. Replace label text with \code{alt_text}. 122 | Generated barcode will contain more information than text label. Use with 123 | caution!} 124 | 125 | \item{denote}{character (prefix) or vector of length 2 (prefix, suffix). 126 | Denotes alt_text that is not encoded in the barcode image. 127 | Default is brackets before and after ().} 128 | } 129 | \value{ 130 | a PDF file containing QR-coded labels, saved to the default 131 | directory. 132 | } 133 | \description{ 134 | Input a vector or data frame of ID codes to produce a PDF of barcode labels 135 | that can then be printed. The PDF setup is for the ULINE 1.75" * 0.5" WEATHER 136 | RESISTANT LABEL for laser printer; item # S-19297 (uline.ca). See details for 137 | how to format text labels properly. 138 | } 139 | \details{ 140 | \code{qrcode_make} is the helper function for generating a QR code matrix. 141 | \code{code_128_make} is the helper function for generating a linear barcode 142 | according to code 128 set B. \code{code_128_make2} is the extended helper function for generating a linear barcode 143 | according to code 128 set B, all Latin-1 characters, set C and partially A. \code{custom_create_PDF} is the main function 144 | which sets page layout, and creates the PDF file. 145 | 146 | 147 | Correction levels for QR codes refer to the level of damage a label can 148 | tolerate before the label become unreadable by a scanner (L = Low (7\%), M = 149 | Medium (15\%), Q = Quantile (25\%), H = High (30\%)). So a label with L 150 | correction can lose up to at most 7% of the code before it is unreadable 151 | while a H label can lose up to 30% of the code. This also means that L codes 152 | can be printed at smaller sizes compared to H codes. 153 | 154 | The escape characters \code{\\n} and \code{\\s} (and the hex equivalents 155 | \code{\\x0A} and \code{\\x20} can be used to format text labels. Tab character 156 | \code{\\t} (\code{\\x09}) does not work for QR codes and should be replaced by 157 | a number of space characters. See the package vignette for examples. 158 | 159 | If \code{ECol} or \code{ERow} is greater than \code{numcol} and \code{numrow}, 160 | the labels will be printed starting on the second page. 161 | } 162 | \examples{ 163 | 164 | ## this is the same examples used with create_PDF 165 | ## data frame 166 | example_vector <- as.data.frame(c("ao1", "a02", "a03")) 167 | 168 | \dontrun{ 169 | ## run with default options 170 | ## pdf file will be "example.pdf" saved into a temp directory 171 | temp_file <- tempfile() 172 | 173 | custom_create_PDF(Labels = example_vector, name = temp_file) 174 | 175 | ## view example output from temp folder 176 | system2("open", paste0(temp_file, ".pdf")) 177 | } 178 | 179 | ## run interactively. Overrides default pdf options 180 | if(interactive()){ 181 | custom_create_PDF(user = TRUE, Labels = example_vector) 182 | } 183 | 184 | \dontrun{ 185 | ## run using a data frame, automatically choosing the "label" column 186 | example_df <- data.frame("level1" = c("a1", "a2"), "label" = c("a1-b1", 187 | "a1-b2"), "level2" = c("b1", "b1")) 188 | 189 | custom_create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), 190 | "example_2")) 191 | } 192 | \dontrun{ 193 | ## run using an unnamed data frame 194 | example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 195 | ## specify column from data frame 196 | custom_create_PDF(user = FALSE, Labels = example_df[,2], name = file.path(tempdir(), "example_3")) 197 | } 198 | \dontrun{ 199 | ## create linear (code128) label rather than matrix (2D/QR) labels 200 | example_df <- data.frame(c("a1", "a2"), c("a1-b1", "a1-b2"), c("b1", "b1")) 201 | ## specify column from data frame 202 | custom_create_PDF(user = FALSE, Labels = example_df, name = file.path(tempdir(), 203 | "example_4", type = "linear")) 204 | } 205 | \dontrun{ 206 | ## Include text for the user that is NOT encoded into the barcode image 207 | ## Excluded text is denoted with brackets by default 208 | example_df <- data.frame(ID = floor(runif(3) * 10000), name = c("A", "B", "C"), 209 | dob = c("1/1/2020", "12/6/2001", "2/8/1986")) 210 | 211 | ## linear (1d) barcodes with custom denote parameter 212 | custom_create_PDF(Labels = example_df$ID, alt_text = paste(example_df$name, 213 | example_df$dob), type = "linear", denote=".") 214 | } 215 | } 216 | \seealso{ 217 | \code{\link{create_PDF}} 218 | } 219 | -------------------------------------------------------------------------------- /man/figures/Flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/man/figures/Flowchart.png -------------------------------------------------------------------------------- /man/figures/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/man/figures/example.png -------------------------------------------------------------------------------- /man/figures/example_file.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/man/figures/example_file.pdf -------------------------------------------------------------------------------- /man/make_labels.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/uniqID_maker_addin.R 3 | \name{make_labels} 4 | \alias{make_labels} 5 | \title{baRcodeR GUI} 6 | \usage{ 7 | make_labels() 8 | } 9 | \value{ 10 | Opens RStudio addin gadget window for making labels and barcodes in a GUI 11 | } 12 | \description{ 13 | This addin will allow you to interactive create ID codes and generate PDF files 14 | of QR codes. 15 | } 16 | \examples{ 17 | if(interactive()){ 18 | library(baRcodeR) 19 | make_labels() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /man/uniqID_hier_maker.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/uniqIDHierarchy.R 3 | \name{uniqID_hier_maker} 4 | \alias{uniqID_hier_maker} 5 | \title{Make hierarchical ID codes} 6 | \usage{ 7 | uniqID_hier_maker(user = FALSE, hierarchy, end = NULL, digits = 2) 8 | } 9 | \arguments{ 10 | \item{user}{logical. Run function using interactive mode (prompts user for 11 | parameter values). Default is \code{FALSE}} 12 | 13 | \item{hierarchy}{list. A list with each element consisting of three members 14 | a vector of three elements (string, beginning value, end value). See examples. 15 | Used only when \code{user=FALSE})} 16 | 17 | \item{end}{character. A string to be appended to the end of each label.} 18 | 19 | \item{digits}{numerical. Default is \code{2}. Number of digits to be printed, 20 | adding leading 0s as needed. This will apply to all levels when \code{user=FALSE}. 21 | When the max number of digits in the ID code is greater than number of digits 22 | defined in \code{digits}, then \code{digits} is automatically increased 23 | to avoid errors.} 24 | } 25 | \value{ 26 | data.frame of text labels in the first column, with additional columns 27 | for each level in the hierarchy list, as defined by the user. 28 | } 29 | \description{ 30 | Generate hierarchical ID codes for barcode labels. 31 | Hierarchical codes have a nested structure: e.g. Y subsamples from 32 | each of X individuals. Use \code{\link{uniqID_maker}} 33 | for sequential single-level labels. Can be run in interactive mode, 34 | prompting user for input. The data.frame can be saved as CSV for 35 | (i) the \code{\link{create_PDF}} function to generate printable 36 | QR-coded labels; and (ii) to downstream data collection using spreadsheet, 37 | relational database, etc. 38 | } 39 | \examples{ 40 | if(interactive()){ 41 | ## for interactive mode 42 | uniqID_hier_maker(user = TRUE) 43 | } 44 | 45 | ## how to make hierarchy list 46 | 47 | ## create vectors for each level in the order string_prefix, beginning_value, 48 | ## end_value and combine in list 49 | 50 | a <- c("a", 3, 6) 51 | b <- c("b", 1, 3) 52 | c <- list(a, b) 53 | Labels <- uniqID_hier_maker(hierarchy = c) 54 | Labels 55 | 56 | ## add string at end of each label 57 | Labels <- uniqID_hier_maker(hierarchy = c, end = "end") 58 | Labels 59 | 60 | } 61 | \seealso{ 62 | \code{\link{uniqID_maker}} 63 | } 64 | -------------------------------------------------------------------------------- /man/uniqID_maker.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/uniqIDMaker.R 3 | \name{uniqID_maker} 4 | \alias{uniqID_maker} 5 | \title{Generate a list of ID codes} 6 | \usage{ 7 | uniqID_maker( 8 | user = FALSE, 9 | string = NULL, 10 | level, 11 | digits = 3, 12 | ending_string = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{user}{logical. Run function using interactive mode (prompts user for 17 | parameter values). Default is \code{FALSE}} 18 | 19 | \item{string}{character. Text string for label. Default \code{null}.} 20 | 21 | \item{level}{integer vector. Defines the numerical values to be appended 22 | to the character string. Can be any sequence of numbers (see examples).} 23 | 24 | \item{digits}{numerical. Default is \code{2}. Number of digits to be printed, 25 | adding leading 0s as needed. This will apply to all levels when \code{user=FALSE}. 26 | When the numeric value of the label has a greater number of digits than 27 | \code{digits}, \code{digits} is automatically increased for the entire level. 28 | Default is \code{3}.} 29 | 30 | \item{ending_string}{a character string or vector of strings to attach to the label. 31 | If a vector is used, all combinations of that vector with a unique label will be produced.} 32 | } 33 | \value{ 34 | data.frame with text labels in the first column, along with string 35 | and numeric values in two additional columns. 36 | } 37 | \description{ 38 | Create ID codes consisting of a text string and unique numbers (string001, string002, ...). 39 | Can be run in interactive mode, prompting user for input. The data.frame 40 | output can be saved as CSV for (i) the \code{\link{create_PDF}} function 41 | to generate printable QR-coded labels; and (ii) to downstream data 42 | collection software (spreadsheets, relational databases, etc.) 43 | } 44 | \details{ 45 | When the function is called with \code{user = TRUE}, a sequence of 46 | numbers is generated between the starting and ending number provided by the 47 | user. When \code{user = FALSE}, a vector of custom numbers can be provided. 48 | See example below. 49 | } 50 | \examples{ 51 | 52 | 53 | ## sequential string of numbers in label 54 | Labels <- uniqID_maker(string = "string", level = c(1:5), digits = 2) 55 | Labels 56 | 57 | ## can also use nonsequential strings in input for levels 58 | level <- c(1:5, 8:10, 999:1000) 59 | Labels <- uniqID_maker(string = "string", level = level, digits = 4) 60 | Labels 61 | 62 | 63 | ## Using the ending_string to produce labels with unique endings 64 | ## this is different from hierarchical labels with two levels as there 65 | ## is no numbering, just the text string 66 | 67 | 68 | Labels <- uniqID_maker(string = "string", level = c(1:5), digits = 2, ending_string = "A") 69 | Labels 70 | 71 | Labels <- uniqID_maker(string = "string", level = c(1:5), 72 | digits = 2, ending_string = c("A", "B")) 73 | Labels 74 | 75 | 76 | if(interactive()){ 77 | ## function using user prompt does not use any of the other parameters 78 | Labels <- uniqID_maker(user = TRUE) 79 | Labels 80 | } 81 | } 82 | \seealso{ 83 | \code{\link{uniqID_hier_maker}} 84 | } 85 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(baRcodeR) 3 | 4 | test_check("baRcodeR") 5 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/app.R: -------------------------------------------------------------------------------- 1 | library(baRcodeR) 2 | 3 | baRcodeR:::make_labels_internals() 4 | 5 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-current/001.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "across": "TRUE", 4 | "addin_tabs": "Hierarchical ID Code Generation", 5 | "cancel": 0, 6 | "digits": 3, 7 | "done": 0, 8 | "ecol": 0, 9 | "end_number": null, 10 | "erow": 0, 11 | "err_corr": "L", 12 | "filename": "LabelsOut", 13 | "font_size": 12, 14 | "header": true, 15 | "height_margin": 0.5, 16 | "hier_digits": 2, 17 | "hier_end_number": null, 18 | "hier_label_make": 0, 19 | "hier_prefix": "", 20 | "hier_start_number": null, 21 | "insertBtn": 1, 22 | "label_check": 0, 23 | "label_height": null, 24 | "label_width": null, 25 | "labels": null, 26 | "make": 0, 27 | "make_pdf": 0, 28 | "numcol": 4, 29 | "numrow": 20, 30 | "page_height": 11, 31 | "page_width": 8.5, 32 | "prefix": "", 33 | "removeBtn": 0, 34 | "start_number": null, 35 | "trunc": false, 36 | "type": "matrix", 37 | "width_margin": 0.25, 38 | "x_space": 0, 39 | "y_space": 0.5 40 | }, 41 | "output": { 42 | "hier_code": "uniqID_hier_maker(user = FALSE, hierarchy = list(c(Prefix=\"a\",start=\"1\",end=\"2\")), end = NULL, digits = 2)", 43 | "hier_label_df": [ 44 | "Please add a level", 45 | "NULL", 46 | "c(\"shiny.silent.error\", \"validation\")" 47 | ], 48 | "label_code": "[1] uniqID_maker(user = FALSE, string = '', level = c(NA,NA), digits = 3)", 49 | "label_df": [ 50 | "Please enter a prefix\nPlease enter a starting value\nPlease enter an ending value", 51 | "NULL", 52 | "c(\"shiny.silent.error\", \"validation\")" 53 | ], 54 | "list_check": " Prefix start end\n1 a 1 2" 55 | }, 56 | "export": { 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-current/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/tests/testthat/apps/make_labels/tests/hier_labels-current/001.png -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-current/002.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "across": "TRUE", 4 | "addin_tabs": "Hierarchical ID Code Generation", 5 | "cancel": 0, 6 | "digits": 3, 7 | "done": 0, 8 | "ecol": 0, 9 | "end_number": null, 10 | "erow": 0, 11 | "err_corr": "L", 12 | "filename": "LabelsOut", 13 | "font_size": 12, 14 | "header": true, 15 | "height_margin": 0.5, 16 | "hier_digits": 2, 17 | "hier_end_number": null, 18 | "hier_label_df_cell_clicked": { 19 | 20 | }, 21 | "hier_label_df_cells_selected": [ 22 | 23 | ], 24 | "hier_label_df_columns_selected": null, 25 | "hier_label_df_rows_all": [ 26 | 1, 27 | 2, 28 | 3, 29 | 4, 30 | 5, 31 | 6 32 | ], 33 | "hier_label_df_rows_current": [ 34 | 1, 35 | 2, 36 | 3, 37 | 4, 38 | 5, 39 | 6 40 | ], 41 | "hier_label_df_rows_selected": null, 42 | "hier_label_df_search": "", 43 | "hier_label_df_state": { 44 | "start": 0, 45 | "length": 10, 46 | "order": [ 47 | 48 | ], 49 | "search": { 50 | "search": "", 51 | "smart": true, 52 | "regex": false, 53 | "caseInsensitive": true 54 | }, 55 | "columns": [ 56 | { 57 | "visible": true, 58 | "search": { 59 | "search": "", 60 | "smart": true, 61 | "regex": false, 62 | "caseInsensitive": true 63 | } 64 | }, 65 | { 66 | "visible": true, 67 | "search": { 68 | "search": "", 69 | "smart": true, 70 | "regex": false, 71 | "caseInsensitive": true 72 | } 73 | }, 74 | { 75 | "visible": true, 76 | "search": { 77 | "search": "", 78 | "smart": true, 79 | "regex": false, 80 | "caseInsensitive": true 81 | } 82 | }, 83 | { 84 | "visible": true, 85 | "search": { 86 | "search": "", 87 | "smart": true, 88 | "regex": false, 89 | "caseInsensitive": true 90 | } 91 | } 92 | ] 93 | }, 94 | "hier_label_make": 0, 95 | "hier_prefix": "", 96 | "hier_start_number": null, 97 | "insertBtn": 2, 98 | "label_check": 0, 99 | "label_height": null, 100 | "label_width": null, 101 | "labels": null, 102 | "make": 0, 103 | "make_pdf": 0, 104 | "numcol": 4, 105 | "numrow": 20, 106 | "page_height": 11, 107 | "page_width": 8.5, 108 | "prefix": "", 109 | "removeBtn": 0, 110 | "start_number": null, 111 | "trunc": false, 112 | "type": "matrix", 113 | "width_margin": 0.25, 114 | "x_space": 0, 115 | "y_space": 0.5 116 | }, 117 | "output": { 118 | "hier_code": "uniqID_hier_maker(user = FALSE, hierarchy = list(c(Prefix=\"a\",start=\"1\",end=\"2\"),c(Prefix=\"b\",start=\"1\",end=\"3\")), end = NULL, digits = 2)", 119 | "hier_label_df": { 120 | "x": { 121 | "filter": "none", 122 | "vertical": false, 123 | "container": "\n \n \n
<\/th>\n label<\/th>\n a<\/th>\n b<\/th>\n <\/tr>\n <\/thead>\n<\/table>", 124 | "options": { 125 | "columnDefs": [ 126 | { 127 | "orderable": false, 128 | "targets": 0 129 | }, 130 | { 131 | "name": " ", 132 | "targets": 0 133 | }, 134 | { 135 | "name": "label", 136 | "targets": 1 137 | }, 138 | { 139 | "name": "a", 140 | "targets": 2 141 | }, 142 | { 143 | "name": "b", 144 | "targets": 3 145 | } 146 | ], 147 | "order": [ 148 | 149 | ], 150 | "autoWidth": false, 151 | "orderClasses": false, 152 | "ajax": { 153 | "type": "POST", 154 | "data": "function(d) {\nd.search.caseInsensitive = true;\nd.search.smart = true;\nd.escape = true;\nvar encodeAmp = function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v) {encodeAmp(v.search);});\n}" 155 | }, 156 | "serverSide": true, 157 | "processing": true 158 | }, 159 | "selection": { 160 | "mode": "multiple", 161 | "selected": null, 162 | "target": "row", 163 | "selectable": null 164 | } 165 | }, 166 | "evals": [ 167 | "options.ajax.data" 168 | ], 169 | "jsHooks": [ 170 | 171 | ], 172 | "deps": [ 173 | { 174 | "name": "jquery", 175 | "version": "3.6.0", 176 | "src": { 177 | "href": "jquery-3.6.0" 178 | }, 179 | "meta": null, 180 | "script": "jquery-3.6.0.min.js", 181 | "stylesheet": null, 182 | "head": null, 183 | "attachment": null, 184 | "all_files": true 185 | }, 186 | { 187 | "name": "dt-core", 188 | "version": "1.13.6", 189 | "src": { 190 | "href": "dt-core-1.13.6" 191 | }, 192 | "meta": null, 193 | "script": "js/jquery.dataTables.min.js", 194 | "stylesheet": [ 195 | "css/jquery.dataTables.min.css", 196 | "css/jquery.dataTables.extra.css" 197 | ], 198 | "head": null, 199 | "attachment": null, 200 | "package": null, 201 | "all_files": false 202 | }, 203 | { 204 | "name": "crosstalk", 205 | "version": "1.2.1", 206 | "src": { 207 | "href": "crosstalk-1.2.1" 208 | }, 209 | "meta": null, 210 | "script": "js/crosstalk.min.js", 211 | "stylesheet": "css/crosstalk.min.css", 212 | "head": null, 213 | "attachment": null, 214 | "all_files": true 215 | } 216 | ] 217 | }, 218 | "label_code": "[1] uniqID_maker(user = FALSE, string = '', level = c(NA,NA), digits = 3)", 219 | "label_df": [ 220 | "Please enter a prefix\nPlease enter a starting value\nPlease enter an ending value", 221 | "NULL", 222 | "c(\"shiny.silent.error\", \"validation\")" 223 | ], 224 | "list_check": " Prefix start end\n1 a 1 2\n2 b 1 3" 225 | }, 226 | "export": { 227 | 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-current/002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/tests/testthat/apps/make_labels/tests/hier_labels-current/002.png -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-expected/001.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "across": "TRUE", 4 | "addin_tabs": "Hierarchical ID Code Generation", 5 | "cancel": 0, 6 | "digits": 3, 7 | "done": 0, 8 | "ecol": 0, 9 | "end_number": null, 10 | "erow": 0, 11 | "err_corr": "L", 12 | "filename": "LabelsOut", 13 | "font_size": 12, 14 | "header": true, 15 | "height_margin": 0.5, 16 | "hier_digits": 2, 17 | "hier_end_number": null, 18 | "hier_label_make": 0, 19 | "hier_prefix": "", 20 | "hier_start_number": null, 21 | "insertBtn": 1, 22 | "label_check": 0, 23 | "label_height": null, 24 | "label_width": null, 25 | "labels": null, 26 | "make": 0, 27 | "make_pdf": 0, 28 | "numcol": 4, 29 | "numrow": 20, 30 | "page_height": 11, 31 | "page_width": 8.5, 32 | "prefix": "", 33 | "removeBtn": 0, 34 | "start_number": null, 35 | "trunc": false, 36 | "type": "matrix", 37 | "width_margin": 0.25, 38 | "x_space": 0, 39 | "y_space": 0.5 40 | }, 41 | "output": { 42 | "hier_code": "uniqID_hier_maker(user = FALSE, hierarchy = list(c(Prefix=\"a\",start=\"1\",end=\"2\")), end = NULL, digits = 2)", 43 | "hier_label_df": [ 44 | "Please add a level", 45 | "NULL", 46 | "c(\"shiny.silent.error\", \"validation\")" 47 | ], 48 | "label_code": "[1] uniqID_maker(user = FALSE, string = '', level = c(NA,NA), digits = 3)", 49 | "label_df": [ 50 | "Please enter a prefix\nPlease enter a starting value\nPlease enter an ending value", 51 | "NULL", 52 | "c(\"shiny.silent.error\", \"validation\")" 53 | ], 54 | "list_check": " Prefix start end\n1 a 1 2" 55 | }, 56 | "export": { 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-expected/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/tests/testthat/apps/make_labels/tests/hier_labels-expected/001.png -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-expected/002.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "across": "TRUE", 4 | "addin_tabs": "Hierarchical ID Code Generation", 5 | "cancel": 0, 6 | "digits": 3, 7 | "done": 0, 8 | "ecol": 0, 9 | "end_number": null, 10 | "erow": 0, 11 | "err_corr": "L", 12 | "filename": "LabelsOut", 13 | "font_size": 12, 14 | "header": true, 15 | "height_margin": 0.5, 16 | "hier_digits": 2, 17 | "hier_end_number": null, 18 | "hier_label_df_cell_clicked": { 19 | 20 | }, 21 | "hier_label_df_cells_selected": [ 22 | 23 | ], 24 | "hier_label_df_columns_selected": null, 25 | "hier_label_df_rows_all": [ 26 | 1, 27 | 2, 28 | 3, 29 | 4, 30 | 5, 31 | 6 32 | ], 33 | "hier_label_df_rows_current": [ 34 | 1, 35 | 2, 36 | 3, 37 | 4, 38 | 5, 39 | 6 40 | ], 41 | "hier_label_df_rows_selected": null, 42 | "hier_label_df_search": "", 43 | "hier_label_df_state": { 44 | "start": 0, 45 | "length": 10, 46 | "order": [ 47 | 48 | ], 49 | "search": { 50 | "search": "", 51 | "smart": true, 52 | "regex": false, 53 | "caseInsensitive": true 54 | }, 55 | "columns": [ 56 | { 57 | "visible": true, 58 | "search": { 59 | "search": "", 60 | "smart": true, 61 | "regex": false, 62 | "caseInsensitive": true 63 | } 64 | }, 65 | { 66 | "visible": true, 67 | "search": { 68 | "search": "", 69 | "smart": true, 70 | "regex": false, 71 | "caseInsensitive": true 72 | } 73 | }, 74 | { 75 | "visible": true, 76 | "search": { 77 | "search": "", 78 | "smart": true, 79 | "regex": false, 80 | "caseInsensitive": true 81 | } 82 | }, 83 | { 84 | "visible": true, 85 | "search": { 86 | "search": "", 87 | "smart": true, 88 | "regex": false, 89 | "caseInsensitive": true 90 | } 91 | } 92 | ] 93 | }, 94 | "hier_label_make": 0, 95 | "hier_prefix": "", 96 | "hier_start_number": null, 97 | "insertBtn": 2, 98 | "label_check": 0, 99 | "label_height": null, 100 | "label_width": null, 101 | "labels": null, 102 | "make": 0, 103 | "make_pdf": 0, 104 | "numcol": 4, 105 | "numrow": 20, 106 | "page_height": 11, 107 | "page_width": 8.5, 108 | "prefix": "", 109 | "removeBtn": 0, 110 | "start_number": null, 111 | "trunc": false, 112 | "type": "matrix", 113 | "width_margin": 0.25, 114 | "x_space": 0, 115 | "y_space": 0.5 116 | }, 117 | "output": { 118 | "hier_code": "uniqID_hier_maker(user = FALSE, hierarchy = list(c(Prefix=\"a\",start=\"1\",end=\"2\"),c(Prefix=\"b\",start=\"1\",end=\"3\")), end = NULL, digits = 2)", 119 | "hier_label_df": { 120 | "x": { 121 | "filter": "none", 122 | "vertical": false, 123 | "container": "\n \n \n
<\/th>\n label<\/th>\n a<\/th>\n b<\/th>\n <\/tr>\n <\/thead>\n<\/table>", 124 | "options": { 125 | "columnDefs": [ 126 | { 127 | "orderable": false, 128 | "targets": 0 129 | } 130 | ], 131 | "order": [ 132 | 133 | ], 134 | "autoWidth": false, 135 | "orderClasses": false, 136 | "ajax": { 137 | "type": "POST", 138 | "data": "function(d) {\nd.search.caseInsensitive = true;\nd.search.smart = true;\nd.escape = true;\nvar encodeAmp = function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v) {encodeAmp(v.search);});\n}" 139 | }, 140 | "serverSide": true, 141 | "processing": true 142 | }, 143 | "selection": { 144 | "mode": "multiple", 145 | "selected": null, 146 | "target": "row", 147 | "selectable": null 148 | } 149 | }, 150 | "evals": [ 151 | "options.ajax.data" 152 | ], 153 | "jsHooks": [ 154 | 155 | ], 156 | "deps": [ 157 | { 158 | "name": "jquery", 159 | "version": "3.6.0", 160 | "src": { 161 | "href": "jquery-3.6.0" 162 | }, 163 | "meta": null, 164 | "script": "jquery-3.6.0.min.js", 165 | "stylesheet": null, 166 | "head": null, 167 | "attachment": null, 168 | "all_files": true 169 | }, 170 | { 171 | "name": "dt-core", 172 | "version": "1.11.3", 173 | "src": { 174 | "href": "dt-core-1.11.3" 175 | }, 176 | "meta": null, 177 | "script": "js/jquery.dataTables.min.js", 178 | "stylesheet": [ 179 | "css/jquery.dataTables.min.css", 180 | "css/jquery.dataTables.extra.css" 181 | ], 182 | "head": null, 183 | "attachment": null, 184 | "package": null, 185 | "all_files": false 186 | }, 187 | { 188 | "name": "crosstalk", 189 | "version": "1.2.0", 190 | "src": { 191 | "href": "crosstalk-1.2.0" 192 | }, 193 | "meta": null, 194 | "script": "js/crosstalk.min.js", 195 | "stylesheet": "css/crosstalk.min.css", 196 | "head": null, 197 | "attachment": null, 198 | "all_files": true 199 | } 200 | ] 201 | }, 202 | "label_code": "[1] uniqID_maker(user = FALSE, string = '', level = c(NA,NA), digits = 3)", 203 | "label_df": [ 204 | "Please enter a prefix\nPlease enter a starting value\nPlease enter an ending value", 205 | "NULL", 206 | "c(\"shiny.silent.error\", \"validation\")" 207 | ], 208 | "list_check": " Prefix start end\n1 a 1 2\n2 b 1 3" 209 | }, 210 | "export": { 211 | 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels-expected/002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/tests/testthat/apps/make_labels/tests/hier_labels-expected/002.png -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/hier_labels.R: -------------------------------------------------------------------------------- 1 | app <- ShinyDriver$new("../") 2 | app$snapshotInit("hier_labels") 3 | 4 | app$setInputs(addin_tabs = "Hierarchical ID Code Generation") 5 | app$setInputs(hier_prefix = "a", wait_=FALSE, values_=FALSE) 6 | app$setInputs(hier_start_number = character(0), wait_=FALSE, values_=FALSE) 7 | app$setInputs(hier_start_number = 1, wait_=FALSE, values_=FALSE) 8 | app$setInputs(hier_end_number = character(0), wait_=FALSE, values_=FALSE) 9 | app$setInputs(hier_end_number = 2, wait_=FALSE, values_=FALSE) 10 | app$setInputs(insertBtn = "click") 11 | app$snapshot() 12 | app$setInputs(hier_prefix = "b", wait_=FALSE, values_=FALSE) 13 | app$setInputs(hier_start_number = 1, wait_=FALSE, values_=FALSE) 14 | app$setInputs(hier_end_number = 3, wait_=FALSE, values_=FALSE) 15 | app$setInputs(insertBtn = "click") 16 | app$setInputs(hier_label_df_rows_current = c(1, 2, 3, 4, 5, 6), allowInputNoBinding_ = TRUE) 17 | app$setInputs(hier_label_df_rows_all = c(1, 2, 3, 4, 5, 6), allowInputNoBinding_ = TRUE, wait_=FALSE, values_=FALSE) 18 | app$snapshot() 19 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/labels-current/001.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "across": "TRUE", 4 | "addin_tabs": "Simple ID Code Generation", 5 | "cancel": 0, 6 | "digits": 3, 7 | "done": 0, 8 | "ecol": 0, 9 | "end_number": 11, 10 | "erow": 0, 11 | "err_corr": "L", 12 | "filename": "LabelsOut", 13 | "font_size": 12, 14 | "header": true, 15 | "height_margin": 0.5, 16 | "hier_digits": 2, 17 | "hier_end_number": null, 18 | "hier_label_make": 0, 19 | "hier_prefix": "", 20 | "hier_start_number": null, 21 | "insertBtn": 0, 22 | "label_check": 0, 23 | "label_df_cell_clicked": { 24 | 25 | }, 26 | "label_df_cells_selected": [ 27 | 28 | ], 29 | "label_df_columns_selected": null, 30 | "label_df_rows_all": [ 31 | 1, 32 | 2, 33 | 3 34 | ], 35 | "label_df_rows_current": [ 36 | 1, 37 | 2, 38 | 3 39 | ], 40 | "label_df_rows_selected": null, 41 | "label_df_search": "", 42 | "label_df_state": { 43 | "start": 0, 44 | "length": 10, 45 | "order": [ 46 | 47 | ], 48 | "search": { 49 | "search": "", 50 | "smart": true, 51 | "regex": false, 52 | "caseInsensitive": true 53 | }, 54 | "columns": [ 55 | { 56 | "visible": true, 57 | "search": { 58 | "search": "", 59 | "smart": true, 60 | "regex": false, 61 | "caseInsensitive": true 62 | } 63 | }, 64 | { 65 | "visible": true, 66 | "search": { 67 | "search": "", 68 | "smart": true, 69 | "regex": false, 70 | "caseInsensitive": true 71 | } 72 | }, 73 | { 74 | "visible": true, 75 | "search": { 76 | "search": "", 77 | "smart": true, 78 | "regex": false, 79 | "caseInsensitive": true 80 | } 81 | }, 82 | { 83 | "visible": true, 84 | "search": { 85 | "search": "", 86 | "smart": true, 87 | "regex": false, 88 | "caseInsensitive": true 89 | } 90 | } 91 | ] 92 | }, 93 | "label_height": null, 94 | "label_width": null, 95 | "labels": null, 96 | "make": 0, 97 | "make_pdf": 0, 98 | "numcol": 4, 99 | "numrow": 20, 100 | "page_height": 11, 101 | "page_width": 8.5, 102 | "prefix": "example", 103 | "removeBtn": 0, 104 | "start_number": 9, 105 | "trunc": false, 106 | "type": "matrix", 107 | "width_margin": 0.25, 108 | "x_space": 0, 109 | "y_space": 0.5 110 | }, 111 | "output": { 112 | "label_code": "[1] uniqID_maker(user = FALSE, string = 'example', level = c(9,11), digits = 3)", 113 | "label_df": { 114 | "x": { 115 | "filter": "none", 116 | "vertical": false, 117 | "container": "\n \n \n
<\/th>\n label<\/th>\n ind_string<\/th>\n ind_number<\/th>\n <\/tr>\n <\/thead>\n<\/table>", 118 | "options": { 119 | "columnDefs": [ 120 | { 121 | "orderable": false, 122 | "targets": 0 123 | }, 124 | { 125 | "name": " ", 126 | "targets": 0 127 | }, 128 | { 129 | "name": "label", 130 | "targets": 1 131 | }, 132 | { 133 | "name": "ind_string", 134 | "targets": 2 135 | }, 136 | { 137 | "name": "ind_number", 138 | "targets": 3 139 | } 140 | ], 141 | "order": [ 142 | 143 | ], 144 | "autoWidth": false, 145 | "orderClasses": false, 146 | "ajax": { 147 | "type": "POST", 148 | "data": "function(d) {\nd.search.caseInsensitive = true;\nd.search.smart = true;\nd.escape = true;\nvar encodeAmp = function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v) {encodeAmp(v.search);});\n}" 149 | }, 150 | "serverSide": true, 151 | "processing": true 152 | }, 153 | "selection": { 154 | "mode": "multiple", 155 | "selected": null, 156 | "target": "row", 157 | "selectable": null 158 | } 159 | }, 160 | "evals": [ 161 | "options.ajax.data" 162 | ], 163 | "jsHooks": [ 164 | 165 | ], 166 | "deps": [ 167 | { 168 | "name": "jquery", 169 | "version": "3.6.0", 170 | "src": { 171 | "href": "jquery-3.6.0" 172 | }, 173 | "meta": null, 174 | "script": "jquery-3.6.0.min.js", 175 | "stylesheet": null, 176 | "head": null, 177 | "attachment": null, 178 | "all_files": true 179 | }, 180 | { 181 | "name": "dt-core", 182 | "version": "1.13.6", 183 | "src": { 184 | "href": "dt-core-1.13.6" 185 | }, 186 | "meta": null, 187 | "script": "js/jquery.dataTables.min.js", 188 | "stylesheet": [ 189 | "css/jquery.dataTables.min.css", 190 | "css/jquery.dataTables.extra.css" 191 | ], 192 | "head": null, 193 | "attachment": null, 194 | "package": null, 195 | "all_files": false 196 | }, 197 | { 198 | "name": "crosstalk", 199 | "version": "1.2.1", 200 | "src": { 201 | "href": "crosstalk-1.2.1" 202 | }, 203 | "meta": null, 204 | "script": "js/crosstalk.min.js", 205 | "stylesheet": "css/crosstalk.min.css", 206 | "head": null, 207 | "attachment": null, 208 | "all_files": true 209 | } 210 | ] 211 | } 212 | }, 213 | "export": { 214 | 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/labels-current/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/tests/testthat/apps/make_labels/tests/labels-current/001.png -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/labels-expected/001.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "across": "TRUE", 4 | "addin_tabs": "Simple ID Code Generation", 5 | "cancel": 0, 6 | "digits": 3, 7 | "done": 0, 8 | "ecol": 0, 9 | "end_number": 11, 10 | "erow": 0, 11 | "err_corr": "L", 12 | "filename": "LabelsOut", 13 | "font_size": 12, 14 | "header": true, 15 | "height_margin": 0.5, 16 | "hier_digits": 2, 17 | "hier_end_number": null, 18 | "hier_label_make": 0, 19 | "hier_prefix": "", 20 | "hier_start_number": null, 21 | "insertBtn": 0, 22 | "label_check": 0, 23 | "label_df_cell_clicked": { 24 | 25 | }, 26 | "label_df_cells_selected": [ 27 | 28 | ], 29 | "label_df_columns_selected": null, 30 | "label_df_rows_all": [ 31 | 1, 32 | 2, 33 | 3 34 | ], 35 | "label_df_rows_current": [ 36 | 1, 37 | 2, 38 | 3 39 | ], 40 | "label_df_rows_selected": null, 41 | "label_df_search": "", 42 | "label_df_state": { 43 | "start": 0, 44 | "length": 10, 45 | "order": [ 46 | 47 | ], 48 | "search": { 49 | "search": "", 50 | "smart": true, 51 | "regex": false, 52 | "caseInsensitive": true 53 | }, 54 | "columns": [ 55 | { 56 | "visible": true, 57 | "search": { 58 | "search": "", 59 | "smart": true, 60 | "regex": false, 61 | "caseInsensitive": true 62 | } 63 | }, 64 | { 65 | "visible": true, 66 | "search": { 67 | "search": "", 68 | "smart": true, 69 | "regex": false, 70 | "caseInsensitive": true 71 | } 72 | }, 73 | { 74 | "visible": true, 75 | "search": { 76 | "search": "", 77 | "smart": true, 78 | "regex": false, 79 | "caseInsensitive": true 80 | } 81 | }, 82 | { 83 | "visible": true, 84 | "search": { 85 | "search": "", 86 | "smart": true, 87 | "regex": false, 88 | "caseInsensitive": true 89 | } 90 | } 91 | ] 92 | }, 93 | "label_height": null, 94 | "label_width": null, 95 | "labels": null, 96 | "make": 0, 97 | "make_pdf": 0, 98 | "numcol": 4, 99 | "numrow": 20, 100 | "page_height": 11, 101 | "page_width": 8.5, 102 | "prefix": "example", 103 | "removeBtn": 0, 104 | "start_number": 9, 105 | "trunc": false, 106 | "type": "matrix", 107 | "width_margin": 0.25, 108 | "x_space": 0, 109 | "y_space": 0.5 110 | }, 111 | "output": { 112 | "label_code": "[1] uniqID_maker(user = FALSE, string = 'example', level = c(9,11), digits = 3)", 113 | "label_df": { 114 | "x": { 115 | "filter": "none", 116 | "vertical": false, 117 | "container": "\n \n \n
<\/th>\n label<\/th>\n ind_string<\/th>\n ind_number<\/th>\n <\/tr>\n <\/thead>\n<\/table>", 118 | "options": { 119 | "columnDefs": [ 120 | { 121 | "orderable": false, 122 | "targets": 0 123 | } 124 | ], 125 | "order": [ 126 | 127 | ], 128 | "autoWidth": false, 129 | "orderClasses": false, 130 | "ajax": { 131 | "type": "POST", 132 | "data": "function(d) {\nd.search.caseInsensitive = true;\nd.search.smart = true;\nd.escape = true;\nvar encodeAmp = function(x) { x.value = x.value.replace(/&/g, \"%26\"); }\nencodeAmp(d.search);\n$.each(d.columns, function(i, v) {encodeAmp(v.search);});\n}" 133 | }, 134 | "serverSide": true, 135 | "processing": true 136 | }, 137 | "selection": { 138 | "mode": "multiple", 139 | "selected": null, 140 | "target": "row", 141 | "selectable": null 142 | } 143 | }, 144 | "evals": [ 145 | "options.ajax.data" 146 | ], 147 | "jsHooks": [ 148 | 149 | ], 150 | "deps": [ 151 | { 152 | "name": "jquery", 153 | "version": "3.6.0", 154 | "src": { 155 | "href": "jquery-3.6.0" 156 | }, 157 | "meta": null, 158 | "script": "jquery-3.6.0.min.js", 159 | "stylesheet": null, 160 | "head": null, 161 | "attachment": null, 162 | "all_files": true 163 | }, 164 | { 165 | "name": "dt-core", 166 | "version": "1.11.3", 167 | "src": { 168 | "href": "dt-core-1.11.3" 169 | }, 170 | "meta": null, 171 | "script": "js/jquery.dataTables.min.js", 172 | "stylesheet": [ 173 | "css/jquery.dataTables.min.css", 174 | "css/jquery.dataTables.extra.css" 175 | ], 176 | "head": null, 177 | "attachment": null, 178 | "package": null, 179 | "all_files": false 180 | }, 181 | { 182 | "name": "crosstalk", 183 | "version": "1.2.0", 184 | "src": { 185 | "href": "crosstalk-1.2.0" 186 | }, 187 | "meta": null, 188 | "script": "js/crosstalk.min.js", 189 | "stylesheet": "css/crosstalk.min.css", 190 | "head": null, 191 | "attachment": null, 192 | "all_files": true 193 | } 194 | ] 195 | } 196 | }, 197 | "export": { 198 | 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/labels-expected/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/tests/testthat/apps/make_labels/tests/labels-expected/001.png -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/labels.R: -------------------------------------------------------------------------------- 1 | app <- ShinyDriver$new("../") 2 | app$snapshotInit("labels") 3 | 4 | app$setInputs(prefix = "example", wait_=FALSE, values_=FALSE) 5 | app$setInputs(start_number = character(0), wait_=FALSE, values_=FALSE) 6 | app$setInputs(start_number = 9, wait_=FALSE, values_=FALSE) 7 | app$setInputs(end_number = character(0), wait_=FALSE, values_=FALSE) 8 | app$setInputs(end_number = 11, wait_=FALSE, values_=FALSE) 9 | app$setInputs(label_df_rows_current = c(1, 2, 3), allowInputNoBinding_ = TRUE) 10 | app$setInputs(label_df_rows_all = c(1, 2, 3), allowInputNoBinding_ = TRUE) 11 | app$snapshot() 12 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-current/001.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: 4a42d5c8a1931ceef96e9b9aa3c0b15a6ebaad58]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-current/002.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: e238285e834d27f7cdca48cadaa858c929d6b03e]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-current/003.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: e238285e834d27f7cdca48cadaa858c929d6b03e]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-current/004.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: b74633cd437ed031bd87c608655449798b3bdedc]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-expected/001.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: 4a42d5c8a1931ceef96e9b9aa3c0b15a6ebaad58]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-expected/002.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: e238285e834d27f7cdca48cadaa858c929d6b03e]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-expected/003.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: e238285e834d27f7cdca48cadaa858c929d6b03e]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar-expected/004.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": { 3 | "label_preview": { 4 | "src": "[image data sha1: b74633cd437ed031bd87c608655449798b3bdedc]", 5 | "width": 160, 6 | "height": 40, 7 | "alt": "Label Preview" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_bar.R: -------------------------------------------------------------------------------- 1 | app <- ShinyDriver$new("../") 2 | app$snapshotInit("test_bar") 3 | 4 | app$setInputs(addin_tabs = "Barcode Creation") 5 | app$uploadFile(labels = "test_labels.csv") 6 | app$setInputs(label_check = "click") 7 | app$snapshot(list(output = "label_preview")) 8 | app$setInputs(type = "linear") 9 | app$snapshot(list(output = "label_preview")) 10 | app$setInputs(font_size = 12) 11 | app$snapshot(list(output = "label_preview")) 12 | app$setInputs(check_make_labels_columns_selected = 2, allowInputNoBinding_ = TRUE) 13 | app$setInputs(check_make_labels_cell_clicked = c("2", "2", "a01"), allowInputNoBinding_ = TRUE) 14 | app$snapshot(list(output = "label_preview")) 15 | -------------------------------------------------------------------------------- /tests/testthat/apps/make_labels/tests/test_labels.csv: -------------------------------------------------------------------------------- 1 | "label","a","b" 2 | "a01-b01","a01","b01" 3 | "a01-b02","a01","b02" 4 | "a01-b03","a01","b03" 5 | "a02-b01","a02","b01" 6 | "a02-b02","a02","b02" 7 | "a02-b03","a02","b03" 8 | -------------------------------------------------------------------------------- /tests/testthat/test-interactive.R: -------------------------------------------------------------------------------- 1 | context("Checking custom input functions") 2 | 3 | test_that("numeric input works", { 4 | f <- file() 5 | options(baRcodeR.connection = f) 6 | ans <- paste(c("a", "a", "a", 7 | "3", 3, 3.5, 3.5), collapse = "\n") 8 | write(ans, f) 9 | 10 | expect_error(numeric_input("Testing ... : "), "Invalid input. Please try again") 11 | expect_equal(numeric_input("Testing ...: "), 3) 12 | expect_equal(numeric_input("Testing ...: "), 3) 13 | expect_equal(numeric_input("Testing ...: "), 3) 14 | expect_equal(numeric_input("Testing ...: ", integer = FALSE), 3.5) 15 | 16 | options(baRcodeR.connection = stdin()) 17 | close(f) 18 | }) 19 | 20 | 21 | test_that("fake menu works", { 22 | f <- file() 23 | options(baRcodeR.connection = f) 24 | ans <- paste(c(1, 2, 4, 0, 4), collapse = "\n") 25 | write(ans, f) 26 | 27 | expect_equal(fake_menu(c("Yes", "No"), 28 | "Menu testing ... "), 1) 29 | expect_equal(fake_menu(c("Yes", "No"), 30 | "Menu testing ... "), 2) 31 | expect_error(fake_menu(c("Yes", "No"), 32 | "Menu testing ... "), "Invalid input. Please try again.") 33 | 34 | options(baRcodeR.connection = stdin()) 35 | close(f) 36 | }) 37 | 38 | 39 | context("Interactive with uniqID-maker") 40 | 41 | 42 | test_that("interactive for sequential works properly", { 43 | # this only tests the steps in the user prompts and the prompt specific errors 44 | # set up mock user input 45 | f <- file() 46 | options(baRcodeR.connection = f) 47 | ans <- paste(c("example", "1", "2", "3", 48 | "example", "1", "2", "1", 49 | "example", "a", "a", "a"), collapse = "\n") 50 | write(ans, f) 51 | 52 | expect_identical( 53 | uniqID_maker(user = T), 54 | data.frame(label = c("example001", "example002"), 55 | ind_string = c("example", "example"), 56 | ind_number = c("001", "002"), stringsAsFactors = FALSE)) 57 | 58 | expect_identical( 59 | uniqID_maker(user = T), 60 | data.frame(label = c("example1", "example2"), 61 | ind_string = c("example", "example"), 62 | ind_number = c("1", "2"), stringsAsFactors = FALSE)) 63 | 64 | expect_error( 65 | uniqID_maker(user = T), 66 | "Invalid input. Please try again." 67 | ) 68 | 69 | options(baRcodeR.connection = stdin()) 70 | close(f) 71 | 72 | }) 73 | 74 | 75 | 76 | 77 | context("Interactive with uniqID-hier") 78 | 79 | test_that("hierarchical user prompts work correctly", { 80 | g <- file() 81 | options(baRcodeR.connection = g) 82 | ans <- paste(c(2, 2, 2, 83 | "a", "4", "5", 84 | "b", 1, 2), collapse = "\n") 85 | write(ans, g) 86 | 87 | example_hier_df <- data.frame(label = c("a04-b01", "a04-b02", "a05-b01", "a05-b02"), a = c("a04", "a04", "a05", "a05"), b = c("b01", "b02", "b01", "b02"), stringsAsFactors = FALSE) 88 | example_hier_df$label <- as.character(example_hier_df$label) 89 | expect_equal( 90 | uniqID_hier_maker(user = T), 91 | example_hier_df 92 | ) 93 | 94 | options(baRcodeR.connection = stdin()) 95 | close(g) 96 | 97 | }) 98 | 99 | 100 | context("Interactive with create PDF") 101 | 102 | test_that("PDF creation prompts work correctly", { 103 | # skip_on_cran() 104 | pdftemp <- tempfile(fileext = ".pdf") 105 | pdf_name <- tools::file_path_sans_ext(pdftemp) 106 | 107 | f <- file() 108 | options(baRcodeR.connection = f) 109 | ans <- paste(c(pdf_name, 12, 4, 110 | 1, 1, 1, 111 | 1, 0, 0, 112 | 20, 4, 0.5, 0.25, 113 | 2, 0.5, 2, collapse = "\n")) 114 | write(ans, f) 115 | 116 | custom_create_PDF(user = T, Labels = data.frame(label = c("example09", "example10"), ind_string = c("example", "example"), ind_number = c("09", "10"))) 117 | 118 | expect_true(file.exists(pdftemp)) 119 | options(baRcodeR.connection = stdin()) 120 | close(f) 121 | 122 | }) 123 | -------------------------------------------------------------------------------- /tests/testthat/test-label_generation.R: -------------------------------------------------------------------------------- 1 | context("Label Generation") 2 | 3 | test_that("labels are generated properly", { 4 | expect_identical( 5 | uniqID_maker(string="example", level=1:2), 6 | data.frame(label = c("example001", "example002"), ind_string = c("example", "example"), ind_number = c("001", "002"), stringsAsFactors = FALSE)) 7 | expect_identical( 8 | uniqID_maker(string="example", level=c(3,1)), 9 | data.frame(label = c("example003", "example001"), ind_string = c("example", "example"), ind_number = c("003", "001"), stringsAsFactors = FALSE)) 10 | expect_identical( 11 | uniqID_maker(string = "example", level = 1:2, ending_string = "end"), 12 | data.frame(label = c("example001-end", "example002-end"), ind_string = c("example", "example"), ind_number = c("001", "002"), end_string = c("end", "end"), stringsAsFactors = FALSE) 13 | ) 14 | expect_identical( 15 | uniqID_maker(string="example", level=1:2, digits = 1), 16 | data.frame(label = c("example1", "example2"), ind_string = c("example", "example"), ind_number = c("1", "2"), stringsAsFactors = FALSE)) 17 | example_hier_df <- data.frame(label = c("a04-b01", "a04-b02", "a05-b01", "a05-b02"), a = c("a04", "a04", "a05", "a05"), b = c("b01", "b02", "b01", "b02"), stringsAsFactors = FALSE) 18 | example_hier_df$label <- as.character(example_hier_df$label) 19 | expect_equal( 20 | uniqID_hier_maker(hierarchy = list(c("a",4,5), c("b", 1, 2))), 21 | example_hier_df 22 | ) 23 | }) 24 | 25 | test_that("are rasters generated?", { 26 | expect_s3_class(code_128_make("test"), "rastergrob") 27 | expect_s3_class(qrcode_make("test", "H"), "rastergrob") 28 | }) -------------------------------------------------------------------------------- /tests/testthat/test-pdf_creation.R: -------------------------------------------------------------------------------- 1 | context("Create PDF testing") 2 | 3 | 4 | test_that("PDF successful generation", { 5 | # skip_on_cran() 6 | pdftemp <- tempfile(fileext = ".pdf") 7 | pdf_name <- tools::file_path_sans_ext(pdftemp) 8 | expect_invisible( 9 | custom_create_PDF(Labels = data.frame(label = c("example09", "example10"), ind_string = c("example", "example"), ind_number = c("09", "10")), name = pdf_name)) 10 | expect_true(file.exists(pdftemp)) 11 | expect_warning( 12 | custom_create_PDF(Labels = data.frame(not_label = c("example09", "example10"), ind_string = c("example", "example"), ind_number = c("09", "10")), name = pdf_name), 13 | "Cannot find a label column. Using first column as label input." 14 | ) 15 | expect_warning( 16 | custom_create_PDF(Labels = c(1, 2), type = "linear", label_width = 0.02, name = pdf_name), 17 | "Linear barcodes created will have bar width smaller than 0.03 inches") 18 | expect_warning( 19 | custom_create_PDF(Labels = data.frame(label = c("example09", "example10"), ind_string = c("example", "example"), ind_number = c("09", "10")), numcol = 2, ECols = 3, name = pdf_name), 20 | "Number of rows/columns to skip greater than number of rows/columns on page.") 21 | 22 | }) 23 | 24 | test_that("PDF input errors", { 25 | expect_error(create_PDF(), "Labels do not exist. Please pass in Labels") 26 | expect_error(create_PDF(Labels = matrix(data=c(1:15), nrow=3, ncol = 5)), "Label input not a vector or a data frame") 27 | expect_error(custom_create_PDF(Labels = c(1, 2), x_space = 21), "ERROR: x_space value out of bounds.") 28 | expect_error(custom_create_PDF(Labels = c(1, 2), x_space = 251), "ERROR: x_space value out of bounds.") 29 | expect_error(custom_create_PDF(Labels = c(1, 2), y_space = 21), "ERROR: y_space value out of bounds.") 30 | expect_error(custom_create_PDF(Labels = c(1, 2), y_space = 251), "ERROR: y_space value out of bounds.") 31 | expect_error(custom_create_PDF(Labels = c(1, 2), y_space = "test"), "One or more numerical parameters are not numeric") 32 | expect_error(custom_create_PDF(Labels = data.frame(label = c("example09", "example10"), ind_string = c("example", "example"), ind_number = c("09", "10")), type="noformat"), 33 | "Barcode type must be linear, linear2, matrix or matrix2") 34 | 35 | }) -------------------------------------------------------------------------------- /tests/testthat/test-test-addin.R: -------------------------------------------------------------------------------- 1 | context("add-in tests") 2 | 3 | library(shinytest) 4 | 5 | test_that("labels", { 6 | skip_on_cran() 7 | expect_pass(testApp("apps/make_labels/", compareImages = FALSE)) 8 | }) 9 | 10 | -------------------------------------------------------------------------------- /tests/testthat/test_warnings.R: -------------------------------------------------------------------------------- 1 | library(baRcodeR) 2 | 3 | context("Input warnings") 4 | 5 | test_that("input errors are produced", { 6 | expect_error( 7 | uniqID_maker(string="example", level="hi"), 8 | "Level is not a string of numbers") 9 | 10 | expect_error( 11 | uniqID_maker(string="example", level = c(1:5), digits="a"), 12 | "Digits is not a numerical value") 13 | 14 | expect_warning( 15 | uniqID_maker(string="example", level=1:300, digits=2), 16 | "Digits specified less than max number. Increasing number of digits.") 17 | 18 | expect_warning( 19 | uniqID_maker(string="example", level=9:10, digits = 1), 20 | "Digits specified less than max number. Increasing number of digits.") 21 | 22 | expect_error( 23 | uniqID_hier_maker(hierarchy = c("a",3,6)), 24 | "Hierarchy is not in list format") 25 | 26 | expect_error( 27 | uniqID_hier_maker(hierarchy = list(c("a",3,6), c("b",1))), 28 | "Hierarchy entries are not of equal length.") 29 | 30 | expect_error( 31 | uniqID_hier_maker(hierarchy = list(c(3,6), c(1, 3))), 32 | "Each level in hierarchy should have a string, a beginning value and an end value") 33 | 34 | expect_error( 35 | uniqID_hier_maker(hierarchy = list(c("a",3,6), c("b",1,"j"))), 36 | "Invalid ending number on level") 37 | 38 | expect_error( 39 | uniqID_hier_maker(hierarchy = list(c("a",3,6), c("b","j",3))), 40 | "Invalid starting number") 41 | 42 | expect_error( 43 | uniqID_hier_maker(hierarchy = list(c("a",3,6))), 44 | "Input list has only one level") 45 | 46 | expect_warning( 47 | uniqID_hier_maker(hierarchy = list(c("a",3,6), c("b",100,103)), digits = 2), 48 | "Digits specified less than max level number") 49 | 50 | expect_warning( 51 | qrcode_make(1, "H"), 52 | "Label is single character or blank.") 53 | 54 | temp_file <- tempfile() 55 | expect_error( 56 | custom_create_PDF(Labels = data.frame(label = c("ao1", "a02", "a03")), 57 | name = temp_file, 58 | numrow = "20"), 59 | "One or more numerical parameters are not numeric") 60 | expect_error( 61 | custom_create_PDF( 62 | Labels = data.frame(label = c("ao1", "a02", "a03")), 63 | name = temp_file, 64 | x_space = 1.5), 65 | "x_space value out of bounds. Must be between 0 and 1" 66 | ) 67 | expect_error( 68 | custom_create_PDF( 69 | Labels = data.frame(label = c("ao1", "a02", "a03")), 70 | name = temp_file, 71 | y_space = 1.5), 72 | "y_space value out of bounds. Must be between 0 and 1" 73 | ) 74 | 75 | }) 76 | 77 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/Using-baRcodeR.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using baRcodeR with command line prompts" 3 | author: "Yihan Wu and Robert I. Colautti" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Quick Start to Use baRcodeR} 8 | %\VignetteEncoding{UTF-8} 9 | %\VignetteEngine{knitr::rmarkdown} 10 | editor_options: 11 | chunk_output_type: console 12 | --- 13 | 14 | BaRcodeR is an open-source program to facilitate repeatable label generation and management for labelling, tracking and curating data from biological samples. 15 | 16 | Flowchart of major functions 17 | drawing 18 | 19 | For a quick start, see the [introduction](https://docs.ropensci.org/baRcodeR/). 20 | 21 | 22 | # Cheat Sheet 23 | 24 | A 2-page, quick-reference guide is available via [Figshare](https://dx.doi.org/10.6084/m9.figshare.7043309) 25 | 26 | # Overview 27 | 28 | Creating unique, scannable 2-D barcodes involves two steps: 29 | 30 | 1. Generate unique ID codes with `uniqID_maker()` or `uniqID_hier_maker()` 31 | 2. Create a PDF file containing unique ID codes coupled with 2D barcode using `create_PDF()` 32 | 33 | If you already have ID codes saved in a CSV file, skip step #1 and import directly as a `data.frame()` object for step #2: see [Create barcodes](#create-barcodes). 34 | 35 | For using the baRcodeR RStudio addin, refer to the package vignette *Use baRcodeR addin* through `vignette("use-addin", package="baRcodeR")`. 36 | 37 | The functions in `baRcodeR` will accept parameters in two ways: 1) On the command line as part of the function, and 2) interactively through user input when `user=TRUE` is specified as part of the function. This vignette will cover the two different ways to obtain the same text identifiers and PDF sheets needed for printing. 38 | 39 | 40 | # Create simple ID codes {#uniqID-maker} 41 | 42 | Simple ID codes can be generated using the `uniqID_maker()` function. One-level ID codes consist of two parts, a leading string shared by all samples and a number unique to each sample. 43 | 44 | For example, if we want to generate basic ID codes for 5 individuals: 45 | 46 | ``` 47 | example005 48 | example006 49 | example007 50 | example008 51 | example009 52 | example010 53 | ``` 54 | 55 | First, load the `baRcodeR` library. 56 | 57 | ```{r eval=T, include=T} 58 | 59 | library(baRcodeR) 60 | 61 | ``` 62 | 63 | ## By user prompt {#uniqID-maker-user-prompt} 64 | 65 | Run the `uniqID_make(r))` function in interactive mode. 66 | 67 | ```{r eval=F, include=T} 68 | IDcodes <- uniqID_maker(user = TRUE) 69 | ``` 70 | 71 | > NOTE: When typing into the console for user prompts, strings should not be quoted. 72 | 73 | User prompts will appear in the console. Inputs received from the user are passed as parameters to the `uniqID_maker()` to create the object `IDcodes`, which is a `data.frame()` object containing a vector of unique IDs in the first column, and additional columns for strings and individual numbers provided by the user. 74 | 75 | 76 | > `Please enter string for level: ` 77 | 78 | 79 | The string entered here defines the leading part of the ID code that will be the same for each individual code. This can be the name of a population, a species or a location. In this example, the string entered by the user into the console as denoted by the `>` symbol is "example". 80 | 81 | 82 | > `Please enter string for level: ` example 83 | 84 | 85 | The second user prompt is: 86 | 87 | > `Please enter the starting number for level (integer): ` 88 | 89 | The prompt asks for the starting number to generate unique IDs. These codes do not have to start from 1. 90 | 91 | > `Please enter the starting number for level (integer):` 5 92 | 93 | The third user prompt is: 94 | 95 | > `Enter the ending number for level: ` 96 | 97 | The prompt asks for the ending number. Unique IDs are generated sequentially from the starting number to the ending number. Note that a higher number can be used as the starting number to generate a reverse order. It is possible to generate IDs that are not sequentially numbered by passing a vector through `uniqID_maker()` (e.g. `seq()`) (see [By arguments](#IDcode-maker-arguments)) 98 | 99 | > `Enter the ending number for level: ` 10 100 | 101 | After the starting and ending numbers are set, the function generates a series of numbers. The user is then asked for the number of digits in the unique ID. 102 | 103 | > `Number of digits to print for level:` 104 | 105 | This number must be >= the maximum number of digits in the unique ID code and will add leading zeros as needed. This is particularly useful for generating a smaller number ID codes that are expected to be part of a much larger sample set. 106 | 107 | > `Number of digits to print for level: ` 3 108 | 109 | 110 | ## By arguments {#IDcode-maker-arguments} 111 | 112 | It is also possible to create unique ID codes directly, without user prompts, by defining parameters in `uniqID_maker`. The interactive example above can be reproduced a single line of code: 113 | 114 | ```{r eval=T, include=T} 115 | IDcodes <- uniqID_maker(string = "example", level = 5:10, digits = 3) 116 | IDcodes 117 | ``` 118 | 119 | More complicated, non-sequential ID codes can be generated via the `levels` parameter: 120 | 121 | ```{r eval=T, include=T} 122 | number_sequence <- seq(1, 10, 2) 123 | IDcodes <- uniqID_maker(string = "example", level = number_sequence, digits = 3) 124 | ``` 125 | 126 | The output will then be: 127 | 128 | ```{r eval=T, include=F} 129 | IDcodes 130 | ``` 131 | 132 | ID codes can be saved to a text file for use with other programs (e.g. spreadsheet): 133 | 134 | ```{r eval=F, include=T} 135 | write.csv(IDcodes, "IDcodes.csv") 136 | ``` 137 | 138 | 139 | # Create hierarchical ID codes {#uniqID_hier_maker} 140 | 141 | `uniqID_hier_maker` is used to make unique ID codes that follow a hierarchical (i.e. nested) structure, for example we might sample B individuals from A populations at each of C time points. Similar to `uniqID_maker`, this function can be run interactively or by directly defining parameters. In contrast to `uniqID_maker`, `uniqID_hier_maker` is used to generate nested pairs of strings and unique ID codes. Below is an example of a list of hierarchical identifier codes with three levels (a, b, c) and varying numbers of individuals for each level (a=3, b=2, c=2). 142 | 143 | ``` 144 | a1-b1-c1 145 | a1-b1-c2 146 | a1-b2-c1 147 | a1-b2-c2 148 | a2-b1-c1 149 | a2-b1-c2 150 | a2-b2-c1 151 | a2-b2-c2 152 | a3-b1-c1 153 | a3-b1-c2 154 | a3-b2-c1 155 | a3-b2-c2 156 | ``` 157 | 158 | 159 | 160 | ## By user prompts {#uniqID-hier-maker-user-prompt} 161 | 162 | To create hierarchical ID codes in interactive mode, start with the argument `user=T` in the function. 163 | 164 | ```{r eval=F, include=T} 165 | IDcodes <- uniqID_hier_maker(user = TRUE) 166 | ``` 167 | 168 | The first prompt that appears in the console is: 169 | 170 | > `What is the number of levels in hierarchy: ` 171 | 172 | In this example, we have levels a, b, and c; so three levels in total. 173 | 174 | > `What is the # of levels in hierarchy: ` 3 175 | 176 | The second prompt asks if a string should be appended to the end of the IDs. 177 | 178 | > `String at end of label:` 179 | 180 | > `1 : Yes` 181 | 182 | > `2 : No` 183 | 184 | There are only two possible inputs, 1 or 2. Typing any other number will result in an "invalid input" warning. 185 | 186 | In this example, there is no ending string. 187 | 188 | > `String at end of label: ` 189 | 190 | >` 1 : Yes ` 191 | 192 | >` 2 : No ` 193 | 194 | > 2 195 | 196 | A series of prompts will repeat for each level, allowing the user to set the number of digits to be printed, the leading string, the starting number, and the ending number. These are similar to `uniqID_maker`(see [uniqID_maker](#uniqID-maker-user-prompt) for step by step instructions). The number of digits to print applies to all levels. 197 | 198 | ## By argument 199 | 200 | Instead of interactive mode, it is possible to define arguments directly into `uniqID_hier_maker`. Unlike `uniqID_maker`, a `list` object is required to specify the parameters in each level of the hierarchy. First, define a vector for each level with three parameters: the leading string, the start value, and the end value. Second, combine vectors into a `list` object in the order of their hierarchy. For the example below, 'c' is nested within 'b' within 'a'. 201 | 202 | ```{r} 203 | level_one <- c("a", 1, 3) 204 | level_two <- c("b", 1, 2) 205 | level_three <- c("c", 10, 12) 206 | hier_list <- list(level_one, level_two, level_three) 207 | ``` 208 | 209 | You can specify a custom suffix string for all ID codes using the `end` argument, and the number of digits to print for all levels through the `digits` argument. It is not possible at this time to vary the number of digits printed for each level, however this can be done using interactive mode (i.e. user=T). 210 | 211 | The list can then be passed into `uniqID_hier_maker` to generate the unique ID codes. 212 | 213 | ```{r, eval=T, include=T} 214 | IDcodes <- uniqID_hier_maker(hierarchy = hier_list, digits = 1) 215 | ``` 216 | 217 | The output will be: 218 | 219 | ```{r eval=T, include=T} 220 | IDcodes 221 | ``` 222 | 223 | The data frame contains ID codes in the first column, and a separate column for each level of the hierarchy, with the user-defined string as the header. This can be saved to a CSV: 224 | 225 | ```{r eval=F, include=T} 226 | write.csv(IDcodes, "IDcodes.csv") 227 | ``` 228 | 229 | This file is useful for archiving ID codes and as a starting point for data entry. For example, it can be opened in a spreadsheet program to add data measurement columns. It is also the input for creating printable, QR-coded labels with `create_PDF`. 230 | 231 | 232 | # Create barcodes {#create-barcodes} 233 | 234 | 2D barcodes (i.e. QR codes) paired with ID code strings are created from an input vector of text labels. Users can manually create their own ID codes as a vector, as the first column of an existing `data.frame()` object, or as a `data.frame()` from `<-uniqID_maker` or `<-uniqID_hier_maker`. 235 | 236 | The function `create_PDF()` produces a pdf file containing barcodes that fit to the dimensions of ULINE 1.75" * 0.5" WEATHER RESISTANT LABEL for laser printer; item # S-19297 (uline.ca). If needed, the page setup can be modified using advanced options in [custom_create_PDF](#custom-create-pdf). 237 | 238 | The first step is to read in the vector of ID codes, in this example from a CSV file: 239 | 240 | ```{r eval=F, include=T} 241 | # Reading in from a csv file 242 | IDcodes<-read.csv("IDcodes.csv") 243 | ``` 244 | 245 | ## By user prompt {#create-barcodes-user-prompt} 246 | 247 | In the following example, the IDcodes data.frame object is used to create a PDF file called "example.pdf", with a font size of 3.5, and an error correction level "Q" meaning the barcode can tolerate up to 25% damage. The parameter `user=T` will prompt the user to guide creation of the pdf file containing scannable barcodes. 248 | 249 | If `IDcodes` is a vector, the vector will be directly used to generate barcodes. If `IDcodes` is a data frame, the function will use the column called `label` or else the first column in the data frame. 250 | 251 | ```{r eval=F, include=T} 252 | create_PDF(user=TRUE, Labels=IDcodes) 253 | ``` 254 | A user prompt is printed into the console. For example: 255 | 256 | > `Please enter name for PDF output file: ` 257 | 258 | Any combination of letters and numbers can be used for the name of the pdf file. Here, the file name is set to "example." 259 | 260 | > `Please enter name for PDF output file: ` example 261 | 262 | The next user prompt is to set the size of the text printed on each barcode. 263 | 264 | > `Please enter a font size: ` 265 | 266 | This font size is the point size and will apply to the size of the text on the PDF. For example, entering 12 will create 12 point font on the PDF. 267 | 268 | > `Please enter a font size: ` 12 269 | 270 | The last basic parameter to set is the error correction level. There are four possible levels: L, M, Q, and H. 271 | 272 | Level "L" - up to 7% damage -- ideal for very small labels (large pixels) 273 | Level "M" - up to 15% damage 274 | Level "Q" - up to 25% damage 275 | Level "H" - up to 30% damage -- good for bigger labels (small pixels) 276 | 277 | The user prompt for error correction level is similar to previous prompts. 278 | 279 | > `Select an error correction level. ` 280 | 281 | > `1 : L (up to 7% damage)` 282 | 283 | > `2 : M (up to 15% damage)` 284 | 285 | > `3 : Q (up to 25% damage)` 286 | 287 | > `4 : H (up to 30% damage) ` 288 | 289 | This example uses an error correction level "Q" so `3` should be entered. 290 | 291 | > `Select an error correction level. ` 292 | 293 | > `1 : L (up to 7% damage)` 294 | 295 | > `2 : M (up to 15% damage)` 296 | 297 | > `3 : Q (up to 25% damage)` 298 | 299 | > `4 : H (up to 30% damage) ` 300 | 301 | > 3 302 | 303 | The last user prompt asks whether the user wants to modify the advanced parameters. 304 | 305 | > `Edit advanced parameters?` 306 | 307 | > `1 : Yes` 308 | 309 | > `2 : No` 310 | 311 | 312 | In this example, no advanced parameters are modified (input `2`). Using advanced parameters are covered in [advanced options](#custom-create-pdf) 313 | 314 | > `Edit advanced parameters?` 315 | 316 | > `1 : Yes` 317 | 318 | > `2 : No` 319 | 320 | > 2 321 | 322 | ## By arguments 323 | 324 | The same example above can be reproduced directly with the following parameters: 325 | 326 | ```{r eval=F, include=T} 327 | create_PDF(Labels = IDcodes, name = "example", ErrCorr = "Q", Fsz = 2.5) 328 | ``` 329 | 330 | 331 | # Advanced Options for pdf output {#custom-create-pdf} 332 | 333 | There are advanced options for the pdf output which can be accessed interactively or by specifying additional arguments in `create_PDF`. The user prompts are similar to the ones shown above but allow customization of the output document for other printing formats. Documentation of the advanced options can be found using through the man page `?custom_create_PDF`. 334 | 335 | Arguments can be passed from `create_PDF` to `custom_create_PDF` as `create_PDF` is just a wrapper for `custom_create_PDF`. 336 | 337 | ```{r eval=F, include=T} 338 | 339 | ## This will create a pdf sheet where the labels are printed in columns then rows. It will skip 3 rows from the top and 1 column from the left. 340 | create_PDF(Labels = Labels, name = "example_advanced", ErrCorr = "Q", Fsz = 2.5, Across = F, ERows = 3, ECol = 1) 341 | ``` 342 | 343 | 344 | # Formatting of text labels 345 | 346 | Trying to format text labels in the baRcodeR GUI is not recommended. 347 | 348 | ## New Lines 349 | 350 | It is possible to force formatting of labels by inserting `\n` as line breaks. 351 | 352 | ## Tabs 353 | 354 | Using `\t` will create error due to the underlying `qrcode` library used in this package. One solution is to use the space character in place of tabs. 355 | 356 | ```{r} 357 | # original label 358 | X <- "text\ttext" 359 | cat(X) 360 | cat(gsub("\\t", "\x20\x20\x20\x20", X)) 361 | ``` 362 | 363 | ## When reading from file 364 | 365 | R automatically escapes the escape characters when reading from file. For example, `text\ntext` will be read in as `text\\ntext` from `read.csv`. 366 | 367 | Use a global substitution to replace the double slashes. 368 | 369 | ```{r} 370 | X <- "text\\ntext" 371 | cat(X) 372 | cat(gsub("\\\\n","\n",X)) 373 | ``` 374 | 375 | -------------------------------------------------------------------------------- /vignettes/add-in-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/vignettes/add-in-screenshot.png -------------------------------------------------------------------------------- /vignettes/tab-1-screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/vignettes/tab-1-screenshot-2.png -------------------------------------------------------------------------------- /vignettes/tab-1-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/vignettes/tab-1-screenshot.png -------------------------------------------------------------------------------- /vignettes/tab-2-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/vignettes/tab-2-screenshot.png -------------------------------------------------------------------------------- /vignettes/tab-3-screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/vignettes/tab-3-screenshot-2.png -------------------------------------------------------------------------------- /vignettes/tab-3-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/baRcodeR/9fbe83be4970176f5913e3f334392d543c6ba675/vignettes/tab-3-screenshot.png -------------------------------------------------------------------------------- /vignettes/use-addin.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Use baRcodeR addin" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Use baRcodeR addin} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r} 11 | knitr::opts_chunk$set(echo = F) 12 | ``` 13 | 14 | BaRcodeR is an open-source program to facilitate repeatable label generation and management for labelling, tracking and curating data from biological samples. 15 | 16 | Flowchart of major functions 17 | drawing 18 | 19 | For a quick start, see the [introduction](https://docs.ropensci.org/baRcodeR/). 20 | 21 | # Cheat Sheet 22 | 23 | A 2-page, quick-reference guide is available via [Figshare](https://dx.doi.org/10.6084/m9.figshare.7043309) 24 | 25 | If RStudio is not available, see the [introduction](https://docs.ropensci.org/baRcodeR/) and `vignette("Using-baRcodeR)"` for command line use. 26 | 27 | ## Using the RStudio addin 28 | 29 | The main baRcodeR functions for unique identifiers and QR code generation can be performed interactive via the RStudio addin found on the toolbar. 30 | 31 | ### Find the addin 32 | 33 | Make sure to restart RStudio after installing. Then the addin should appear in the toolbar. 34 | 35 | Click on the add-in, and a popup window will appear. 36 | 37 | ```{r, fig.cap = "Screenshot of RStudio addins bar"} 38 | knitr::include_graphics("add-in-screenshot.png") 39 | ``` 40 | 41 | Note the 3 tabs along the bottom, corresponding to the three main baRcodeR commands: `uniqID_maker`, `uniqID_hier_maker` and `create_PDF`. 42 | 43 | 44 | ```{r, fig.cap = "Screenshot of the simple ID Code tab"} 45 | knitr::include_graphics("tab-1-screenshot.png") 46 | ``` 47 | 48 | ### Generate simple ID codes 49 | 50 | The first tab generates basic ID codes with user input as seen below: 51 | 52 | ```{r, fig.cap = "Active simple ID code tab"} 53 | knitr::include_graphics("tab-1-screenshot-2.png") 54 | ``` 55 | 56 | 57 | As you fill in the fields, a preview of the ID codes will appear on the right-hand side along with reproducible code, which can be copied for archival purposes. Clicking 'Create Label.csv' will create a CSV file called 'Label_YYYY-MM-DD.csv', which contains a data frame with the full unique ID strings as the first column, the user-defined prefix string in the second column, and the unique ID number in the third column. This file is useful for archiving ID codes and as a starting point for data entry. For example, it can be opened in a spreadsheet program to add data measurement columns. It is also the input for creating printable, QR-coded labels with `create_PDF`. 58 | 59 | ```{r, fig.cap = "Screenshot of the hierarchical ID code tab"} 60 | knitr::include_graphics("tab-2-screenshot.png") 61 | ``` 62 | 63 | 64 | ### Generate Hierarchical ID codes 65 | 66 | You can switch from the simple ID code generation tab to the hierarchical ID code generation or QR code creation tabs at the bottom. 67 | 68 | Hierarchical ID codes have a nested structure (e.g. X subsamples from Y individuals at Z time points), the information for each level is saved under the "Hierarchy" section. The "Add level" button is used to add more levels to the hierarchy, and the "Remove level" button will remove the most recently added level. The data frame output will contain ID codes in the first column, and a separate column for each level of the hierarchy, with the user-defined string as the header; as shown under 'Preview'. As with the simple ID code tab, the output of Hierarchical ID codes is a CSV file "Labels_YYYY-MM-DD.csv", saved in the working directory. This file is useful for archiving ID codes and as a starting point for data entry. For example, it can be opened in a spreadsheet program to add data measurement columns. It is also the input for creating printable, QR-coded labels with `create_PDF`. 69 | 70 | ```{r, fig.cap = "Sceenshot of PDF creation tab"} 71 | knitr::include_graphics("tab-3-screenshot.png") 72 | ``` 73 | 74 | ### Create the PDF for sticker printing 75 | 76 | The Barcode Creation tab contains all the advanced options for page layout. The default options fit a specific format: ULINE 1.75" * 0.5" WEATHER RESISTANT LABEL for laser printer; item # S-19297 (uline.ca). A text file containing ID codes is imported by clicking the "Browse" button and selecting the CSV text file in the file browser. The file is be previewed by clicking "Import File". 77 | 78 | After importing a CSV file, the preview shows part of the expected output PDF file based on font size and other layout options. The first column is highlighted by default and defines the column to use for the labels. Clicking on a different column will set it as the ID code column, as shown in the preview. 79 | 80 | ```{r, fig.cap = "Screenshot of Column Selection"} 81 | knitr::include_graphics("tab-3-screenshot-2.png") 82 | ``` 83 | 84 | 85 | Clicking "Make PDF" will generate a printable PDF of all barcodes provided. This can take several minutes for >100 barcodes, depending on computer speed. The text "Done" will appear upon completion of the PDF file. 86 | 87 | > NOTE: When printing from pdf, ensure that 'anti-aliasing' or 'smoothing' options are turned OFF, and that you are not using 'fit to page' or similar options that will re-scale the output. 88 | 89 | ```{r} 90 | sessionInfo() 91 | ``` 92 | 93 | --------------------------------------------------------------------------------