Skip to content

Commit acf7cb1

Browse files
authored
Merge pull request #661 from datashield/refactor/perf-batch-2
Refactor/perf batch 2
2 parents b1653ca + 2da6e87 commit acf7cb1

139 files changed

Lines changed: 1645 additions & 1439 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
^\.circleci$
2424
^\.circleci/config\.yml$
2525
^\.github$
26+
^man-roxygen$

DESCRIPTION

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Description: Base 'DataSHIELD' functions for the client side. 'DataSHIELD' is a
55
you to do non-disclosive federated analysis on sensitive data. 'DataSHIELD' analytic functions have
66
been designed to only share non disclosive summary statistics, with built in automated output
77
checking based on statistical disclosure control. With data sites setting the threshold values for
8-
the automated output checks. For more details, see citation("dsBaseClient").
8+
the automated output checks. For more details, see citation('dsBaseClient').
99
Authors@R: c(person(given = "Paul",
1010
family = "Burton",
1111
role = c("aut"),
@@ -56,12 +56,18 @@ Authors@R: c(person(given = "Paul",
5656
family = "Wheater",
5757
role = c("aut", "cre"),
5858
email = "stuart.wheater@arjuna.com",
59-
comment = c(ORCID = "0009-0003-2419-1964")))
59+
comment = c(ORCID = "0009-0003-2419-1964")),
60+
person(given = "Tim",
61+
family = "Cadman",
62+
role = c("aut"),
63+
comment = c(ORCID = "0000-0002-7682-5645",
64+
affiliation = "Genomics Coordination Centre, UMCG, Netherlands")))
6065
License: GPL-3
6166
Depends:
6267
R (>= 4.0.0),
6368
DSI (>= 1.7.1)
6469
Imports:
70+
cli,
6571
fields,
6672
metafor,
6773
meta,
@@ -81,6 +87,6 @@ Suggests:
8187
DSOpal,
8288
DSMolgenisArmadillo,
8389
DSLite
84-
RoxygenNote: 7.3.3
90+
RoxygenNote: 8.0.0
8591
Encoding: UTF-8
8692
Language: en-GB

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ export(ds.var)
119119
export(ds.vectorCalc)
120120
import(DSI)
121121
import(data.table)
122+
importFrom(DSI,datashield.connections_find)
123+
importFrom(cli,cli_abort)
122124
importFrom(stats,as.formula)
123125
importFrom(stats,na.omit)
124126
importFrom(stats,ts)

