All Downloads are FREE. Search and download functionalities are using the official Maven repository.

R.commons.R Maven / Gradle / Ivy

################################################################################
#' OpencgaR Common functions
#' 
#' @include AllClasses.R
#' @description This is an S4 class which defines the OpencgaR object
#' @details This S4 class holds the default configuration required by OpencgaR 
#' methods to stablish the connection with the web services. By default it is 
#' configured to query HGVA (http://hgva.opencb.org/). 
#' @slot host a character specifying the host url. Default 
#' "http://bioinfo.hpc.cam.ac.uk/hgva"
#' @slot version a character specifying the API version. Default "v1"
#' @seealso  \url{https://github.com/opencb/opencga/wiki} 
#' and the RESTful API documentation 
#' \url{http://bioinfo.hpc.cam.ac.uk/opencga/webservices/}
#' @export


fetchOpenCGA <- function(object=object, category=NULL, categoryId=NULL, 
                         subcategory=NULL, subcategoryId=NULL, action=NULL, 
                         params=NULL, httpMethod="GET", skip=0,
                         num_threads=NULL, as.queryParam=NULL, batch_size=1000){
    
    # Need to disable scientific notation to avoid errors in the URL
    options(scipen=999)
    
    # Get connection info
    host <- object@host
    version <- object@version
    
    # real_batch_size <- real_batch_size
    
    if(!endsWith(x = host, suffix = "/")){
        host <- paste0(host, "/")
    }
    if (!grepl("webservices/rest", host)){
        host <- paste0(host, "webservices/rest/")
    }
    
    if(!endsWith(x = version, suffix = "/")){
        version <- paste0(version, "/")
    }
    
    # Format category and subcategory
    if(is.null(category)){
        category <- ""
    }else{
        category <- paste0(category, "/", sep="")
    }
    
    if(is.null(subcategory)){
        subcategory <- ""
    }else{
        subcategory <- paste0(subcategory, "/")
    }
    
    # Format IDs
    if(is.null(categoryId)){
        categoryId <- ""
    }else{
        categoryId <- paste0(categoryId, collapse = ",")
        categoryId <- paste0(categoryId, "/")
    }
    
    if(is.null(subcategoryId)){
        subcategoryId <- ""
    }else{
        subcategoryId <- paste0(subcategoryId, collapse = ",")
        subcategoryId <- paste0(subcategoryId, "/")
    }
    
    # Extract limit from params
    if(is.null(params)){
       limit <- 400000
    }else{
        if(is.null(params$limit)){
            limit <- 400000
        }else{
            limit <- params$limit
        }
    }
    
    # Call server
    i <- 1
    real_batch_size <- min(c(batch_size, limit))
    skip <- 0
    num_results <- real_batch_size
    container <- list()
    count <- 0
    
    # Initialise array of RestResponse objects
    restResponseList = list()
    
    if (is.null(params)){
        params <- list()
    }
    
    while((unlist(num_results) == real_batch_size) && count <= limit){
        pathUrl <- paste0(host, version, category, categoryId, subcategory, 
                          subcategoryId, action)
        
        ## send batch size as limit to callrest
        real_batch_size <- min(c(real_batch_size, limit-count))
        # if(real_batch_size == 0){
        #     break()
        # }
        params$limit <- real_batch_size
        
        # check expiration time
        sessionTable <- jsonlite::fromJSON(object@sessionFile)
        sessionTableMatch <- which(sessionTable$host==object@host & 
                                       sessionTable$version == object@version & 
                                       sessionTable$user == object@user)
        if (length(sessionTableMatch) == 0){
            stop("You are not logged into openCGA. Please, log in before launching a query.")
        }else if (length(sessionTableMatch) == 1){
            token <- sessionTable[sessionTableMatch, "token"]
            expirationTime <- sessionTable[sessionTableMatch, "expirationTime"]
        }else{
            stop(paste("There is more than one connection to this host in your rsession file. Please, remove any duplicated entries in", 
                       object@sessionFile))
        }
        timeNow <- Sys.time()
        timeLeft <- as.numeric(difftime(as.POSIXct(expirationTime, format="%Y%m%d%H%M%S"), timeNow, units="mins"))
        if (timeLeft > 0 & timeLeft <= 5){
            print("INFO: Your session will expire in less than 5 minutes.")
            urlNewToken <- paste0(host, version, "users/login")
            resp <- httr::POST(url=urlNewToken, 
                               httr::add_headers(.headers=c("Content-Type"="application/json",
                                                            "Accept"="application/json",
                                                            "Authorisation"="Bearer ")), 
                               body=list(refreshToken=object@refreshToken),
                               encode = "json")
            content <- httr::content(resp, as="text", encoding = "utf-8")
            if (length(jsonlite::fromJSON(content)$responses$results[[1]]$token) > 0){
                token <- jsonlite::fromJSON(content)$responses$results[[1]]$token
                loginInfo <- unlist(strsplit(x=token, split="\\."))[2]
                loginInfojson <- jsonlite::fromJSON(rawToChar(base64enc::base64decode(what=loginInfo)))
                expirationTime <- as.POSIXct(loginInfojson$exp, origin="1970-01-01")
                expirationTime <- as.character(expirationTime, format="%Y%m%d%H%M%S")
                sessionTable[sessionTableMatch, "token"] <- token
                sessionTable[sessionTableMatch, "expirationTime"] <- expirationTime
                write(x = jsonlite::toJSON(sessionTable), file = object@sessionFile)
                print("Your session has been renewed!")
            }else{
                warning(paste0("WARNING: Your token could not be renewed, your session will expire in ", 
                             round(x = timeLeft, digits = 2), " minutes"))
            }
        }else if(timeLeft <= 0){
            stop("ERROR: Your session has expired, please renew your connection.")
        }

        response <- callREST(pathUrl=pathUrl, params=params, 
                             httpMethod=httpMethod, skip=skip, token=token,
                             as.queryParam=as.queryParam, verbose=object@verbose, 
                             sid=object@showToken)
        
        skip <- skip+real_batch_size
        res_list <- parseResponse(resp=response$resp, content=response$content, 
                                  verbose=object@verbose)
        num_results <- res_list$numResults
        restResponseList <- append(x = restResponseList, values = res_list$restResponse)
        
        count <- count + num_results
        if (isTRUE(object@verbose)){
            print(paste("Number of retrieved documents:", count))
        }
        
        if(num_results == limit){
          break()
        }
    }
    
    # Merge RestResponses
    finalRestResponse <- opencgaR::mergeResponses(restResponseList = restResponseList)
    return(finalRestResponse)
}


## all working functions

## Format query params
get_qparams <- function(params){
    paramsVec <- c()
    for(p in seq_along(params)){
        paramsVec <- append(paramsVec, paste0(names(params)[p], "=", params[p]))
    }
    paramsStr <- paste(paramsVec, collapse = "&")
    return(paramsStr)
}

## Make call to server
callREST <- function(pathUrl, params, httpMethod, skip, token, as.queryParam, 
                     verbose, sid=FALSE){
    content <- list()
    session <- paste("Bearer", token)
    skip=paste0("?skip=", as.character(skip))
    
    # Make GET call
    if (httpMethod == "GET"){
        if (!is.null(params)){
            params <- get_qparams(params)
            fullUrl <- paste0(pathUrl, skip, "&", params)
        }else{
            fullUrl <- paste0(pathUrl, skip)
        }
        
        if (sid){
            fullUrl <- paste0(fullUrl, "&sid=", token)
        }
        
        # Encode the URL
        fullUrl <- httr::build_url(httr::parse_url(fullUrl))
        if (isTRUE(verbose)){
            print(paste("URL:", fullUrl))
        }
        resp <- httr::GET(url=fullUrl,
                          httr::add_headers(.headers=c(Accept="application/json", 
                                                    Authorization=session)),
                          httr::timeout(30))
        
    }else if(httpMethod == "POST"){
    # Make POST call
        if (!is.null(as.queryParam)){
            if(class(as.queryParam) == "character"){
                as.queryParam <- unique(c(as.queryParam, "study", "skip", "limit", "include", "exclude"))
            }
        } else {
          as.queryParam = c("skip", "limit", "include", "exclude")
        }
        
        if (!is.null(params)){
            # extract study as query param
            if (any(as.queryParam %in% names(params))){
                queryParams <- get_qparams(params[which(names(params) %in% as.queryParam)])
                bodyParams <- params[-which(names(params) %in% as.queryParam)]
            }else{
                bodyParams <- params
                queryParams <- ""
            }
        }
        
        if (is.null(params) | queryParams == ""){
            fullUrl <- paste0(pathUrl, skip)
        }else{
            fullUrl <- paste0(pathUrl, skip, "&", queryParams)
        }
        
        if (sid){
            fullUrl <- paste0(fullUrl, "&sid=", token)
        }
        
        # Encode the URL
        fullUrl <- httr::build_url(httr::parse_url(fullUrl))
        if (isTRUE(verbose)){
            print(paste("URL:",fullUrl))
        }
        if (exists("bodyParams")){
            resp <- httr::POST(url=fullUrl, 
                               body=bodyParams,
                               httr::add_headers(.headers=c(Authorization=session)), 
                               encode = "json")
        }else{
            resp <- httr::POST(url=fullUrl, 
                               httr::add_headers(.headers=c(Authorization=session)), 
                               encode = "json")
        }
    }
    
    content <- httr::content(resp, as="text", encoding = "utf-8")
    return(list(resp=resp, content=content))
}

## A function to parse the json data into R dataframes
parseResponse <- function(resp, content, verbose){
    js <- jsonlite::fromJSON(content)
    if (resp$status_code == 200){
        if (!("warning" %in% js[[1]]) || js[[1]]$warning == ""){
            if (isTRUE(verbose)){
                print("Query successful!")
            }
        }else{
            print("Query successful with warnings.")
            print(paste("WARNING:", js[[1]]$warning))
        }
    }else{
        print("Query unsuccessful.")
        print(paste("Category:", httr::http_status(resp)$category))
        print(paste("Reason:", httr::http_status(resp)$reason))
        if (js[[1]]$warning != ""){
            print(paste("WARNING:", js[[1]]$warning))
            print()
        }
        if (js[[1]]$error != ""){
            stop(paste("ERROR:", js[[1]]$error))
        }
    }
    
    #responsesJSON <- jsonlite::toJSON(js$responses)
    myRestResponse = new("RestResponse",
                         apiVersion = js$apiVersion,
                         time = js$time,
                         events = js$events,
                         params = js$params,
                         responses = list(
                             time = js$responses$time,
                             events = js$responses$events,
                             numResults = js$responses$numResults,
                             resultType = js$responses$resultType,
                             numTotalResults = js$responses$numTotalResults,
                             numMatches = js$responses$numMatches,
                             numInserted = js$responses$numInserted,
                             numUpdated = js$responses$numUpdated,
                             numDeleted = js$responses$numDeleted,
                             attributes = js$responses$attributes,
                             results = js$responses$results))
    
    return(list(restResponse = myRestResponse, 
                numResults = js$responses$numResults))
}
###############################################




© 2015 - 2025 Weber Informatics LLC | Privacy Policy