Skip to content

Commit c66f616

Browse files
committed
solve issue #15
1 parent 0ff7510 commit c66f616

13 files changed

+341
-241
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ Encoding: UTF-8
4545
LazyData: true
4646
RoxygenNote: 7.3.1
4747
Language: en-US
48+
Config/testthat/start-first: mf_login, mf_list_collections, mf_list_variables, mf_get_url, mf_download_data, mf_import_data

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ export(mf_import_data)
77
export(mf_list_collections)
88
export(mf_list_variables)
99
export(mf_login)
10+
export(modisfast)
1011
import(cli)
1112
import(dplyr)
1213
import(httr)
1314
import(parallel)
1415
import(purrr)
1516
import(sf)
17+
importFrom(cli,cli_alert_success)
1618
importFrom(curl,has_internet)
1719
importFrom(lubridate,floor_date)
1820
importFrom(lubridate,hour)

README.Rmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,4 +275,4 @@ We thank NASA and its partners for making all their Earth science data freely av
275275

276276
We also thank the contributors that have tested the package, reviewed the documentation and brought valuable feedbacks to improve the package : [Florian de Boissieu](https://github.com/floriandeboissieu), Julien Taconet.
277277

278-
This work has been developed over the course of several research projects (REACT 1, REACT 2, ANORHYTHM and DIV-YOO) funded by Expertise France and the French National Research Agency (ANR).
278+
This work has been developed over the course of several research projects (REACT 1, REACT 2, ANORHYTHM and DIV-YOO) funded by Expertise France, the French National Research Agency (ANR), and the French National Research Institute for Sustainable Development (IRD).

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1502,4 +1502,5 @@ Taconet.
15021502

15031503
This work has been developed over the course of several research
15041504
projects (REACT 1, REACT 2, ANORHYTHM and DIV-YOO) funded by Expertise
1505-
France and the French National Research Agency (ANR).
1505+
France, the French National Research Agency (ANR), and the French
1506+
National Research Institute for Sustainable Development (IRD).

tests/testthat.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ library(modisfast)
33

44
### Instructions to run the tests in order to verify the functionality of modisfast :
55

6-
# - open the file test/testthat/test-modisfast.R
7-
# - uncomment the 2 first two lines of the script (earthdata_un = "my_username" and earthdata_pw = "my_password")
6+
# - open the file : test/testthat/helper-modisfast.R
7+
# - uncomment the lines : earthdata_un = "my_username" and earthdata_pw = "my_password"
88
# - replace "my_username" and "my_password" with your own Earthdata username and password
9-
# - run devtools::test() (or run the script test/testthat/test-modisfast.R manually)
9+
# - run devtools::test()
1010

1111
message("tests are not executed automatically")
1212

tests/testthat/helper-modisfast.R

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# here are "global" variable which can be used for all tests, as explained in https://github.com/r-lib/testthat/issues/422
2+
3+
earthdata_un = "my_username"
4+
earthdata_pw = "my_password"
5+
6+
7+
library(sf)
8+
library(terra)
9+
10+
roi <- st_as_sf(data.frame(id = "madagascar", geom = "POLYGON((41.95 -11.37,51.26 -11.37,51.26 -26.17,41.95 -26.17,41.95 -11.37))"), wkt = "geom", crs = 4326)
11+
time_range <- as.Date(c("2023-01-01", "2023-03-31"))
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
test_that("function mf_download_data() works to download a MODIS datacube", {
3+
4+
skip_on_cran()
5+
skip_on_ci()
6+
7+
urls_modis <- mf_get_url(collection = "MOD13A3.061",
8+
variables = c("_1_km_monthly_NDVI"),
9+
roi = roi,
10+
time_range = time_range
11+
)
12+
13+
res_dl_modis <- mf_download_data(df_to_dl = urls_modis)
14+
15+
expect_is(res_dl_modis,'data.frame') # output is a data.frame
16+
expect_named(res_dl_modis, c("id_roi","time_start","collection","name","url","destfile", "fileDl", "fileSize", "dlStatus")) # column names are ok
17+
expect_equal(ncol(res_dl_modis), 9) # there are 9 columns
18+
expect_equal(nrow(res_dl_modis), 5)# there are 5 rows (corresponding to 5 tiles)
19+
expect_equal(unique(res_dl_modis$fileDl), TRUE) # all files were properly downloaded (fileDl == TRUE for all files)
20+
expect_gt(sum(res_dl_modis$fileSize),5500000) # file size for this very specific example should be around 6000000 bites
21+
expect_lt(sum(res_dl_modis$fileSize),6500000)
22+
23+
24+
25+
})
26+
27+
28+
29+
test_that("function mf_download_data() works to download a GPM datacube", {
30+
31+
skip_on_cran()
32+
skip_on_ci()
33+
34+
urls_gpm <- mf_get_url(collection = "GPM_3IMERGDF.07",
35+
variables = c("precipitation"),
36+
roi = roi,
37+
time_range = time_range
38+
)
39+
40+
res_dl_gpm <- mf_download_data(df_to_dl = urls_gpm, parallel = TRUE) # download data, with parallelization
41+
42+
expect_is(res_dl_gpm,'data.frame') # output is a data.frame
43+
expect_named(res_dl_gpm, c("id_roi","time_start","collection","name","url","destfile", "fileDl", "fileSize", "dlStatus")) # column names are ok
44+
expect_equal(ncol(res_dl_gpm), 9) # there are 9 columns
45+
expect_equal(nrow(res_dl_gpm), 90 ) # there are 90 rows (corresponding to 90 dates)
46+
expect_equal(unique(res_dl_gpm$fileDl), TRUE) # all files were properly downloaded (fileDl == TRUE for all files)
47+
expect_gt(sum(res_dl_gpm$fileSize),5000000) # file size for this very specific example should be 5500000 bites
48+
expect_lt(sum(res_dl_gpm$fileSize),6000000)
49+
50+
51+
52+
})

tests/testthat/test-mf_get_url.R

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
2+
3+
test_that("function mf_get_url() sends back the expected output for a MODIS query", {
4+
5+
skip_on_cran()
6+
skip_on_ci()
7+
8+
urls_modis <- mf_get_url(collection = "MOD13A3.061",
9+
variables = c("_1_km_monthly_NDVI"),
10+
roi = roi,
11+
time_range = time_range
12+
)
13+
14+
expect_is(urls_modis, "data.frame") # output is a data.frame
15+
expect_named(urls_modis, c("id_roi","time_start","collection","name","url")) # column names are ok
16+
expect_equal(ncol(urls_modis), 5) # there are 5 columns
17+
expect_equal(nrow(urls_modis), 5)# there are 5 rows (corresponding to 5 tiles)
18+
expect_match(urls_modis$url[1], "https://opendap.cr.usgs.gov") # urls starts with the right OPENDAP url
19+
20+
expect_equal(urls_modis, data.frame(id_roi = rep("madagascar",5),
21+
time_start = rep(as.Date("2023-01-01"), 5),
22+
collection = rep("MOD13A3.061", 5),
23+
name = c("MOD13A3.061.2023001_2023060.h21v10.nc4", "MOD13A3.061.2023001_2023060.h21v11.nc4", "MOD13A3.061.2023001_2023060.h22v10.nc4", "MOD13A3.061.2023001_2023060.h22v11.nc4", "MOD13A3.061.2023001_2023060.h23v10.nc4"),
24+
url = c( "https://opendap.cr.usgs.gov/opendap/hyrax/MOD13A3.061/h21v10.ncml.nc4?MOD_Grid_monthly_1km_VI_eos_cf_projection,_1_km_monthly_NDVI%5B275:277%5D%5B922:1199%5D%5B1132:1199%5D,time%5B275:277%5D,YDim%5B922:1199%5D,XDim%5B1132:1199%5D",
25+
"https://opendap.cr.usgs.gov/opendap/hyrax/MOD13A3.061/h21v11.ncml.nc4?MOD_Grid_monthly_1km_VI_eos_cf_projection,_1_km_monthly_NDVI%5B275:277%5D%5B0:749%5D%5B919:1199%5D,time%5B275:277%5D,YDim%5B0:749%5D,XDim%5B919:1199%5D",
26+
"https://opendap.cr.usgs.gov/opendap/hyrax/MOD13A3.061/h22v10.ncml.nc4?MOD_Grid_monthly_1km_VI_eos_cf_projection,_1_km_monthly_NDVI%5B275:277%5D%5B165:1199%5D%5B0:1199%5D,time%5B275:277%5D,YDim%5B165:1199%5D,XDim%5B0:1199%5D",
27+
"https://opendap.cr.usgs.gov/opendap/hyrax/MOD13A3.061/h22v11.ncml.nc4?MOD_Grid_monthly_1km_VI_eos_cf_projection,_1_km_monthly_NDVI%5B275:277%5D%5B0:749%5D%5B0:982%5D,time%5B275:277%5D,YDim%5B0:749%5D,XDim%5B0:982%5D",
28+
"https://opendap.cr.usgs.gov/opendap/hyrax/MOD13A3.061/h23v10.ncml.nc4?MOD_Grid_monthly_1km_VI_eos_cf_projection,_1_km_monthly_NDVI%5B275:277%5D%5B165:351%5D%5B0:40%5D,time%5B275:277%5D,YDim%5B165:351%5D,XDim%5B0:40%5D")
29+
)
30+
)
31+
32+
})
33+
34+
35+
36+
test_that("function mf_get_url() sends back the expected output for a GPM query", {
37+
38+
skip_on_cran()
39+
skip_on_ci()
40+
41+
urls_gpm <- mf_get_url(collection = "GPM_3IMERGDF.07",
42+
variables = c("precipitation"),
43+
roi = roi,
44+
time_range = time_range
45+
)
46+
47+
expect_is(urls_gpm, "data.frame") # output is a data.frame
48+
expect_named(urls_gpm, c("id_roi","time_start","collection","name","url")) # column names are ok
49+
expect_equal(ncol(urls_gpm), 5) # there are 5 columns
50+
expect_equal(nrow(urls_gpm), 90) # there are 90 rows (corresponding to 90 dates)
51+
expect_match(urls_gpm$url[1], "https://gpm1.gesdisc.eosdis.nasa.gov") # urls starts with the right OPENDAP url
52+
53+
expect_equal(urls_gpm[1,], data.frame(id_roi = "madagascar",
54+
time_start = as.Date("2023-01-01"),
55+
collection = "GPM_3IMERGDF.07",
56+
name = "3B-DAY.MS.MRG.3IMERG.20230101-S000000-E235959.V07B.nc4",
57+
url ="https://gpm1.gesdisc.eosdis.nasa.gov/opendap/GPM_L3/GPM_3IMERGDF.07/2023/01/3B-DAY.MS.MRG.3IMERG.20230101-S000000-E235959.V07B.nc4.nc4?precipitation%5B0:0%5D%5B2220:2313%5D%5B639:787%5D,time%5B0:0%5D,lon%5B2220:2313%5D,lat%5B639:787%5D"
58+
)
59+
)
60+
61+
62+
})
63+
64+
65+
test_that("function mf_get_url() sends back the expected errors when necessary", {
66+
67+
skip_on_cran()
68+
skip_on_ci()
69+
70+
# wrong type for roi
71+
expect_error(mf_get_url(collection = "MOD13A3.061",
72+
roi = "not_a_sf_object",
73+
time_range = as.Date(c("2017-01-01","2017-02-01"))),
74+
"Argument roi must be an object of class sf or sfc with POLYGON-type feature geometry and at least two columns : 'id' and a geometry column that must not be NULL or NA",
75+
fixed = TRUE)
76+
77+
# wrong type for time range
78+
expect_error(mf_get_url(collection = "MOD13A3.061",
79+
roi = roi,
80+
time_range = c("2017-01-01","2017-02-01")),
81+
"Argument time_range is not of class Date or POSIXlt or is not of length 1 or 2 \n",
82+
fixed = TRUE)
83+
84+
# wrong dates
85+
expect_error(mf_get_url(collection = "MOD13A3.061",
86+
roi = roi,
87+
time_range = as.Date(c("2000-01-01","2017-02-01"))),
88+
"First time frame in time_range argument is before the beginning of the mission\n",
89+
fixed = TRUE)
90+
91+
expect_error(mf_get_url(collection = "MOD13A3.061",
92+
roi = roi,
93+
time_range = as.Date(c("2000-01-01","1999-02-01"))),
94+
"Time end is superior to time start in time_range argument \n",
95+
fixed = TRUE)
96+
97+
# wrong length for time range
98+
expect_error(mf_get_url(collection = "MOD13A3.061",
99+
roi = roi,
100+
time_range = as.Date(c("2017-01-01","2017-02-01","2017-02-03"))),
101+
"Argument time_range is not of class Date or POSIXlt or is not of length 1 or 2 \n",
102+
fixed = TRUE)
103+
104+
# wrong type for singleNetcdf
105+
expect_error(mf_get_url(collection = "MOD13A3.061",
106+
roi = roi,
107+
time_range = as.Date(c("2017-01-01","2017-02-01")),
108+
single_netcdf = "TRUE"),
109+
"single_netcdf argument must be boolean\n",
110+
fixed = TRUE)
111+
112+
# Collection does not exist
113+
expect_error(mf_get_url(collection = "MOD13A3v006",
114+
roi = roi,
115+
time_range = as.Date(c("2017-01-01","2017-02-01"))),
116+
"The collection that you specified does not exist. Check mf_list_collections() to see which collections are implemented\n",
117+
fixed = TRUE)
118+
119+
# output format is not specified
120+
expect_error(mf_get_url(collection = "MOD13A3.061",
121+
roi = roi,
122+
time_range = as.Date(c("2017-01-01","2017-02-01")),
123+
output_format = NA),
124+
"Specified output format is not valid. Please specify a valid output format \n",
125+
fixed = TRUE)
126+
127+
# wrong variables specified
128+
expect_error(mf_get_url(collection = "MOD13A3.061",
129+
roi = roi,
130+
time_range = as.Date(c("2017-01-01","2017-02-01")),
131+
variables = c("LST_Day_1km","not_a_good_var")),
132+
"Specified variables do not exist or are not extractable for the specified collection. Use the function mf_list_variables to check which variables are available and extractable for the collection\n",
133+
fixed = TRUE)
134+
135+
expect_error(mf_get_url(collection = "MOD13A3.061",
136+
roi = roi,
137+
time_range = as.Date(c("2017-01-01","2017-02-01")),
138+
variables = c("LST_Day_1km","time")),
139+
"Specified variables do not exist or are not extractable for the specified collection. Use the function mf_list_variables to check which variables are available and extractable for the collection\n",
140+
fixed = TRUE)
141+
142+
})

tests/testthat/test-mf_import_data.R

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
test_that("function mf_import_data() works to import a MODIS datacube", {
2+
3+
skip_on_cran()
4+
skip_on_ci()
5+
6+
modis_directory <- dirname(list.files(path = tempdir(), pattern = "MOD13A3.061.2023001_2023060.h21v10.nc4", recursive = TRUE, full.names = TRUE))
7+
8+
r_to_test_modis <- mf_import_data(
9+
path = modis_directory,
10+
collection = "MOD13A3.061"
11+
)
12+
13+
# the resulting raster should be equal to :
14+
# > r_to_test_modis
15+
# class : SpatRaster
16+
# dimensions : 1785, 1522, 3 (nrow, ncol, nlyr)
17+
# resolution : 926.6254, 926.6254 (x, y)
18+
# extent : 4186957, 5597281, -2918407, -1264380 (xmin, xmax, ymin, ymax)
19+
# coord. ref. : +proj=sinu +lon_0=0 +x_0=0 +y_0=0 +R=6371007.181 +units=m +no_defs
20+
# source(s) : memory
21+
# varname : _1_km_monthly_NDVI (1 km monthly NDVI)
22+
# names : _1_km_monthly_NDVI_1, _1_km_monthly_NDVI_2, _1_km_monthly_NDVI_3
23+
# min values : -0.2000, -0.2, -0.1993
24+
# max values : 0.9868, 1.0, 1.0000
25+
# time (days) : 2023-01-01 to 2023-03-01
26+
27+
expect_is(r_to_test_modis,'SpatRaster') # output is a SpatRaster
28+
expect_equal(dim(r_to_test_modis),c(1785, 1522, 3)) # dimension
29+
expect_equal(round(res(r_to_test_modis)),c(927, 927)) # resolution
30+
expect_equal(ext(r_to_test_modis),ext(4186957.01926165, 5597280.9283724, -2918406.80140823, -1264380.40340488)) # extent
31+
expect_equal(time(r_to_test_modis),as.Date(c("2023-01-01", "2023-02-01", "2023-03-01"))) # dates
32+
expect_equal(names(r_to_test_modis), c("_1_km_monthly_NDVI_1", "_1_km_monthly_NDVI_2", "_1_km_monthly_NDVI_3"))
33+
expect_equal(varnames(r_to_test_modis), "_1_km_monthly_NDVI")
34+
35+
36+
})
37+
38+
39+
test_that("function mf_import_data() works to import a GPM datacube", {
40+
41+
skip_on_cran()
42+
skip_on_ci()
43+
44+
gpm_directory <- dirname(list.files(path = tempdir(), pattern = "3B-DAY.MS.MRG.3IMERG.20230101-S000000-E235959.V07B.nc4", recursive = TRUE, full.names = TRUE))
45+
46+
r_to_test_gpm <- mf_import_data(
47+
path = gpm_directory,
48+
collection = "GPM_3IMERGDF.07"
49+
)
50+
51+
# the resulting raster should be equal to :
52+
# > r_to_test_gpm
53+
# class : SpatRaster
54+
# dimensions : 149, 94, 90 (nrow, ncol, nlyr)
55+
# resolution : 0.09999999, 0.1 (x, y)
56+
# extent : 42, 51.4, -26.1, -11.2 (xmin, xmax, ymin, ymax)
57+
# coord. ref. : lon/lat WGS 84 (EPSG:4326)
58+
# source(s) : memory
59+
# varname : precipitation (Daily mean precipitation rate (combined microwave-IR) estimate. Formerly precipitationCal.)
60+
# names : preci~ation, preci~ation, preci~ation, preci~ation, preci~ation, preci~ation, ...
61+
# min values : 0.000, 0.000, 0.00, 0.00, 0.00, 0.00, ...
62+
# max values : 169.725, 175.575, 106.55, 138.54, 172.57, 167.06, ...
63+
# time (days) : 2023-01-01 to 2023-03-31
64+
65+
expect_is(r_to_test_gpm,'SpatRaster') # output is a SpatRaster
66+
expect_equal(dim(r_to_test_gpm),c(149, 94, 90)) # dimension
67+
expect_equal(round(res(r_to_test_gpm),1),c(0.1,0.1)) # resolution
68+
expect_equal(ext(r_to_test_gpm),ext(41.9999992411624, 51.3999984700193, -26.1, -11.2)) # extent
69+
expect_equal(time(r_to_test_gpm),seq(as.Date("2023-01-01"),as.Date("2023-03-31"), 1)) # dates
70+
expect_equal(varnames(r_to_test_gpm), "precipitation") # variable names
71+
72+
73+
})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
test_that("function mf_list_collections() sends back the expected output", {
3+
4+
skip_on_cran()
5+
skip_on_ci()
6+
7+
coll <- mf_list_collections()
8+
9+
expect_is(coll,'data.frame') # output is a data.frame
10+
expect_equal(ncol(coll), 26) # there are 26 columns
11+
expect_named(coll, c("collection" ,"source","long_name" ,"nature","provider" ,
12+
"url_metadata", "doi", "version", "spatial_resolution_m" , "temporal_resolution",
13+
"temporal_resolution_unit", "spatial_coverage", "start_date", "end_date","indicative_latency_days" ,
14+
"url_manual_access" ,"status","login", "url_opendapserver" , "url_programmatic_access" ,
15+
"url_opendapexample","dim_lon","dim_lat","dim_time" ,"dim_proj", "crs" )) # column names are ok
16+
17+
# number of rows is not tested since it can evolve with integration of additional opendap data sources
18+
19+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
test_that("function mf_list_variables() sends back the expected output", {
3+
4+
skip_on_cran()
5+
skip_on_ci()
6+
7+
# here we test with the collections "MOD13A3.061" and "GPM_3IMERGDF.07"
8+
vars_mod13a3 <- mf_list_variables(collection = "MOD13A3.061")
9+
10+
expect_is(vars_mod13a3,'data.frame') # output is a data.frame
11+
expect_named(vars_mod13a3, c("name","long_name","units","indices","all_info","extractable_with_modisfast")) # column names are ok
12+
expect_equal(nrow(vars_mod13a3), 17) # there are 17 rows (corresponding to 17 variables/bands for this collection)
13+
14+
vars_gpm <- mf_list_variables(collection = "GPM_3IMERGDF.07")
15+
16+
expect_is(vars_gpm,'data.frame') # output is a data.frame
17+
expect_named(vars_gpm, c("name","long_name","units","indices","all_info","extractable_with_modisfast")) # column names are ok
18+
expect_equal(nrow(vars_gpm), 14) # there are 14 rows (corresponding to 14 variables/bands for this collection)
19+
20+
})
21+

tests/testthat/test-mf_login.R

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
3+
test_that("function mf_login() sends back the expected outputs and errors when necessary", {
4+
5+
skip_on_cran()
6+
skip_on_ci()
7+
8+
expect_error(mf_login(credentials = c(earthdata_un,earthdata_pw,"hello")),"credentials must be a vector character string of length 2 (username and password)\n", fixed = TRUE)
9+
expect_error(mf_login(credentials = c(earthdata_un)),"credentials must be a vector character string of length 2 (username and password)\n", fixed = TRUE)
10+
expect_error(mf_login(credentials = c(earthdata_un,"wrong password"))) # error if wrong password is provided
11+
expect_error(mf_login(credentials = c("wrong username",earthdata_pw))) # error if wrong username is provided
12+
expect_no_error(mf_login(credentials = c(earthdata_un,earthdata_pw))) # no error if right password or username are provided
13+
14+
})

0 commit comments

Comments
 (0)