Commit df23bc82 authored by Marek Ostaszewski's avatar Marek Ostaszewski
Browse files

gitlab package build

parent 860c44da
Pipeline #58163 failed with stage
in 1 second
^minervar\.Rproj$
^\.Rproj\.user$
^LICENSE\.md$
^data-raw$
^\.gitlab-ci\.yml$
.Rproj.user
image: $CI_registry/r3/docker/r-ggplot2
test:
script:
- R -e 'install.packages(c("httr", "jsonlite", "testthat"))'
- R CMD build . --no-build-vignettes --no-manual
- R CMD check *tar.gz --no-build-vignettes --no-manual
Package: minervar
Title: Convenience functions for accessing the MINERVA Platform
Version: 0.8
Authors@R:
person("Marek", "Ostaszewski", , "marek.ostaszewski@uni.lu", role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-1473-370X"))
Description: The MINERVA Platform has an elaborate API. This package is for easier communication with the MINERVA instances, accessing information on elements, interactions, annotations and metadata of related projects.
License: GPL (>= 3)
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.0
Imports:
httr,
jsonlite,
utils
Suggests:
testthat (>= 3.0.0)
Config/testthat/edition: 3
Depends:
R (>= 2.10)
LazyData: true
This diff is collapsed.
# Generated by roxygen2: do not edit by hand
export(get_annotation)
export(get_bioentity_pathway_groupings)
export(get_components_annotations)
export(get_default_project)
export(get_map_components)
export(mnet_gather_projects)
export(mnet_get_projects)
#' Parameters of a test MINERVA instance
#'
#' @format A list with the following variables:
#' - *address*: the address of the minerva instance
#' - *project_id*: id of a simple, example project
"example_instance"
#' Example map
#'
#' @format A list with the following components:
#' - *models*: a data frame of model information
#' - *elements*: a data frame of elements
#' - *reactions*: a data frame of reactions
"example_map_components"
#' References of an element in a diagram of a test MINERVA instance
#'
#' @format A list with the following variables:
#' - *link*: a link to a given reference in the source database
#' - *type*: a type of the resource (internal to the MINERVA Platform)
#' - *resource*: a stable identifier of a given resource
#' - *id*: internal MINERVA identifier of this reference
#' - *annotatorClassName*: if annotated externally - by which annotator
"example_references"
# get_annotation.R
#' Function that gets the components of a given map/project on the MINERVA Platform.
#'
#' @param references (`tbl`) a data frame containing references (annotations) of an element or a reaction
#' @param selected_type (`character`) the type of annotation to retrieve
#'
#' @return (`tbl`) a data frame with references (annotations) having the selected type
#' @examples
#'
#' get_annotation(example_references, "UNIPROT")
#'
#' @export
get_annotation <- function(references, selected_type) {
if(length(references) == 0) { return(NA) }
with(data.frame(references), resource[type == selected_type])
}
## get_bioentity_pathway_groupings.R
#' Function retrieving element aliases associated with pathways of all models in the project
#' Caution! Pathways are treated by name, multiple pathway entries with the same name will be pooled together
#'
#' @param components (`list`) a list of components grom the `get_map_components` or
#' @param map_api (`character`) the address of the MINERVA I=instance to call `get_map_components`
#' @param project_id (`character`) the project id at the MINERVA I=instance to call `get_map_components`
#'
#' @return (`list`) a list of data frames with annotations for all components having this given type
#' @examples
#'
#' get_bioentity_pathway_groupings(example_map_components)
#'
#' @export
get_bioentity_pathway_groupings <- function(components = NULL, map_api = NULL, project_id = NULL) {
### Either run it for an existing "components" object or
if(is.null(components)) {
### Retrieve the components based on the API address and (optionally) a project ID
if(is.null(map_api)) {
message("Provide either map components or map API address with (optionally) a project ID")
return(NULL)
}
components <- get_map_components(map_api, project_id = NULL, e_columns = "id,name,type,bounds")
}
### A helper function to define if a given bioentity contains (covers) entirely
### all bioentities in the given "bounds" table, as an argument we provide
### its position in the "bounds" table; this way we use logical vectors, which is faster
global_bounds_contain <- function(position, bounds) {
bounds$x[position] <= bounds$x & bounds$y[position] <= bounds$y &
bounds$x[position]+bounds$width[position] >= bounds$x+bounds$width &
bounds$y[position]+bounds$height[position] >= bounds$y+bounds$height
}
ret <- list()
for(m in 1:length(components$map_elements)) {
pathways <- with(components$map_elements[[m]], name[type == "Pathway"])
message("In model ",components$models$name[m])
### Unique pathway groupings for this model
ups_per_model <- list()
message("Grouping for ", length(pathways), " pathways into ", length(unique(pathways)), " unique groups")
for(unique_pathway in unique(pathways)) {
### Handling multiple instances (multipe pathways with the same name)
### The list will contain one vector of MINERVA ids per instance, named after each pathway instance MINERVA id
this_up <- list()
for(pathway_instance in with(components$map_elements[[m]],
which(type == "Pathway" & name == unique_pathway))) {
pi_contains <- global_bounds_contain(pathway_instance, components$map_elements[[m]]$bounds)
this_up[[length(this_up) + 1]] <- components$map_elements[[m]]$id[pi_contains]
}
### Name and push the outcomes
names(this_up) <- with(components$map_elements[[m]],
id[type == "Pathway" & name == unique_pathway])
ups_per_model[[length(ups_per_model) + 1]] <- this_up
}
names(ups_per_model) <- unique(pathways)
ret[[length(ret) + 1]] <- ups_per_model
}
return(ret)
}
## get_components_annotations.R
#' Function retrieving element identifiers from a given MINERVA elements.
#'
#' @param components (`list`) a list of components
#' @param annotation_type (`character`) the type of annotation to retrieve
#'
#' @return (`list`) a list of data frames with annotations for all components having this given type
#' @examples
#'
#' get_components_annotations(example_map_components, "UNIPROT")
#'
#' @export
get_components_annotations <- function(components, annotation_type) {
### Get MINERVA references as a named list
message(paste0("Retrieving ", annotation_type, " identifiers for this MINERVA collection"))
### Apply get_annotation function
mnv_refs <- sapply(components$map_elements, function(x) sapply(x$references, get_annotation, annotation_type) )
names(mnv_refs) <- components$models$name
return(mnv_refs)
}
# get_default_project.R
#' Function which gets the id of the default project for a given instance of the MINERVA platform
#'
#' @param map_api (`character`) the address of the MINERVA Platform instance
#'
#' @return (`character`) default project id for this MINERVA instance
#'
#' @export
#'
get_default_project <- function(map_api) {
cfg <- jsonlite::fromJSON(ask_GET(paste0(map_api, "configuration/")))
return(cfg$options[cfg$options$type == "DEFAULT_MAP","value"])
}
# get_map_components.R
#' Function that gets the components of a given map/project on the MINERVA Platform.
#'
#' @param map_api (`character`) The address of the MINERVA Platform to query
#' @param project_id (`character`) the id of the project to query; if NULL the default project will be queried
#' @param e_columns (`character`) a concatenated list of element parameters
#' @param r_columns (`character`) a concatenated list of reaction parameters
#'
#' @return (`list`) a list containing 1) information about all the diagrams in the proejct, 2) elements and 3) reactions in the project
#'
#' @examples
#'
#' get_map_components("https://minerva-dev.lcsb.uni.lu/minerva/api/")
#' get_map_components("https://minerva-dev.lcsb.uni.lu/minerva/api/",
#' project_id = "minervar_example",
#' e_columns = "id,name,type,bounds")
#'
#' @export
get_map_components <- function(map_api, project_id = NULL,
e_columns = "",
r_columns = "") {
if(is.null(project_id)) {
### If project id not given, get configuration of the map, to obtain the latest (default) version
project_id <- get_default_project(map_api)
}
### The address of the latest (default) build
mnv_base <- paste0(map_api, "projects/",project_id,"/")
message(paste0("Asking for diagrams in: ", mnv_base, "models/"))
### Get diagrams
models <- jsonlite::fromJSON(ask_GET(paste0(mnv_base, "models/")))
if(e_columns != "") { e_columns <- paste0("?columns=", e_columns) }
if(r_columns != "") { r_columns <- paste0("?columns=", r_columns) }
### Get elements of the chosen diagram
model_elements <- lapply(models$idObject,
function(x)
jsonlite::fromJSON(ask_GET(paste0(mnv_base,"models/",x,"/","bioEntities/elements/",e_columns)),
flatten = F))
names(model_elements) <- models$idObject
### Request for reactions the chosen diagram
model_reactions <- lapply(models$idObject,
function(x)
jsonlite::fromJSON(ask_GET(paste0(mnv_base,"models/",x,"/","bioEntities/reactions/",r_columns)),
flatten = F))
names(model_reactions) <- models$idObject
### Pack all into a list and return
return(list(models = models, map_elements = model_elements, map_reactions = model_reactions))
}
#' @keywords internal
"_PACKAGE"
## usethis namespace: start
## usethis namespace: end
NULL
## mnet_gather_projects.R
#' Retrieves project information across MINERVA-Net machines
#'
#' @param disease (`character`) MeSH id of a disease to filter by, can be a character vector
#' @param organism (`character`) Taxonomy ID of an organism to filter by, can be a character vector
#'
#' @return (`tbl`) a data frame with all projects matching the query
#' @examples
#'
#' mnet_gather_projects(disease = "D010300")
#'
#' @export
mnet_gather_projects <- function(disease = NULL, organism = NULL) {
this_page <- 0
resp <- jsonlite::fromJSON(ask_GET(paste0("https://minerva-net.lcsb.uni.lu/api/machines/?page=",this_page,"&size=50")))
mnet_ids <- with(resp$pageContent, id[status == "OK"])
while(!resp$isLastPage) {
this_page <- this_page + 1
resp <- jsonlite::fromJSON(ask_GET(paste0("https://minerva-net.lcsb.uni.lu/api/machines/?page=",this_page,"&size=50")))
mnet_ids <- c(mnet_ids, with(resp$pageContent, id[status == "OK"]))
}
all_projects <- do.call(rbind, lapply(mnet_ids, mnet_get_projects, disease, organism))
return(all_projects)
}
## mnet_get_projects.R
#' Retrieves all project information for a given MINERVA-Net id
#'
#' @param mnet_id (`character`) a MINERVA-Net id
#' @param disease (`character`) MeSH id of a disease to filter by, can be a character vector
#' @param organism (`character`) Taxonomy ID of an organism to filter by, can be a character vector
#'
#' @return (`tbl`) a data frame with all projects registered for this given id
#' @examples
#'
#' mnet_get_projects("1749")
#'
#' @export
mnet_get_projects <- function(mnet_id, disease = NULL, organism = NULL) {
### The results are paginated, going in a `while` loop
this_page <- 0
resp <- jsonlite::fromJSON(ask_GET(paste0("https://minerva-net.lcsb.uni.lu/api/machines/",mnet_id,"/projects/?page=",this_page,"&size=50")))
### Un-nesting a data.frame, to avoid downstream issues with 'rbind'
projects <- do.call(data.frame, resp$pageContent)
while(!resp$isLastPage) {
this_page <- this_page + 1
resp <- jsonlite::fromJSON(ask_GET(paste0("https://minerva-net.lcsb.uni.lu/api/machines/?page=",this_page,"&size=50")))
projects <- rbind(projects, do.call(data.frame, resp$pageContent))
}
if(!is.null(disease)) {
projects <- projects[projects$disease %in% disease,]
}
if(!is.null(organism)) {
projects <- projects[projects$organism %in% organism,]
}
return(projects)
}
### Login to an instance of MINERVA Platform
# curl -X POST -c - --data "login=anonymous&password=" https://minerva-dev.lcsb.uni.lu/minerva/api/doLogin
login <- function(furl, login = NULL, password = NULL, verbose = F) {
logstring <- "login=anonymous&password="
if(!is.null(login)) {
logstring <- paste0("login=", login, "&password=", password)
}
auth <- httr::POST(url = paste0(furl, "doLogin"),
httr::add_headers('Content-Type' = "application/x-www-form-urlencoded"),
body = logstring,
httr::config(verbose = verbose))
return(httr::cookies(auth)$value[1])
}
### A convenience function to handle API GET queries that may require a token
ask_GET <- function(fask_url, token = "", verbose = F, encoding = "UTF-8", ctype ="application/json") {
if(verbose) {
message(utils::URLencode(fask_url))
}
resp <- httr::GET(url = fask_url,
httr::add_headers('Content-Type' = ctype),
httr::set_cookies(MINERVA_AUTH_TOKEN = token),
httr::config(verbose = verbose))
if(httr::status_code(resp) == 200) {
### when the content is sent as a zip file, it needs to be handled differently,
### i.e. saved to a tmp file and unzipped
if(httr::headers(resp)$`content-type` == "application/zip") {
tmp <- tempfile()
tmpc <- file(tmp, "wb")
writeBin(httr::content(resp, as = "raw"), con = tmpc)
close(tmpc)
unzipped <- utils::unzip(tmp)
file.remove(tmp)
return(unzipped)
} else {
return(httr::content(resp, as = "text", encoding = encoding))
}
} else {
message("API call error:")
message(resp)
}
return(NULL)
}
### A convenience function to handle API POST queries that require a token
# curl -X POST --data "content=name%09color%0ACAPN1%09%2300FF00%0APARK7%09%23AC0000&description=test%20description&filename=test.txt&name=test%20name&googleLicenseConsent=true" \
# --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" \
# "https://minerva-dev.lcsb.uni.lu/minerva/api/projects/PD_150625_3/overlays/"
ask_POST <- function(fask_url, token, body, verbose = F) {
httr::POST(url = fask_url,
httr::add_headers('Content-Type' = "application/x-www-form-urlencoded"),
httr::set_cookies(MINERVA_AUTH_TOKEN = token),
body = utils::URLencode(body),
httr::config(verbose = verbose))
}
### A convenience function to handle API DELETE queries that require a token
# curl -X DELETE --cookie "MINERVA_AUTH_TOKEN=xxxxxxxx" \
# "https://minerva-dev.lcsb.uni.lu/minerva/api/projects/PD_150625_3/overlays/505/"
ask_DELETE <- function(fask_url, token, verbose = F) {
resp <- httr::DELETE(url = fask_url,
httr::add_headers('Content-Type' = "application/x-www-form-urlencoded"),
httr::set_cookies(MINERVA_AUTH_TOKEN = token),
httr::config(verbose = verbose))
}
### A convenience function to handle API PATCH queries that require a token
ask_PATCH <- function(fask_url, token, body, verbose = F) {
httr::PATCH(url = fask_url,
httr::set_cookies(MINERVA_AUTH_TOKEN = token),
body = body,
encode = "raw",
httr::config(verbose = verbose))
}
......@@ -15,7 +15,7 @@ login <- function(furl, login = NULL, password = NULL, verbose = F) {
if(!is.null(login)) {
logstring <- paste0("login=", login, "&password=", password)
}
auth <- httr::POST(url = paste0(base_url, "doLogin"),
auth <- httr::POST(url = paste0(base_url, "doLogin"),
httr::add_headers('Content-Type' = "application/x-www-form-urlencoded"),
body = logstring,
httr::config(verbose = verbose))
......@@ -23,12 +23,12 @@ login <- function(furl, login = NULL, password = NULL, verbose = F) {
}
### A convenience function to handle API GET queries that may require a token
ask_GET <- function(fask_url, token = "", verbose = F, encoding = "UTF-8") {
ask_GET <- function(fask_url, token = "", verbose = F, encoding = "UTF-8", ctype ="application/json") {
if(verbose) {
message(URLencode(fask_url))
}
resp <- httr::GET(url = fask_url,
httr::add_headers('Content-Type' = "application/x-www-form-urlencoded"),
httr::add_headers('Content-Type' = ctype),
httr::set_cookies(MINERVA_AUTH_TOKEN = token),
httr::config(verbose = verbose))
if(httr::status_code(resp) == 200) {
......@@ -43,7 +43,7 @@ ask_GET <- function(fask_url, token = "", verbose = F, encoding = "UTF-8") {
file.remove(tmp)
return(unzipped)
} else {
return(httr::content(resp, as = "text", encoding = encoding))
return(httr::content(resp, as = "text", encoding = encoding))
}
} else {
message("API call error:")
......@@ -90,26 +90,26 @@ get_default_project <- function(map_api) {
}
### Get the components of a given map/project on the MINERVA Platform
get_map_components <- function(map_api, project_id = NULL,
get_map_components <- function(map_api, project_id = NULL,
e_columns = "",
r_columns = "") {
if(is.null(project_id)) {
### If project id not given, get configuration of the map, to obtain the latest (default) version
project_id <- get_default_project(map_api)
}
### The address of the latest (default) build
### The address of the latest (default) build
mnv_base <- paste0(map_api, "projects/",project_id,"/")
message(paste0("Asking for diagrams in: ", mnv_base, "models/"))
### Get diagrams
models <- fromJSON(ask_GET(paste0(mnv_base, "models/")))
if(e_columns != "") { e_columns <- paste0("?columns=", e_columns) }
if(r_columns != "") { r_columns <- paste0("?columns=", r_columns) }
### Get elements of the chosen diagram
model_elements <- lapply(models$idObject,
model_elements <- lapply(models$idObject,
function(x)
fromJSON(ask_GET(paste0(mnv_base,"models/",x,"/","bioEntities/elements/",e_columns)),
flatten = F))
......@@ -157,7 +157,7 @@ get_bioentity_pathway_groupings <- function(components = NULL, map_api = NULL, p
### its position in the "bounds" table; this way we use logical vectors, which is faster
global_bounds_contain <- function(position, bounds) {
bounds$x[position] <= bounds$x & bounds$y[position] <= bounds$y &
bounds$x[position]+bounds$width[position] >= bounds$x+bounds$width &
bounds$x[position]+bounds$width[position] >= bounds$x+bounds$width &
bounds$y[position]+bounds$height[position] >= bounds$y+bounds$height
}
ret <- list()
......@@ -171,13 +171,13 @@ get_bioentity_pathway_groupings <- function(components = NULL, map_api = NULL, p
### Handling multiple instances (multipe pathways with the same name)
### The list will contain one vector of MINERVA ids per instance, named after each pathway instance MINERVA id
this_up <- list()
for(pathway_instance in with(components$map_elements[[m]],
for(pathway_instance in with(components$map_elements[[m]],
which(type == "Pathway" & name == unique_pathway))) {
pi_contains <- global_bounds_contain(pathway_instance, components$map_elements[[m]]$bounds)
this_up[[length(this_up) + 1]] <- components$map_elements[[m]]$id[pi_contains]
}
### Name and push the outcomes
names(this_up) <- with(components$map_elements[[m]],
names(this_up) <- with(components$map_elements[[m]],
id[type == "Pathway" & name == unique_pathway])
ups_per_model[[length(ups_per_model) + 1]] <- this_up
}
......@@ -186,5 +186,3 @@ get_bioentity_pathway_groupings <- function(components = NULL, map_api = NULL, p
}
return(ret)
}
install.packages("usethis")
install.packages("roxygen2")
### Set up all necessary files
usethis::create_package("~/Work/Projects/Minerva/minervar/")
### Edit description
usethis:::edit_file("DESCRIPTION")
### Set up docs
usethis::use_package_doc()
usethis::use_roxygen_md()
### Set up licensing
usethis::use_gpl3_license()
### Set up dependencies
usethis::use_package("utils")
usethis::use_package("dplyr")
usethis::use_package("httr")
usethis::use_package("jsonlite")
### Creating functions
usethis::use_r("get_default_project")
### Set up raw dataset
usethis::use_data_raw()
### Run tests
usethis::use_testthat()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment