Skip to content

Commit bf6fab0

Browse files
author
mckeea
committed
New logic for generate_query_template() && Bug fixes
1 parent 1a4d511 commit bf6fab0

File tree

5 files changed

+117
-60
lines changed

5 files changed

+117
-60
lines changed

R/client.R

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ Client <- R6::R6Class("Client",
2222
#' @return An instance of the `Client` class.
2323
#' @export
2424
initialize = function(user, password, save_credentials = FALSE) {
25-
26-
2725
private$credentials_file_path <- "~/.hdarc"
2826

2927
if (missing(user) || missing(password)) {
@@ -343,7 +341,8 @@ Client <- R6::R6Class("Client",
343341
resp <- self$send_request(req)$data
344342

345343
if (to_json) {
346-
resp <- jsonlite::toJSON(resp, pretty = TRUE, auto_unbox = TRUE)
344+
resp <- jsonlite::toJSON(resp, pretty = TRUE, auto_unbox = TRUE, digits = 17)
345+
print(resp)
347346
}
348347
resp
349348
},
@@ -364,7 +363,6 @@ Client <- R6::R6Class("Client",
364363
auth = NULL,
365364
credentials_file_path = NULL,
366365
read_credentials_from_file = function() {
367-
368366
if (!file.exists(private$credentials_file_path)) {
369367
return(c("", ""))
370368
}
@@ -408,8 +406,14 @@ Client <- R6::R6Class("Client",
408406
for (param in names(data))
409407
{
410408
if (param == "dataset_id") next
411-
if (param == "itemsPerPage") next
412-
if (param == "startIndex") next
409+
if (param == "itemsPerPage") {
410+
obj$itemsPerPage <- 11
411+
next
412+
}
413+
if (param == "startIndex") {
414+
obj$startIndex <- 0
415+
next
416+
}
413417
if (is.null(data[[param]])) next
414418

415419
if (grepl("bbox", param, fixed = TRUE)) {
@@ -423,22 +427,15 @@ Client <- R6::R6Class("Client",
423427
next
424428
}
425429

426-
pValue <- extract_template_param_default_value(data[[param]])
427-
if (is.null(pValue)) {
428-
switch(param,
429-
"itemsPerPage" = {
430-
pValue <- 11
431-
},
432-
"startIndex" = {
433-
pValue <- 0
434-
},
435-
next
436-
)
430+
param_meta <- extract_param_metadata(data[[param]])
431+
obj <- c(obj, setNames(param_meta$value, param))
432+
if (!is.na(param_meta$comment)) {
433+
obj <- c(obj, setNames(param_meta$comment, paste0("_comment_", param)))
437434
}
438-
obj <- c(obj, setNames(pValue, param))
439435
}
436+
440437
if (to_json) {
441-
jsonlite::toJSON(obj, pretty = TRUE, auto_unbox = TRUE)
438+
jsonlite::toJSON(obj, pretty = TRUE, auto_unbox = TRUE, digits = 17)
442439
} else {
443440
obj
444441
}
@@ -508,7 +505,7 @@ Client <- R6::R6Class("Client",
508505
if (grepl("application/json", content_type)) {
509506
resp %>%
510507
httr2::resp_body_json() %>%
511-
jsonlite::toJSON(pretty = TRUE, auto_unbox = TRUE)
508+
jsonlite::toJSON(pretty = TRUE, auto_unbox = TRUE, digits = 17)
512509
} else {
513510
# For other content types (e.g., text)
514511
resp %>% httr2::resp_body_string()

R/paginator.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Paginator <- R6::R6Class("Paginator",
2626
}
2727
}
2828

29-
if ((!is.null(limit) && length(results) >= limit) ||
29+
if ((!is.null(limit) && length(results) > limit) ||
3030
length(results) >= resp$properties$totalResults || length(results) == 0) {
3131
break
3232
}

R/search_results.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ SearchResults <- R6::R6Class("SearchResults",
3434
x$id
3535
}))
3636
if (self$total_count > 0) {
37-
self$total_size <- sum(sapply(results, function(x) if (!is.null(x$properties$size)) x$properties$size else 0))
37+
self$total_size <- sum(sapply(results, function(x) if (!is.null(x$properties$size) && is.numeric(x$properties$size)) x$properties$size else 0))
3838
} else {
3939
self$total_size <- 0
4040
}

R/utils.R

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,92 @@ is_placeholder <- function(value) {
99
is_single_string(value) && stringr::str_detect(value, paste0("^", PLACEHOLDER_TAG))
1010
}
1111

12-
extract_template_param_string_default_value <- function(meta) {
12+
extract_param_meta_for_string <- function(meta) {
1313
value <- NULL
14+
comment <- NA
1415

1516
if (exists("default", where = meta)) {
1617
value <- meta$default
1718
}
1819

19-
if ((is.null(value) || value == "") && exists("type", where = meta)) {
20+
description <- NA
21+
if (exists("type", where = meta)) {
22+
description <- paste("Value of", meta$type)
23+
2024
if (exists("pattern", where = meta)) {
21-
value <- paste(PLACEHOLDER_TAG, "Value of", meta$type, "type with pattern:", meta$pattern)
22-
} else {
23-
value <- paste(PLACEHOLDER_TAG, "Value of", meta$type)
25+
description <- paste(description, "type with pattern:", meta$pattern)
26+
}
27+
if (exists("format", where = meta)) {
28+
description <- paste(description, "type with format:", meta$format)
2429
}
2530
}
2631

32+
if (is.null(value) || nchar(value) == 0) {
33+
value <- paste(PLACEHOLDER_TAG, description)
34+
} else {
35+
comment <- description
36+
}
37+
2738
if (exists("oneOf", where = meta) && length(meta$oneOf) > 0) {
2839
value <- meta$oneOf[[1]]$const
40+
41+
possible_values <- sapply(meta$oneOf, function(x) x$const)
42+
comment <- paste0("One of: ", paste(possible_values, collapse = ","))
2943
}
3044

31-
if (is.null(value) || nchar(value) == 0) NULL else value
45+
data.frame(value = value, comment = comment)
3246
}
3347

34-
extract_template_param_array_default_value <- function(meta) {
48+
extract_param_meta_for_number <- function(meta) {
49+
value <- NULL
50+
comment <- NA
51+
52+
if (exists("default", where = meta)) {
53+
value <- meta$default
54+
}
55+
56+
description <- ""
57+
58+
if (exists("minimum", where = meta)) {
59+
description <- paste0(description, "Min: ", meta$minimum, " ")
60+
}
61+
if (exists("maximum", where = meta)) {
62+
description <- paste0(description, "Max: ", meta$maximum, " ")
63+
}
64+
65+
if (is.null(value) || nchar(value) == 0) {
66+
value <- paste(PLACEHOLDER_TAG, description)
67+
} else {
68+
comment <- description
69+
}
70+
71+
data.frame(value = value, comment = comment)
72+
}
73+
74+
extract_param_meta_for_array <- function(meta) {
75+
value <- NULL
76+
3577
if (exists("items", where = meta)) {
3678
if (exists("oneOf", meta$items) && length(meta$items$oneOf) > 0) {
3779
value <- sapply(meta$items$oneOf, function(x) {
3880
x$const
3981
})
40-
return(I(list(value)))
82+
if (length(value) == 1) {
83+
value <- I(list(list(value)))
84+
} else {
85+
value <- I(list(value))
86+
}
4187
}
4288
}
4389

44-
NULL
90+
data.frame(value = I(value), comment = NA)
4591
}
4692

47-
extract_template_param_default_value <- function(meta) {
93+
extract_param_metadata <- function(meta) {
4894
switch(meta$type,
49-
"string" = extract_template_param_string_default_value(meta),
50-
"array" = extract_template_param_array_default_value(meta)
95+
"string" = extract_param_meta_for_string(meta),
96+
"number" = extract_param_meta_for_number(meta),
97+
"array" = extract_param_meta_for_array(meta),
5198
)
5299
}
53100

@@ -57,12 +104,13 @@ strip_off_template_placeholders <- function(template) {
57104
t <- jsonlite::fromJSON(template, simplifyVector = FALSE)
58105
for (param in names(t))
59106
{
107+
if (startsWith(param, "_comment_")) next
60108
value <- t[[param]]
61109
if (!is_placeholder(value)) {
62110
output[[param]] <- value
63111
}
64112
}
65-
jsonlite::toJSON(output, pretty = TRUE, auto_unbox = TRUE)
113+
jsonlite::toJSON(output, pretty = TRUE, auto_unbox = TRUE, digits = 17)
66114
}
67115

68116
is_single_string <- function(input) {

vignettes/hdar.Rmd

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ vignette: >
1010
%\VignetteEncoding{UTF-8}
1111
---
1212

13-
1413
# Introduction
1514

1615
The `hdar` R package provides seamless access to the WEkEO Harmonised Data Access (HDA) API, enabling users to programmatically query and download data from within R.
@@ -76,12 +75,16 @@ client$get_token()
7675
```
7776

7877
# Copernicus Terms and Conditions (T&C)
78+
7979
Copernicus data is free to use and modify, still T&Cs must be accepted in order to download the data. `hdarc` offers a confortable functionality to read and accept/reject T&C of the individual Copernicus service:
80+
8081
```{r,eval=FALSE}
8182
client$show_terms()
8283
```
84+
8385
Will open a browser where you can read all the available T&Cs.
8486
To accept/reject individual T&Cs or all at once use:
87+
8588
```{r,eval=FALSE}
8689
client$terms_and_conditions()
8790
@@ -111,6 +114,7 @@ client$terms_and_conditions(term_id = 'all')
111114
10 CNES_Open_2.0_ETALAB_Licence TRUE
112115
113116
```
117+
114118
# Finding Datasets
115119

116120
WEkEO offers a vast amount of different products. To find what you need the Client class provides a method called `datasets` that lists available datasets, optionally filtered by a text pattern.
@@ -138,37 +142,38 @@ filtered_datasets <- client$datasets("Seasonal Trajectories")
138142
139143
# list dataset IDs
140144
sapply(filtered_datasets,FUN = function(x){x$dataset_id})
141-
[1] "EO:EEA:DAT:CLMS_HRVPP_VPP-LAEA" "EO:EEA:DAT:CLMS_HRVPP_ST" "EO:EEA:DAT:CLMS_HRVPP_ST-LAEA"
142-
[4] "EO:EEA:DAT:CLMS_HRVPP_VPP"
145+
[1] "EO:EEA:DAT:CLMS_HRVPP_VPP-LAEA" "EO:EEA:DAT:CLMS_HRVPP_ST" "EO:EEA:DAT:CLMS_HRVPP_ST-LAEA"
146+
[4] "EO:EEA:DAT:CLMS_HRVPP_VPP"
143147
144148
145149
filtered_datasets <- client$datasets("Baltic")
146150
147151
# list dataset IDs
148152
sapply(filtered_datasets,FUN = function(x){x$dataset_id})
149-
[1] "EO:MO:DAT:BALTICSEA_ANALYSISFORECAST_BGC_003_007:cmems_mod_bal_bgc-pp_anfc_P1D-i_202311"
150-
[2] "EO:MO:DAT:NWSHELF_MULTIYEAR_PHY_004_009:cmems_mod_nws_phy-sst_my_7km-2D_PT1H-i_202112"
151-
[3] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L4_MY_009_134:cmems_obs-oc_bal_bgc-plankton_my_l4-multi-1km_P1M_202211"
152-
[4] "EO:MO:DAT:SST_BAL_PHY_SUBSKIN_L4_NRT_010_034:cmems_obs-sst_bal_phy-subskin_nrt_l4_PT1H-m_202211"
153-
[5] "EO:MO:DAT:BALTICSEA_MULTIYEAR_PHY_003_011:cmems_mod_bal_phy_my_P1Y-m_202303"
154-
[6] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L3_NRT_009_131:cmems_obs-oc_bal_bgc-transp_nrt_l3-olci-300m_P1D_202207"
155-
[7] "EO:MO:DAT:BALTICSEA_MULTIYEAR_BGC_003_012:cmems_mod_bal_bgc_my_P1Y-m_202303"
156-
[8] "EO:MO:DAT:SST_BAL_SST_L4_REP_OBSERVATIONS_010_016:DMI_BAL_SST_L4_REP_OBSERVATIONS_010_016_202012"
157-
[9] "EO:MO:DAT:BALTICSEA_ANALYSISFORECAST_PHY_003_006:cmems_mod_bal_phy_anfc_PT15M-i_202311"
158-
[10] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L3_MY_009_133:cmems_obs-oc_bal_bgc-plankton_my_l3-multi-1km_P1D_202207"
159-
[11] "EO:MO:DAT:SST_BAL_PHY_L3S_MY_010_040:cmems_obs-sst_bal_phy_my_l3s_P1D-m_202211"
160-
[12] "EO:MO:DAT:SEAICE_BAL_SEAICE_L4_NRT_OBSERVATIONS_011_004:FMI-BAL-SEAICE_THICK-L4-NRT-OBS"
161-
[13] "EO:MO:DAT:SEAICE_BAL_PHY_L4_MY_011_019:cmems_obs-si_bal_seaice-conc_my_1km_202112"
162-
[14] "EO:MO:DAT:BALTICSEA_ANALYSISFORECAST_WAV_003_010:cmems_mod_bal_wav_anfc_PT1H-i_202311"
163-
[15] "EO:MO:DAT:BALTICSEA_REANALYSIS_WAV_003_015:dataset-bal-reanalysis-wav-hourly_202003"
153+
[1] "EO:MO:DAT:BALTICSEA_ANALYSISFORECAST_BGC_003_007:cmems_mod_bal_bgc-pp_anfc_P1D-i_202311"
154+
[2] "EO:MO:DAT:NWSHELF_MULTIYEAR_PHY_004_009:cmems_mod_nws_phy-sst_my_7km-2D_PT1H-i_202112"
155+
[3] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L4_MY_009_134:cmems_obs-oc_bal_bgc-plankton_my_l4-multi-1km_P1M_202211"
156+
[4] "EO:MO:DAT:SST_BAL_PHY_SUBSKIN_L4_NRT_010_034:cmems_obs-sst_bal_phy-subskin_nrt_l4_PT1H-m_202211"
157+
[5] "EO:MO:DAT:BALTICSEA_MULTIYEAR_PHY_003_011:cmems_mod_bal_phy_my_P1Y-m_202303"
158+
[6] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L3_NRT_009_131:cmems_obs-oc_bal_bgc-transp_nrt_l3-olci-300m_P1D_202207"
159+
[7] "EO:MO:DAT:BALTICSEA_MULTIYEAR_BGC_003_012:cmems_mod_bal_bgc_my_P1Y-m_202303"
160+
[8] "EO:MO:DAT:SST_BAL_SST_L4_REP_OBSERVATIONS_010_016:DMI_BAL_SST_L4_REP_OBSERVATIONS_010_016_202012"
161+
[9] "EO:MO:DAT:BALTICSEA_ANALYSISFORECAST_PHY_003_006:cmems_mod_bal_phy_anfc_PT15M-i_202311"
162+
[10] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L3_MY_009_133:cmems_obs-oc_bal_bgc-plankton_my_l3-multi-1km_P1D_202207"
163+
[11] "EO:MO:DAT:SST_BAL_PHY_L3S_MY_010_040:cmems_obs-sst_bal_phy_my_l3s_P1D-m_202211"
164+
[12] "EO:MO:DAT:SEAICE_BAL_SEAICE_L4_NRT_OBSERVATIONS_011_004:FMI-BAL-SEAICE_THICK-L4-NRT-OBS"
165+
[13] "EO:MO:DAT:SEAICE_BAL_PHY_L4_MY_011_019:cmems_obs-si_bal_seaice-conc_my_1km_202112"
166+
[14] "EO:MO:DAT:BALTICSEA_ANALYSISFORECAST_WAV_003_010:cmems_mod_bal_wav_anfc_PT1H-i_202311"
167+
[15] "EO:MO:DAT:BALTICSEA_REANALYSIS_WAV_003_015:dataset-bal-reanalysis-wav-hourly_202003"
164168
[16] "EO:MO:DAT:OCEANCOLOUR_BAL_BGC_L4_NRT_009_132:cmems_obs-oc_bal_bgc-plankton_nrt_l4-olci-300m_P1M_202207"
165-
[17] "EO:MO:DAT:SST_BAL_SST_L3S_NRT_OBSERVATIONS_010_032:DMI-BALTIC-SST-L3S-NRT-OBS_FULL_TIME_SERIE_201904"
169+
[17] "EO:MO:DAT:SST_BAL_SST_L3S_NRT_OBSERVATIONS_010_032:DMI-BALTIC-SST-L3S-NRT-OBS_FULL_TIME_SERIE_201904"
166170
167171
```
168172

169173
## Understanding the Results
170174

171175
The datasets method returns a list containing datasets and associated information. This information may include dataset names, descriptions, and other metadata.
176+
172177
```{r, eval=FALSE}
173178
client$datasets("EO:ECMWF:DAT:DERIVED_NEAR_SURFACE_METEOROLOGICAL_VARIABLES")
174179
[[1]]
@@ -201,6 +206,7 @@ To search for a specific product, you need to create a query template. You can e
201206
knitr::include_graphics(c("WEkEO_UI_JSON_1.png","WEkEO_UI_JSON_2.png"))
202207
203208
```
209+
204210
```{r,echo=TRUE}
205211
query <- '{
206212
"dataset_id": "EO:ECMWF:DAT:CEMS_GLOFAS_HISTORICAL",
@@ -253,15 +259,20 @@ query_template <- client$generate_query_template("EO:EEA:DAT:CLMS_HRVPP_ST")
253259
query_template
254260
{
255261
"dataset_id": "EO:EEA:DAT:CLMS_HRVPP_ST",
262+
"itemsPerPage": 11,
263+
"startIndex": 0,
256264
"uid": "__### Value of string type with pattern: [\\w-]+",
257265
"productType": "PPI",
266+
"_comment_productType": "One of: PPI,QFLAG",
258267
"platformSerialIdentifier": "S2A, S2B",
268+
"_comment_platformSerialIdentifier": "One of: S2A, S2B",
259269
"tileId": "__### Value of string type with pattern: [\\w-]+",
260270
"productVersion": "__### Value of string type with pattern: [\\w-]+",
261271
"resolution": "10",
262-
"processingDate": "__### Value of string",
263-
"start": "__### Value of string",
264-
"end": "__### Value of string",
272+
"_comment_resolution": "One of: 10",
273+
"processingDate": "__### Value of string type with format: date-time",
274+
"start": "__### Value of string type with format: date-time",
275+
"end": "__### Value of string type with format: date-time",
265276
"bbox": [
266277
-180,
267278
-90,
@@ -271,10 +282,11 @@ query_template
271282
}
272283
```
273284

274-
275285
## Modify and use the generated Query Template
276286

277-
You can and should customize the generated query template to fit your specific needs. Fields starting with `__###` are placeholders indicating possible values. If these placeholders are left unchanged, they will be automatically removed before sending the query to the HDA service.
287+
You can and should customize the generated query template to fit your specific needs. Fields starting with `__###` are placeholders indicating possible values. If these placeholders are left unchanged, they will be automatically removed before sending the query to the HDA service. Additionally, fields with the prefix `_comment_` provide relevant information regarding the specified field, such as possible values, format, or data patterns. Like the placeholders, these comment fields will also be automatically removed before the query is sent.
288+
289+
Placeholders are used when there is no way to derive the value from the metadata endpoint, while comment fields appear when the field has a value already defined, offering additional context for customizing the query.
278290

279291
To modify the query, it is often easier to transform the JSON into an R list using the `jsonlite::fromJSON()` function:
280292

@@ -365,7 +377,7 @@ Once you have made the necessary modifications, you can convert the list back to
365377

366378
```{r, eval = FALSE}
367379
# convert to JSON format
368-
query_template <- toJSON(query_template, auto_unbox = TRUE) # don't forget to put auto_unbox = TRUE
380+
query_template <- toJSON(query_template, auto_unbox = TRUE, digits = 17) # don't forget to put auto_unbox = TRUE
369381
```
370382

371383
# Searching and Downloading Data

0 commit comments

Comments
 (0)