R/checkClass.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
checkClass <- function(datasources=NULL, obj=NULL){
1414
# check the class of the input object
1515
cally <- call("classDS", obj)
16-
classesBy <- DSI::datashield.aggregate(datasources, cally, async = FALSE)
16+
classesBy <- DSI::datashield.aggregate(datasources, cally)
1717
classes <- unique(unlist(classesBy))
1818
for (n in names(classesBy)) {
1919
if (!all(classes == classesBy[[n]])) {

R/ds.abs.R

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#' the input numeric or integer vector specified in the argument \code{x}. The created vectors
1818
#' are stored in the servers.
1919
#' @author Demetris Avraam for DataSHIELD Development Team
20+
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
2021
#' @export
2122
#' @examples
2223
#' \dontrun{
@@ -72,41 +73,17 @@
7273
#'
7374
ds.abs <- function(x=NULL, newobj=NULL, datasources=NULL){
7475

75-
# look for DS connections
76-
if(is.null(datasources)){
77-
datasources <- datashield.connections_find()
78-
}
79-
80-
# ensure datasources is a list of DSConnection-class
81-
if(!(is.list(datasources) && all(unlist(lapply(datasources, function(d) {methods::is(d,"DSConnection")}))))){
82-
stop("The 'datasources' were expected to be a list of DSConnection-class objects", call.=FALSE)
83-
}
76+
datasources <- .set_datasources(datasources)
8477

8578
if(is.null(x)){
8679
stop("Please provide the name of the input object!", call.=FALSE)
8780
}
8881

89-
# check if the input object is defined in all the studies
90-
isDefined(datasources, x)
91-
92-
# call the internal function that checks the input object is of the same class in all studies.
93-
typ <- checkClass(datasources, x)
94-
95-
# call the internal function that checks the input object(s) is(are) of the same class in all studies.
96-
if(!('numeric' %in% typ) && !('integer' %in% typ)){
97-
stop("Only objects of type 'numeric' or 'integer' are allowed.", call.=FALSE)
98-
}
99-
100-
# create a name by default if the user did not provide a name for the new variable
10182
if(is.null(newobj)){
10283
newobj <- "abs.newobj"
10384
}
10485

105-
# call the server side function that does the operation
10686
cally <- call("absDS", x)
10787
DSI::datashield.assign(datasources, newobj, cally)
10888

109-
# check that the new object has been created and display a message accordingly
110-
finalcheck <- isAssigned(datasources, newobj)
111-
11289
}

R/ds.asCharacter.R

Lines changed: 3 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
#' objects obtained after login. If the \code{datasources} argument is not specified
1414
#' the default set of connections will be used: see \code{\link[DSI]{datashield.connections_default}}.
1515
#' @return \code{ds.asCharacter} returns the object converted into a class character
16-
#' that is written to the server-side. Also, two validity messages are returned to the client-side
17-
#' indicating the name of the \code{newobj} which has been created in each data source and if
18-
#' it is in a valid form.
16+
#' that is written to the server-side.
1917
#' @examples
2018
#' \dontrun{
2119
#' ## Version 6, for version 5 see the Wiki
@@ -53,115 +51,22 @@
5351
#'
5452
#' }
5553
#' @author DataSHIELD Development Team
54+
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
5655
#' @export
5756
#'
5857
ds.asCharacter <- function(x.name=NULL, newobj=NULL, datasources=NULL){
5958

60-
# look for DS connections
61-
if(is.null(datasources)){
62-
datasources <- datashield.connections_find()
63-
}
64-
65-
# ensure datasources is a list of DSConnection-class
66-
if(!(is.list(datasources) && all(unlist(lapply(datasources, function(d) {methods::is(d,"DSConnection")}))))){
67-
stop("The 'datasources' were expected to be a list of DSConnection-class objects", call.=FALSE)
68-
}
59+
datasources <- .set_datasources(datasources)
6960

7061
if(is.null(x.name)){
7162
stop("Please provide the name of the input vector!", call.=FALSE)
7263
}
7364

74-
# check if the input object is defined in all the studies
75-
isDefined(datasources, x.name)
76-
77-
# create a name by default if user did not provide a name for the new variable
7865
if(is.null(newobj)){
7966
newobj <- "ascharacter.newobj"
8067
}
8168

82-
# call the server side function that does the job
83-
8469
calltext <- call("asCharacterDS", x.name)
85-
8670
DSI::datashield.assign(datasources, newobj, calltext)
8771

88-
89-
#############################################################################################################
90-
#DataSHIELD CLIENTSIDE MODULE: CHECK KEY DATA OBJECTS SUCCESSFULLY CREATED #
91-
#
92-
#SET APPROPRIATE PARAMETERS FOR THIS PARTICULAR FUNCTION #
93-
test.obj.name<-newobj #
94-
# #
95-
#
96-
# CALL SEVERSIDE FUNCTION #
97-
calltext <- call("testObjExistsDS", test.obj.name) #
98-
#
99-
object.info<-DSI::datashield.aggregate(datasources, calltext) #
100-
#
101-
# CHECK IN EACH SOURCE WHETHER OBJECT NAME EXISTS #
102-
# AND WHETHER OBJECT PHYSICALLY EXISTS WITH A NON-NULL CLASS #
103-
num.datasources<-length(object.info) #
104-
#
105-
#
106-
obj.name.exists.in.all.sources<-TRUE #
107-
obj.non.null.in.all.sources<-TRUE #
108-
#
109-
for(j in 1:num.datasources){ #
110-
if(!object.info[[j]]$test.obj.exists){ #
111-
obj.name.exists.in.all.sources<-FALSE #
112-
} #
113-
if(is.null(object.info[[j]]$test.obj.class) || ("ABSENT" %in% object.info[[j]]$test.obj.class)){ #
114-
obj.non.null.in.all.sources<-FALSE #
115-
} #
116-
} #
117-
#
118-
if(obj.name.exists.in.all.sources && obj.non.null.in.all.sources){ #
119-
#
120-
return.message<- #
121-
paste0("A data object <", test.obj.name, "> has been created in all specified data sources") #
122-
#
123-
#
124-
}else{ #
125-
#
126-
return.message.1<- #
127-
paste0("Error: A valid data object <", test.obj.name, "> does NOT exist in ALL specified data sources") #
128-
#
129-
return.message.2<- #
130-
paste0("It is either ABSENT and/or has no valid content/class,see return.info above") #
131-
#
132-
return.message.3<- #
133-
paste0("Please use ds.ls() to identify where missing") #
134-
#
135-
#
136-
return.message<-list(return.message.1,return.message.2,return.message.3) #
137-
#
138-
} #
139-
#
140-
calltext <- call("messageDS", test.obj.name) #
141-
studyside.message<-DSI::datashield.aggregate(datasources, calltext) #
142-
#
143-
no.errors<-TRUE #
144-
for(nd in 1:num.datasources){ #
145-
if(studyside.message[[nd]]!="ALL OK: there are no studysideMessage(s) on this datasource"){ #
146-
no.errors<-FALSE #
147-
} #
148-
} #
149-
#
150-
#
151-
if(no.errors){ #
152-
validity.check<-paste0("<",test.obj.name, "> appears valid in all sources") #
153-
return(list(is.object.created=return.message,validity.check=validity.check)) #
154-
} #
155-
#
156-
if(!no.errors){ #
157-
validity.check<-paste0("<",test.obj.name,"> invalid in at least one source. See studyside.messages:") #
158-
return(list(is.object.created=return.message,validity.check=validity.check, #
159-
studyside.messages=studyside.message)) #
160-
} #
161-
#
162-
#END OF CHECK OBJECT CREATED CORECTLY MODULE #
163-
#############################################################################################################
164-
165-
16672
}
167-
# ds.asCharacter

R/ds.asDataMatrix.R

Lines changed: 3 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@
1212
#' objects obtained after login. If the \code{datasources} argument is not specified
1313
#' the default set of connections will be used: see \code{\link[DSI]{datashield.connections_default}}.
1414
#' @return \code{ds.asDataMatrix} returns the object converted into a matrix
15-
#' that is written to the server-side. Also, two validity messages are returned
16-
#' to the client-side
17-
#' indicating the name of the \code{newobj} which
18-
#' has been created in each data source and if
19-
#' it is in a valid form.
15+
#' that is written to the server-side.
2016
#' @examples
2117
#' \dontrun{
2218
#' ## Version 6, for version 5 see the Wiki
@@ -54,113 +50,22 @@
5450
#'
5551
#' }
5652
#' @author DataSHIELD Development Team
53+
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
5754
#' @export
5855
#'
5956
ds.asDataMatrix <- function(x.name=NULL, newobj=NULL, datasources=NULL){
6057

61-
# look for DS connections
62-
if(is.null(datasources)){
63-
datasources <- datashield.connections_find()
64-
}
65-
66-
# ensure datasources is a list of DSConnection-class
67-
if(!(is.list(datasources) && all(unlist(lapply(datasources, function(d) {methods::is(d,"DSConnection")}))))){
68-
stop("The 'datasources' were expected to be a list of DSConnection-class objects", call.=FALSE)
69-
}
58+
datasources <- .set_datasources(datasources)
7059

7160
if(is.null(x.name)){
7261
stop("Please provide the name of the input vector!", call.=FALSE)
7362
}
7463

75-
# check if the input object is defined in all the studies
76-
isDefined(datasources, x.name)
77-
78-
# create a name by default if user did not provide a name for the new variable
7964
if(is.null(newobj)){
8065
newobj <- "asdatamatrix.newobj"
8166
}
8267

83-
# call the server side function that does the job
8468
calltext <- call("asDataMatrixDS", x.name)
8569
DSI::datashield.assign(datasources, newobj, calltext)
8670

87-
88-
#############################################################################################################
89-
#DataSHIELD CLIENTSIDE MODULE: CHECK KEY DATA OBJECTS SUCCESSFULLY CREATED #
90-
#
91-
#SET APPROPRIATE PARAMETERS FOR THIS PARTICULAR FUNCTION #
92-
test.obj.name<-newobj #
93-
# #
94-
#
95-
# CALL SEVERSIDE FUNCTION #
96-
calltext <- call("testObjExistsDS", test.obj.name) #
97-
#
98-
object.info<-DSI::datashield.aggregate(datasources, calltext) #
99-
#
100-
# CHECK IN EACH SOURCE WHETHER OBJECT NAME EXISTS #
101-
# AND WHETHER OBJECT PHYSICALLY EXISTS WITH A NON-NULL CLASS #
102-
num.datasources<-length(object.info) #
103-
#
104-
#
105-
obj.name.exists.in.all.sources<-TRUE #
106-
obj.non.null.in.all.sources<-TRUE #
107-
#
108-
for(j in 1:num.datasources){ #
109-
if(!object.info[[j]]$test.obj.exists){ #
110-
obj.name.exists.in.all.sources<-FALSE #
111-
} #
112-
if(is.null(object.info[[j]]$test.obj.class) || ("ABSENT" %in% object.info[[j]]$test.obj.class)){ #
113-
obj.non.null.in.all.sources<-FALSE #
114-
} #
115-
} #
116-
#
117-
if(obj.name.exists.in.all.sources && obj.non.null.in.all.sources){ #
118-
#
119-
return.message<- #
120-
paste0("A data object <", test.obj.name, "> has been created in all specified data sources") #
121-
#
122-
#
123-
}else{ #
124-
#
125-
return.message.1<- #
126-
paste0("Error: A valid data object <", test.obj.name, "> does NOT exist in ALL specified data sources") #
127-
#
128-
return.message.2<- #
129-
paste0("It is either ABSENT and/or has no valid content/class,see return.info above") #
130-
#
131-
return.message.3<- #
132-
paste0("Please use ds.ls() to identify where missing") #
133-
#
134-
#
135-
return.message<-list(return.message.1,return.message.2,return.message.3) #
136-
#
137-
} #
138-
#
139-
calltext <- call("messageDS", test.obj.name) #
140-
studyside.message<-DSI::datashield.aggregate(datasources, calltext) #
141-
#
142-
no.errors<-TRUE #
143-
for(nd in 1:num.datasources){ #
144-
if(studyside.message[[nd]]!="ALL OK: there are no studysideMessage(s) on this datasource"){ #
145-
no.errors<-FALSE #
146-
} #
147-
} #
148-
#
149-
#
150-
if(no.errors){ #
151-
validity.check<-paste0("<",test.obj.name, "> appears valid in all sources") #
152-
return(list(is.object.created=return.message,validity.check=validity.check)) #
153-
} #
154-
#
155-
if(!no.errors){ #
156-
validity.check<-paste0("<",test.obj.name,"> invalid in at least one source. See studyside.messages:") #
157-
return(list(is.object.created=return.message,validity.check=validity.check, #
158-
studyside.messages=studyside.message)) #
159-
} #
160-
#
161-
#END OF CHECK OBJECT CREATED CORECTLY MODULE #
162-
#############################################################################################################
163-
164-
16571
}
166-
# ds.asDataMatrix

0 commit comments

Comments
 (0)