From b0cabd18cc385f7b908394641971a23675ae3142 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 20:53:46 -0500 Subject: [PATCH 01/20] move from magrittr to base r --- vignettes/Basic-Use.Rmd | 64 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/vignettes/Basic-Use.Rmd b/vignettes/Basic-Use.Rmd index eff9586..0dab28d 100644 --- a/vignettes/Basic-Use.Rmd +++ b/vignettes/Basic-Use.Rmd @@ -17,7 +17,6 @@ knitr::opts_chunk$set( knitr::opts_chunk$set(echo = TRUE) suppressMessages(library(depict)) -suppressMessages(library(magrittr)) suppressMessages(library(grid)) ``` @@ -30,16 +29,15 @@ A simple wrapper around cdk's excellent depict module. ```{r} library(depict) -library(magrittr) # load a smiles string pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") # `depiction` is the base class; styles are applied to it # `depict` applies the styles to the molecule -depiction() %>% - depict(pen) %>% - get_image() %>% +depiction() |> + depict(pen) |> + get_image() |> grid::grid.raster() ``` @@ -59,10 +57,10 @@ atmcontainers <- purrr::map( many_containers <- atomcontainer_list_to_jarray(atmcontainers) -depiction() %>% - set_zoom(10) %>% - depict(many_containers) %>% - get_image() %>% +depiction() |> + set_zoom(10) |> + depict(many_containers) |> + get_image() |> grid::grid.raster() ``` @@ -88,16 +86,16 @@ bnds <- pen$bonds() lactam <- match_smarts("C1(=O)NCC1", pen) # use piping to change the behavior as desired -depiction() %>% - highlight_atoms(atms, color$LIGHT_GRAY) %>% - highlight_atoms(bnds, color$LIGHT_GRAY) %>% - highlight_atoms(lactam, color$RED) %>% - set_size(400, 400) %>% - set_zoom(3) %>% - outerglow() %>% - add_title() %>% - depict(pen) %>% - get_image() %>% +depiction() |> + highlight_atoms(atms, color$LIGHT_GRAY) |> + highlight_atoms(bnds, color$LIGHT_GRAY) |> + highlight_atoms(lactam, color$RED) |> + set_size(400, 400) |> + set_zoom(3) |> + outerglow() |> + add_title() |> + depict(pen) |> + get_image() |> grid::grid.raster() ``` @@ -110,13 +108,13 @@ depiction() %>% small_highlight <- match_smarts("C1CCC1", many_containers) depiction() %>% - highlight_atoms(small_highlight, color$RED) %>% + highlight_atoms(small_highlight, color$RED) |> set_size(400, 400) %>% - set_zoom(3) %>% - outerglow() %>% - add_title() %>% - depict(many_containers) %>% - get_image() %>% + set_zoom(3) |> + outerglow() |> + add_title() |> + depict(many_containers) |> + get_image() |> grid::grid.raster() ``` @@ -156,14 +154,14 @@ insulin <- read_mol(insulinmol) cysteine <- match_smarts("C(=O)C(CS)N", insulin) xlinks <- match_smarts("SS", insulin) -depiction()%>% - set_size(700, 400) %>% - set_zoom(10) %>% - outerglow() %>% - highlight_atoms(cysteine, color$YELLOW) %>% - highlight_atoms(xlinks, color$YELLOW) %>% - depict(insulin)%>% - get_image() %>% +depiction() |> + set_size(700, 400) |> + set_zoom(10) |> + outerglow() |> + highlight_atoms(cysteine, color$YELLOW) |> + highlight_atoms(xlinks, color$YELLOW) |> + depict(insulin) |> + get_image() |> grid::grid.raster() ``` From 435ce5985940069edc4991506844f8a44eb2e783 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 20:54:47 -0500 Subject: [PATCH 02/20] fix imports and add url --- DESCRIPTION | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 30f62f3..4f0e98b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -12,11 +12,12 @@ Depends: rcdk (>= 3.7), rcdklibs (>= 2.8) Imports: - png, - magrittr + png RoxygenNote: 7.2.2 +URL: https://cdk-r.github.io/depict/ Suggests: knitr, + magrittr rmarkdown, - testthat + testthat, VignetteBuilder: knitr From d0da0377b1001656c55bb0062184e66c3a46d5c4 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:02:41 -0500 Subject: [PATCH 03/20] update docs and Description --- DESCRIPTION | 7 ++++--- _pkgdown.yml => pkgdown/_pkgdown.yml | 0 vignettes/Basic-Use.Rmd | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) rename _pkgdown.yml => pkgdown/_pkgdown.yml (100%) diff --git a/DESCRIPTION b/DESCRIPTION index 4f0e98b..92c1b84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,19 +1,20 @@ Package: depict Type: Package Title: Draw Beautiful Molecular Structures -Version: 0.3.1 +Version: 0.3.2 Authors@R: c(person('Zachary', 'Charlop-Powers', role=c('cre','aut',"cph"), email='zach.charlop.powers@gmail.com')) Description: Generate images of molecules using the Depiction API of the 'Chemistry Development Kit'. CDK's Depict Api License: LGPL LazyData: TRUE Depends: - rJava (>= 1.0-6), + rJava (>= 1.0-11), rcdk (>= 3.7), rcdklibs (>= 2.8) Imports: png -RoxygenNote: 7.2.2 +RoxygenNote: 7.3.1 +Encoding: UTF-8 URL: https://cdk-r.github.io/depict/ Suggests: knitr, diff --git a/_pkgdown.yml b/pkgdown/_pkgdown.yml similarity index 100% rename from _pkgdown.yml rename to pkgdown/_pkgdown.yml diff --git a/vignettes/Basic-Use.Rmd b/vignettes/Basic-Use.Rmd index 0dab28d..93f2bcc 100644 --- a/vignettes/Basic-Use.Rmd +++ b/vignettes/Basic-Use.Rmd @@ -107,9 +107,9 @@ depiction() |> small_highlight <- match_smarts("C1CCC1", many_containers) -depiction() %>% +depiction() |> highlight_atoms(small_highlight, color$RED) |> - set_size(400, 400) %>% + set_size(400, 400) |> set_zoom(3) |> outerglow() |> add_title() |> From 41acd419827ff2307eb8c55824383468eda8c4f1 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:03:58 -0500 Subject: [PATCH 04/20] style pkgdown --- pkgdown/_pkgdown.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index d71acfb..84d0022 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -1,4 +1,7 @@ url: ~ template: bootstrap: 5 - + bslib: + primary: "#0054AD" + border-radius: 0.5rem + btn-border-radius: 0.25rem From 8bb901a6893da11773b0d969441ef2df57d4946a Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:05:16 -0500 Subject: [PATCH 05/20] add orcid --- DESCRIPTION | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 92c1b84..47f742c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,9 @@ Package: depict Type: Package Title: Draw Beautiful Molecular Structures Version: 0.3.2 -Authors@R: c(person('Zachary', 'Charlop-Powers', role=c('cre','aut',"cph"), email='zach.charlop.powers@gmail.com')) +Authors@R: c( + person('Zachary', 'Charlop-Powers', ,'zach.charlop.powers@gmail.com',role=c('cre'), + comment = c(ORCID = "0000-0001-8816-4680"))) Description: Generate images of molecules using the Depiction API of the 'Chemistry Development Kit'. CDK's Depict Api License: LGPL From cebc2d4d5239a2dd6d76a42614983d520acc2ab3 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:09:17 -0500 Subject: [PATCH 06/20] rename --- vignettes/{Basic-Use.Rmd => depict.Rmd} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vignettes/{Basic-Use.Rmd => depict.Rmd} (100%) diff --git a/vignettes/Basic-Use.Rmd b/vignettes/depict.Rmd similarity index 100% rename from vignettes/Basic-Use.Rmd rename to vignettes/depict.Rmd From 81f3abf833806c24c482496a76064093ea1838e4 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:13:59 -0500 Subject: [PATCH 07/20] update depict for rxn check --- DESCRIPTION | 4 ++-- R/depict.R | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 47f742c..9406c89 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: depict Type: Package Title: Draw Beautiful Molecular Structures -Version: 0.3.2 +Version: 0.4.0 Authors@R: c( person('Zachary', 'Charlop-Powers', ,'zach.charlop.powers@gmail.com',role=c('cre'), comment = c(ORCID = "0000-0001-8816-4680"))) @@ -20,7 +20,7 @@ Encoding: UTF-8 URL: https://cdk-r.github.io/depict/ Suggests: knitr, - magrittr + magrittr, rmarkdown, testthat, VignetteBuilder: knitr diff --git a/R/depict.R b/R/depict.R index fd84953..a936bec 100644 --- a/R/depict.R +++ b/R/depict.R @@ -90,14 +90,17 @@ add_terminal_carbons <- function(dg) { #' @export depict <- function(dg, mol) { if (!checkJavaClass(dg, "org/openscience/cdk/depict/DepictionGenerator")) { + print(.jclass(dg)) stop("depict requires a Depiction Generator") } if (!checkJavaClass(mol, c("org/openscience/cdk/AtomContainer", "org/openscience/cdk/AtomContainer2", + "org/openscience/cdk/Reaction", "org/openscience/cdk/silent/AtomContainer", "org/openscience/cdk/silent/AtomContainer2", "org/openscience/cdk/silent/IAtomContainer", + "org/openscience/cdk/silent/Reaction", "java/util/ArrayList" ))) { stop("depict requires an AtomContainer or an ArrayList of them") From 4bedf7c452e589dff215d8eb7ccb3da6b3ab4e7b Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:19:37 -0500 Subject: [PATCH 08/20] add rxn smiles test --- R/depict.R | 2 +- R/utilities.R | 3 +-- tests/testthat/test_IO.R | 12 ++++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/R/depict.R b/R/depict.R index a936bec..9483c00 100644 --- a/R/depict.R +++ b/R/depict.R @@ -152,7 +152,7 @@ save_image <- function(molgrid, filepath) { #' get_image <- function(molgrid) { if (!checkJavaClass(molgrid, "org/openscience/cdk/depict/MolGridDepiction")) { - stop("highlight_atoms requires a Depiction Generator") + stop("get_image requires a Depiction Generator") } # CDK apends a ".png" to the name diff --git a/R/utilities.R b/R/utilities.R index fdbcae3..6ba4f53 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -40,8 +40,7 @@ checkJavaClass <- function(jobj, klass ) { atomcontainer_list_to_jarray <- function(atomcontainers) { new_array <- .jnew('java.util.ArrayList') - - for (atmcntnr in atomcontainers) { + for (atmcntnr in as.list(atomcontainers)) { new_array$add(atmcntnr) } diff --git a/tests/testthat/test_IO.R b/tests/testthat/test_IO.R index a7540cc..d7af3eb 100644 --- a/tests/testthat/test_IO.R +++ b/tests/testthat/test_IO.R @@ -13,3 +13,15 @@ test_that("we can open MOL file", { expect_equal(attr(mol, "jclass"), "org/openscience/cdk/AtomContainer") expect_equal(attr(sdf, "jclass"), "org/openscience/cdk/AtomContainer") }) + + +test_that("we can parse a reaction smiles", { + sp <- J('org.openscience.cdk.smiles.SmilesParser') + silentchemobject <- J("org.openscience.cdk.silent.SilentChemObjectBuilder") + smiles_parser <- new(sp, silentchemobject$getInstance()) + + rxn <- smiles_parser$parseReactionSmiles("[CH3:9][CH:8]([CH3:10])[c:7]1[cH:11][cH:12][cH:13][cH:14][cH:15]1.[CH2:3]([CH2:4][C:5](=[O:6])Cl)[CH2:2][Cl:1]>[Al+3].[Cl-].[Cl-].[Cl-].C(Cl)Cl>[CH3:9][CH:8]([CH3:10])[c:7]1[cH:11][cH:12][c:13]([cH:14][cH:15]1)[C:5](=[O:6])[CH2:4][CH2:3][CH2:2][Cl:1] |f:2.3.4.5| Friedel-Crafts acylation [3.10.1]") + expect_equal(attr(rxn, "jclass"), "org/openscience/cdk/silent/Reaction") +}) + + From 911eab160011dead0c03bcd614a95e72ed499450 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:27:21 -0500 Subject: [PATCH 09/20] style pass --- R/IO.R | 19 ++++++--------- R/depict.R | 42 ++++++++++++++++++--------------- R/selection_functions.R | 34 ++++++++++++-------------- R/smarts.R | 20 +++++++--------- R/utilities.R | 6 ++--- tests/testthat/test_IO.R | 10 ++++---- tests/testthat/test_depiction.R | 32 ++++++++++++------------- vignettes/depict.Rmd | 36 +++++++++++++--------------- 8 files changed, 93 insertions(+), 106 deletions(-) diff --git a/R/IO.R b/R/IO.R index 22232be..fef301a 100644 --- a/R/IO.R +++ b/R/IO.R @@ -8,27 +8,25 @@ #' @param kekulise Optional. Boolean. Default \code{TRUE} #' @export #' -parse_smiles <- function(smi, generatecoords=TRUE, kekulise=TRUE) { - +parse_smiles <- function(smi, generatecoords = TRUE, kekulise = TRUE) { SmilesParser <- J("org.openscience.cdk.smiles.SmilesParser") SChemObjectBuilder <- J("org.openscience.cdk.silent.SilentChemObjectBuilder") StructureDiagramGenerator <- J("org.openscience.cdk.layout.StructureDiagramGenerator") sinst <- SChemObjectBuilder$getInstance() - sp <- new(SmilesParser, sinst) + sp <- new(SmilesParser, sinst) sp$kekulise(kekulise) - - mol <- sp$parseSmiles(smi) + + mol <- sp$parseSmiles(smi) if (generatecoords) { - sdg <- new(StructureDiagramGenerator) + sdg <- new(StructureDiagramGenerator) sdg$setMolecule(mol) sdg$generateCoordinates() mol <- sdg$getMolecule() } mol - } #' read_mol @@ -39,16 +37,13 @@ parse_smiles <- function(smi, generatecoords=TRUE, kekulise=TRUE) { #' @return an AtomContainer #' @export read_mol <- function(molfile) { - jAtomContainer <- J("org.openscience.cdk.AtomContainer") - jfileobj <- .jnew("java.io.File", molfile) + jfileobj <- .jnew("java.io.File", molfile) jreaderobj <- .jnew("java.io.FileReader", jfileobj) jmolreader <- .jnew("org.openscience.cdk.io.MDLV2000Reader") - AC <- .jnew("org.openscience.cdk.AtomContainer") + AC <- .jnew("org.openscience.cdk.AtomContainer") jmolreader$setReader(jreaderobj) jmolreader$read(AC) - } - diff --git a/R/depict.R b/R/depict.R index 9483c00..f751243 100644 --- a/R/depict.R +++ b/R/depict.R @@ -10,7 +10,7 @@ depiction <- function() { #' color atoms #' #' set the atom color -#' +#' #' @param dg a CDK DepictionGenerator #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export @@ -45,7 +45,7 @@ set_size <- function(dg, width, height) { stop("set_size requires a Depiction Generator") } - dg$withSize(width,height) + dg$withSize(width, height) } #' add_title @@ -54,7 +54,6 @@ set_size <- function(dg, width, height) { #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export add_title <- function(dg) { - if (!checkJavaClass(dg, "org/openscience/cdk/depict/DepictionGenerator")) { stop("add_title requires a Depiction Generator") } @@ -86,7 +85,7 @@ add_terminal_carbons <- function(dg) { #' @param mol Required. An AtomContainer #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/AtomContainer.html} -#' +#' #' @export depict <- function(dg, mol) { if (!checkJavaClass(dg, "org/openscience/cdk/depict/DepictionGenerator")) { @@ -94,19 +93,20 @@ depict <- function(dg, mol) { stop("depict requires a Depiction Generator") } - if (!checkJavaClass(mol, c("org/openscience/cdk/AtomContainer", - "org/openscience/cdk/AtomContainer2", - "org/openscience/cdk/Reaction", - "org/openscience/cdk/silent/AtomContainer", - "org/openscience/cdk/silent/AtomContainer2", - "org/openscience/cdk/silent/IAtomContainer", - "org/openscience/cdk/silent/Reaction", - "java/util/ArrayList" - ))) { + if (!checkJavaClass(mol, c( + "org/openscience/cdk/AtomContainer", + "org/openscience/cdk/AtomContainer2", + "org/openscience/cdk/Reaction", + "org/openscience/cdk/silent/AtomContainer", + "org/openscience/cdk/silent/AtomContainer2", + "org/openscience/cdk/silent/IAtomContainer", + "org/openscience/cdk/silent/Reaction", + "java/util/ArrayList" + ))) { stop("depict requires an AtomContainer or an ArrayList of them") - } + } - #.jcall(dg, "Lorg/openscience/cdk/depict/Depiction;", "depict", mol) + # .jcall(dg, "Lorg/openscience/cdk/depict/Depiction;", "depict", mol) dg$depict(mol) } @@ -151,13 +151,17 @@ save_image <- function(molgrid, filepath) { #' @export #' get_image <- function(molgrid) { - if (!checkJavaClass(molgrid, "org/openscience/cdk/depict/MolGridDepiction")) { + if (!checkJavaClass(molgrid, c( + "org/openscience/cdk/depict/MolGridDepiction", + "org/openscience/cdk/depict/ReactionDepiction" + ))) { + print(.jclass(molgrid)) stop("get_image requires a Depiction Generator") } # CDK apends a ".png" to the name - output <- paste(tempfile(),"png") - output1 <- paste0(output,".png") + output <- paste(tempfile(), "png") + output1 <- paste0(output, ".png") molgrid$writeTo("png", output) img <- readPNG(output1) @@ -176,7 +180,7 @@ get_image <- function(molgrid) { #' @param zoom Optional. Default \code{1} #' @export #' -set_zoom <- function(dg, zoom=1) { +set_zoom <- function(dg, zoom = 1) { if (!checkJavaClass(dg, "org/openscience/cdk/depict/DepictionGenerator")) { stop("highlight_atoms requires a Depiction Generator") } diff --git a/R/selection_functions.R b/R/selection_functions.R index fd5e4db..2cfb04c 100644 --- a/R/selection_functions.R +++ b/R/selection_functions.R @@ -1,58 +1,54 @@ #' match_smarts -#' +#' #' Find matches to a given molecule using a SMARTs pattern. #' #' @param smarts a SMARTS string #' @param mol a CDK IAtomContainer or a java.util.Arraylist of them #' @param limit limit of the number of matches -#' +#' #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/isomorphism/Mappings.html} #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/smiles/smarts/SmartsPattern.html} -#' +#' #' @return a hashset of atoms and bonds #' @export #' -#' -match_smarts <- function(smarts, mol, limit=10) { - - - hashset <- J("java/util/HashSet") +#' +match_smarts <- function(smarts, mol, limit = 10) { + hashset <- J("java/util/HashSet") smartspattern <- J("org/openscience/cdk/smiles/smarts/SmartsPattern") - spattern <- smartspattern$create(smarts, NULL) + spattern <- smartspattern$create(smarts, NULL) # handle the base case first if (!.jclass(mol) == "java.util.ArrayList") { - matches <- spattern$matchAll(mol) matches <- matches$limit(as.integer(limit)) # Note: switching below to chemobjects due to reflection access with the atom-bond map # atombondmap <- matches$uniqueAtoms()$toAtomBondMap() - atombonds <- matches$uniqueAtoms()$toChemObjects() - + atombonds <- matches$uniqueAtoms()$toChemObjects() + # somewhat convoluted code to get all of the matching atoms highlight <- new(hashset) - + for (l in as.list(atombonds)) { highlight$add(l) } - - # then handle the array list of atom containers + + # then handle the array list of atom containers } else { - # somewhat convoluted code to get all of the matching atoms highlight <- new(hashset) - + for (atmcont in as.list(mol)) { matches <- spattern$matchAll(atmcont) matches <- matches$limit(as.integer(limit)) # Note: switching below to chemobjects due to reflection access with the atom-bond map # atombondmap <- matches$uniqueAtoms()$toAtomBondMap() - atombonds <- matches$uniqueAtoms()$toChemObjects() + atombonds <- matches$uniqueAtoms()$toChemObjects() for (l in as.list(atombonds)) { highlight$add(l) } } } - + highlight } diff --git a/R/smarts.R b/R/smarts.R index dde66f8..d2da521 100644 --- a/R/smarts.R +++ b/R/smarts.R @@ -6,22 +6,20 @@ #' @seealso \url{http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html} #' @seealso \url{http://www.daylight.com/dayhtml_tutorials/languages/smarts/index.html} #' @export -#' +#' #' amino_acids <- function() { list( # Generic amino acid: low specificity. - amino_acids="[NX3,NX4+][CX4H]([*])[CX3](=[OX1])[O,N]", #For use w/ non-standard a.a. search. hits pro but not gly. Hits acids and conjugate bases. Hits single a.a.s and specific residues w/in polypeptides (internal, or terminal). + amino_acids = "[NX3,NX4+][CX4H]([*])[CX3](=[OX1])[O,N]", # For use w/ non-standard a.a. search. hits pro but not gly. Hits acids and conjugate bases. Hits single a.a.s and specific residues w/in polypeptides (internal, or terminal). # A.A. Template for 20 standard a.a.s - amino_acids20="[$([$([NX3H,NX4H2+]),$([NX3](C)(C)(C))]1[CX4H]([CH2][CH2][CH2]1)[CX3](=[OX1])[OX2H,OX1-,N]), + amino_acids20 = "[$([$([NX3H,NX4H2+]),$([NX3](C)(C)(C))]1[CX4H]([CH2][CH2][CH2]1)[CX3](=[OX1])[OX2H,OX1-,N]), $([$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H2][CX3](=[OX1])[OX2H,OX1-,N]),$([$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([*])[CX3](=[OX1])[OX2H,OX1-,N])]", - - proline="[$([NX3H,NX4H2+]),$([NX3](C)(C)(C))]1[CX4H]([CH2][CH2][CH2]1)[CX3](=[OX1])[OX2H,OX1-,N]", - glycine="[$([$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H2][CX3](=[OX1])[OX2H,OX1-,N])]", - amino_acids18="[$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([*])[CX3](=[OX1])[OX2H,OX1-,N]", - - alanine="[$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([CH3X4])[CX3](=[OX1])[OX2H,OX1-,N]", + proline = "[$([NX3H,NX4H2+]),$([NX3](C)(C)(C))]1[CX4H]([CH2][CH2][CH2]1)[CX3](=[OX1])[OX2H,OX1-,N]", + glycine = "[$([$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H2][CX3](=[OX1])[OX2H,OX1-,N])]", + amino_acids18 = "[$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([*])[CX3](=[OX1])[OX2H,OX1-,N]", + alanine = "[$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([CH3X4])[CX3](=[OX1])[OX2H,OX1-,N]", # $([CH2X4][CX3](=[OX1])[NX3H2]), # $([CH2X4][CX3](=[OX1])[OH0-,OH]), @@ -38,6 +36,6 @@ amino_acids <- function() { # $([CH2X4][cX3]1[cX3H][nX3H][cX3]2[cX3H][cX3H][cX3H][cX3H][cX3]12), # $([CH2X4][cX3]1[cX3H][cX3H][cX3]([OHX2,OH0X1-])[cX3H][cX3H]1), # $([CHX4]([CH3X4])[CH3X4]) - amino_acids18="[$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([*])[CX3](=[OX1])[OX2H,OX1-,N]" - ) + amino_acids18 = "[$([NX3H2,NX4H3+]),$([NX3H](C)(C))][CX4H]([*])[CX3](=[OX1])[OX2H,OX1-,N]" + ) } diff --git a/R/utilities.R b/R/utilities.R index 6ba4f53..050a6bf 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -5,11 +5,11 @@ #' @param jobj Required. A Java Object #' @param klass Required. A string defining a java class #' @return Boolean -checkJavaClass <- function(jobj, klass ) { +checkJavaClass <- function(jobj, klass) { if (is.null(attr(jobj, 'jclass'))) stop("this is not a Java Object") - for (k in klass ) { - if (attr(jobj, "jclass") == k) { + for (kl in klass) { + if (attr(jobj, "jclass") == kl) { return(TRUE) } } diff --git a/tests/testthat/test_IO.R b/tests/testthat/test_IO.R index d7af3eb..f6dabfa 100644 --- a/tests/testthat/test_IO.R +++ b/tests/testthat/test_IO.R @@ -4,8 +4,8 @@ library("depict") context("Test IO") test_that("we can open MOL file", { - molfile <- system.file("molfiles/ChEBI_5931.mol", package="depict") - sdffile <- system.file("molfiles/Structure2D_CID_14969.sdf", package="depict") + molfile <- system.file("molfiles/ChEBI_5931.mol", package = "depict") + sdffile <- system.file("molfiles/Structure2D_CID_14969.sdf", package = "depict") mol <- read_mol(molfile) sdf <- read_mol(sdffile) @@ -16,12 +16,10 @@ test_that("we can open MOL file", { test_that("we can parse a reaction smiles", { - sp <- J('org.openscience.cdk.smiles.SmilesParser') + sp <- J("org.openscience.cdk.smiles.SmilesParser") silentchemobject <- J("org.openscience.cdk.silent.SilentChemObjectBuilder") smiles_parser <- new(sp, silentchemobject$getInstance()) - + rxn <- smiles_parser$parseReactionSmiles("[CH3:9][CH:8]([CH3:10])[c:7]1[cH:11][cH:12][cH:13][cH:14][cH:15]1.[CH2:3]([CH2:4][C:5](=[O:6])Cl)[CH2:2][Cl:1]>[Al+3].[Cl-].[Cl-].[Cl-].C(Cl)Cl>[CH3:9][CH:8]([CH3:10])[c:7]1[cH:11][cH:12][c:13]([cH:14][cH:15]1)[C:5](=[O:6])[CH2:4][CH2:3][CH2:2][Cl:1] |f:2.3.4.5| Friedel-Crafts acylation [3.10.1]") expect_equal(attr(rxn, "jclass"), "org/openscience/cdk/silent/Reaction") }) - - diff --git a/tests/testthat/test_depiction.R b/tests/testthat/test_depiction.R index 1889de6..3a1106a 100644 --- a/tests/testthat/test_depiction.R +++ b/tests/testthat/test_depiction.R @@ -7,24 +7,24 @@ library("grid") context("Test Depiction") test_that("we can depict a molecule", { - # load in penicillin - pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") - cav <- parse_smiles("CN1C=NC2=C1C(=O)N(C(=O)N2C)C") - - atomcontainerclasses <- c("org/openscience/cdk/AtomContainer2", - "org/openscience/cdk/AtomContainer", - "org/openscience/cdk/silent/AtomContainer2", - "org/openscience/cdk/silent/AtomContainer", - "org/openscience/cdk/IAtomContainer") - + pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") + cav <- parse_smiles("CN1C=NC2=C1C(=O)N(C(=O)N2C)C") + + atomcontainerclasses <- c( + "org/openscience/cdk/AtomContainer2", + "org/openscience/cdk/AtomContainer", + "org/openscience/cdk/silent/AtomContainer2", + "org/openscience/cdk/silent/AtomContainer", + "org/openscience/cdk/IAtomContainer" + ) + expect_true(attr(pen, "jclass") %in% atomcontainerclasses) expect_true(attr(cav, "jclass") %in% atomcontainerclasses) - - dep <- depiction() %>% depict(pen) + + dep <- depiction() %>% depict(pen) expect_equal(attr(dep, "jclass"), "org/openscience/cdk/depict/MolGridDepiction") - + img <- get_image(dep) - expect_true(inherits(img, 'array')) - -}) \ No newline at end of file + expect_true(inherits(img, "array")) +}) diff --git a/vignettes/depict.Rmd b/vignettes/depict.Rmd index 93f2bcc..1e6ef5b 100644 --- a/vignettes/depict.Rmd +++ b/vignettes/depict.Rmd @@ -18,7 +18,6 @@ knitr::opts_chunk$set( knitr::opts_chunk$set(echo = TRUE) suppressMessages(library(depict)) suppressMessages(library(grid)) - ``` @@ -31,7 +30,7 @@ A simple wrapper around cdk's excellent depict module. library(depict) # load a smiles string -pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") +pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") # `depiction` is the base class; styles are applied to it # `depict` applies the styles to the molecule @@ -47,13 +46,13 @@ depiction() |> # Multiple Smiles ```{r} - # load a few smiles as AtomContainers -atmcontainers <- purrr::map( +atmcontainers <- purrr::map( c("CCCC", "CCCCCC", "CCCC1CCC1CC2CCCC2"), - parse_smiles) + parse_smiles +) -# convert them into a java iterable +# convert them into a java iterable many_containers <- atomcontainer_list_to_jarray(atmcontainers) @@ -62,7 +61,6 @@ depiction() |> depict(many_containers) |> get_image() |> grid::grid.raster() - ``` @@ -70,13 +68,12 @@ depiction() |> # Use Colors, SMARTS, Highlighting ```{r } - -# you must supply java colors +# you must supply java colors color <- J("java.awt.Color") # load in penicillin -pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") -cav <- parse_smiles("CN1C=NC2=C1C(=O)N(C(=O)N2C)C") +pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicillin") +cav <- parse_smiles("CN1C=NC2=C1C(=O)N(C(=O)N2C)C") # define the regions to highlight # either all atoms/bonds @@ -97,14 +94,12 @@ depiction() |> depict(pen) |> get_image() |> grid::grid.raster() - ``` ## SMARTS for highlighting mutiple containers ```{r} - small_highlight <- match_smarts("C1CCC1", many_containers) depiction() |> @@ -121,12 +116,14 @@ depiction() |> ## Multiple Colors ```{r} -mol <- parse_smiles(paste("CC(n1c(C)ncc1c1ccnc(n1)Nc1ccc(cc1)S(=O)(=O)C)C", - "CMGC:CDC2:6gu3:A:FB8", sep=" ")) +mol <- parse_smiles(paste("CC(n1c(C)ncc1c1ccnc(n1)Nc1ccc(cc1)S(=O)(=O)C)C", + "CMGC:CDC2:6gu3:A:FB8", + sep = " " +)) # imid <- 'c1cnc[nH]1' #1H-imidazole highlight_imid <- match_smarts("c1cncn1", mol) -highlight_2 <- match_smarts("n1cccnc1Nc2ccccc2", mol) +highlight_2 <- match_smarts("n1cccnc1Nc2ccccc2", mol) color <- J("java.awt.Color") @@ -148,11 +145,11 @@ depiction() |> ```{r} # laoding a molfile -insulinmol <- system.file("molfiles/ChEBI_5931.mol", package="depict") -insulin <- read_mol(insulinmol) +insulinmol <- system.file("molfiles/ChEBI_5931.mol", package = "depict") +insulin <- read_mol(insulinmol) cysteine <- match_smarts("C(=O)C(CS)N", insulin) -xlinks <- match_smarts("SS", insulin) +xlinks <- match_smarts("SS", insulin) depiction() |> set_size(700, 400) |> @@ -163,6 +160,5 @@ depiction() |> depict(insulin) |> get_image() |> grid::grid.raster() - ``` From 7a7400c17105aa07d7e6c086d15ca16a1732ab57 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Wed, 28 Feb 2024 21:28:28 -0500 Subject: [PATCH 10/20] update allowable classes --- R/depict.R | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/R/depict.R b/R/depict.R index f751243..d7870f4 100644 --- a/R/depict.R +++ b/R/depict.R @@ -134,7 +134,10 @@ highlight_atoms <- function(dg, atoms, color) { #' @param outfile Required. Filepath to the output #' @export save_image <- function(molgrid, filepath) { - if (!checkJavaClass(molgrid, "org/openscience/cdk/depict/MolGridDepiction")) { + if (!checkJavaClass(molgrid, c( + "org/openscience/cdk/depict/MolGridDepiction", + "org/openscience/cdk/depict/ReactionDepiction" + ))) { stop("highlight_atoms requires a Depiction Generator") } molgrid$writeTo(filepath) From 80e01c6970decdeb3bd9d34842d7f019552149df Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Sat, 2 Mar 2024 09:51:53 -0500 Subject: [PATCH 11/20] add a get_svg_string function --- NAMESPACE | 1 + R/depict.R | 28 ++++++++++++++++++++++++++-- man/get_svg_string.Rd | 18 ++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 man/get_svg_string.Rd diff --git a/NAMESPACE b/NAMESPACE index f24a7c4..5f20e7f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ export(color_atoms) export(depict) export(depiction) export(get_image) +export(get_svg_string) export(highlight_atoms) export(match_smarts) export(outerglow) diff --git a/R/depict.R b/R/depict.R index d7870f4..4a43716 100644 --- a/R/depict.R +++ b/R/depict.R @@ -97,13 +97,15 @@ depict <- function(dg, mol) { "org/openscience/cdk/AtomContainer", "org/openscience/cdk/AtomContainer2", "org/openscience/cdk/Reaction", + "org/openscience/cdk/ReactionSet", "org/openscience/cdk/silent/AtomContainer", "org/openscience/cdk/silent/AtomContainer2", "org/openscience/cdk/silent/IAtomContainer", "org/openscience/cdk/silent/Reaction", + "org/openscience/cdk/silent/ReactionSet", "java/util/ArrayList" ))) { - stop("depict requires an AtomContainer or an ArrayList of them") + stop("depict requires an AtomContainer, Reaction, ReactionSet, or an ArrayList of them") } # .jcall(dg, "Lorg/openscience/cdk/depict/Depiction;", "depict", mol) @@ -159,7 +161,7 @@ get_image <- function(molgrid) { "org/openscience/cdk/depict/ReactionDepiction" ))) { print(.jclass(molgrid)) - stop("get_image requires a Depiction Generator") + stop("get_image requires a Depiction") } # CDK apends a ".png" to the name @@ -175,6 +177,28 @@ get_image <- function(molgrid) { img } +#' get_svg_string +#' +#' @param molgrid Required. A MolGridDepiction. Usually obtained from +#' the \code{depict} function. +#' @returns an SVG string literal +#' @export +get_svg_string <- function(molgrid) { + if (!checkJavaClass(molgrid, c( + "org/openscience/cdk/depict/MolGridDepiction", + "org/openscience/cdk/depict/ReactionDepiction" + ))) { + print(.jclass(molgrid)) + stop("get_image requires a Depiction") + } + + svg_str <- grid$toSvgStr() + svg_list <- strsplit(svg_str, "\n")[[1]] + # return the svg without the two header lines + paste(svg_list[3:length(svg_list)], collapse="\n") +} + + #' set_zoom #' #' set_zoom diff --git a/man/get_svg_string.Rd b/man/get_svg_string.Rd new file mode 100644 index 0000000..306d4ab --- /dev/null +++ b/man/get_svg_string.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/depict.R +\name{get_svg_string} +\alias{get_svg_string} +\title{get_svg_string} +\usage{ +get_svg_string(molgrid) +} +\arguments{ +\item{molgrid}{Required. A MolGridDepiction. Usually obtained from +the \code{depict} function.} +} +\value{ +an SVG string literal +} +\description{ +get_svg_string +} From d0ed6ad0ee91bcb48843d0d7c5ad5551d9a31e13 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Sat, 2 Mar 2024 19:15:27 -0500 Subject: [PATCH 12/20] add icon --- man/figures/logo.png | Bin 0 -> 42833 bytes pkgdown/favicon/apple-touch-icon-120x120.png | Bin 0 -> 4662 bytes pkgdown/favicon/apple-touch-icon-152x152.png | Bin 0 -> 6245 bytes pkgdown/favicon/apple-touch-icon-180x180.png | Bin 0 -> 7601 bytes pkgdown/favicon/apple-touch-icon-60x60.png | Bin 0 -> 2370 bytes pkgdown/favicon/apple-touch-icon-76x76.png | Bin 0 -> 2927 bytes pkgdown/favicon/apple-touch-icon.png | Bin 0 -> 7601 bytes pkgdown/favicon/favicon-16x16.png | Bin 0 -> 748 bytes pkgdown/favicon/favicon-32x32.png | Bin 0 -> 1333 bytes pkgdown/favicon/favicon.ico | Bin 0 -> 15086 bytes 10 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 man/figures/logo.png create mode 100644 pkgdown/favicon/apple-touch-icon-120x120.png create mode 100644 pkgdown/favicon/apple-touch-icon-152x152.png create mode 100644 pkgdown/favicon/apple-touch-icon-180x180.png create mode 100644 pkgdown/favicon/apple-touch-icon-60x60.png create mode 100644 pkgdown/favicon/apple-touch-icon-76x76.png create mode 100644 pkgdown/favicon/apple-touch-icon.png create mode 100644 pkgdown/favicon/favicon-16x16.png create mode 100644 pkgdown/favicon/favicon-32x32.png create mode 100644 pkgdown/favicon/favicon.ico diff --git a/man/figures/logo.png b/man/figures/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2d9b4e72bd7e7a1e9dd462d751626c203bc85acf GIT binary patch literal 42833 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 T=R5wAfS;Y)oVFHx=N0`wj8Le1 literal 0 HcmV?d00001 diff --git a/pkgdown/favicon/apple-touch-icon-120x120.png b/pkgdown/favicon/apple-touch-icon-120x120.png new file mode 100644 index 0000000000000000000000000000000000000000..85d1560ccb98d6ecacae03d13dfc85affd88852a GIT binary patch literal 4662 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 KHJjA!WB(5>-ipZp literal 0 HcmV?d00001 diff --git a/pkgdown/favicon/apple-touch-icon-180x180.png b/pkgdown/favicon/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..2febf9bb71302a8e72330705535b9e5644314467 GIT binary patch literal 7601 zcmZ{pbyO5U*YKB;lJ0JhbXjUykX&MEkXTZ30clteP&$_mL1IBzkrr4$q?KmrP>@hM z1*N6bkLP*+_}=f2@0^*r6X(vIGk4CMdwv&XWS~Vs#!3bN04QMEP?I~^{GUofc-Ow_ zpJ=-igs!UkssI2so&45;=x)sIq-~-P0E7wx0Fki(!1di!JS=j5$^Ip0 zC*mQm|C5?V*_?~Gac0kHX5ipcH=rgW+sOUstobmgqo>&`Ws@rG8m)BdpfnbQn9%N3 znU!sR#l3aH_mk?o21X4*pWE57J!RR2#<2Z--P#Gg;(s1+!H^}PS-N7r8w7vn+8Pd zN#CVwywGhA_%gBtPhb-lYO&ASS$IdmwK;SqHS5W6n}X|_*K?<9t& z*dD;*E*erFl@*A43O9qM$t)TN0{hI;mcYcuDks9)W%4S@K9gmf8%mVh^xZ_$)ll+@ zHJ_IsTPvNUUO9^6UPE7YDNb;udnj+Y-j}mRHr;#A3%N2}_sMd1>-jgw-#mB3KO^KC7ofT}V^m&+66Y6wG&=g<>`{b1Gm|%O z@}C@WYZWd{ZPRwe{?cBNcij`L>$QA^jqjKKxCRS5BKQ*?K45xUu&9XX^4v^#^!lT5 zd(;Gx)z%d&_)~p|@T1e`EyujLZRrp4P;2;*`DEY^&kxw7MfjFU#_$p6pH3DXrJkm4=bUYmx;(r_$c zG-7G*q+ynMpehV<&Q3`cOL8P2u`R&)C1e7Y2Ck$f2naoYcQqW3mU2pnqqPb<7f+r`2{6B${b{Oh6oKXX5hzf#Ng%&OeXYwpEn zLf;(~I#A~RUTqBlkE|E#+9&+Ub(Q1zUq`F#02M-H7@y}J9*D{{TX9a)dbAC7uYnA? zm|A@Qd(S6~f7sbaZ?lNyO(tZvsJl`WHho@y2&S_rzQ;4EsmeR7doV*x`Ge|+gzofD zxDqDp%)RGvG8xeFF+Z%- z)V9K|L-?{TWfX#!Ze!$x76&4*f6oQF$8BtWzu@iZwR38r88;zBfp2zqreNn0*uE5z zQ_RiV^@#7^!{kPPpyNt6TqwMtjMT1A`pFKyq^B`0W;Ge%-^+z1^R$+9-`_5fmKUcO!&b%}|TJ^)8V)2(Zap%hRM5-rzJa2^@WpH)(7% z(rKvcgvN%PTMkWv(lWfWw&haYIHF>m?ehawG}YAAL zbhq0Mn@zl!iDQe?GoCF%uJuLhBu?9aRV#`HQl!Rt7c;aaalsS!&uCSM6RB! z9%xrWS-8^*PkrC`bF%uSeUTEV%1LBAYs427aX)~QOXP9lnK{VNk_RANtp8lWI33Sgu*kG zU3b`*(awp|LAkRNI+&1joMBd<9^dr1Nhk>@Wfh!_PM4WyAMQ| z3ik1=yXjZidE-wrGQI&0(tsijg6Bkc`}H%@weciDt;g%5uRiXh?MWgDz44KtBu)Gi zgUYl7iPiqvMN+(2KYUhWjP#I!9NLY8ic?ziWbP^(F?t!v|MPamy|(ofT9H5UN2yO5 zj~%YfOO|-*Akfp#4jHKZrz~TaK%QUb@U0=1W4BBy0!p7)iP?77!6)<2eBwx)RaRhE z1!2UZJ2@~g`GVMu^G!46Qv zd^S~$c>ME;U@*kN1b)PZHbw#L#6nWV=JYtGurz?)dwcXI;Vz+fZF$K%^T`_Nr8`OKV}H*rj7F@r`M?!SpJ$~=CvnJ&$! z59AOT@>|`&$MEAZZT?B;9! z`!&9D8YpVjN#K#&3+=KsXSpah)tA5b-f|F2Af+*}0X>{Ws_SCCsZ>##Nl;Y_w;@tz z<{kdWR~xLbVTu|esm>wC+g2Jk{(vWXNqk~`sX3b!8gEoHRv!?+Gw^bx^DWIo(89HF z>dG=iQ565LH+b$QP3(`f1E?iMC78B>=3?4y3eM>X!Cd6{<0a&e)KN+rlU1dG4oyU? z$IE)IYb-@zSW*JVHQJpb${?#Bt&oUWk)hR3)k;p9G+mc#p3B&3wq(3S4q0N@VrLN| zqQk~B`XpcH$tp;vqe&dB#($be&&Ilei(v6hvh5CFU1W@J?(V%cv1y9l|EM%UXSOCFUMa$H_7M(+7?-V-4RU=HuM*DRWmRo&jWS zz|0Rs6WS!HNeDv;=;-!Unm>)wDiWz9;wYulwxW;6<6VxcT(w-Q#52kL_{et+C85h~jIO%)&{V#DhTY#kBb;kLGnJ4DM!X7}-E?VMoFK z)z3E?HfzN}ZmI6+dbWW*lE|;$+Ou%bA7TptHU4 zzh(eZ3F%VI+Lp9!J)1369($i$YM1tXsw7oxrjr74N#xQDKjwGpNlT?Od#40H&HW+p zv<;+xQSK$EsXyp(#9*~stZ`c9RD?8pTNG%7jYavC(i9H)k~r7GGk?%;esGWpsmp8& znDthvilaoEDRxkntMhrm^>f4)I><4n=al1An7qmz)a`Lf*U#Ozm@d zZc#Cuibl}D0>9|;&#>UVQVNf{C79$mNh$06Awus7@|cCR1NNsSwkzpjT{%=Y*nhw+ zdpP(+ZXPB%*x+8A@o5tDB1A#Zp@L0eD8H)8Tqto(nj2PVmT`vCdz%$ppwq0T&=m{= zj(}0lgrJi&Ti#RMLy1jfb&)V&D=j!a3? zeLY_7NlVd*re168^eK`So{1%0<@OGa(-S&`%A<&=%(-EC?v7?HjcOS2vxW!C-L!CQ zmP0HLo!_Wx)#m}vBClwmgJT&PtMEnzn{w_8YUP3ZZ^m9~#Hk3V0hngv%~HY{@%U0o zom6o+%djCEo@ogPMLZTKB6fOE^X6V@vDo-*%6hLMm2H1M50rP_1_jV{)qhAr7}W0T z8(q~%GL6a{Om(ym;1KJbAjz&&X}qV4v4A$m4t-k7^mDR|eBfSw#0D{e3FbQ&kajk& z4eBP5@bL2cHU>|K8JMd*OorvOWtc^SDGxND*1Lm-dDE=kJC;1tlmrnL_Ue|A+7Kzd zhRRCaG2nzWM8w!pZ*4F=9e_s*#j;MJa|X3s^YO0l(_fin!tg`xaPo(a%AZPaiEjm>jRb(hJS+*GhLloeF3gC@Y%fNp=);$~2i!_vCD{Jk)>etljqRzDN)an5DZ=5nacDW85U;Nk^T zqdc233tj7;LL@?Yn~+~H3;4DQ4>Uq$s0a=AN6!V;mRYho5Y{dKB2o&aPMHHgg`=SI zWnf%?EtNiBzwbDNBD1EfXi|3nGzD)*LHXvDWLB$x+$AOBntc)$qSt1o2ukrqli(@t z_LG1t`;Iz?vo78E2DNQxUWf=<3F$*bHRtandFq?D^uXd zt$MMBQkJ;}BFH9wCV6`82P&BAl5qJ-e?}WM%!Oz>Nf`(=0rXzqsn!D-Yg&jL&00%i zUEb7G%m4Iet|2>z#bx>zImjnU!l%StGZE;X#>_$DoZw%50U~=vP>Xn4IyJsd<=*&B!^VaS8?c#IF>J1>)}0 z^z}?I(2A1iE}VMhj&JpR`+=OW{Ii+vyNxyJXY1b^>#w2 zG!uu%S%Qyodm<V+viL?&ZeuKzE7C=1Wq zwkceRqd3hCP!p|+#J?)-)I_^`A_3|$EBoDK7=eSY0HUSn?YPvRHWbqfSMIt4&>v86 zR7oAS7zNnYa{Ar`VMQ%3!f*eu1BvpZ`urri;1@{dd3?-|AR8l~h)<3zm+{S5ujVL%+TVv3M=tG$M7AUx-2 zmoLsZWTUgeNz5lrDhR=8cW@kF`x>pGSpP+x+`Nn|Q8vBCY&L3KGe}Eah-`Hbre$ea z${CvEuh*!*&pSA*Xwh**TP!y&I6+OV;!5AZYXqC?h!@bGu{XfyZYu$%6um``7d*`w z86h)soAgPMVls#1N$ip0n)&h`@cl%8*_T)zhSRw9=ZRQeI}7?OXw&w4_^QTF;p1!>CI89t(e3vmS>={j{Q>MPCP@K7T|WT27`%!$NgB z<8{&l`3d^vFF*cH} zWD_|SMceq_u!ts4ff-2jGX>Qlzw1+71Z@M%Cz_*_Zb<37%t@8;W|z$xSWFiY^#Pbo zYyM38YUc;v(7Uid=l|vvsy*#l;+|>KiG6(_HUM^5-0e+ImK;R!%<4a!=!`fV97=Rp za~5_Z%;!zjxyL}kApRV@> z;CIIMidXcjtRbp*!8KBRp*!Q>anu4SNd(FgpGLEy1p)~f*()_T(qmUX!(!-TQfT-x zXA$Dc2>M+(d1!Jklk@;QGYzsUd)Cq9Qh;z$7V;8YWS$H=?z>G&0R8${d}ST}^yhg_ zQm#;N;Z85=nK{=P*izb~2I%C_l&nCiczMiX+9xs`yR+MzMwhme*NUn#2JZ`^08yLKu4#&4C4=shc( z*R#rABYfzm+#w{$wXUV;b%YS*WktpZ3!Wx8b=@!$ztyM7YIfs*S;5viQfq zefKiny{YAW<#PcZ~Kc*C_+nuRd2DqU=Um^CJ#kJB`16Y6gI^ksy{IHxCZ0pP!0A5QjB8H} zl@J*O);snYsru58|Fogm{_tTccZ^Ht%z`#n^77cD zqE~gVe9D%9+P@rS@M6egUYKI0OePK)3ag$*w=8eB@0L+0&_ZBpDcel``RV0O2ablI z<^->q(a>rW(wgxY%l;2#3Ks7=Qv+L*33GN4A(@i}&XH^F{M6?6h!le8o0sv|PmKks z^-dHG-G!+9AO0b%33+->suewXMDXL#W9j-*F<0K%^;O|zKj%I_bH17XvggZ>{M}IW z{8wCp`u^mlun^-#|5FDS4(mtrc3w-vBl6Lr&C~hT6|(9ne&q$NUQU4-Mj`3p-|q_r zVPl>#&UlF_#!ZY0hJOt>)}Nt3(!)KYC=?jE^&KZLg72uJ>?4IjBp;oUErmFgo;JP5 znc0jyEBl4+aHf0GE1xj+^hCXoBFa8~<;WxKC?j0?qhllE?^+6erAaC;wvVgd#^N4S z14_6?Q~6#DW7sj)Q;PFXQf)de$^GV&WZ3#;f~}3}iJ~Qo zw^+Q+ID#5#pxp)(#b&=+(4)V_BEtQ&xFVw8za7p^JRwuK+Ks)S{?~8Rg{oAh@9t-u zxA=I_nkvKaO8GM}Eeqw;*6U~cdIs6Y7y9WR;g zy0l;`Bs1$Yy<5JGKGAtrYv;%IM3&^8>^=M*`iDnlN-r{QE-etOzc&Y4PMem!zP&(2 zNHHMf6roJ;#8(ySwc4+;lT22cty$QSg@|&*n*FjW>X+& zk09ZkI5-w{NAyFWG5uCQu|BP1vqN!#td+X_3zJU&LpZN0Lw*`aq3-<$lHOW`4ctLe z4^Jo|Bw+zpgZG~w#L$QbKGytz#qWk0Kt@S|Qr3bV{1=u^QSYyyR5EL}|ip3(L z8Gjn!aanhgO5SnPdVeW8H4&P(a!ja|zW;CdA+vkXMoD1ez5k1P3m>~0k@C-U_BnMb z#jDky)1;A#?jDxGUjyk0o}5-U_am#NSSbRR=eA5>vcIb za{e;KWM@{~%scYMbDH0`h7|3#2N@{Tf6!1wpI&uu{di68iSWuVHA6AiH)Qh>EcPjm z**6v1f3BR1jjQ>(|91p(qd8|3S|ahkh__o+$urJ(I?|B|6w9++7alXA?RsJ@0D~hB zJDvYBb1T8NNuwF_LC0?KZ&<{_U4F&vC4oTRHc{~m@yd=8r%U@nZ?0Mm9R)3u--q|V zOrCHtO^!rm{cmi);5d;mC&c<`P{#AzHY_!eU=;UrIVdswLSx+!8}mmz0~vO&XOe?` z_sh?jXZ!y!5w<>tO|O>pM5HGjqu>(}ISCVAUj0~CZ<$)~^b_gXbATvCjR`EnGG6%9QN&%+Q2?m{M>;zoT_8^WE_VU|0)nK)fl_zH6bOV! z%0Pf%(Yp>1IPs%M=l@ag@^N-Yg#7;%KDG#4+$mUun!=GL4$ruK{e2Mbo-W+T5MLK= zcVDCv01%AcIJr;aXa3;9h~elMY|8{dz(+3OL{7&?r<+YrK*tS@l(uO{{|^&%CO!ZF literal 0 HcmV?d00001 diff --git a/pkgdown/favicon/apple-touch-icon-60x60.png b/pkgdown/favicon/apple-touch-icon-60x60.png new file mode 100644 index 0000000000000000000000000000000000000000..ae046e9842e41d920be7457334ee2f57d0a51049 GIT binary patch literal 2370 zcmV-I3BC4-P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0RM-N%)bBt00(qQO+^Rj0|NjL1(YNXF#rGu=Sf6CR9M5UnOkfW*BQruXJ&Tx z>f3s~ti1*tY%ZlVC@m!fg0a;mQbpCPP*GE-SmQ;F9rA$F|)TKn<#J#C7V z=Ua&kceS3&m){t@MCwTsOEtUp9_#$Z7u-(tVy}sFHQM!F|HpgGXdryk!tH_pv z+W3|IzvyV+Y_nPOA0UzDcB=c*2PZcZ=XZlYi zZk2LV(E_rC>ENzohu-++fvtAi8mfbVN{eIruE4>hef++6K4HaT3B9WAI|q*L-?>2& zYbi;~RO>v{d$07qIe1RY8wGFkVe{|bcf8}PpR=nKJGdAmQrt{*zu$Las-H|LV&UBO z?2*pHU#zQoBBV>?b6lD1dgnjCPv0vbb~Eqa`Eut^o_lH?#$!3S7z8j*-@WeN-T1S8 zI+btno|8X3x&^5useyxP!Udx)oJ?CH*ZIWw<7-!56{a6de+2w3luITBH(mq+6$y|~ zup!XV0D+2vN&`yCg-bjo{0&R`axY59)u5IJWF%yQ$moo)0RtN$Wa>!Jh@ClPnxVie zOVF1YCSd_G0m6)urJ5R2)ZoTWh!FL}k@4VWkT7wgOj%KAl^7(l80It15D9cL2o_Ie z1KmtYtBGleSZ9((0%VAgpav&83eETkp`#Ha%_jV$5%?_V^F;}+Fbh{f7hwhGF+x|$#|<4jdlz2&@OwAch!Ky0IxTA+#~QHwDY1Xzd0FcEXa zg^fg!q$^2mV8aQ39VgM;s4%m;_?%i=u>lG<$pAiDQJLi)$rZ9?La3MyP7u$H1Zkzd zjP*`z=2O8yCWs3KAHITM6|s0BDqb3RgcF4c<`ICPg=Pc+?hr0P9wUJhh@hEsO4(OH ztWt%B3lF125xJw%z=;n5sQ8&CYbsR`WK0=Blsg1a7$gg1iBXLp%H(RqHnvbtmN1`^ z&K&{^N|!nlJB=iXq2Z?qnJI>I=`&4~CN#jH8iN~1#7Gu+D392{O&t;vhUu#1ND*QK z5=n-LQ%evV4cGuTIuCOT%%I^Uf{LFob6D6;f;1WmMnMiPEb9?jYI#TmgCvTX!62w( zm~2jN9tTm@kswks5m&f6&V4pA!&p(_3{eDg2=hRQ<=$w^vQ{ADrwWNdN~0jTrtvUp z#eQJ2s}s zkYOALUMTueR8YC{pUWW=B#4H}gsDoRg(jdGJGV_=7}O9oJ&<9Xbu^(fpO=1l!~zL} zNxZ0J0hN?l<`-+Vj}~Mcw2~r*ii#VbIlC4o5d;bW0!$J$mysdMR%8;~VJ2_4EE4PC znGrTI#Z5fKaj=0&k~HFCnhA6S)#mkqN{|SkFU$W$XRf0a2@g7t%t-o>0VjTD_>9S! z6~y&?_?kA=`J>%U2D2ClT-4J-ErNQoOdxW5QYTD^g{DAdJpz~_fk04=1PH2gi(1@% zW1N4~^@op7SLFf+KmsE=(sR8l~;*&Bxu9|NF%fb^V1ijwB8`VQ7v@gAbLQyqUx}r2q0NUq_`?3<2lj7PWT1^^Aj@qg5P*#;j9mPd zvSTS{6@t_dVZ=NpB{T-p{au$%40V&vpS1!iY47&K9Y^+UZ4!2ZxR}nX#H+XNi$z8N z!^Q_Ux_@)`U3o6MLaN}pDGQ14z}0__q>atB?j&I%c_+{6-R8pLBxdLtJNwo@etDql zR;q9xm)0ZKeR=Qk&VxH#jx}7cCAb#r`rC&mBmXNkxr_k5o*21Uw4W&D>O5rhPX^8ng;T9wug8Lu1%grI;@z{q{`afttJzFB*;W2Yq#-`h zf9=8;qOIQPC~LRG9DU(;-#+)s_yrQ#@`|m0NBj0Yf4t+x?GClXMR}5&iLUc~Z_a$g zYMd1jBcXd*ztw)M{h5s`?l=WHgW2AJo)bgoMcisGSpNNEK-zV^_uTND*5L^c2b09SfcSaechcOY6Cgx@G{a;ABePT> o%h=S&#LUDT#0SfONT5nC0O}VJbn-$ql>h($07*qoM6N<$f@p*}vH$=8 literal 0 HcmV?d00001 diff --git a/pkgdown/favicon/apple-touch-icon-76x76.png b/pkgdown/favicon/apple-touch-icon-76x76.png new file mode 100644 index 0000000000000000000000000000000000000000..5ced8d16d45acfaacf5e929f6156104f07658d68 GIT binary patch literal 2927 zcmV-#3y}1QP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0RM-N%)bBt00(qQO+^Rj0|NjL1`RD=ivR!$6iGxuRA}DCnrm!a#TCbYGkf>_ zw%5;?I0=rM5J=M`r3RWpacn?ps01GXm8wWZrGiEz>EjdqSgBv?Kv5}3Ev-}#(3Ywd zDo`f@lBN*R7*rP$lLVYNj^B>={oZ@~!8e=T^*-%2J(le2xpQa!^Pe;4oH;WF>Lq4l zpP^G7N3C0nbr8Xp>z;k=@*}g|2iaJkCJifZKxD z$GS4HyT949uYbo4(u4{~5`35$eDD2(;Wvo=zkn&mo4>Tb@6H~JGf%N3e%_57dTsb% zW{Avk8(;oZc6UE<@6R6C{zb)vmiI!#LbvJq>pgb|8W+y})PL;rVoadkr-DvIec>1eWSzjKkwce>3)5^LVwy zRSV4PyYH)e`!;V9hGm&{Ns3eI;PAUoExbyoUck(@-km?}-?hVNU6H?$M0h_jc;thD z#4%DU1t#UzEsyWMcbBuF4o*-YnBmyM;a5hU=5%>|C z80FCDvF9d!FQ?Tq^-77;d+*JU_ix=ImAVHEk|e{K!ILMR48BIB7GOs6*R~(%@4eA% zU$rPk668c|@Qwcrq)rrbT%t(H=FNM1@4MC8RHIp_RRn@b-ky8w59glYTv=cewWa-` zTfe`1-TE@lroP}*&T{C?@n229DCV`iH&?~xy1Qq8|BkH&Qxy}al~GTvCc7<(^I>}M zz4r$qZxX*!nvE{Dk^0_ue*Hk_dRYxuRy-xbEe$vJtL;}I8V1(NZJqW#XFh8jzG8jl zmDfA)w(T&xs^Ut;Mw|Y8MGvn&37s!Z|1n{zI8+rc+wHEF)@+G#wL4I&(kll}T>7ZI zm~(2Cl`9lTA2q(S?GG zP6X|AATVIWhOyReY6m80!OtkOXeju|prYUg;*4<~6DAf=QSdR&7_&r(F-u_efhnX| zT+9+dk`&`CAjsq?fPDgr^2D3H|OL6G1wCbMQ>S2QN~H>8PEs7s>Y@2UeU1~ovi&c3xSz*vRgsCLWu zIZ2hk1cnvoUuu)8rqV$>7Q#%_6gA|EmR-Gd1ZJTdH_(WMGdcFWdJ%YN0Os>tlR%Ww z&5FP@TsZaT25bbDF{KT3V*#2O!LOIuXv0Q?$r3)H3dTflm27d)`GN%(G0u2o(9=*higUdx`p)4>Bg?2oQ z;=)3h@$A?H*RU1|G%!*j{gokrM_2xUu2mw(FBDge62K&qG*+&`z-L5|7|3K*Rl`oJ zZfPvE=5eNFJG@#lfr$nbrkT>;g^6JYAV|0%u7(!nH2ojD_M;+TnWkz}=u8QDMs;9-J`di-7}2~ycl6L|0uAxIn_ z>#zbbMw!W}uM#GNm7qSXHB2*yfpkfOu>_cg1xFTQaS_Crq!R-WxmRhQkVuL8iF=b%%YY}X%}HEO&Svb$&%|$W1J+N1ehQIga~6|tqu#oij#1`U?fHo zG~nb@G8OFM5??8ZGfn~(Ka*t)L55kvjOzwd013i*^$VL$k;a3QHl~PGG}A>G)0jZT z&1i*0v!pQGiIB*0mROR}Y@``887>#KTNN1tP)QN5nEw_9zy#s!8cQ;kr(qg4uEmK7 zD^6WeYGw?;P%$3TbjCzp*(Jhsl43%4Jy*qnRe!Q$C%&AiEJ@@N#+G_YjRhR2EG+3b zldY>(6`{zQiVNy!MXgW@;}TecAoFN|MzX5bi!x@#g#l}YO{y%Bgh}EolJ-k6iisov zVl<=brnV+v4!UsxX3ms7E08(fGgs0m7)TYcrePw;c`|6EXn_jQirBF>+z13N+RLh_ zEXtRg4jSmfT~Kbo%RFfor*(>EoMpqMC5(ye>H!O~q}%Y&j*TSKIc7z}%_i(X8!kq2 zIMHxG&W=0;Gyy5J68@!#uZ+;BKgUbD*ao_>0vm90Mz>u8g*H8y0XwaPvRzteCY;w= z5F_0vsLU{4WcXQN0)YfHCb8oI;#lx8PX>X&n6u0!Z91=lMw$p>#*7&Y-khdwS-yR& z!%hN)OIfHA4^9MNCBc;5dl6v6_~$-KHz`)4jNm{J!A>(SCegSC7bzx~Lj#nY={C@U z1(ggjLYOdT-=uU9X4c^ZtaK8>uTQ6Y zBKlUbu)l-_6==SeZ|!=lZ{tSY47f=$S<#V{5)F|9SCVE#8$9*yFX#T4-I`YiOqY!t zAHDs-+k9<$!}Unb3E&b(rr!D8=yTUyI90Y@IZ=!~+Ya>Id6U&ym*kwp&%Yvv{`TJ| zGehMYtR_QZckSuf-@kLKtmag%9H_-pwto+V->jU^sw#D}@^egq##si>9Dio|h5U2L z6#>(0Zr;4N_x@WwwVwPgp5(qW_tpz%pW$rvU)3VZI4jSdeIHD{SIecX+Ou#j?>*Jt zF3@ia44pVw`nEv*fMFrtvG(EH9`0RJ?moui{ffiqk3L)eenlODEs`O(ZrQi{p5ixH z1cF(PE*yE~bj2Gf^#%rDw(Z_|VCkKo+V1eI1~33`)BU&npnvlh^jlJrG#}S=>#3Bi z^tx$0dUE8A)5&m`&*28f`0J&Yo;>+u?N}zc!j|hI2IVW;U;0saU*Lx4<+l191J&;w z#%|q1GWPni4^Il@e-cQUgN8OtBLDyZC3HntbYx+4WjbSWWnpw>05UK#G%YYQEif}w zFfckXH99ahD=;uRFfg9f<`)0}03~!qSaf7zbY(hiZ)9m^c>ppnGBhnPGc7PPR4_0) zF*Q0cHY+eNIxsNriC(J!0038dR9JLUVRs;Ka&Km7Y-J#Hd2nSQX>fF7004NL)zMJpcg70|1zO z(e1{HcMJFqx>``czl8L$k9Q+tBurm}c$a_xKt)=VrN#;Xu$#l6s;0qtju2GVrNHgZ2YYd#F>=xO#!*`x})Mk}2nl*WQwCbWB1 zW@VZmdCNK$&<=A4IU@2kBHi39BQqK@Op~A1kA$TrUS(93HG+9XBt>LN|0ru$@Pc`N z-VCMQ{OtJk{r9RUD}LJozG;f{GERe?@4Kh!gwy4v$gx4iwjnmbxAQ4|7rN~MUq+VT32b75E%sSE3-2hnHiyn6XFYj#)NAMtw_RG0e{rE#n(fomJBi^b zwg<4di-y!kWd&lMLe1c5GKYAE@{ zn$OFRt(A_FuN=g1uc0ry6eqaSJ(Rax@5@>vo9?~mgcGdo-o?Dc-u1Y)+^}9sY|`)oPV+B+|#S$L?qW5 zJ_Ee-_Ax{&7;UjWz4LX#!)gDjHdJ++_9u2Fw5=n3(v;?I2cXG8#cP6%{5xOworfB9 zCEE3HoIELBSsG%Hv&!9koI%olS1o7r9=Sg2!ZsEBxC#;)y<=X( zy_jEq%IRR+nwvR%P8nar-;4FIAA1n}+LIS$XnUrQ`b57QQ(rx$v9gt$W~_5azPS#( zNUdEvYaDsYow-JJ)};J$8P~-Q-_>ddVTg84AB{%b+Sp5a?BE0;96U4|3_<=*D$ny0 zSZs#77}bzWEA-Fa!Mid&SULZD(|*Mp?p~X=KetHLzN}P1p1(>~nNg z0a_vG6@I>t2)5@nqfyoIZuz4N>z&6sI|38x5cR+|YFhX2rLUh=n56r2ahcXx=FoK& zbiDMj`TA|hS&a5Sp6IAp^1#FPyY2#{-3!Y$6v{1duCN`<~8?X zGr{i;3LPkOf3LQNfJfGgb?p=Wt6k-D_Y& zE~XaW|K9Tn;~#eR(c3Iyd6Nn0E$Xfmg-xH=AA;#Ditq7EYO3-M>mJMyQ~sbjBB49| z6Rv~_JM(+?OG6g+g#SoLhFO!Ekz)IOKFARrP~-;!Nq|H?B8?#?r|HN-!FK3dhHxrXvR$lQF1rCJ5#Xp2y9=9 z@G0iz?Rv!b?_si|KhSZd8_pD7P)2IkC;emxU((Z52id zkSA4EhF|wEbZ__Pt2RnwS_A|J_uUBLRx{KhZ@o*T4+3oR*77u|g*G@1OaezA5=axg0;Is_ytZms;H;$-SC;R+B6-_mDb=eaB=Q-xSn#{|#nk8F$uhS9& zGTrUA!)6mNX5!f5^o(bVkZXO>I*HRZa;ghqwPr|3BB==;3Q4_ z6NAdM1o74W+C@^lSU-GLV~o_0fh^jMgNjp1^JMNS+hz1J68Q6W#l5!m6k3r#@<*vp z3XdJG%}bVeis0|*XNL^b{!^B=OCZlLLwsw9<=8EgjDXT7R${i@b@0jjGoLsRXO$J$ zRY92axvc~ga={oi08KB^PISB~py@KP|28JUrGyk(fyWXT8}+;JUinq!{V*iJonQx~ zVLqFxMm+xcL?9S~Fo7Sjp^Z@hJJFC-(K$ViDJ%`3_ugN1W(s0E^&&?7vi3D7IYtjp zcTY`~+XYo3smjVF;=4H^*T7&S!pGy=K>N^LGx^M%nm2JwXEB3D8}7g9Vw8FOW;0!i zQ6I!1Jmj~!fsX;=F>U@y=N_``F@YqOmaaNwQJq>WwnhT+nJB^Rj)Ren^g|76YfVsC zsr?#XISmxG>d61d?S*#Pnv-mlo9fHodv7_2#gS5&*nl3+BGq-#-c+h6%_OL*h1(FR z6Y~!6@zn+^Y?z{kNV0Rt;kK2=4H)o5FNsgIFEwYgLgS5U#_9tCcm`gMRKBHo2wJEX zPF-2%QWORJ^#;$~q>25Jb^x`6h&aXlDqZJY{E7G+3sanZNlcwvk&2t%B&6bRp$RSG%TkNch zu*k6Sj6TWNd9n)9>1Yy!)%Z{I=-F5|xguD6lT158P8S*Do4b2&O>~-~_dhC4P+5|| zpkD=rZOb~9Y}5E6l%Cp7+SJOaL&*24MTxn`({Zv)|MWrQ%vi(sF7t72`INb<6VCuL zHge1lL=xI0s7VMz3FzqdRhmDI(kc?EyTnmSrENtYkH^JQ$Wl6i`xCP~NfrXRtxD;h z89S+!7jg6H&%4LTv>)5!##>{Von4BrSuzVJZ4wUxxfj#sr#zb19Wl6@sbORTy@eeG z`&U2TXxOY32f4vAJd&Qq!R*<-w4jxJVfOJYjzwXvoL20pF_>|D!I6_OJ1=Jza)ZwH z#{ZfDNF}68F>71Ww)JebRC(-ua;aU~_oX{2pfy?DWxeK@+EPqg=hYt-~51(4yns* z3z+p*sfwdSn<;ismaFr5!S!=Q7dps2gZ&%{vY;eidJctizJq?FW0#x?T?D;(8JODV z^4y|gI2Dbcfdzii<)2}}d!-Z}bxSabagtKj`9l}IC&*(K(hk_4me{VOhjryp-C+L# zx9s8I6WMu~#9)JaamJ@f@QV-y0Yn9x!ccxymAPQzniMyz&@AH&rS~=~xIm{_O`$6o z1{#s0#e30KVuE%r*Qr(5D|^N`ZmE5_D=pMh$tYBQ#0bQ9&2(z7ER>OqT#(F(aF^y= z)M4uSN-8-9WZ|A*HV1;sbdm(7(^g6>a^3i}G4b2#jvArej}A$pl#>HY$U15HJVRn)MO4$8aRe@6Dko_xF^ zWR)}{8mi{CDzWD&^sU)aI+2-40qbBKcs%9wyow1tQVEQW4XAq)2*@ed?}MDzkpiSM zGDC;6q+k;>gQpBo>*MJ(0@WlIHMzY3{aD1~OkH(xEF?LL{BNE*Hy_`WvGHgq4mOyl z)`J5h`yhFuqOH`xfZxPL_j%$;%)Y2v=rtGFwfnz`;86AxeV_;K1h|gb_{LFkYmQ7w z(0x5#?MX|~iKbp_?DQ#;5}Ju6UFG%;j?)u7gvz6csLZ)xdF~EoEsbgzv9pE;%H6bZ zY!)Jxht6+Qwd(VLXOUMl2;oph#wxT?!KR%1f?9dt{+qFv8gVN8Y5=C$c(asnMm)Zh zQb$!B&N6JshG$wFLJ^O}35%W{)V#S@S}Zy~o3h?(NM+lf&jaP1w?P4PUG*Q55C*mT z`bJkZl1!sA2U8vF12{x`CrGj@RT}TTX%CT^+fMo)Cab5A zc@#=aj9$9_v~em?A~`P6*;n%w*+3XIvC^X7hB(W)w_~Sh(OhE5hMIV=m^UK=(W*ya zDlW`x#fNfPO%YR^VBeCHSoA}v^68_629x6zSbCxP{aWb=)Tz+d8OikR%P;XLBzN`FQhHOz%bJ4qQBH39No->KFE8*5q!AI(}z zVV&R9RLlSLXRaYThs9<37a`;mCE!zHu9+_Ap2o8UHNiT}8+%^NDXcfB;OS;ydwM9OTH+~`+Wh^VabmZ^D|iOtA4q;U!b{sdGC#e#76 zY5Mxb9pUF9e3>3&f_rMe;J&N_=53be1QXN+TwHD3b5=R8?|yz^G>T)C~N!W{QP_BMvA? zg1L(m1^WOHyfd&?-WG;;kB~EWsyN_Wta+oS&uE-Xn&>45te7GPDPC@~@E)H_JX&v} zz-kT!inI$LFrk^I%$<_2nWcg6;it`Omz?ze9hlPQ%TGDe>CsVO-O$+h^ngHx__I-s z$X#TXv6T4c$W4JKOS<6;?~ay5XbusRIq(*UG6SNBWmWqw14MmP;-5kTiJ;cW{vw7P zznNaV_@Z7u^QVpe7P;B@3vxv5oKyv_!p>0Y72G#;kbezzZ51%R`&zIOLcaFzU^Avc zYu;@Ks>yNQj9cVV&S<%#b%)9ndCw@e*C-`d8b|6~=x6AE4g=<(6;*`1TkSPu1LHYG zJAZM)Asd|xPGUZ3Qb7n#yMyBZ+t+9f#riMmz%f9&XFr3D%KTp{5+DX7?L7TSU!&fza3Lk%q z>>H7kYvwqaK5K5TE275{!bsohn@=l-7|>;70XuI=zD=Cb;O0X5uJzd-4`cB$W&+1E z-VM)_qTlaBESNarQ3Uut#zLLLhf$UGJr@47W<7{T{j{Q>MPGzqpTA2UT2{J8!$NgB z3)To=CL-D5PFWkLHh7HE7p%=u2V{$$c@MR{XptN0Zu1w7h0DgzV7CamuA( zLlTIKf1Pg$d9-4xO^T5gFv=u@08^>`2C;mlG=lLXQmT;SCPLXaW1DAIJz4-N#zxYW zY$AuEXdC|<7LnvBIR+B_OaXPs@A_0{0owrciRLJ!8&di%b5doz*=4f^7SlzS`T)$P zH89h@+UdbJ^e*hr`M-IEYEOHXxM$jQqF*0~4#*)EcYD*5B?eJEv-%GwIwKAThY}HM zPC{;k`Mjw*_ZTP`#9pP9I11Xs=fiZ$*AEoP!~4Fgl&1R4@}xOj4-~OJLN6ZvJ(sI5 z_?@x6;uZZWYl!MyaE&Bi=+5|e95sJR5`nV#r_rov{y;)T_DT(o^w^cpuo(K76dJzF zSr;*77y4Z|d1!Jklhgn_GYzsUbJo%1T;SrUEa)Y$$UGT#+;^Ll0RHu{_{uu`>Cf|= zq+G$^!ku2!GjpypIZG*z8jvHRDOrJ3@$#6(v`=_Ac4xOajV^t!72I37CtLDn9aPnp z3Vyjn-me*NUn#2JZ`^08yLK-92DHj{={+l) z*R#rABYfzm+#x8ywXUV;b>t$#%ZiK-7C23C?7Cqjeyef0eRcPQ6ztS7{OcMEpIPXa z?>X$oZc}WRX>&7;F;>U2jQKd(l0-e5AVXA8JCB*N1WMUxK#JDP{<0~jzYf;Cp`nsc zdYJ5N(CjSN|MPPAdCkQKzEHoh$3=&-??5Pe4Um+{0}bauNM^|G(m{O|R2zfAWC6$I z`tEu7ps(K#OjXyE=T}*l8Dp7(wFEDfZ(RfbE$w~W`4~{v`AO?avOwbd>Q%}0#Xgmd zU8s?c_|k?f55$dHScgt)DC^fi;LI4v)aA;ufJC)C-yzzsT&GNK->HEqL>ST&QeJzu z?9WV#-y@ZN#CM&Z@K-is$YZO+IOqD7?1@uyz@JwfAN_sKn((xSH1&;UGW?Xw> zs07I%u->uHNY$5yz|)3i`@@H++%e9bGY5)ky?Eh+zg)A@QCtd?E@wLEFHdJAmzT#L z6}_r^i%bqVk0=uE; z`LDPH_5I09AwkBA{-+3M4(mtrc3w-vBl6KA&C~hT6*B56e&q$NUXFnoMj`3p-|q_s zVPl>#&UlF`#!ZY0gntb<)}Nt3(!)KYC=?jE^&KWK0`I7z>>~w3Bp#iTErlRTPn+K3 z%xp%UmHk3@IMF@nl~0&@dZJ!P5oI60a^w+qlo77{(V>y?cP#}_X_Cr|?c?gVvA72n z`41E)**|mt%6XmN@}!|>||B8PeW0KM@JU)(FxAt*!HUM_1@lw|3O76 zO(w}H*zo9>>zw$?RnsHv-}Ori+>0o&w8HM){SC#7VRDSsxWWucs!{A*wRn(H*-+C$~dMdXDq`ER7{iF8O8%*L}s0)cgwfYCpyn+?flrD$dJ5~xrg6F|L~|x=|#rPrG*RY@6ExM)23ywZ!b_0 zl1xl-=0B+ZhwL?62ZWDc2W7gZ8~mlMyXI{imp+lP${H!>7@ld$9Rn3EKWI*>NEN#Q zxWbmdJ)hQ}u^^TD`+`FYo#u5Vbbw`2e(p!tLfjda* z;Rz*#BrM=+uwR=zU7rMeDE5$<2HUYAoN z>n~kQc4o!Rydz&cr}=$rNYQS4kby$|2MtB^=~egEkJsd$E?)ViW+>+RhHO59#XiL` z`=&zs&y{nraW!A}|BgUzH0O*$OT_;d@ph{!dB*upM=CObVtKaf!eb`1T~D+HU~uGN zr}JNCZY9t*X*6R#=+G_p4ePRSmtQe^Nx+}CO;kKXyt1Rj>D<21o2ynsM?uTv_u>67 zlP6qElOs`C{~OycI7}qW39^0~l=eKg4NDCq7{&cu4oVEa&{#Lb#{3b>K!)AxndD&K z{ql3>+5SIFgsqQZ)2k&tVW~-nDELG~PQt{OS3lO(Tc#E~{e*k=5D=xPG5%#(#%td) zvwQQd;xCh4@p$3gMs(FjtG=y1invQU@*_3iNGAl+8RF>gd?x^45LikKBzad%K_G~P zGz26sa@PTY+|apy{~rY}A18O0kpI5|OOLqPoq|QEDI95nc*gDP@8ja`>CBA`@pa~Q z_eDAa0Kw>ullvro<_{i>7>b literal 0 HcmV?d00001 diff --git a/pkgdown/favicon/favicon-16x16.png b/pkgdown/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..a940a92dfdc2492934594bb2fe4c71b188635187 GIT binary patch literal 748 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+ueoXe|!I#{Xiaj ziKnkC`wM1f27caI|J#@u7#Jsdx;TbtocHbX_n2HLbIkt!{ol8z<-d(C?qMxk+0l_^%H`Vf^ZDJl?SJd! zwt1d^*!cWm<-GUeyLK=J?TNg1t7fxNt4Ng@pTiW{Z|rjV{_A+psV%?6|1Rrqvhs~X zB~1PvJ2n+OPc6IX&Dk{D=id1{yLayX zs$0_a^JWUO$h&eMOyGP`T--nB$dRU9tCDJ0-4;pGsPYmlwOx9UscBi;(StGn@)>V; zN(()?xFbSmnu_y}CDzutGV79mI!_6#Ve1eU5_&x^NY+YOVTo6>$zPTj#V7I%QY~U^ z23Imabc;2;`^Fk-yzHUy@uSHzEF>>g%qj5Wi?%m9=UDvacjl^kmDT=*7Rydb1}e#1 zoBiI-{`NWxgUG)h>^|w9n0Zh*Q@G$<;qFf#ytPNxs7%;e<)I-sbo1c=IR*73fp>*LSpoZ|Okcg6?#Bzm# zqWrYXoK%I9%7Rpd%z~0+28N0`k3aEn6ozSNobo??#`9?q1G6%>UNX0^vat7L5oTcp zmj;u=Da^{7LljQmxN_pinIkes*iScjEb!7}cqJ}a^2y0`D$oiBPgg&ebxsLQ07(TR Aod5s; literal 0 HcmV?d00001 diff --git a/pkgdown/favicon/favicon-32x32.png b/pkgdown/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..4c98736554d22d197c396e22be4666477c234feb GIT binary patch literal 1333 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 Date: Sat, 2 Mar 2024 19:30:30 -0500 Subject: [PATCH 13/20] update to use SVG strings directly --- R/depict.R | 4 +++- vignettes/depict.Rmd | 48 ++++++++++++++++++-------------------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/R/depict.R b/R/depict.R index 4a43716..b258859 100644 --- a/R/depict.R +++ b/R/depict.R @@ -192,7 +192,9 @@ get_svg_string <- function(molgrid) { stop("get_image requires a Depiction") } - svg_str <- grid$toSvgStr() + # svg_str <- grid$toSvgStr() + svg_str <- .jcall(molgrid, 'S' ,'toSvgStr') + svg_list <- strsplit(svg_str, "\n")[[1]] # return the svg without the two header lines paste(svg_list[3:length(svg_list)], collapse="\n") diff --git a/vignettes/depict.Rmd b/vignettes/depict.Rmd index 1e6ef5b..895b61d 100644 --- a/vignettes/depict.Rmd +++ b/vignettes/depict.Rmd @@ -26,7 +26,7 @@ suppressMessages(library(grid)) A simple wrapper around cdk's excellent depict module. -```{r} +```{r, results='asis'} library(depict) # load a smiles string @@ -36,8 +36,7 @@ pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicill # `depict` applies the styles to the molecule depiction() |> depict(pen) |> - get_image() |> - grid::grid.raster() + get_svg_string() ``` @@ -45,7 +44,7 @@ depiction() |> # Multiple Smiles -```{r} +```{r, results='asis'} # load a few smiles as AtomContainers atmcontainers <- purrr::map( c("CCCC", "CCCCCC", "CCCC1CCC1CC2CCCC2"), @@ -57,17 +56,16 @@ many_containers <- atomcontainer_list_to_jarray(atmcontainers) depiction() |> - set_zoom(10) |> + set_zoom(2) |> depict(many_containers) |> - get_image() |> - grid::grid.raster() + get_svg_string() ``` # Use Colors, SMARTS, Highlighting -```{r } +```{r, results='asis'} # you must supply java colors color <- J("java.awt.Color") @@ -87,35 +85,32 @@ depiction() |> highlight_atoms(atms, color$LIGHT_GRAY) |> highlight_atoms(bnds, color$LIGHT_GRAY) |> highlight_atoms(lactam, color$RED) |> - set_size(400, 400) |> - set_zoom(3) |> + #set_size(400, 400) |> + set_zoom(2) |> outerglow() |> add_title() |> depict(pen) |> - get_image() |> - grid::grid.raster() + get_svg_string() ``` ## SMARTS for highlighting mutiple containers -```{r} +```{r, results='asis'} small_highlight <- match_smarts("C1CCC1", many_containers) depiction() |> highlight_atoms(small_highlight, color$RED) |> - set_size(400, 400) |> - set_zoom(3) |> + set_zoom(2) |> outerglow() |> add_title() |> depict(many_containers) |> - get_image() |> - grid::grid.raster() + get_svg_string() ``` ## Multiple Colors -```{r} +```{r, results='asis'} mol <- parse_smiles(paste("CC(n1c(C)ncc1c1ccnc(n1)Nc1ccc(cc1)S(=O)(=O)C)C", "CMGC:CDC2:6gu3:A:FB8", sep = " " @@ -130,20 +125,18 @@ color <- J("java.awt.Color") depiction() |> highlight_atoms(highlight_imid, color$GREEN) |> highlight_atoms(highlight_2, color$RED) |> - set_size(400, 400) |> - set_zoom(4) |> + #set_size(400, 400) |> + #set_zoom(4) |> outerglow() |> add_title() |> depict(mol) |> - get_image() |> - grid::grid.raster() + get_svg_string() ``` ## A Larger Example - -```{r} +```{r, results='asis'} # laoding a molfile insulinmol <- system.file("molfiles/ChEBI_5931.mol", package = "depict") insulin <- read_mol(insulinmol) @@ -152,13 +145,12 @@ cysteine <- match_smarts("C(=O)C(CS)N", insulin) xlinks <- match_smarts("SS", insulin) depiction() |> - set_size(700, 400) |> - set_zoom(10) |> + # set_size(700, 400) |> + set_zoom(0.7) |> outerglow() |> highlight_atoms(cysteine, color$YELLOW) |> highlight_atoms(xlinks, color$YELLOW) |> depict(insulin) |> - get_image() |> - grid::grid.raster() + get_svg_string() ``` From 110e44b86f9f12a4ab61cbb6723df2baaf49e076 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Sat, 2 Mar 2024 19:37:34 -0500 Subject: [PATCH 14/20] use cat to get cleaner vignette --- R/depict.R | 1 + vignettes/depict.Rmd | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/R/depict.R b/R/depict.R index b258859..435e78e 100644 --- a/R/depict.R +++ b/R/depict.R @@ -196,6 +196,7 @@ get_svg_string <- function(molgrid) { svg_str <- .jcall(molgrid, 'S' ,'toSvgStr') svg_list <- strsplit(svg_str, "\n")[[1]] + # return the svg without the two header lines paste(svg_list[3:length(svg_list)], collapse="\n") } diff --git a/vignettes/depict.Rmd b/vignettes/depict.Rmd index 895b61d..e051265 100644 --- a/vignettes/depict.Rmd +++ b/vignettes/depict.Rmd @@ -35,8 +35,10 @@ pen <- parse_smiles("CC1(C(N2C(S1)C(C2=O)NC(=O)CC3=CC=CC=C3)C(=O)[O-])C penicill # `depiction` is the base class; styles are applied to it # `depict` applies the styles to the molecule depiction() |> + set_zoom(2) |> depict(pen) |> - get_svg_string() + get_svg_string() |> + cat() ``` @@ -58,7 +60,8 @@ many_containers <- atomcontainer_list_to_jarray(atmcontainers) depiction() |> set_zoom(2) |> depict(many_containers) |> - get_svg_string() + get_svg_string() |> + cat() ``` @@ -66,6 +69,7 @@ depiction() |> # Use Colors, SMARTS, Highlighting ```{r, results='asis'} + # you must supply java colors color <- J("java.awt.Color") @@ -85,12 +89,12 @@ depiction() |> highlight_atoms(atms, color$LIGHT_GRAY) |> highlight_atoms(bnds, color$LIGHT_GRAY) |> highlight_atoms(lactam, color$RED) |> - #set_size(400, 400) |> set_zoom(2) |> outerglow() |> add_title() |> depict(pen) |> - get_svg_string() + get_svg_string() |> + cat() ``` @@ -105,7 +109,8 @@ depiction() |> outerglow() |> add_title() |> depict(many_containers) |> - get_svg_string() + get_svg_string() |> + cat() ``` ## Multiple Colors @@ -125,19 +130,20 @@ color <- J("java.awt.Color") depiction() |> highlight_atoms(highlight_imid, color$GREEN) |> highlight_atoms(highlight_2, color$RED) |> - #set_size(400, 400) |> - #set_zoom(4) |> + set_zoom(2) |> outerglow() |> add_title() |> depict(mol) |> - get_svg_string() + get_svg_string() |> + cat() ``` ## A Larger Example ```{r, results='asis'} -# laoding a molfile + +# loading a molfile insulinmol <- system.file("molfiles/ChEBI_5931.mol", package = "depict") insulin <- read_mol(insulinmol) @@ -145,12 +151,12 @@ cysteine <- match_smarts("C(=O)C(CS)N", insulin) xlinks <- match_smarts("SS", insulin) depiction() |> - # set_size(700, 400) |> set_zoom(0.7) |> outerglow() |> highlight_atoms(cysteine, color$YELLOW) |> highlight_atoms(xlinks, color$YELLOW) |> depict(insulin) |> - get_svg_string() + get_svg_string() |> + cat() ``` From 0ce2cf4a3772bbc5bb7060cf9acc9ff3ef4ab3b2 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Mon, 4 Mar 2024 23:00:14 -0500 Subject: [PATCH 15/20] fix imports and update example code --- NAMESPACE | 1 + R/depict.R | 1 + R/utilities.R | 4 ++-- man/atomcontainer_list_to_jarray.Rd | 4 ++-- tests/testthat/test_IO.R | 1 - tests/testthat/test_depiction.R | 14 ++++++++++++++ 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 5f20e7f..2d5c46b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -17,4 +17,5 @@ export(read_mol) export(save_image) export(set_size) export(set_zoom) +import(rJava) importFrom(png,readPNG) diff --git a/R/depict.R b/R/depict.R index 435e78e..2ccb1ad 100644 --- a/R/depict.R +++ b/R/depict.R @@ -3,6 +3,7 @@ #' create the CDK depiction object that can be manipulated #' #' @export +#' @import rJava depiction <- function() { .jnew("org/openscience/cdk/depict/DepictionGenerator") } diff --git a/R/utilities.R b/R/utilities.R index 050a6bf..0178419 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -27,10 +27,10 @@ checkJavaClass <- function(jobj, klass) { #' #' @export #' @examples -#' \dontrun { +#' \dontrun{ #' #' atmcontnrs <- purrr::map( -#' c("CCCCCC", "CCC1CCC1NC", "COCCOCCO") +#' c("CCCCCC", "CCC1CCC1NC", "COCCOCCO"), #' parse_smiles) #' #' atomcontainer_list_to_jarray(atmcontnrs) diff --git a/man/atomcontainer_list_to_jarray.Rd b/man/atomcontainer_list_to_jarray.Rd index cf73bfd..34c7b43 100644 --- a/man/atomcontainer_list_to_jarray.Rd +++ b/man/atomcontainer_list_to_jarray.Rd @@ -16,10 +16,10 @@ a java ArrayList of AtomContainers atomcontainer_list_to_jarray } \examples{ -\dontrun { +\dontrun{ atmcontnrs <- purrr::map( - c("CCCCCC", "CCC1CCC1NC", "COCCOCCO") + c("CCCCCC", "CCC1CCC1NC", "COCCOCCO"), parse_smiles) atomcontainer_list_to_jarray(atmcontnrs) diff --git a/tests/testthat/test_IO.R b/tests/testthat/test_IO.R index f6dabfa..cc3a14a 100644 --- a/tests/testthat/test_IO.R +++ b/tests/testthat/test_IO.R @@ -19,7 +19,6 @@ test_that("we can parse a reaction smiles", { sp <- J("org.openscience.cdk.smiles.SmilesParser") silentchemobject <- J("org.openscience.cdk.silent.SilentChemObjectBuilder") smiles_parser <- new(sp, silentchemobject$getInstance()) - rxn <- smiles_parser$parseReactionSmiles("[CH3:9][CH:8]([CH3:10])[c:7]1[cH:11][cH:12][cH:13][cH:14][cH:15]1.[CH2:3]([CH2:4][C:5](=[O:6])Cl)[CH2:2][Cl:1]>[Al+3].[Cl-].[Cl-].[Cl-].C(Cl)Cl>[CH3:9][CH:8]([CH3:10])[c:7]1[cH:11][cH:12][c:13]([cH:14][cH:15]1)[C:5](=[O:6])[CH2:4][CH2:3][CH2:2][Cl:1] |f:2.3.4.5| Friedel-Crafts acylation [3.10.1]") expect_equal(attr(rxn, "jclass"), "org/openscience/cdk/silent/Reaction") }) diff --git a/tests/testthat/test_depiction.R b/tests/testthat/test_depiction.R index 3a1106a..5ab0481 100644 --- a/tests/testthat/test_depiction.R +++ b/tests/testthat/test_depiction.R @@ -28,3 +28,17 @@ test_that("we can depict a molecule", { img <- get_image(dep) expect_true(inherits(img, "array")) }) + + +test_that("we can depict a moleculeset", { + # + # + # multi_smiles <- "ClC1=NC=2N(C(=C1)N(CC3=CC=CC=C3)CC4=CC=CC=C4)N=CC2C(OCC)=O>C1(=CC(=CC(=N1)C)N)N2C[C@H](CCC2)O.O1CCOCC1.CC1(C2=C(C(=CC=C2)P(C3=CC=CC=C3)C4=CC=CC=C4)OC5=C(C=CC=C15)P(C6=CC=CC=C6)C7=CC=CC=C7)C.C=1C=CC(=CC1)\\C=C\\C(=O)\\C=C\\C2=CC=CC=C2.C=1C=CC(=CC1)\\C=C\\C(=O)\\C=C\\C2=CC=CC=C2.C=1C=CC(=CC1)\\C=C\\C(=O)\\C=C\\C2=CC=CC=C2.[Pd].[Pd].[Cs]OC(=O)O[Cs]>C1(=CC(=CC(=N1)C)NC2=NC=3N(C(=C2)N(CC4=CC=CC=C4)CC5=CC=CC=C5)N=CC3C(OCC)=O)N6C[C@H](CCC6)O>CO.C1CCOC1.O.O[Li]>C1(=CC(=CC(=N1)C)NC2=NC=3N(C(=C2)N(CC4=CC=CC=C4)CC5=CC=CC=C5)N=CC3C(O)=O)N6C[C@H](CCC6)O>CN(C)C(=[N+](C)C)ON1C2=C(C=CC=N2)N=N1.F[P-](F)(F)(F)(F)F.[NH4+].[Cl-].CN(C)C=O.CCN(C(C)C)C(C)C>C1(=CC(=CC(=N1)C)NC2=NC=3N(C(=C2)N(CC4=CC=CC=C4)CC5=CC=CC=C5)N=CC3C(N)=O)N6C[C@H](CCC6)O>>C1(=CC(=CC(=N1)C)NC2=NC=3N(C(=C2)N)N=CC3C(N)=O)N4C[C@H](CCC4)O |f:4.5.6.7.8,16.17,18.19| US20190241576A1" + # + # rxn_set <- smiles_parser$parseReactionSetSmiles(multi_smiles) + # .jclass(rxn_set) + # svg <- depiction() |> depict(rxn_set) + # + # expect_equal(svg, 'svg') + +}) From 552d3a09a346242a14dfeb5faab32fdde5c4dcef Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Mon, 4 Mar 2024 23:02:54 -0500 Subject: [PATCH 16/20] remove rcdk --- DESCRIPTION | 1 - R/depict.R | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 9406c89..a796955 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -11,7 +11,6 @@ License: LGPL LazyData: TRUE Depends: rJava (>= 1.0-11), - rcdk (>= 3.7), rcdklibs (>= 2.8) Imports: png diff --git a/R/depict.R b/R/depict.R index 2ccb1ad..854fab5 100644 --- a/R/depict.R +++ b/R/depict.R @@ -118,7 +118,7 @@ depict <- function(dg, mol) { #' Highlight atoms #' #' @param dg Required. A Depiction Generator -#' @param highlights Required. A list of CDK IChemOjbects, usually atoms or bonds +#' @param atoms Required. A list of CDK IChemOjbects, usually atoms or bonds #' @param color Required. A java.awt.Color #' @export highlight_atoms <- function(dg, atoms, color) { @@ -152,7 +152,6 @@ save_image <- function(molgrid, filepath) { #' #' @param molgrid Required. A MolGridDepiction. Usually obtained from #' the \code{depict} function. -#' @param outfile Required. Filepath to the output #' @importFrom png readPNG #' @export #' From 7c79602898818009d844a132489645b8b3720b1b Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Mon, 4 Mar 2024 23:04:13 -0500 Subject: [PATCH 17/20] update jovs --- man/get_image.Rd | 2 -- man/highlight_atoms.Rd | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/man/get_image.Rd b/man/get_image.Rd index f47c8c7..47bbb9a 100644 --- a/man/get_image.Rd +++ b/man/get_image.Rd @@ -9,8 +9,6 @@ get_image(molgrid) \arguments{ \item{molgrid}{Required. A MolGridDepiction. Usually obtained from the \code{depict} function.} - -\item{outfile}{Required. Filepath to the output} } \description{ get image diff --git a/man/highlight_atoms.Rd b/man/highlight_atoms.Rd index 0c4a5fa..797be71 100644 --- a/man/highlight_atoms.Rd +++ b/man/highlight_atoms.Rd @@ -9,9 +9,9 @@ highlight_atoms(dg, atoms, color) \arguments{ \item{dg}{Required. A Depiction Generator} -\item{color}{Required. A java.awt.Color} +\item{atoms}{Required. A list of CDK IChemOjbects, usually atoms or bonds} -\item{highlights}{Required. A list of CDK IChemOjbects, usually atoms or bonds} +\item{color}{Required. A java.awt.Color} } \description{ Highlight atoms From dd3f3db8539d2503ae069cc5e4ffc404907282d8 Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Mon, 4 Mar 2024 23:14:45 -0500 Subject: [PATCH 18/20] update docs and description --- DESCRIPTION | 6 ++---- NAMESPACE | 1 + R/depict.R | 7 ++++--- man/save_image.Rd | 4 ++-- tests/testthat/test_depiction.R | 5 +---- vignettes/depict.Rmd | 3 +-- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index a796955..0272fc2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,8 +5,7 @@ Version: 0.4.0 Authors@R: c( person('Zachary', 'Charlop-Powers', ,'zach.charlop.powers@gmail.com',role=c('cre'), comment = c(ORCID = "0000-0001-8816-4680"))) -Description: Generate images of molecules using the Depiction API of the 'Chemistry Development Kit'. - CDK's Depict Api +Description: Generate images of molecules using the Depiction API of the 'Chemistry Development Kit'. License: LGPL LazyData: TRUE Depends: @@ -19,7 +18,6 @@ Encoding: UTF-8 URL: https://cdk-r.github.io/depict/ Suggests: knitr, - magrittr, rmarkdown, - testthat, + testthat VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 2d5c46b..41dc045 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -18,4 +18,5 @@ export(save_image) export(set_size) export(set_zoom) import(rJava) +import(rcdklibs) importFrom(png,readPNG) diff --git a/R/depict.R b/R/depict.R index 854fab5..253ddd0 100644 --- a/R/depict.R +++ b/R/depict.R @@ -4,6 +4,7 @@ #' #' @export #' @import rJava +#' @import rcdklibs depiction <- function() { .jnew("org/openscience/cdk/depict/DepictionGenerator") } @@ -130,20 +131,20 @@ highlight_atoms <- function(dg, atoms, color) { #' save_image #' -#' Highlight atoms +#' save image to disk #' #' @param molgrid Required. A MolGridDepiction. Usually obtained from #' the \code{depict} function. #' @param outfile Required. Filepath to the output #' @export -save_image <- function(molgrid, filepath) { +save_image <- function(molgrid, outfile) { if (!checkJavaClass(molgrid, c( "org/openscience/cdk/depict/MolGridDepiction", "org/openscience/cdk/depict/ReactionDepiction" ))) { stop("highlight_atoms requires a Depiction Generator") } - molgrid$writeTo(filepath) + molgrid$writeTo(outfile) } #' get_image diff --git a/man/save_image.Rd b/man/save_image.Rd index 7985bef..200cfaa 100644 --- a/man/save_image.Rd +++ b/man/save_image.Rd @@ -4,7 +4,7 @@ \alias{save_image} \title{save_image} \usage{ -save_image(molgrid, filepath) +save_image(molgrid, outfile) } \arguments{ \item{molgrid}{Required. A MolGridDepiction. Usually obtained from @@ -13,5 +13,5 @@ the \code{depict} function.} \item{outfile}{Required. Filepath to the output} } \description{ -Highlight atoms +save image to disk } diff --git a/tests/testthat/test_depiction.R b/tests/testthat/test_depiction.R index 5ab0481..33ef22f 100644 --- a/tests/testthat/test_depiction.R +++ b/tests/testthat/test_depiction.R @@ -1,8 +1,5 @@ library("testthat") library("depict") -library("magrittr") -library("grid") - context("Test Depiction") @@ -22,7 +19,7 @@ test_that("we can depict a molecule", { expect_true(attr(pen, "jclass") %in% atomcontainerclasses) expect_true(attr(cav, "jclass") %in% atomcontainerclasses) - dep <- depiction() %>% depict(pen) + dep <- depiction() |> depict(pen) expect_equal(attr(dep, "jclass"), "org/openscience/cdk/depict/MolGridDepiction") img <- get_image(dep) diff --git a/vignettes/depict.Rmd b/vignettes/depict.Rmd index e051265..9036879 100644 --- a/vignettes/depict.Rmd +++ b/vignettes/depict.Rmd @@ -17,7 +17,6 @@ knitr::opts_chunk$set( knitr::opts_chunk$set(echo = TRUE) suppressMessages(library(depict)) -suppressMessages(library(grid)) ``` @@ -48,7 +47,7 @@ depiction() |> ```{r, results='asis'} # load a few smiles as AtomContainers -atmcontainers <- purrr::map( +atmcontainers <- lapply( c("CCCC", "CCCCCC", "CCCC1CCC1CC2CCCC2"), parse_smiles ) From b1249f156b8e6e7bc2d7538fa7c73f25e55a51ff Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Mon, 4 Mar 2024 23:19:08 -0500 Subject: [PATCH 19/20] more CRAN compat --- DESCRIPTION | 2 +- R/smarts.R | 4 ++-- man/amino_acids.Rd | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 0272fc2..0acaabd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -3,7 +3,7 @@ Type: Package Title: Draw Beautiful Molecular Structures Version: 0.4.0 Authors@R: c( - person('Zachary', 'Charlop-Powers', ,'zach.charlop.powers@gmail.com',role=c('cre'), + person('Zachary', 'Charlop-Powers', ,'zach.charlop.powers@gmail.com',role=c('cre', 'aut'), comment = c(ORCID = "0000-0001-8816-4680"))) Description: Generate images of molecules using the Depiction API of the 'Chemistry Development Kit'. License: LGPL diff --git a/R/smarts.R b/R/smarts.R index d2da521..1fd74b8 100644 --- a/R/smarts.R +++ b/R/smarts.R @@ -3,8 +3,8 @@ #' return a named list of SMARTS #' patterns for amino_acids #' -#' @seealso \url{http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html} -#' @seealso \url{http://www.daylight.com/dayhtml_tutorials/languages/smarts/index.html} +#' @seealso \url{https://www.daylight.com/dayhtml/doc/theory/theory.smarts.html} +#' @seealso \url{https://www.daylight.com/dayhtml_tutorials/languages/smarts/index.html} #' @export #' #' diff --git a/man/amino_acids.Rd b/man/amino_acids.Rd index 886eddb..a451ee0 100644 --- a/man/amino_acids.Rd +++ b/man/amino_acids.Rd @@ -11,7 +11,7 @@ return a named list of SMARTS patterns for amino_acids } \seealso{ -\url{http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html} +\url{https://www.daylight.com/dayhtml/doc/theory/theory.smarts.html} -\url{http://www.daylight.com/dayhtml_tutorials/languages/smarts/index.html} +\url{https://www.daylight.com/dayhtml_tutorials/languages/smarts/index.html} } From 103bde8495f7b0111b55ab17e3ed6634eec0cffa Mon Sep 17 00:00:00 2001 From: Zachary Charlop-Powers Date: Mon, 4 Mar 2024 23:27:56 -0500 Subject: [PATCH 20/20] update docs --- R/IO.R | 3 ++- R/depict.R | 15 ++++++++++----- R/utilities.R | 1 + man/add_terminal_carbons.Rd | 3 +++ man/add_title.Rd | 3 +++ man/checkJavaClass.Rd | 19 ------------------- man/color_atoms.Rd | 3 +++ man/depict-package.Rd | 23 +++++++++++++++++++++++ man/depict.Rd | 7 ++++--- man/depiction.Rd | 6 ++++++ man/outerglow.Rd | 3 +++ man/parse_smiles.Rd | 3 +++ man/read_mol.Rd | 2 +- man/set_size.Rd | 3 +++ man/set_zoom.Rd | 3 +++ 15 files changed, 68 insertions(+), 29 deletions(-) delete mode 100644 man/checkJavaClass.Rd create mode 100644 man/depict-package.Rd diff --git a/R/IO.R b/R/IO.R index fef301a..9fc3673 100644 --- a/R/IO.R +++ b/R/IO.R @@ -6,6 +6,7 @@ #' @param generatecoords Optional. Default \code{TRUE}. Whether #' to generate coordinates from the smiles #' @param kekulise Optional. Boolean. Default \code{TRUE} +#' @return an IAtomContainer #' @export #' parse_smiles <- function(smi, generatecoords = TRUE, kekulise = TRUE) { @@ -31,7 +32,7 @@ parse_smiles <- function(smi, generatecoords = TRUE, kekulise = TRUE) { #' read_mol #' -#' Read a Molfile and return an AtomContainer +#' Read a Molfile and return an `AtomContainer` #' #' @param molfile Required. A filepath to a MOLfile. #' @return an AtomContainer diff --git a/R/depict.R b/R/depict.R index 253ddd0..24d8f19 100644 --- a/R/depict.R +++ b/R/depict.R @@ -2,9 +2,9 @@ #' #' create the CDK depiction object that can be manipulated #' +#' @return DepictionGenerator +#' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export -#' @import rJava -#' @import rcdklibs depiction <- function() { .jnew("org/openscience/cdk/depict/DepictionGenerator") } @@ -15,6 +15,7 @@ depiction <- function() { #' #' @param dg a CDK DepictionGenerator #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} +#' @return DepictionGenerator #' @export color_atoms <- function(dg) { if (!checkJavaClass(dg, "org/openscience/cdk/depict/DepictionGenerator")) { @@ -26,6 +27,7 @@ color_atoms <- function(dg) { #' outerglow #' #' @param dg a CDK Depiction Generator +#' @return DepictionGenerator #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export outerglow <- function(dg) { @@ -40,6 +42,7 @@ outerglow <- function(dg) { #' @param dg a CDK Depiction Generator #' @param width width (int) #' @param height height (int) +#' @return DepictionGenerator #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export set_size <- function(dg, width, height) { @@ -53,6 +56,7 @@ set_size <- function(dg, width, height) { #' add_title #' #' @param dg a CDK Depiction Generator +#' @return DepictionGenerator #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export add_title <- function(dg) { @@ -66,6 +70,7 @@ add_title <- function(dg) { #' add terminal carbons #' #' @param dg a Depiction Generator +#' @return DepictionGenerator #' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} #' @export add_terminal_carbons <- function(dg) { @@ -85,9 +90,8 @@ add_terminal_carbons <- function(dg) { #' #' @param dg Required. A DepictionGenerator #' @param mol Required. An AtomContainer -#' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} -#' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/AtomContainer.html} -#' +#' @return A Depiction +#' @seealso \url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/Depiction.html} #' @export depict <- function(dg, mol) { if (!checkJavaClass(dg, "org/openscience/cdk/depict/DepictionGenerator")) { @@ -209,6 +213,7 @@ get_svg_string <- function(molgrid) { #' #' @param dg a Depiction Generator #' @param zoom Optional. Default \code{1} +#' @return DepictionGenerator #' @export #' set_zoom <- function(dg, zoom = 1) { diff --git a/R/utilities.R b/R/utilities.R index 0178419..baba40b 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -5,6 +5,7 @@ #' @param jobj Required. A Java Object #' @param klass Required. A string defining a java class #' @return Boolean +#' @noRd checkJavaClass <- function(jobj, klass) { if (is.null(attr(jobj, 'jclass'))) stop("this is not a Java Object") diff --git a/man/add_terminal_carbons.Rd b/man/add_terminal_carbons.Rd index 7a72f2f..b6ebafd 100644 --- a/man/add_terminal_carbons.Rd +++ b/man/add_terminal_carbons.Rd @@ -9,6 +9,9 @@ add_terminal_carbons(dg) \arguments{ \item{dg}{a Depiction Generator} } +\value{ +DepictionGenerator +} \description{ add terminal carbons } diff --git a/man/add_title.Rd b/man/add_title.Rd index 3e4731c..7e3d462 100644 --- a/man/add_title.Rd +++ b/man/add_title.Rd @@ -9,6 +9,9 @@ add_title(dg) \arguments{ \item{dg}{a CDK Depiction Generator} } +\value{ +DepictionGenerator +} \description{ add_title } diff --git a/man/checkJavaClass.Rd b/man/checkJavaClass.Rd deleted file mode 100644 index f1b4028..0000000 --- a/man/checkJavaClass.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utilities.R -\name{checkJavaClass} -\alias{checkJavaClass} -\title{checkJavaClass} -\usage{ -checkJavaClass(jobj, klass) -} -\arguments{ -\item{jobj}{Required. A Java Object} - -\item{klass}{Required. A string defining a java class} -} -\value{ -Boolean -} -\description{ -check if an object is of a specified JavaClass -} diff --git a/man/color_atoms.Rd b/man/color_atoms.Rd index 8514e3c..b74aec0 100644 --- a/man/color_atoms.Rd +++ b/man/color_atoms.Rd @@ -9,6 +9,9 @@ color_atoms(dg) \arguments{ \item{dg}{a CDK DepictionGenerator} } +\value{ +DepictionGenerator +} \description{ set the atom color } diff --git a/man/depict-package.Rd b/man/depict-package.Rd new file mode 100644 index 0000000..49e4e62 --- /dev/null +++ b/man/depict-package.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/depict-package.R +\docType{package} +\name{depict-package} +\alias{depict-package} +\title{depict: Draw Beautiful Molecular Structures} +\description{ +\if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} + +Generate images of molecules using the Depiction API of the 'Chemistry Development Kit'. +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://cdk-r.github.io/depict/} +} + +} +\author{ +\strong{Maintainer}: Zachary Charlop-Powers \email{zach.charlop.powers@gmail.com} (\href{https://orcid.org/0000-0001-8816-4680}{ORCID}) + +} +\keyword{internal} diff --git a/man/depict.Rd b/man/depict.Rd index 63fade9..df43cea 100644 --- a/man/depict.Rd +++ b/man/depict.Rd @@ -11,13 +11,14 @@ depict(dg, mol) \item{mol}{Required. An AtomContainer} } +\value{ +A Depiction +} \description{ Depict a molecule using the depiction generator. Display options are set on the Generator. This function applies those settings to a given molecule or set of molecules. } \seealso{ -\url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} - -\url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/AtomContainer.html} +\url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/Depiction.html} } diff --git a/man/depiction.Rd b/man/depiction.Rd index 6f1fd31..44d3e8e 100644 --- a/man/depiction.Rd +++ b/man/depiction.Rd @@ -6,6 +6,12 @@ \usage{ depiction() } +\value{ +DepictionGenerator +} \description{ create the CDK depiction object that can be manipulated } +\seealso{ +\url{https://cdk.github.io/cdk/latest/docs/api/org/openscience/cdk/depict/DepictionGenerator.html} +} diff --git a/man/outerglow.Rd b/man/outerglow.Rd index f47f1e8..f732ce1 100644 --- a/man/outerglow.Rd +++ b/man/outerglow.Rd @@ -9,6 +9,9 @@ outerglow(dg) \arguments{ \item{dg}{a CDK Depiction Generator} } +\value{ +DepictionGenerator +} \description{ outerglow } diff --git a/man/parse_smiles.Rd b/man/parse_smiles.Rd index 08fb682..c4f2709 100644 --- a/man/parse_smiles.Rd +++ b/man/parse_smiles.Rd @@ -14,6 +14,9 @@ to generate coordinates from the smiles} \item{kekulise}{Optional. Boolean. Default \code{TRUE}} } +\value{ +an IAtomContainer +} \description{ simple smiles parser } diff --git a/man/read_mol.Rd b/man/read_mol.Rd index 153c3d0..0bc25b5 100644 --- a/man/read_mol.Rd +++ b/man/read_mol.Rd @@ -13,5 +13,5 @@ read_mol(molfile) an AtomContainer } \description{ -Read a Molfile and return an AtomContainer +Read a Molfile and return an `AtomContainer` } diff --git a/man/set_size.Rd b/man/set_size.Rd index 59336d1..bdd265d 100644 --- a/man/set_size.Rd +++ b/man/set_size.Rd @@ -13,6 +13,9 @@ set_size(dg, width, height) \item{height}{height (int)} } +\value{ +DepictionGenerator +} \description{ set_size } diff --git a/man/set_zoom.Rd b/man/set_zoom.Rd index 52f4fa1..c1327bb 100644 --- a/man/set_zoom.Rd +++ b/man/set_zoom.Rd @@ -11,6 +11,9 @@ set_zoom(dg, zoom = 1) \item{zoom}{Optional. Default \code{1}} } +\value{ +DepictionGenerator +} \description{ set_zoom }