From c9f5d490410b92709768852bed8ce3027a1019f0 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sun, 15 Dec 2024 17:35:38 +0800 Subject: [PATCH 01/60] Reknit vingette with proper values after bug fixes in code --- vignettes/getCRUCLdata.Rmd | 112 +++++++++++++++++++----------------- vignettes/plot_t-1.png | Bin 33938 -> 126264 bytes vignettes/violin_plot-1.png | Bin 44969 -> 61761 bytes 3 files changed, 58 insertions(+), 54 deletions(-) diff --git a/vignettes/getCRUCLdata.Rmd b/vignettes/getCRUCLdata.Rmd index 0a93dbf..f5a13ff 100644 --- a/vignettes/getCRUCLdata.Rmd +++ b/vignettes/getCRUCLdata.Rmd @@ -86,32 +86,32 @@ CRU_data <- get_CRU_df(pre = TRUE, elv = TRUE) CRU_data -#> lat lon month dtr frs pre pre_cv rd0 reh sun tmp wnd elv tmx -#> -#> 1: -55.583 -68.250 NA NA NA NA NA NA NA NA NA 62 NA -#> 2: -55.417 -69.750 NA NA NA NA NA NA NA NA NA 86 NA -#> 3: -55.417 -69.583 NA NA NA NA NA NA NA NA NA 83 NA -#> 4: -55.417 -69.417 NA NA NA NA NA NA NA NA NA 121 NA -#> 5: -55.417 -69.250 NA NA NA NA NA NA NA NA NA 51 NA -#> --- -#> 566374: -55.750 -67.417 dec 7.7 8.7 68.4 47.6 11.1 80.1 34.2 7.3 5.3 103 11.15 -#> 566375: -55.750 -67.250 dec 7.6 8.7 67.1 47.6 11.1 79.9 34.2 7.5 5.3 63 11.30 -#> 566376: -55.583 -68.083 dec 7.9 8.4 69.8 48.6 10.9 80.1 34.7 7.6 5.2 123 11.55 -#> 566377: -55.583 -67.583 dec 7.8 8.3 65.2 48.4 10.9 79.4 34.6 8.0 5.2 19 11.90 -#> 566378: -55.583 -67.417 dec 7.8 8.5 64.0 48.3 11.1 79.1 34.4 7.7 5.3 77 11.60 -#> tmn -#> -#> 1: NA -#> 2: NA -#> 3: NA -#> 4: NA -#> 5: NA -#> --- -#> 566374: 3.45 -#> 566375: 3.70 -#> 566376: 3.65 -#> 566377: 4.10 -#> 566378: 3.80 +#> lat lon month dtr frs pre pre_cv rd0 reh sun tmp wnd elv tmx +#> +#> 1: 30.917 35.417 NA NA NA NA NA NA NA NA NA -260 NA +#> 2: 31.083 35.417 NA NA NA NA NA NA NA NA NA -361 NA +#> 3: 31.250 35.417 NA NA NA NA NA NA NA NA NA -336 NA +#> 4: 31.417 35.417 NA NA NA NA NA NA NA NA NA -284 NA +#> 5: 31.750 35.583 NA NA NA NA NA NA NA NA NA -248 NA +#> --- +#> 6795146: 83.583 -30.083 dec 8.7 31 0.1 72.7 5.1 70.6 0 -31.3 5.6 283 -26.95 +#> 6795147: 83.583 -29.917 dec 8.6 31 0.1 72.8 4.9 70.6 0 -30.7 5.6 186 -26.40 +#> 6795148: 83.583 -29.750 dec 8.6 31 0.1 72.9 4.9 70.6 0 -30.8 5.6 195 -26.50 +#> 6795149: 83.583 -29.583 dec 8.6 31 0.1 73.0 5.0 70.6 0 -31.2 5.6 268 -26.90 +#> 6795150: 83.583 -29.417 dec 8.6 31 0.1 73.1 5.1 70.6 0 -31.5 5.6 328 -27.20 +#> tmn +#> +#> 1: NA +#> 2: NA +#> 3: NA +#> 4: NA +#> 5: NA +#> --- +#> 6795146: -35.65 +#> 6795147: -35.00 +#> 6795148: -35.10 +#> 6795149: -35.50 +#> 6795150: -35.80 ``` Perhaps you only need one or two elements, it is easy to create a tidy data frame of mean temperature only. @@ -121,19 +121,19 @@ Perhaps you only need one or two elements, it is easy to create a tidy data fram t <- get_CRU_df(tmp = TRUE) t -#> lat lon month tmp -#> -#> 1: -59.083 -26.583 jan 0.2 -#> 2: -58.417 -26.250 jan 0.6 -#> 3: -58.417 -26.417 jan 0.4 -#> 4: -55.917 -67.250 jan 8.0 -#> 5: -55.750 -67.250 jan 8.2 -#> --- -#> 116: -55.750 -67.417 dec 7.3 -#> 117: -55.750 -67.583 dec 7.7 -#> 118: -55.583 -67.417 dec 7.7 -#> 119: -55.583 -67.583 dec 8.0 -#> 120: -55.583 -68.083 dec 7.6 +#> lat lon month tmp +#> +#> 1: -59.083 -26.583 jan 0.2 +#> 2: -58.417 -26.250 jan 0.6 +#> 3: -58.417 -26.417 jan 0.4 +#> 4: -55.917 -67.250 jan 8.0 +#> 5: -55.750 -67.250 jan 8.2 +#> --- +#> 6795140: 83.583 -36.083 dec -32.6 +#> 6795141: 83.583 -36.250 dec -33.0 +#> 6795142: 83.583 -36.417 dec -33.4 +#> 6795143: 83.583 -36.583 dec -33.3 +#> 6795144: 83.583 -36.750 dec -33.3 ``` #### Plotting data from the tidy dataframe @@ -209,6 +209,10 @@ CRU_stack <- get_CRU_stack( wnd = TRUE, elv = TRUE ) +#> +|---------|---------|---------|---------| +========================================= + CRU_stack #> $dtr @@ -250,10 +254,10 @@ CRU_stack #> resolution : 0.1666667, 0.1666667 (x, y) #> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) #> coord. ref. : lon/lat WGS 84 -#> source : spat_4486664f1fd6_17542_SskviV5XwhZb4QV.tif -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 65.3, 70.3, 73.4, 74.0, 63.3, 62.4, ... -#> max values : 106.6, 121.9, 142.1, 147.5, 160.3, 163.5, ... +#> source : spat_fe274b2a6660_65063_GdaPwXHptgIOPSx.tif +#> names : jan, feb, mar, apr, may, jun, ... +#> min values : 0.0, 0.0, 0.0, 0.0, 0, 0.0, ... +#> max values : 910.1, 824.3, 727.3, 741.3, 1100, 2512.6, ... #> #> $rd0 #> class : SpatRaster @@ -295,9 +299,9 @@ CRU_stack #> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) #> coord. ref. : lon/lat WGS 84 #> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 0.2, 0.3, 0.2, -1.9, -6.0, -9.8, ... -#> max values : 8.6, 8.6, 7.3, 5.6, 3.4, 2.0, ... +#> names : jan, feb, mar, apr, may, jun, ... +#> min values : -51.6, -47.6, -45.2, -36.6, -22.2, -16.3, ... +#> max values : 32.5, 32.1, 32.4, 34.3, 36.0, 38.3, ... #> #> $wnd #> class : SpatRaster @@ -317,9 +321,9 @@ CRU_stack #> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) #> coord. ref. : lon/lat WGS 84 #> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : -0.95, -0.75, -0.9, -3.05, -7.90, -12.05, ... -#> max values : 4.70, 4.75, 3.5, 2.20, 0.45, -0.75, ... +#> names : jan, feb, mar, apr, may, jun, ... +#> min values : -55.05, -52.95, -48.75, -41.35, -28, -21.40, ... +#> max values : 26.30, 26.25, 27.40, 27.50, 30, 30.65, ... #> #> $tmx #> class : SpatRaster @@ -328,9 +332,9 @@ CRU_stack #> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) #> coord. ref. : lon/lat WGS 84 #> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 1.35, 1.35, 1.3, -0.75, -4.10, -7.55, ... -#> max values : 12.50, 12.45, 11.1, 9.00, 6.35, 4.75, ... +#> names : jan, feb, mar, apr, may, jun, ... +#> min values : -48.2, -43.35, -41.65, -32.45, -17.55, -11.50, ... +#> max values : 39.7, 38.40, 40.25, 41.85, 43.60, 45.95, ... ``` The `create_CRU_stack()` function works in the same way with only one minor difference. @@ -410,6 +414,6 @@ are compared to an earlier data set at 0.5 degrees latitude/longitude resolution and show added value over most regions. The data will have many applications in applied climatology, biogeochemical modelling, hydrology and agricultural meteorology and are available through the School of Geography Oxford -(https://www.geog.ox.ac.uk/), the International Water Management Institute -"World Water and Climate Atlas" (https://www.iwmi.org/) and the Climatic +(https://www.geog.ox.ac.uk), the International Water Management Institute +"World Water and Climate Atlas" (https://www.iwmi.cgiar.org/) and the Climatic Research Unit (https://www.uea.ac.uk/groups-and-centres/climatic-research-unit). diff --git a/vignettes/plot_t-1.png b/vignettes/plot_t-1.png index ad5d32c9e4602cece768d3be67f03bddc44d13bc..1591135c3f3551c5ebd9c735749615d536c890d3 100644 GIT binary patch literal 126264 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 bk=$^<0jH>wA*IK>KpaYP>ax|+7NP$IhNrh4 literal 33938 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
N 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 LyH%=c750AsCd@ic diff --git a/vignettes/violin_plot-1.png b/vignettes/violin_plot-1.png index 32ed2070a0b85b624a385144cceefc9a8f0ec425..8c7d69729c63b22046f937d1b15bebded77d3fc4 100644 GIT binary patch literal 61761 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%0AJ?%L@n{Q=u;TCbT8A7Z`0#=!@b5#U?n)I%TJ!X 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 We can also generate a violin plot of the same data to visualise how the temperatures change throughout the year. @@ -170,17 +171,18 @@ ggplot(data = t, aes(x = month, y = tmp)) + ```
-plot of chunk violin_plot -

plot of chunk violin_plot

+Monthly values of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991. +

Monthly values of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991.

-#### Saving the tidy `data.frame` as a CSV (comma separated values file) locally +#### Saving the `data.frame` as a CSV (comma separated values file) locally -Save the resulting tidy `data.frame` to local disk as a comma separated (CSV) +Save the resulting `data.frame` to local disk as a comma separated (CSV) file to local disk, using _data.table_'s `fwrite()`. ``` r +library(data.table) fwrite(x = t, file = "~/CRU_tmp.csv") ``` @@ -188,7 +190,7 @@ fwrite(x = t, file = "~/CRU_tmp.csv") For working with spatial data, _getCRUCLdata_ provides a function that create lists of _terra_ stacks of the data. -The `get_CRU_stack()` functions provide similar functionality to `get_CRU_df()`, but rather than returning a tidy data frame, it returns a list of `terra::rast()` objects for use in an R session. +The `get_CRU_stack()` functions provide similar functionality to `get_CRU_df()`, but rather than returning a data frame, it returns a list of `terra::rast()` objects for use in an R session. The `get_CRU_stack()` function automates the download process and creates a `terra::rast()` object of the CRU CL v. 2.0 climatology elements. Illustrated here is creating a `terra::rast()` of all CRU CL v. 2.0 climatology elements available. @@ -209,10 +211,6 @@ CRU_stack <- get_CRU_stack( wnd = TRUE, elv = TRUE ) -#> -|---------|---------|---------|---------| -========================================= - CRU_stack #> $dtr @@ -254,7 +252,7 @@ CRU_stack #> resolution : 0.1666667, 0.1666667 (x, y) #> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) #> coord. ref. : lon/lat WGS 84 -#> source : spat_fe274b2a6660_65063_GdaPwXHptgIOPSx.tif +#> source : spat_613232ecfe11_24882_GdaPwXHptgIOPSx.tif #> names : jan, feb, mar, apr, may, jun, ... #> min values : 0.0, 0.0, 0.0, 0.0, 0, 0.0, ... #> max values : 910.1, 824.3, 727.3, 741.3, 1100, 2512.6, ... diff --git a/vignettes/getCRUCLdata.Rmd.orig b/vignettes/getCRUCLdata.Rmd.orig index 3d389eb..d00894a 100644 --- a/vignettes/getCRUCLdata.Rmd.orig +++ b/vignettes/getCRUCLdata.Rmd.orig @@ -12,6 +12,7 @@ vignette: > %\VignetteDepends{terra} %\VignetteDepends{ggplot2} %\VignetteDepends{viridis} + %\VignetteDepends{data.table} --- ```{r setup, include=FALSE} @@ -71,7 +72,7 @@ The arguments for selecting the climatology elements for importing are: - **dsn** *For `create_CRU_stack()`* and *`create_CRU_df()`* only. Local file path where CRU CL v. 2.0 .dat.gz files are located. -### Creating tidy data frames for use in R +### Creating data frames for use in R The `get_CRU_df()` function automates the download process and creates data frames of the climatology elements. @@ -94,7 +95,7 @@ CRU_data <- get_CRU_df(pre = TRUE, CRU_data ``` -Perhaps you only need one or two elements, it is easy to create a tidy data frame of mean temperature only. +Perhaps you only need one or two elements, it is easy to create a data frame of mean temperature only. ```{r get_t_only, eval=TRUE} t <- get_CRU_df(tmp = TRUE) @@ -102,11 +103,11 @@ t <- get_CRU_df(tmp = TRUE) t ``` -#### Plotting data from the tidy dataframe +#### Plotting data from the data frame Now that we have the data, we can plot it easily using _ggplot2_ and the _viridis_ package for the colour scale. -```{r plot_t, eval=TRUE, message=FALSE} +```{r plot_t, eval=TRUE, message=FALSE, fig.cap="Maps of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991."} library(ggplot2) library(viridis) @@ -120,7 +121,7 @@ ggplot(data = t, aes(x = lon, y = lat, fill = tmp)) + We can also generate a violin plot of the same data to visualise how the temperatures change throughout the year. -```{r violin_plot, eval=TRUE} +```{r violin_plot, eval=TRUE, fig.cap = "Monthly values of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991."} ggplot(data = t, aes(x = month, y = tmp)) + geom_violin() + ylab("Temperature (˚C)") + @@ -128,12 +129,13 @@ ggplot(data = t, aes(x = month, y = tmp)) + subtitle = "Excludes Antarctica") ``` -#### Saving the tidy `data.frame` as a CSV (comma separated values file) locally +#### Saving the `data.frame` as a CSV (comma separated values file) locally -Save the resulting tidy `data.frame` to local disk as a comma separated (CSV) +Save the resulting `data.frame` to local disk as a comma separated (CSV) file to local disk, using _data.table_'s `fwrite()`. ```{r save_t, eval=FALSE} +library(data.table) fwrite(x = t, file = "~/CRU_tmp.csv") ``` @@ -141,7 +143,7 @@ fwrite(x = t, file = "~/CRU_tmp.csv") For working with spatial data, _getCRUCLdata_ provides a function that create lists of _terra_ stacks of the data. -The `get_CRU_stack()` functions provide similar functionality to `get_CRU_df()`, but rather than returning a tidy data frame, it returns a list of `terra::rast()` objects for use in an R session. +The `get_CRU_stack()` functions provide similar functionality to `get_CRU_df()`, but rather than returning a data frame, it returns a list of `terra::rast()` objects for use in an R session. The `get_CRU_stack()` function automates the download process and creates a `terra::rast()` object of the CRU CL v. 2.0 climatology elements. Illustrated here is creating a `terra::rast()` of all CRU CL v. 2.0 climatology elements available. From 7d1087e5b88106a2ac9b3f6f7cfba8b831482d08 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 16 Dec 2024 20:52:22 +0800 Subject: [PATCH 07/60] polish documentation --- DESCRIPTION | 2 +- R/create_CRU_df.R | 6 +++--- codemeta.json | 4 ++-- man/getCRUCLdata-package.Rd | 2 +- vignettes/Advanced_use.Rmd | 3 +-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 9fa85c8..904e3c1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -8,7 +8,7 @@ Authors@R: Description: Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature - and maximum temperature and formats the data into a data frame or a + and maximum temperature and formats the data into a data.table object or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index 53c60af..e2f9935 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -1,9 +1,9 @@ #' Create a data.table of Climatology Variables From Local Disk Files #' #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology -#' data and creates a tidy data frame of the data. If requested, minimum and -#' maximum temperature may also be automatically calculated as described in the -#' data readme.txt file. This function can be useful if you have network +#' data and creates a \CRANpkg{data.table} of the data. If requested, minimum +#' and maximum temperature may also be automatically calculated as described in +#' the data readme.txt file. This function can be useful if you have network #' connection issues that mean automated downloading of the files using \R #' does not work properly. #' diff --git a/codemeta.json b/codemeta.json index f9f5622..35e44ff 100644 --- a/codemeta.json +++ b/codemeta.json @@ -2,7 +2,7 @@ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "identifier": "getCRUCLdata", - "description": "Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature and maximum temperature and formats the data into a data frame or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit, .", + "description": "Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature and maximum temperature and formats the data into a data.table object or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit, .", "name": "getCRUCLdata: 'CRU' 'CL' v. 2.0 Climatology Client", "relatedLink": "https://docs.ropensci.org/getCRUCLdata/", "codeRepository": "https://github.com/ropensci/getCRUCLdata", @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.679KB", + "fileSize": "910.693KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/getCRUCLdata-package.Rd b/man/getCRUCLdata-package.Rd index ec5cf3c..e95db91 100644 --- a/man/getCRUCLdata-package.Rd +++ b/man/getCRUCLdata-package.Rd @@ -6,7 +6,7 @@ \alias{getCRUCLdata-package} \title{getCRUCLdata: 'CRU' 'CL' v. 2.0 Climatology Client} \description{ -Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature and maximum temperature and formats the data into a data frame or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit, \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}. +Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature and maximum temperature and formats the data into a data.table object or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit, \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}. } \seealso{ Useful links: diff --git a/vignettes/Advanced_use.Rmd b/vignettes/Advanced_use.Rmd index 7643474..ec7d743 100644 --- a/vignettes/Advanced_use.Rmd +++ b/vignettes/Advanced_use.Rmd @@ -19,8 +19,7 @@ knitr::opts_chunk$set( ## Caching files for later use When using the `get_CRU_df()` or `get_CRU_stack()` functions, files may be cached in the users' local space for later use (optional) or stored in a temporary directory and deleted when the R session is closed and not saved (this is the default behaviour already illustrated above). -Illustrated here, create a tidy data frame of all CRU CL v. 2.0 climatology elements available and cache -them to save time in the future. +Illustrated here, create a data.table of all CRU CL v. 2.0 climatology elements available and cache them to save time in the future. *In order to take advantage of the cached data, you must use the `get_CRU_df()` function again in the future*. This functionality is somewhat modelled after the raster package's `raster::getData()` that will not download files that already exist in the working directory, however in this case the function is portable and it will work for any working directory. That is, if you have cached the data and you use `get_CRU_df()` again, it will use the cached data no matter what working directory you are in. From 1ea4ac114f21a0548c31d1366397429ab9d9d967 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 09:57:11 +0800 Subject: [PATCH 08/60] Roxygen linting --- DESCRIPTION | 3 +- R/create_CRU_df.R | 55 ++++++------- R/create_CRU_stack.R | 6 +- R/get_CRU_df.R | 59 +++++++------- R/get_CRU_stack.R | 12 ++- R/internal_functions.R | 168 ++++++++++++++++++++-------------------- R/manage_cached_files.R | 4 +- codemeta.json | 2 +- man/create_CRU_df.Rd | 61 ++++++++------- man/create_CRU_stack.Rd | 55 ++++++------- man/get_CRU_df.Rd | 59 +++++++------- man/get_CRU_stack.Rd | 64 ++++++++------- man/manage_cache.Rd | 4 +- 13 files changed, 276 insertions(+), 276 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 904e3c1..e308643 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -51,7 +51,8 @@ Config/testthat/parallel: true Encoding: UTF-8 Language: en-US Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", - "roxyglobals::global_roclet")) + "roxyglobals::global_roclet", "roxylint::roxylint")) +Config/roxylint: list(linters = roxylint::tidy) RoxygenNote: 7.3.2 X-schema.org-applicationCategory: Tools X-schema.org-isPartOf: https://ropensci.org diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index e2f9935..15a3b9b 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -1,4 +1,4 @@ -#' Create a data.table of Climatology Variables From Local Disk Files +#' Create a data.table of CRU CL 2.0 climatology elements from local disk files #' #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology #' data and creates a \CRANpkg{data.table} of the data. If requested, minimum @@ -9,32 +9,33 @@ #' #' @inheritSection get_CRU_df Nomenclature and Units #' -#' @param pre Boolean. Load precipitation (millimetres/month) from server and -#' return in the data frame? Defaults to `FALSE`. -#' @param pre_cv Boolean. Load cv of precipitation (percent) from server and -#' return in the data frame? Defaults to `FALSE`. NOTE. Setting this to -#' `TRUE` will always results in **pre** being set to `TRUE` and +#' @param pre Loads precipitation (millimetres/month) from server and +#' returns in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param pre_cv Loads cv of precipitation (percent) from server and +#' returns in the data frame, `TRUE`. Defaults to `FALSE`. NOTE. Setting this +#' to `TRUE` will always results in **pre** being set to `TRUE` and #' returned as well. -#' @param rd0 Boolean. Load wet-days (number days with >0.1millimetres rain per -#' month) and return in the data frame? Defaults to `FALSE`. -#' @param dtr Boolean. Load mean diurnal temperature range (degrees Celsius) -#' and return it in the data frame? Defaults to `FALSE`. -#' @param tmp Boolean. Load temperature (degrees Celsius) and return it in the -#' data frame? Defaults to `FALSE`. -#' @param tmn Boolean. Calculate minimum temperature values (degrees Celsius) -#' and return it in the data frame? Defaults to `FALSE`. -#' @param tmx Boolean. Calculate maximum temperature (degrees Celsius) and -#' return it in the data frame? Defaults to `FALSE`. -#' @param reh Boolean. Load relative humidity and return it in the data frame? +#' @param rd0 Loads wet-days (number days with >0.1millimetres rain per +#' month) and returns in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param dtr Loads mean diurnal temperature range (degrees Celsius) +#' and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmp Loads temperature (degrees Celsius) and returns it in the +#' data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmn Calculate minimum temperature values (degrees Celsius) +#' and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmx Calculate maximum temperature (degrees Celsius) and +#' return it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param reh Loads relative humidity and returns it in the data frame, `TRUE`. #' Defaults to `FALSE`. -#' @param sunp Boolean. Load sunshine, percent of maximum possible (percent of -#' day length) and return it in the data frame? Defaults to `FALSE`. -#' @param frs Boolean. Load ground-frost records (number of days with ground- -#' frost per month) and return it in the data frame? Defaults to `FALSE`. -#' @param wnd Boolean. Load 10m wind speed (metres/second) and return it in the -#' data frame? Defaults to `FALSE`. -#' @param elv Boolean. Load elevation (converted to metres) and return it in -#' the data frame? Defaults to `FALSE`. +#' @param sunp Loads sunshine, percent of maximum possible (percent of +#' day length) and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param frs Loads ground-frost records (number of days with ground- +#' frost per month) and returns it in the data frame, `TRUE`. Defaults to +#' `FALSE`. +#' @param wnd Load 10m wind speed (metres/second) and returns it in the +#' data frame, `TRUE`. Defaults to `FALSE`. +#' @param elv Loads elevation (converted to metres) and returns it in +#' the data frame, `TRUE`. Defaults to `FALSE`. #' @param dsn Local file path where \acronym{CRU} \acronym{CL} v.2.0 .dat.gz #' files are located. #' @@ -52,10 +53,10 @@ #' CRU_tmp #' #' @seealso -#' [get_CRU_df()] +#' [get_CRU_df]. #' #' @return A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -#' climatology elements +#' climatology elements. #' #' @author Adam H Sparks, \email{adamhsparks@@gmail.com} #' diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index e06ae47..b2e545f 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -1,4 +1,4 @@ -#' Create a List of terra rast Objects From Local Disk Files +#' Create a list of terra rast objects of CRU CL 2.0 climatology elements from local disk files #' #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology #' data and creates a \CRANpkg{terra} [terra::rast] object of the @@ -22,10 +22,10 @@ #' CRU_tmp #' #' @seealso -#' [get_CRU_stack()] +#' [get_CRU_stack]. #' #' @return A [base::list] of [terra::rast] objects of \acronym{CRU} \acronym{CL} -#' v. 2.0 climatology elements +#' v. 2.0 climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index aa19334..ce71b9c 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -1,4 +1,4 @@ -#' Download and Create a data.table of Climatology Parameters +#' Download and create a data.table of CRU CL 2.0 climatology elements #' #' This function automates downloading and importing \acronym{CRU} #' \acronym{CL} v. 2.0 climatology data and creates a \CRANpkg{data.table} of @@ -25,36 +25,36 @@ #' For more information see the description of the data provided by #' \acronym{CRU}, #' -#' @param pre Boolean. Fetch precipitation (millimetres/month) from server and -#' return in the data frame? Defaults to `FALSE`. -#' @param pre_cv Boolean. Fetch cv of precipitation (percent) from server and -#' return in the data frame? Defaults to `FALSE`. NOTE. Setting this to -#' `TRUE` will always results in **pre** being set to `TRUE` and +#' @param pre Fetches precipitation (millimetres/month) from server and +#' returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param pre_cv Fetch cv of precipitation (percent) from server and +#' returns it in the data frame, `TRUE`. Defaults to `FALSE`. NOTE Setting +#' this to `TRUE` will always results in **pre** being set to `TRUE` and #' returned as well. -#' @param rd0 Boolean. Fetch wet-days (number days with >0.1 millimetres rain -#' per month) and return in the data frame? Defaults to `FALSE`. -#' @param dtr Boolean. Fetch mean diurnal temperature range (degrees Celsius) -#' and return it in the data frame? Defaults to `FALSE`. -#' @param tmp Boolean. Fetch temperature (degrees Celsius) and return it in the -#' data frame? Defaults to `FALSE`. -#' @param tmn Boolean. Calculate minimum temperature values (degrees Celsius) -#' and return it in the data frame? Defaults to `FALSE`. -#' @param tmx Boolean. Calculate maximum temperature (degrees Celsius) and -#' return it in the data frame? Defaults to `FALSE`. -#' @param reh Boolean. Fetch relative humidity and return it in the data frame? -#' Defaults to FALSE. -#' @param sunp Boolean. Fetch sunshine, percent of maximum possible (percent of +#' @param rd0 Fetches wet-days (number days with >0.1 millimetres rain +#' per month) and returns it in the data frame? Defaults to `FALSE`. +#' @param dtr Fetches mean diurnal temperature range (degrees Celsius) +#' and returns it in the data frame? Defaults to `FALSE`. +#' @param tmp Fetches temperature (degrees Celsius) and returns it in the +#' data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmn Calculates minimum temperature values (degrees Celsius) +#' and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmx Calculates maximum temperature (degrees Celsius) and +#' returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param reh Fetches relative humidity and returns it in the data frame, +#' `TRUE`. Defaults to FALSE. +#' @param sunp Fetch sunshine, percent of maximum possible (percent of #' day length) and return it in the data frame? Defaults to `FALSE`. -#' @param frs Boolean. Fetch ground-frost records (number of days with ground- +#' @param frs Fetches ground-frost records (number of days with ground- #' frost per month) and return it in the data frame? Defaults to `FALSE`. -#' @param wnd Boolean. Fetch 10m wind speed (metres/second) and return it in the -#' data frame? Defaults to `FALSE`. -#' @param elv Boolean. Fetch elevation (converted to metres) and return it in -#' the data frame? Defaults to `FALSE`. -#' @param cache Boolean. Store CRU CL v. 2.0 data files locally for later use? -#' If `FALSE`, the downloaded files are removed when R session is closed. +#' @param wnd Fetches 10m wind speed (metres/second) and returns it in the +#' data frame, `TRUE`. Defaults to `FALSE`. +#' @param elv Fetches elevation (converted to metres) and returns it in +#' the data frame, `TRUE`. Defaults to `FALSE`. +#' @param cache Stores CRU CL v. 2.0 data files locally for later use. +#' If `FALSE`, the downloaded files are removed when the \R session is closed. #' To take advantage of cached files in future sessions, use `cache = TRUE` -#' after the initial download and caching. Defaults to `FALSE`. +#' even after the initial download and caching. Defaults to `FALSE`. #' #' @examplesIf interactive() #' # Download data and create a data frame of precipitation and temperature @@ -65,11 +65,10 @@ #' CRU_pre_tmp #' #' @seealso -#' [create_CRU_stack()] -#' [manage_cache()] +#' [create_CRU_stack], [manage_cache]. #' #' @return A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -#' climatology elements +#' climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index af83a75..b02ab1b 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -1,8 +1,8 @@ -#' Download and Create a List of terra rast Objects of Climatology Parameters +#' Download and create a list of terra rast objects of CRU CL 2.0 climatology elements #' #' This function automates downloading and importing CRU CL v. 2.0 #' climatology data into \R and creates a list of \CRANpkg{terra} -#' [terra::rast()] objects of the data. If requested, minimum and maximum +#' [terra::rast] objects of the data. If requested, minimum and maximum #' temperature may also be automatically calculated as described in the data #' readme.txt file. Data may be cached for later use by this function, saving #' time downloading files in future using this function. @@ -17,13 +17,11 @@ #' #' CRU_pre_tmp #' -#' #' @seealso -#' [create_CRU_stack()] -#' [manage_cache()] +#' [create_CRU_stack], [manage_cache]. #' -#' @return A [base::list()] of [terra::rast] objects of CRU CL v. 2.0 -#' climatology elements +#' @return A [base::list] of [terra::rast] objects of CRU CL v. 2.0 +#' climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' diff --git a/R/internal_functions.R b/R/internal_functions.R index 8645c17..1def32e 100644 --- a/R/internal_functions.R +++ b/R/internal_functions.R @@ -1,30 +1,31 @@ -#' Check That at Least One var is Requested -#' @param pre Boolean. Fetch precipitation (millimetres/month) from server and -#' return in the data frame? Defaults to `FALSE`. -#' @param pre_cv Boolean. Fetch cv of precipitation (percent) from server and -#' return in the data frame? Defaults to `FALSE`. NOTE. Setting this to -#' `TRUE` will always results in **pre** being set to `TRUE` and +#' Check that at least one element is requested +#' @param pre Fetches precipitation (millimetres/month) from server and +#' returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param pre_cv Fetches cv of precipitation (percent) from server and +#' returns it in the data frame, `TRUE`. Defaults to `FALSE`. Note, setting +#' this to `TRUE` will always results in **pre** being set to `TRUE` and #' returned as well. -#' @param rd0 Boolean. Fetch wet-days (number days with >0.1 millimetres rain -#' per month) and return in the data frame? Defaults to `FALSE`. -#' @param dtr Boolean. Fetch mean diurnal temperature range (degrees Celsius) -#' and return it in the data frame? Defaults to `FALSE`. -#' @param tmp Boolean. Fetch temperature (degrees Celsius) and return it in the -#' data frame? Defaults to `FALSE`. -#' @param tmn Boolean. Calculate minimum temperature values (degrees Celsius) -#' and return it in the data frame? Defaults to `FALSE`. -#' @param tmx Boolean. Calculate maximum temperature (degrees Celsius) and -#' return it in the data frame? Defaults to `FALSE`. -#' @param reh Boolean. Fetch relative humidity and return it in the data frame? -#' Defaults to `FALSE`. -#' @param sunp Boolean. Fetch sunshine, percent of maximum possible (percent of -#' day length) and return it in data frame? Defaults to `FALSE`. -#' @param frs Boolean. Fetch ground-frost records (number of days with ground- -#' frost per month) and return it in data frame? Defaults to `FALSE`. -#' @param wnd Boolean. Fetch 10m wind speed (metres/second) and return it in the -#' data frame? Defaults to `FALSE`. -#' @param elv Boolean. Fetch elevation (converted to metres) and return it in -#' the data frame? Defaults to `FALSE`. +#' @param rd0 Fetches wet-days (number days with >0.1 millimetres rain per +#' month) and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param dtr Fetches mean diurnal temperature range (degrees Celsius) +#' and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmp Fetches temperature (degrees Celsius) and returns it in the +#' data frame, `TRUE`. Defaults to `FALSE`. +#' @param tmn Calculates minimum temperature values (degrees Celsius) +#' and returns it in the data frame. Defaults to `FALSE`. +#' @param tmx Boolean. Calculates maximum temperature (degrees Celsius) and +#' returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param reh Fetches relative humidity and returns it in the data frame, +#' `TRUE`. Defaults to `FALSE`. +#' @param sunp Fetches sunshine, percent of maximum possible (percent of +#' day length), and returns it in the data frame, `TRUE`. Defaults to `FALSE`. +#' @param frs Boolean. Fetches ground-frost records (number of days with +#' ground-frost per month) and returns it in data frame, `TRUE`. Defaults to +#' `FALSE`. +#' @param wnd Fetches 10m wind speed (metres/second) and returns it in the data +#' frame, `TRUE`. Defaults to `FALSE`. +#' @param elv Fetches elevation (converted to metres) and returns it in the +#' data frame, `TRUE`. Defaults to `FALSE`. #' #' @examples #' .check_vars_FALSE( @@ -64,9 +65,9 @@ } } -#' Validates User Entered dsn Value +#' Validates user entered dsn value #' -#' @param dsn User provided value for checking +#' @param dsn User provided value for checking. #' @keywords Internal #' @noRd .validate_dsn <- function(dsn) { @@ -95,23 +96,22 @@ } } -#' Creates a Data Frame From the CRU Data +#' Creates a data.table from the CRU data #' -#' @param tmn Is tmn to be calculated? Boolean -#' @param tmn Is tmx to be calculated? Boolean -#' @param dtr Is dtr to be returned? Boolean -#' @param pre Is pre to be returned? Boolean -#' @param pre_cv Is pre_cv to be returned? Boolean -#' @param elv Is elv to be returned? Boolean -#' @param files File list to be used for creating data frame +#' @param tmn Is tmn to be calculated? Boolean. +#' @param tmn Is tmx to be calculated? Boolean. +#' @param dtr Is dtr to be returned? Boolean. +#' @param pre Is pre to be returned? Boolean. +#' @param pre_cv Is pre_cv to be returned? Boolean. +#' @param elv Is elv to be returned? Boolean. +#' @param files File list to be used for creating data frame. #' -#' @return A \CRANpkg{data.table} of all requested values +#' @return A \CRANpkg{data.table} of all requested values. #' @keywords Internal #' @autoglobal #' @noRd .create_df <- function(tmn, tmx, tmp, dtr, pre, pre_cv, elv, files) { - CRU_df <- .tidy_df(pre_cv, elv, tmn, tmx, .files = files) @@ -184,8 +184,8 @@ #' Read Files From Local cache #' -#' @param .files a list of CRU CL2.0 files in local storage -#' @param .pre_cv `Boolean` return pre_cv in the data? +#' @param .files a list of CRU CL2.0 files in local storage. +#' @param .pre_cv `Boolean` return pre_cv in the data. #' #' @keywords Internal #' @autoglobal @@ -269,18 +269,18 @@ } -#' Create terra rast Objects +#' Create terra rast objects #' -#' @param pre Boolean Return precipitation in the `rast`? -#' @param pre_cv Boolean. Return cv of precipitation (percent) in the `rast`? -#' @param dtr Boolean. Return mean diurnal temperature range (degrees Celsius) -#' in the `rast`? -#' @param tmp Boolean. Return temperature (degrees Celsius) in the `rast`? -#' @param tmn Boolean. Return minimum temperature values (degrees Celsius) -#' in the `rast`? -#' @param tmx Boolean. Return maximum temperature (degrees Celsius) in the -#' `rast`? -#' @param files List. Files that are to be used in creating the `rast` object. +#' @param pre Return precipitation in the `rast`, Boolean. +#' @param pre_cv Return cv of precipitation (percent) in the `rast`, Boolean. +#' @param dtr Return mean diurnal temperature range (degrees Celsius) +#' in the `rast`, Boolean. +#' @param tmp Return temperature (degrees Celsius) in the `rast`, Boolean. +#' @param tmn Return minimum temperature values (degrees Celsius) +#' in the `rast`, Boolean. +#' @param tmx Return maximum temperature (degrees Celsius) in the +#' `rast`, Boolean. +#' @param files List. Files that are to be used in creating the `rast` object. #' #' @keywords Internal #' @autoglobal @@ -353,11 +353,11 @@ #' Helper Function Used in .create_stacks() #' -#' @param files a list of files to use in creating `rast` objects -#' @param wrld an empty [terra::rast] object for filling with values -#' @param month_names A vector of month names from jan -- dec -#' @param pre `Boolean` include precipitation? -#' @param pre_cv `Boolean` include preciptation cv? +#' @param files A list of files to use in creating `rast` objects. +#' @param wrld An empty [terra::rast] object for filling with values. +#' @param month_names A vector of month names from jan -- dec. +#' @param pre `Boolean` include precipitation. +#' @param pre_cv `Boolean` include preciptation cv. #' #' @autoglobal #' @keywords Internal @@ -435,15 +435,17 @@ #' Creates local directory for caching and/or uses it for local caching or #' uses the \R session `tempdir()`. #' -#' @param cache `Boolean` (create) and use local file cache? +#' @param cache `Boolean` (create) and use local file cache. #' #' @keywords Internal #' @noRd .set_cache <- function(cache) { manage_cache <- hoardr::hoard() - manage_cache$cache_path_set(path = "getCRUCLdata", - prefix = "org.R-project.R/R", - type = "user_cache_dir") + manage_cache$cache_path_set( + path = "getCRUCLdata", + prefix = "org.R-project.R/R", + type = "user_cache_dir" + ) if (cache) { if (!dir.exists(manage_cache$cache_path_get())) { manage_cache$mkdir() @@ -457,29 +459,29 @@ #' Create a List of Locally Cached Files for Import #' -#' @param pre Boolean. Load precipitation (millimetres/month) from server and -#' return in the data frame? -#' @param pre_cv Boolean. Load cv of precipitation (percent) from server and -#' return in the data frame? -#' @param rd0 Boolean. Load wet-days (number days with >0.1 millimetres rain -#' per month) and return in the data frame? -#' @param dtr Boolean. Load mean diurnal temperature range (degrees Celsius) -#' and return it in the data frame? -#' @param tmp Boolean. Load temperature (degrees Celsius) and return it in the -#' data frame? -#' @param tmn Boolean. Calculate minimum temperature values (degrees Celsius) -#' and return it in the data frame? -#' @param tmx Boolean. Calculate maximum temperature (degrees Celsius) and -#' return it in the data frame? -#' @param reh Boolean. Load relative humidity and return it in the data frame? -#' @param sunp Boolean. Load sunshine, percent of maximum possible (percent of -#' day length) and return it in data frame? -#' @param frs Boolean. Load ground-frost records (number of days with ground- -#' frost per month) and return it in data frame? -#' @param wnd Boolean. Load 10m wind speed (metres/second) and return it in the -#' data frame? -#' @param elv Boolean. Load elevation (converted to metres) and return it in -#' the data frame? +#' @param pre Boolean, loads precipitation (millimetres/month) from server and +#' returns in the data frame. +#' @param pre_cv Boolean, loads cv of precipitation (percent) from server and +#' returns in the data frame. +#' @param rd0 Boolean, loads wet-days (number days with >0.1 millimetres rain +#' per month) and returns in the data frame. +#' @param dtr Boolean, loads mean diurnal temperature range (degrees Celsius) +#' and returns it in the data frame. +#' @param tmp Boolean, loads temperature (degrees Celsius) and returns it in +#' the data frame. +#' @param tmn Boolean, calculates minimum temperature values (degrees Celsius) +#' and returns it in the data frame. +#' @param tmx Boolean, calculatex maximum temperature (degrees Celsius) and +#' returns it in the data frame. +#' @param reh Boolean, loads relative humidity and return it in the data frame. +#' @param sunp Boolean, loads sunshine, percent of maximum possible (percent of +#' day length) and returns it in data frame. +#' @param frs Boolean, loads ground-frost records (number of days with ground- +#' frost per month) and return it in data frame. +#' @param wnd Boolean, loads 10m wind speed (metres/second) and returns it in +#' the data frame. +#' @param elv Boolean, loads elevation (converted to metres) and returns it in +#' the data frame. #' #' @keywords Internal #' @noRd diff --git a/R/manage_cached_files.R b/R/manage_cached_files.R index 628f946..0ec97e7 100644 --- a/R/manage_cached_files.R +++ b/R/manage_cached_files.R @@ -1,6 +1,6 @@ #' Manage locally cached CRU CL v. 2.0 files #' -#' Manage cached \pkg{getCRUCLdata} files with \CRANpkg{hoardr} +#' Manage cached \pkg{getCRUCLdata} files with \CRANpkg{hoardr}. #' #' @export #' @name manage_cache @@ -13,7 +13,7 @@ #' `manage_cache$cache_delete_all` #' does not accept any names, but deletes all files. For deleting many specific #' files, use `manage_cache$cache_delete` in an -#' [base::lapply()] type call. +#' [base::lapply] type call. #' #' @section Useful user functions: #' \itemize{ diff --git a/codemeta.json b/codemeta.json index 35e44ff..289cfe8 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.693KB", + "fileSize": "910.877KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 21fcd18..70087bc 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/create_CRU_df.R \name{create_CRU_df} \alias{create_CRU_df} -\title{Create a data.table of Climatology Variables From Local Disk Files} +\title{Create a data.table of CRU CL 2.0 climatology elements from local disk files} \usage{ create_CRU_df( pre = FALSE, @@ -21,56 +21,57 @@ create_CRU_df( ) } \arguments{ -\item{pre}{Boolean. Load precipitation (millimetres/month) from server and -return in the data frame? Defaults to \code{FALSE}.} +\item{pre}{Loads precipitation (millimetres/month) from server and +returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{pre_cv}{Boolean. Load cv of precipitation (percent) from server and -return in the data frame? Defaults to \code{FALSE}. NOTE. Setting this to -\code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and +\item{pre_cv}{Loads cv of precipitation (percent) from server and +returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}. NOTE. Setting this +to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and returned as well.} -\item{rd0}{Boolean. Load wet-days (number days with >0.1millimetres rain per -month) and return in the data frame? Defaults to \code{FALSE}.} +\item{rd0}{Loads wet-days (number days with >0.1millimetres rain per +month) and returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmp}{Boolean. Load temperature (degrees Celsius) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{tmp}{Loads temperature (degrees Celsius) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{dtr}{Boolean. Load mean diurnal temperature range (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{dtr}{Loads mean diurnal temperature range (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{reh}{Boolean. Load relative humidity and return it in the data frame? +\item{reh}{Loads relative humidity and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmn}{Boolean. Calculate minimum temperature values (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{tmn}{Calculate minimum temperature values (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmx}{Boolean. Calculate maximum temperature (degrees Celsius) and -return it in the data frame? Defaults to \code{FALSE}.} +\item{tmx}{Calculate maximum temperature (degrees Celsius) and +return it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{sunp}{Boolean. Load sunshine, percent of maximum possible (percent of -day length) and return it in the data frame? Defaults to \code{FALSE}.} +\item{sunp}{Loads sunshine, percent of maximum possible (percent of +day length) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{frs}{Boolean. Load ground-frost records (number of days with ground- -frost per month) and return it in the data frame? Defaults to \code{FALSE}.} +\item{frs}{Loads ground-frost records (number of days with ground- +frost per month) and returns it in the data frame, \code{TRUE}. Defaults to +\code{FALSE}.} -\item{wnd}{Boolean. Load 10m wind speed (metres/second) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{wnd}{Load 10m wind speed (metres/second) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{elv}{Boolean. Load elevation (converted to metres) and return it in -the data frame? Defaults to \code{FALSE}.} +\item{elv}{Loads elevation (converted to metres) and returns it in +the data frame, \code{TRUE}. Defaults to \code{FALSE}.} \item{dsn}{Local file path where \acronym{CRU} \acronym{CL} v.2.0 .dat.gz files are located.} } \value{ A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -climatology elements +climatology elements. } \description{ Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology -data and creates a tidy data frame of the data. If requested, minimum and -maximum temperature may also be automatically calculated as described in the -data readme.txt file. This function can be useful if you have network +data and creates a \CRANpkg{data.table} of the data. If requested, minimum +and maximum temperature may also be automatically calculated as described in +the data readme.txt file. This function can be useful if you have network connection issues that mean automated downloading of the files using \R does not work properly. } @@ -114,7 +115,7 @@ CRU_tmp \dontshow{\}) # examplesIf} } \seealso{ -\code{\link[=get_CRU_df]{get_CRU_df()}} +\link{get_CRU_df}. } \author{ Adam H Sparks, \email{adamhsparks@gmail.com} diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 0b5a8b0..cb9abdd 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/create_CRU_stack.R \name{create_CRU_stack} \alias{create_CRU_stack} -\title{Create a List of terra rast Objects From Local Disk Files} +\title{Create a list of terra rast objects of CRU CL 2.0 climatology elements from local disk files} \usage{ create_CRU_stack( pre = FALSE, @@ -21,50 +21,51 @@ create_CRU_stack( ) } \arguments{ -\item{pre}{Boolean. Load precipitation (millimetres/month) from server and -return in the data frame? Defaults to \code{FALSE}.} +\item{pre}{Loads precipitation (millimetres/month) from server and +returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{pre_cv}{Boolean. Load cv of precipitation (percent) from server and -return in the data frame? Defaults to \code{FALSE}. NOTE. Setting this to -\code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and +\item{pre_cv}{Loads cv of precipitation (percent) from server and +returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}. NOTE. Setting this +to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and returned as well.} -\item{rd0}{Boolean. Load wet-days (number days with >0.1millimetres rain per -month) and return in the data frame? Defaults to \code{FALSE}.} +\item{rd0}{Loads wet-days (number days with >0.1millimetres rain per +month) and returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmp}{Boolean. Load temperature (degrees Celsius) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{tmp}{Loads temperature (degrees Celsius) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{dtr}{Boolean. Load mean diurnal temperature range (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{dtr}{Loads mean diurnal temperature range (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{reh}{Boolean. Load relative humidity and return it in the data frame? +\item{reh}{Loads relative humidity and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmn}{Boolean. Calculate minimum temperature values (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{tmn}{Calculate minimum temperature values (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmx}{Boolean. Calculate maximum temperature (degrees Celsius) and -return it in the data frame? Defaults to \code{FALSE}.} +\item{tmx}{Calculate maximum temperature (degrees Celsius) and +return it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{sunp}{Boolean. Load sunshine, percent of maximum possible (percent of -day length) and return it in the data frame? Defaults to \code{FALSE}.} +\item{sunp}{Loads sunshine, percent of maximum possible (percent of +day length) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{frs}{Boolean. Load ground-frost records (number of days with ground- -frost per month) and return it in the data frame? Defaults to \code{FALSE}.} +\item{frs}{Loads ground-frost records (number of days with ground- +frost per month) and returns it in the data frame, \code{TRUE}. Defaults to +\code{FALSE}.} -\item{wnd}{Boolean. Load 10m wind speed (metres/second) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{wnd}{Load 10m wind speed (metres/second) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{elv}{Boolean. Load elevation (converted to metres) and return it in -the data frame? Defaults to \code{FALSE}.} +\item{elv}{Loads elevation (converted to metres) and returns it in +the data frame, \code{TRUE}. Defaults to \code{FALSE}.} \item{dsn}{Local file path where \acronym{CRU} \acronym{CL} v.2.0 .dat.gz files are located.} } \value{ A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of \acronym{CRU} \acronym{CL} -v. 2.0 climatology elements +v. 2.0 climatology elements. } \description{ Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology @@ -117,7 +118,7 @@ CRU_tmp \dontshow{\}) # examplesIf} } \seealso{ -\code{\link[=get_CRU_stack]{get_CRU_stack()}} +\link{get_CRU_stack}. } \author{ Adam H. Sparks, \email{adamhsparks@gmail.com} diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index 8b4a7d1..e461434 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/get_CRU_df.R \name{get_CRU_df} \alias{get_CRU_df} -\title{Download and Create a data.table of Climatology Parameters} +\title{Download and create a data.table of CRU CL 2.0 climatology elements} \usage{ get_CRU_df( pre = FALSE, @@ -21,52 +21,52 @@ get_CRU_df( ) } \arguments{ -\item{pre}{Boolean. Fetch precipitation (millimetres/month) from server and -return in the data frame? Defaults to \code{FALSE}.} +\item{pre}{Fetches precipitation (millimetres/month) from server and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{pre_cv}{Boolean. Fetch cv of precipitation (percent) from server and -return in the data frame? Defaults to \code{FALSE}. NOTE. Setting this to -\code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and +\item{pre_cv}{Fetch cv of precipitation (percent) from server and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}. NOTE Setting +this to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and returned as well.} -\item{rd0}{Boolean. Fetch wet-days (number days with >0.1 millimetres rain -per month) and return in the data frame? Defaults to \code{FALSE}.} +\item{rd0}{Fetches wet-days (number days with >0.1 millimetres rain +per month) and returns it in the data frame? Defaults to \code{FALSE}.} -\item{tmp}{Boolean. Fetch temperature (degrees Celsius) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{tmp}{Fetches temperature (degrees Celsius) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{dtr}{Boolean. Fetch mean diurnal temperature range (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{dtr}{Fetches mean diurnal temperature range (degrees Celsius) +and returns it in the data frame? Defaults to \code{FALSE}.} -\item{reh}{Boolean. Fetch relative humidity and return it in the data frame? -Defaults to FALSE.} +\item{reh}{Fetches relative humidity and returns it in the data frame, +\code{TRUE}. Defaults to FALSE.} -\item{tmn}{Boolean. Calculate minimum temperature values (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{tmn}{Calculates minimum temperature values (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmx}{Boolean. Calculate maximum temperature (degrees Celsius) and -return it in the data frame? Defaults to \code{FALSE}.} +\item{tmx}{Calculates maximum temperature (degrees Celsius) and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{sunp}{Boolean. Fetch sunshine, percent of maximum possible (percent of +\item{sunp}{Fetch sunshine, percent of maximum possible (percent of day length) and return it in the data frame? Defaults to \code{FALSE}.} -\item{frs}{Boolean. Fetch ground-frost records (number of days with ground- +\item{frs}{Fetches ground-frost records (number of days with ground- frost per month) and return it in the data frame? Defaults to \code{FALSE}.} -\item{wnd}{Boolean. Fetch 10m wind speed (metres/second) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{wnd}{Fetches 10m wind speed (metres/second) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{elv}{Boolean. Fetch elevation (converted to metres) and return it in -the data frame? Defaults to \code{FALSE}.} +\item{elv}{Fetches elevation (converted to metres) and returns it in +the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{cache}{Boolean. Store CRU CL v. 2.0 data files locally for later use? -If \code{FALSE}, the downloaded files are removed when R session is closed. +\item{cache}{Stores CRU CL v. 2.0 data files locally for later use. +If \code{FALSE}, the downloaded files are removed when the \R session is closed. To take advantage of cached files in future sessions, use \code{cache = TRUE} -after the initial download and caching. Defaults to \code{FALSE}.} +even after the initial download and caching. Defaults to \code{FALSE}.} } \value{ A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -climatology elements +climatology elements. } \description{ This function automates downloading and importing \acronym{CRU} @@ -111,8 +111,7 @@ CRU_pre_tmp \dontshow{\}) # examplesIf} } \seealso{ -\code{\link[=create_CRU_stack]{create_CRU_stack()}} -\code{\link[=manage_cache]{manage_cache()}} +\link{create_CRU_stack}, \link{manage_cache}. } \author{ Adam H. Sparks, \email{adamhsparks@gmail.com} diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index b216ca6..a641ee0 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/get_CRU_stack.R \name{get_CRU_stack} \alias{get_CRU_stack} -\title{Download and Create a List of terra rast Objects of Climatology Parameters} +\title{Download and create a list of terra rast objects of CRU CL 2.0 climatology elements} \usage{ get_CRU_stack( pre = FALSE, @@ -21,57 +21,57 @@ get_CRU_stack( ) } \arguments{ -\item{pre}{Boolean. Fetch precipitation (millimetres/month) from server and -return in the data frame? Defaults to \code{FALSE}.} +\item{pre}{Fetches precipitation (millimetres/month) from server and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{pre_cv}{Boolean. Fetch cv of precipitation (percent) from server and -return in the data frame? Defaults to \code{FALSE}. NOTE. Setting this to -\code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and +\item{pre_cv}{Fetch cv of precipitation (percent) from server and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}. NOTE Setting +this to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and returned as well.} -\item{rd0}{Boolean. Fetch wet-days (number days with >0.1 millimetres rain -per month) and return in the data frame? Defaults to \code{FALSE}.} +\item{rd0}{Fetches wet-days (number days with >0.1 millimetres rain +per month) and returns it in the data frame? Defaults to \code{FALSE}.} -\item{tmp}{Boolean. Fetch temperature (degrees Celsius) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{tmp}{Fetches temperature (degrees Celsius) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{dtr}{Boolean. Fetch mean diurnal temperature range (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{dtr}{Fetches mean diurnal temperature range (degrees Celsius) +and returns it in the data frame? Defaults to \code{FALSE}.} -\item{reh}{Boolean. Fetch relative humidity and return it in the data frame? -Defaults to FALSE.} +\item{reh}{Fetches relative humidity and returns it in the data frame, +\code{TRUE}. Defaults to FALSE.} -\item{tmn}{Boolean. Calculate minimum temperature values (degrees Celsius) -and return it in the data frame? Defaults to \code{FALSE}.} +\item{tmn}{Calculates minimum temperature values (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{tmx}{Boolean. Calculate maximum temperature (degrees Celsius) and -return it in the data frame? Defaults to \code{FALSE}.} +\item{tmx}{Calculates maximum temperature (degrees Celsius) and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{sunp}{Boolean. Fetch sunshine, percent of maximum possible (percent of +\item{sunp}{Fetch sunshine, percent of maximum possible (percent of day length) and return it in the data frame? Defaults to \code{FALSE}.} -\item{frs}{Boolean. Fetch ground-frost records (number of days with ground- +\item{frs}{Fetches ground-frost records (number of days with ground- frost per month) and return it in the data frame? Defaults to \code{FALSE}.} -\item{wnd}{Boolean. Fetch 10m wind speed (metres/second) and return it in the -data frame? Defaults to \code{FALSE}.} +\item{wnd}{Fetches 10m wind speed (metres/second) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{elv}{Boolean. Fetch elevation (converted to metres) and return it in -the data frame? Defaults to \code{FALSE}.} +\item{elv}{Fetches elevation (converted to metres) and returns it in +the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{cache}{Boolean. Store CRU CL v. 2.0 data files locally for later use? -If \code{FALSE}, the downloaded files are removed when R session is closed. +\item{cache}{Stores CRU CL v. 2.0 data files locally for later use. +If \code{FALSE}, the downloaded files are removed when the \R session is closed. To take advantage of cached files in future sessions, use \code{cache = TRUE} -after the initial download and caching. Defaults to \code{FALSE}.} +even after the initial download and caching. Defaults to \code{FALSE}.} } \value{ -A \code{\link[base:list]{base::list()}} of \link[terra:rast]{terra::rast} objects of CRU CL v. 2.0 -climatology elements +A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of CRU CL v. 2.0 +climatology elements. } \description{ This function automates downloading and importing CRU CL v. 2.0 climatology data into \R and creates a list of \CRANpkg{terra} -\code{\link[terra:rast]{terra::rast()}} objects of the data. If requested, minimum and maximum +\link[terra:rast]{terra::rast} objects of the data. If requested, minimum and maximum temperature may also be automatically calculated as described in the data readme.txt file. Data may be cached for later use by this function, saving time downloading files in future using this function. @@ -113,12 +113,10 @@ For more information see the description of the data provided by CRU_pre_tmp <- get_CRU_stack(pre = TRUE, tmp = TRUE) CRU_pre_tmp - \dontshow{\}) # examplesIf} } \seealso{ -\code{\link[=create_CRU_stack]{create_CRU_stack()}} -\code{\link[=manage_cache]{manage_cache()}} +\link{create_CRU_stack}, \link{manage_cache}. } \author{ Adam H. Sparks, \email{adamhsparks@gmail.com} diff --git a/man/manage_cache.Rd b/man/manage_cache.Rd index 8a795de..fe2cb81 100644 --- a/man/manage_cache.Rd +++ b/man/manage_cache.Rd @@ -4,7 +4,7 @@ \alias{manage_cache} \title{Manage locally cached CRU CL v. 2.0 files} \description{ -Manage cached \pkg{getCRUCLdata} files with \CRANpkg{hoardr} +Manage cached \pkg{getCRUCLdata} files with \CRANpkg{hoardr}. } \details{ The default cache directory is @@ -15,7 +15,7 @@ set your own path using \code{manage_cache$cache_path_set()} \code{manage_cache$cache_delete_all} does not accept any names, but deletes all files. For deleting many specific files, use \code{manage_cache$cache_delete} in an -\code{\link[base:lapply]{base::lapply()}} type call. +\link[base:lapply]{base::lapply} type call. } \section{Useful user functions}{ From 34c9865375adabea332e96d2c4b87ba4523acb42 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:15:13 +0800 Subject: [PATCH 09/60] update WORDLIST --- codemeta.json | 2 +- inst/WORDLIST | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index 289cfe8..a5b6401 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.877KB", + "fileSize": "910.884KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/inst/WORDLIST b/inst/WORDLIST index 2b971f2..1bc77cb 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -11,6 +11,7 @@ PURRR Precompile README ROxygen +Reknit Reorganises Sri TJ From ba447f2fffb48be499341f9e178b4335a797eb2e Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:22:02 +0800 Subject: [PATCH 10/60] tidy up titles --- R/create_CRU_df.R | 2 +- R/create_CRU_stack.R | 2 +- R/get_CRU_df.R | 2 +- R/get_CRU_stack.R | 2 +- R/manage_cached_files.R | 2 +- codemeta.json | 2 +- man/create_CRU_df.Rd | 2 +- man/create_CRU_stack.Rd | 2 +- man/get_CRU_df.Rd | 2 +- man/get_CRU_stack.Rd | 2 +- man/manage_cache.Rd | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index 15a3b9b..f1c92a9 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -1,4 +1,4 @@ -#' Create a data.table of CRU CL 2.0 climatology elements from local disk files +#' Create a data.table of CRU CL v. 2.0 climatology elements from local disk files #' #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology #' data and creates a \CRANpkg{data.table} of the data. If requested, minimum diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index b2e545f..cd832b3 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -1,4 +1,4 @@ -#' Create a list of terra rast objects of CRU CL 2.0 climatology elements from local disk files +#' Create a list of terra rast objects of CRU CL v. 2.0 climatology elements from local disk files #' #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology #' data and creates a \CRANpkg{terra} [terra::rast] object of the diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index ce71b9c..28b66d1 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -1,4 +1,4 @@ -#' Download and create a data.table of CRU CL 2.0 climatology elements +#' Download and create a data.table of CRU CL v. 2.0 climatology elements #' #' This function automates downloading and importing \acronym{CRU} #' \acronym{CL} v. 2.0 climatology data and creates a \CRANpkg{data.table} of diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index b02ab1b..4bf0439 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -1,4 +1,4 @@ -#' Download and create a list of terra rast objects of CRU CL 2.0 climatology elements +#' Download and create a list of terra rast objects of CRU CL v. 2.0 climatology elements #' #' This function automates downloading and importing CRU CL v. 2.0 #' climatology data into \R and creates a list of \CRANpkg{terra} diff --git a/R/manage_cached_files.R b/R/manage_cached_files.R index 0ec97e7..e79159e 100644 --- a/R/manage_cached_files.R +++ b/R/manage_cached_files.R @@ -7,7 +7,7 @@ #' #' @details The default cache directory is #' `tools::R_user_dir(package = "getCRUCLdata")`, but you can -#' set your own path using `manage_cache$cache_path_set()` +#' set your own path using `manage_cache$cache_path_set()`. #' #' `manage_cache$cache_delete` only accepts one file name, while #' `manage_cache$cache_delete_all` diff --git a/codemeta.json b/codemeta.json index a5b6401..4736215 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.884KB", + "fileSize": "910.908KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 70087bc..fcdcd85 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/create_CRU_df.R \name{create_CRU_df} \alias{create_CRU_df} -\title{Create a data.table of CRU CL 2.0 climatology elements from local disk files} +\title{Create a data.table of CRU CL v. 2.0 climatology elements from local disk files} \usage{ create_CRU_df( pre = FALSE, diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index cb9abdd..17284c8 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/create_CRU_stack.R \name{create_CRU_stack} \alias{create_CRU_stack} -\title{Create a list of terra rast objects of CRU CL 2.0 climatology elements from local disk files} +\title{Create a list of terra rast objects of CRU CL v. 2.0 climatology elements from local disk files} \usage{ create_CRU_stack( pre = FALSE, diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index e461434..ad0f879 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/get_CRU_df.R \name{get_CRU_df} \alias{get_CRU_df} -\title{Download and create a data.table of CRU CL 2.0 climatology elements} +\title{Download and create a data.table of CRU CL v. 2.0 climatology elements} \usage{ get_CRU_df( pre = FALSE, diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index a641ee0..2f69abc 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/get_CRU_stack.R \name{get_CRU_stack} \alias{get_CRU_stack} -\title{Download and create a list of terra rast objects of CRU CL 2.0 climatology elements} +\title{Download and create a list of terra rast objects of CRU CL v. 2.0 climatology elements} \usage{ get_CRU_stack( pre = FALSE, diff --git a/man/manage_cache.Rd b/man/manage_cache.Rd index fe2cb81..a0a5c9e 100644 --- a/man/manage_cache.Rd +++ b/man/manage_cache.Rd @@ -9,7 +9,7 @@ Manage cached \pkg{getCRUCLdata} files with \CRANpkg{hoardr}. \details{ The default cache directory is \code{tools::R_user_dir(package = "getCRUCLdata")}, but you can -set your own path using \code{manage_cache$cache_path_set()} +set your own path using \code{manage_cache$cache_path_set()}. \code{manage_cache$cache_delete} only accepts one file name, while \code{manage_cache$cache_delete_all} From ec3215543d184a34468d754d405841a395ddbda0 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:25:34 +0800 Subject: [PATCH 11/60] tidying Roxygen --- R/manage_cached_files.R | 4 ++-- man/manage_cache.Rd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/manage_cached_files.R b/R/manage_cached_files.R index e79159e..145b704 100644 --- a/R/manage_cached_files.R +++ b/R/manage_cached_files.R @@ -6,8 +6,8 @@ #' @name manage_cache #' #' @details The default cache directory is -#' `tools::R_user_dir(package = "getCRUCLdata")`, but you can -#' set your own path using `manage_cache$cache_path_set()`. +#' `tools::R_user_dir(package = "getCRUCLdata")`, but you can set your own path +#' using `manage_cache$cache_path_set()`. #' #' `manage_cache$cache_delete` only accepts one file name, while #' `manage_cache$cache_delete_all` diff --git a/man/manage_cache.Rd b/man/manage_cache.Rd index a0a5c9e..f9d342f 100644 --- a/man/manage_cache.Rd +++ b/man/manage_cache.Rd @@ -8,8 +8,8 @@ Manage cached \pkg{getCRUCLdata} files with \CRANpkg{hoardr}. } \details{ The default cache directory is -\code{tools::R_user_dir(package = "getCRUCLdata")}, but you can -set your own path using \code{manage_cache$cache_path_set()}. +\code{tools::R_user_dir(package = "getCRUCLdata")}, but you can set your own path +using \code{manage_cache$cache_path_set()}. \code{manage_cache$cache_delete} only accepts one file name, while \code{manage_cache$cache_delete_all} From 9d7b394a903bf57af8789d6b8e25025627104ac8 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:28:01 +0800 Subject: [PATCH 12/60] more Roxygen tidying --- R/manage_cached_files.R | 3 +-- codemeta.json | 2 +- man/manage_cache.Rd | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/R/manage_cached_files.R b/R/manage_cached_files.R index 145b704..739e63a 100644 --- a/R/manage_cached_files.R +++ b/R/manage_cached_files.R @@ -12,8 +12,7 @@ #' `manage_cache$cache_delete` only accepts one file name, while #' `manage_cache$cache_delete_all` #' does not accept any names, but deletes all files. For deleting many specific -#' files, use `manage_cache$cache_delete` in an -#' [base::lapply] type call. +#' files, use `manage_cache$cache_delete` in an [base::lapply] type call. #' #' @section Useful user functions: #' \itemize{ diff --git a/codemeta.json b/codemeta.json index 4736215..8fd803e 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.908KB", + "fileSize": "910.905KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/manage_cache.Rd b/man/manage_cache.Rd index f9d342f..96580dc 100644 --- a/man/manage_cache.Rd +++ b/man/manage_cache.Rd @@ -14,8 +14,7 @@ using \code{manage_cache$cache_path_set()}. \code{manage_cache$cache_delete} only accepts one file name, while \code{manage_cache$cache_delete_all} does not accept any names, but deletes all files. For deleting many specific -files, use \code{manage_cache$cache_delete} in an -\link[base:lapply]{base::lapply} type call. +files, use \code{manage_cache$cache_delete} in an \link[base:lapply]{base::lapply} type call. } \section{Useful user functions}{ From 6f784f36f95eb5cbce1bc8fe20032307b8daa6a0 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:30:25 +0800 Subject: [PATCH 13/60] yet even more polishing Roxygen --- R/get_CRU_stack.R | 4 ++-- codemeta.json | 2 +- man/get_CRU_stack.Rd | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 4bf0439..7af6dc5 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -31,8 +31,8 @@ #' #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the terra rast objects -#' generated by this function. +#' for parts of Antarctica, these data are excluded in the \CRANpkg{terra} +#' [terra::rast] objects generated by this function. #' #' @export get_CRU_stack diff --git a/codemeta.json b/codemeta.json index 8fd803e..3aaa69a 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.905KB", + "fileSize": "910.96KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 2f69abc..93af381 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -82,8 +82,8 @@ metres. This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the terra rast objects -generated by this function. +for parts of Antarctica, these data are excluded in the \CRANpkg{terra} +\link[terra:rast]{terra::rast} objects generated by this function. } \section{Nomenclature and Units}{ From 18fac5475542d4defdcef63927a53faff6a22733 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:44:58 +0800 Subject: [PATCH 14/60] Fixes missing space in documentation --- R/create_CRU_df.R | 2 +- codemeta.json | 2 +- man/create_CRU_df.Rd | 2 +- man/create_CRU_stack.Rd | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index f1c92a9..ff1447c 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -15,7 +15,7 @@ #' returns in the data frame, `TRUE`. Defaults to `FALSE`. NOTE. Setting this #' to `TRUE` will always results in **pre** being set to `TRUE` and #' returned as well. -#' @param rd0 Loads wet-days (number days with >0.1millimetres rain per +#' @param rd0 Loads wet-days (number days with >0.1 millimetres rain per #' month) and returns in the data frame, `TRUE`. Defaults to `FALSE`. #' @param dtr Loads mean diurnal temperature range (degrees Celsius) #' and returns it in the data frame, `TRUE`. Defaults to `FALSE`. diff --git a/codemeta.json b/codemeta.json index 3aaa69a..a8c865b 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.96KB", + "fileSize": "910.963KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index fcdcd85..be6d536 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -29,7 +29,7 @@ returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}. NOTE. Setting to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and returned as well.} -\item{rd0}{Loads wet-days (number days with >0.1millimetres rain per +\item{rd0}{Loads wet-days (number days with >0.1 millimetres rain per month) and returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} \item{tmp}{Loads temperature (degrees Celsius) and returns it in the diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 17284c8..fef4507 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -29,7 +29,7 @@ returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}. NOTE. Setting to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and returned as well.} -\item{rd0}{Loads wet-days (number days with >0.1millimetres rain per +\item{rd0}{Loads wet-days (number days with >0.1 millimetres rain per month) and returns in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} \item{tmp}{Loads temperature (degrees Celsius) and returns it in the From ca0556b5410d7addbd5277ab6292f07374128e87 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 10:46:09 +0800 Subject: [PATCH 15/60] corrects units --- R/create_CRU_df.R | 2 +- codemeta.json | 2 +- man/create_CRU_df.Rd | 2 +- man/create_CRU_stack.Rd | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index ff1447c..f92aa7a 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -32,7 +32,7 @@ #' @param frs Loads ground-frost records (number of days with ground- #' frost per month) and returns it in the data frame, `TRUE`. Defaults to #' `FALSE`. -#' @param wnd Load 10m wind speed (metres/second) and returns it in the +#' @param wnd Load 10 m wind speed (metres/second) and returns it in the #' data frame, `TRUE`. Defaults to `FALSE`. #' @param elv Loads elevation (converted to metres) and returns it in #' the data frame, `TRUE`. Defaults to `FALSE`. diff --git a/codemeta.json b/codemeta.json index a8c865b..e400a3f 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.963KB", + "fileSize": "910.966KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index be6d536..c86daf2 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -54,7 +54,7 @@ day length) and returns it in the data frame, \code{TRUE}. Defaults to \code{FAL frost per month) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{wnd}{Load 10m wind speed (metres/second) and returns it in the +\item{wnd}{Load 10 m wind speed (metres/second) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} \item{elv}{Loads elevation (converted to metres) and returns it in diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index fef4507..edc4b78 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -54,7 +54,7 @@ day length) and returns it in the data frame, \code{TRUE}. Defaults to \code{FAL frost per month) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} -\item{wnd}{Load 10m wind speed (metres/second) and returns it in the +\item{wnd}{Load 10 m wind speed (metres/second) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} \item{elv}{Loads elevation (converted to metres) and returns it in From 90f3a148ac48ba74891082ce593ccbf6ac12098e Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 12:18:41 +0800 Subject: [PATCH 16/60] Still polishing Roxygen --- R/get_CRU_df.R | 2 +- codemeta.json | 2 +- man/create_CRU_df.Rd | 2 +- man/create_CRU_stack.Rd | 2 +- man/get_CRU_df.Rd | 2 +- man/get_CRU_stack.Rd | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 28b66d1..f462ec0 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -13,7 +13,7 @@ #' \describe{ #' \item{cv}{cv of precipitation (percent)} #' } -#' \item{rd0}{wet-days (number days with >0.1mm rain per month)} +#' \item{rd0}{wet-days (number days with >0.1 millimetres rain per month)} #' \item{tmp}{mean temperature (degrees Celsius)} #' \item{dtr}{mean diurnal temperature range (degrees Celsius)} #' \item{reh}{relative humidity (percent)} diff --git a/codemeta.json b/codemeta.json index e400a3f..0133408 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "910.966KB", + "fileSize": "911.016KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index c86daf2..c208e04 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -86,7 +86,7 @@ metres. \describe{ \item{cv}{cv of precipitation (percent)} } -\item{rd0}{wet-days (number days with >0.1mm rain per month)} +\item{rd0}{wet-days (number days with >0.1 millimetres rain per month)} \item{tmp}{mean temperature (degrees Celsius)} \item{dtr}{mean diurnal temperature range (degrees Celsius)} \item{reh}{relative humidity (percent)} diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index edc4b78..869d5a9 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -91,7 +91,7 @@ generated by this function. \describe{ \item{cv}{cv of precipitation (percent)} } -\item{rd0}{wet-days (number days with >0.1mm rain per month)} +\item{rd0}{wet-days (number days with >0.1 millimetres rain per month)} \item{tmp}{mean temperature (degrees Celsius)} \item{dtr}{mean diurnal temperature range (degrees Celsius)} \item{reh}{relative humidity (percent)} diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index ad0f879..e36d99b 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -87,7 +87,7 @@ metres. \describe{ \item{cv}{cv of precipitation (percent)} } -\item{rd0}{wet-days (number days with >0.1mm rain per month)} +\item{rd0}{wet-days (number days with >0.1 millimetres rain per month)} \item{tmp}{mean temperature (degrees Celsius)} \item{dtr}{mean diurnal temperature range (degrees Celsius)} \item{reh}{relative humidity (percent)} diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 93af381..edb38fd 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -92,7 +92,7 @@ for parts of Antarctica, these data are excluded in the \CRANpkg{terra} \describe{ \item{cv}{cv of precipitation (percent)} } -\item{rd0}{wet-days (number days with >0.1mm rain per month)} +\item{rd0}{wet-days (number days with >0.1 millimetres rain per month)} \item{tmp}{mean temperature (degrees Celsius)} \item{dtr}{mean diurnal temperature range (degrees Celsius)} \item{reh}{relative humidity (percent)} From e54c4919014bbe4e846960036811e2dd8a679913 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 12:29:25 +0800 Subject: [PATCH 17/60] add sources and references --- R/create_CRU_df.R | 21 +++++++++++++++++++++ R/create_CRU_stack.R | 22 +++++++++++++++++++--- R/get_CRU_df.R | 22 +++++++++++++++++++--- R/get_CRU_stack.R | 23 ++++++++++++++++++++--- codemeta.json | 2 +- man/create_CRU_df.Rd | 22 ++++++++++++++++++++++ man/create_CRU_stack.Rd | 31 ++++++++++++++++++++++--------- man/get_CRU_df.Rd | 26 ++++++++++++++++++++++---- man/get_CRU_stack.Rd | 36 +++++++++++++++++++++++++++--------- 9 files changed, 173 insertions(+), 32 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index f92aa7a..dda2259 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -60,6 +60,27 @@ #' #' @author Adam H Sparks, \email{adamhsparks@@gmail.com} #' +#' @source +#' \itemize{ +#' \item pre +#' \item rd0 +#' \item tmp +#' \item dtr +#' \item reh +#' \item sunp +#' \item frs +#' \item wnd , +#' areas originally including Antarctica are removed. +#' \item elv , +#' values are converted from kilometres to metres. +#' } +#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +#' xmin = -180, xmax = 180. Note that the original wind data include land area +#' for parts of Antarctica, these data are excluded in the [terra::rast] objects +#' generated by this function. +#' +#' @references +#' #' @note #' This package automatically converts elevation values from kilometres to #' metres. diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index cd832b3..fdf77f8 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -30,14 +30,30 @@ #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' #' @note -#' This package automatically converts elevation values from kilometres to -#' metres. #' + +#' +#' @source +#' \itemize{ +#' \item pre +#' \item rd0 +#' \item tmp +#' \item dtr +#' \item reh +#' \item sunp +#' \item frs +#' \item wnd , +#' areas originally including Antarctica are removed. +#' \item elv , +#' values are converted from kilometres to metres. +#' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the terra rast objects +#' for parts of Antarctica, these data are excluded in the [terra::rast] objects #' generated by this function. #' +#' @references +#' #' @export create_CRU_stack create_CRU_stack <- function(pre = FALSE, diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index f462ec0..9027b9b 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -71,10 +71,26 @@ #' climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} +#' @source +#' \itemize{ +#' \item pre +#' \item rd0 +#' \item tmp +#' \item dtr +#' \item reh +#' \item sunp +#' \item frs +#' \item wnd , +#' areas originally including Antarctica are removed. +#' \item elv , +#' values are converted from kilometres to metres. +#' } +#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +#' xmin = -180, xmax = 180. Note that the original wind data include land area +#' for parts of Antarctica, these data are excluded in the [terra::rast] objects +#' generated by this function. #' -#' @note -#' This package automatically converts elevation values from kilometres to -#' metres. +#' @references #' #' @export diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 7af6dc5..413c0ee 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -25,9 +25,26 @@ #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' -#' @note -#' This package automatically converts elevation values from kilometres to -#' metres. +#' @source +#' \itemize{ +#' \item pre +#' \item rd0 +#' \item tmp +#' \item dtr +#' \item reh +#' \item sunp +#' \item frs +#' \item wnd , +#' areas originally including Antarctica are removed. +#' \item elv , +#' values are converted from kilometres to metres. +#' } +#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +#' xmin = -180, xmax = 180. Note that the original wind data include land area +#' for parts of Antarctica, these data are excluded in the [terra::rast] objects +#' generated by this function. +#' +#' @references #' #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. Note that the original wind data include land area diff --git a/codemeta.json b/codemeta.json index 0133408..23a871d 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "911.016KB", + "fileSize": "919.822KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index c208e04..dc622ff 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -3,6 +3,25 @@ \name{create_CRU_df} \alias{create_CRU_df} \title{Create a data.table of CRU CL v. 2.0 climatology elements from local disk files} +\source{ +\itemize{ +\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} +\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} +\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} +\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} +\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} +\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} +\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} +\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, +areas originally including Antarctica are removed. +\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, +values are converted from kilometres to metres. +} +This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +xmin = -180, xmax = 180. Note that the original wind data include land area +for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects +generated by this function. +} \usage{ create_CRU_df( pre = FALSE, @@ -114,6 +133,9 @@ CRU_tmp <- create_CRU_df(tmp = TRUE, dsn = tempdir()) CRU_tmp \dontshow{\}) # examplesIf} } +\references{ +\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} +} \seealso{ \link{get_CRU_df}. } diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 869d5a9..51faa7c 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -3,6 +3,25 @@ \name{create_CRU_stack} \alias{create_CRU_stack} \title{Create a list of terra rast objects of CRU CL v. 2.0 climatology elements from local disk files} +\source{ +\itemize{ +\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} +\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} +\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} +\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} +\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} +\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} +\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} +\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, +areas originally including Antarctica are removed. +\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, +values are converted from kilometres to metres. +} +This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +xmin = -180, xmax = 180. Note that the original wind data include land area +for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects +generated by this function. +} \usage{ create_CRU_stack( pre = FALSE, @@ -75,15 +94,6 @@ automatically calculated as described in the data readme.txt file. This function can be useful if you have network connection issues that mean automated downloading of the files using \R does not work properly. } -\note{ -This package automatically converts elevation values from kilometres to -metres. - -This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the terra rast objects -generated by this function. -} \section{Nomenclature and Units}{ \describe{ @@ -117,6 +127,9 @@ CRU_tmp <- create_CRU_stack(tmp = TRUE, dsn = tempdir()) CRU_tmp \dontshow{\}) # examplesIf} } +\references{ +\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} +} \seealso{ \link{get_CRU_stack}. } diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index e36d99b..1c950b9 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -3,6 +3,25 @@ \name{get_CRU_df} \alias{get_CRU_df} \title{Download and create a data.table of CRU CL v. 2.0 climatology elements} +\source{ +\itemize{ +\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} +\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} +\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} +\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} +\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} +\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} +\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} +\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, +areas originally including Antarctica are removed. +\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, +values are converted from kilometres to metres. +} +This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +xmin = -180, xmax = 180. Note that the original wind data include land area +for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects +generated by this function. +} \usage{ get_CRU_df( pre = FALSE, @@ -76,10 +95,6 @@ automatically calculated as described in the data readme.txt file. Data may be cached for later use by this function, saving time downloading files in future use of this function. } -\note{ -This package automatically converts elevation values from kilometres to -metres. -} \section{Nomenclature and Units}{ \describe{ @@ -110,6 +125,9 @@ head(CRU_pre_tmp) CRU_pre_tmp \dontshow{\}) # examplesIf} } +\references{ +\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} +} \seealso{ \link{create_CRU_stack}, \link{manage_cache}. } diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index edb38fd..1fbe054 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -3,6 +3,25 @@ \name{get_CRU_stack} \alias{get_CRU_stack} \title{Download and create a list of terra rast objects of CRU CL v. 2.0 climatology elements} +\source{ +\itemize{ +\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} +\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} +\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} +\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} +\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} +\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} +\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} +\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, +areas originally including Antarctica are removed. +\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, +values are converted from kilometres to metres. +} +This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +xmin = -180, xmax = 180. Note that the original wind data include land area +for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects +generated by this function. +} \usage{ get_CRU_stack( pre = FALSE, @@ -76,15 +95,6 @@ temperature may also be automatically calculated as described in the data readme.txt file. Data may be cached for later use by this function, saving time downloading files in future using this function. } -\note{ -This package automatically converts elevation values from kilometres to -metres. - -This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the \CRANpkg{terra} -\link[terra:rast]{terra::rast} objects generated by this function. -} \section{Nomenclature and Units}{ \describe{ @@ -115,6 +125,14 @@ CRU_pre_tmp <- get_CRU_stack(pre = TRUE, tmp = TRUE) CRU_pre_tmp \dontshow{\}) # examplesIf} } +\references{ +\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} + +This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, +xmin = -180, xmax = 180. Note that the original wind data include land area +for parts of Antarctica, these data are excluded in the \CRANpkg{terra} +\link[terra:rast]{terra::rast} objects generated by this function. +} \seealso{ \link{create_CRU_stack}, \link{manage_cache}. } From e1bcc9c77d2418a0f9c03198aa723ff57db903b3 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 13:28:03 +0800 Subject: [PATCH 18/60] simplify @source field --- R/create_CRU_df.R | 4 +--- R/create_CRU_stack.R | 4 +--- R/get_CRU_df.R | 4 +--- R/get_CRU_stack.R | 4 +--- codemeta.json | 2 +- man/create_CRU_df.Rd | 4 +--- man/create_CRU_stack.Rd | 4 +--- man/get_CRU_df.Rd | 4 +--- man/get_CRU_stack.Rd | 4 +--- 9 files changed, 9 insertions(+), 25 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index dda2259..d6a84cd 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -75,9 +75,7 @@ #' values are converted from kilometres to metres. #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the [terra::rast] objects -#' generated by this function. +#' xmin = -180, xmax = 180. #' #' @references #' diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index fdf77f8..34e3259 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -48,9 +48,7 @@ #' values are converted from kilometres to metres. #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the [terra::rast] objects -#' generated by this function. +#' xmin = -180, xmax = 180. #' #' @references #' diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 9027b9b..bbbe105 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -86,9 +86,7 @@ #' values are converted from kilometres to metres. #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the [terra::rast] objects -#' generated by this function. +#' xmin = -180, xmax = 180. #' #' @references #' diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 413c0ee..8a82bfc 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -40,9 +40,7 @@ #' values are converted from kilometres to metres. #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the [terra::rast] objects -#' generated by this function. +#' xmin = -180, xmax = 180. #' #' @references #' diff --git a/codemeta.json b/codemeta.json index 23a871d..457588e 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "919.822KB", + "fileSize": "918.474KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index dc622ff..d5f6066 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -18,9 +18,7 @@ areas originally including Antarctica are removed. values are converted from kilometres to metres. } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects -generated by this function. +xmin = -180, xmax = 180. } \usage{ create_CRU_df( diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 51faa7c..006ba5c 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -18,9 +18,7 @@ areas originally including Antarctica are removed. values are converted from kilometres to metres. } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects -generated by this function. +xmin = -180, xmax = 180. } \usage{ create_CRU_stack( diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index 1c950b9..b34ac72 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -18,9 +18,7 @@ areas originally including Antarctica are removed. values are converted from kilometres to metres. } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects -generated by this function. +xmin = -180, xmax = 180. } \usage{ get_CRU_df( diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 1fbe054..d632973 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -18,9 +18,7 @@ areas originally including Antarctica are removed. values are converted from kilometres to metres. } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the \link[terra:rast]{terra::rast} objects -generated by this function. +xmin = -180, xmax = 180. } \usage{ get_CRU_stack( From 60e1fef42ea766ba9e82cbe64ecd51f60a19c0da Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 13:35:35 +0800 Subject: [PATCH 19/60] use \describe for source(s) --- R/create_CRU_df.R | 22 ++++++++++------------ R/create_CRU_stack.R | 26 ++++++++++---------------- R/get_CRU_df.R | 22 ++++++++++------------ R/get_CRU_stack.R | 22 ++++++++++------------ codemeta.json | 2 +- man/create_CRU_df.Rd | 22 ++++++++++------------ man/create_CRU_stack.Rd | 22 ++++++++++------------ man/get_CRU_df.Rd | 22 ++++++++++------------ man/get_CRU_stack.Rd | 22 ++++++++++------------ 9 files changed, 81 insertions(+), 101 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index d6a84cd..f4ab564 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -61,18 +61,16 @@ #' @author Adam H Sparks, \email{adamhsparks@@gmail.com} #' #' @source -#' \itemize{ -#' \item pre -#' \item rd0 -#' \item tmp -#' \item dtr -#' \item reh -#' \item sunp -#' \item frs -#' \item wnd , -#' areas originally including Antarctica are removed. -#' \item elv , -#' values are converted from kilometres to metres. +#' \describe{ +#' \item{pre}{} +#' \item{rd0}{} +#' \item{tmp}{} +#' \item{dtr}{} +#' \item{reh}{} +#' \item{sunp}{} +#' \item{frs}{} +#' \item{wnd}{, areas originally including Antarctica are removed.} +#' \item{elv}{, values are converted from kilometres to metres.} #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index 34e3259..f1637f2 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -28,24 +28,18 @@ #' v. 2.0 climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} -#' -#' @note -#' - #' #' @source -#' \itemize{ -#' \item pre -#' \item rd0 -#' \item tmp -#' \item dtr -#' \item reh -#' \item sunp -#' \item frs -#' \item wnd , -#' areas originally including Antarctica are removed. -#' \item elv , -#' values are converted from kilometres to metres. +#' \describe{ +#' \item{pre}{} +#' \item{rd0}{} +#' \item{tmp}{} +#' \item{dtr}{} +#' \item{reh}{} +#' \item{sunp}{} +#' \item{frs}{} +#' \item{wnd}{, areas originally including Antarctica are removed.} +#' \item{elv}{, values are converted from kilometres to metres.} #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index bbbe105..7d4b018 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -72,18 +72,16 @@ #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' @source -#' \itemize{ -#' \item pre -#' \item rd0 -#' \item tmp -#' \item dtr -#' \item reh -#' \item sunp -#' \item frs -#' \item wnd , -#' areas originally including Antarctica are removed. -#' \item elv , -#' values are converted from kilometres to metres. +#' \describe{ +#' \item{pre}{} +#' \item{rd0}{} +#' \item{tmp}{} +#' \item{dtr}{} +#' \item{reh}{} +#' \item{sunp}{} +#' \item{frs}{} +#' \item{wnd}{, areas originally including Antarctica are removed.} +#' \item{elv}{, values are converted from kilometres to metres.} #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 8a82bfc..afbad61 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -26,18 +26,16 @@ #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' #' @source -#' \itemize{ -#' \item pre -#' \item rd0 -#' \item tmp -#' \item dtr -#' \item reh -#' \item sunp -#' \item frs -#' \item wnd , -#' areas originally including Antarctica are removed. -#' \item elv , -#' values are converted from kilometres to metres. +#' \describe{ +#' \item{pre}{} +#' \item{rd0}{} +#' \item{tmp}{} +#' \item{dtr}{} +#' \item{reh}{} +#' \item{sunp}{} +#' \item{frs}{} +#' \item{wnd}{, areas originally including Antarctica are removed.} +#' \item{elv}{, values are converted from kilometres to metres.} #' } #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. diff --git a/codemeta.json b/codemeta.json index 457588e..82b6072 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "918.474KB", + "fileSize": "918.578KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index d5f6066..0950841 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -4,18 +4,16 @@ \alias{create_CRU_df} \title{Create a data.table of CRU CL v. 2.0 climatology elements from local disk files} \source{ -\itemize{ -\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} -\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} -\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} -\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} -\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} -\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} -\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} -\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, -areas originally including Antarctica are removed. -\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, -values are converted from kilometres to metres. +\describe{ +\item{pre}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz}} +\item{rd0}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz}} +\item{tmp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz}} +\item{dtr}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz}} +\item{reh}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz}} +\item{sunp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz}} +\item{frs}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz}} +\item{wnd}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, areas originally including Antarctica are removed.} +\item{elv}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, values are converted from kilometres to metres.} } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 006ba5c..274e8df 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -4,18 +4,16 @@ \alias{create_CRU_stack} \title{Create a list of terra rast objects of CRU CL v. 2.0 climatology elements from local disk files} \source{ -\itemize{ -\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} -\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} -\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} -\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} -\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} -\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} -\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} -\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, -areas originally including Antarctica are removed. -\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, -values are converted from kilometres to metres. +\describe{ +\item{pre}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz}} +\item{rd0}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz}} +\item{tmp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz}} +\item{dtr}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz}} +\item{reh}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz}} +\item{sunp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz}} +\item{frs}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz}} +\item{wnd}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, areas originally including Antarctica are removed.} +\item{elv}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, values are converted from kilometres to metres.} } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index b34ac72..44bdca1 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -4,18 +4,16 @@ \alias{get_CRU_df} \title{Download and create a data.table of CRU CL v. 2.0 climatology elements} \source{ -\itemize{ -\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} -\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} -\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} -\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} -\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} -\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} -\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} -\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, -areas originally including Antarctica are removed. -\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, -values are converted from kilometres to metres. +\describe{ +\item{pre}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz}} +\item{rd0}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz}} +\item{tmp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz}} +\item{dtr}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz}} +\item{reh}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz}} +\item{sunp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz}} +\item{frs}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz}} +\item{wnd}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, areas originally including Antarctica are removed.} +\item{elv}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, values are converted from kilometres to metres.} } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index d632973..c3acfd7 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -4,18 +4,16 @@ \alias{get_CRU_stack} \title{Download and create a list of terra rast objects of CRU CL v. 2.0 climatology elements} \source{ -\itemize{ -\item pre \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz} -\item rd0 \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz} -\item tmp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz} -\item dtr \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz} -\item reh \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz} -\item sunp \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz} -\item frs \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz} -\item wnd \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, -areas originally including Antarctica are removed. -\item elv \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, -values are converted from kilometres to metres. +\describe{ +\item{pre}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_pre.dat.gz}} +\item{rd0}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_rd0.dat.gz}} +\item{tmp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_tmp.dat.gz}} +\item{dtr}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_dtr.dat.gz}} +\item{reh}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_reh.dat.gz}} +\item{sunp}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_sunp.dat.gz}} +\item{frs}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_frs.dat.gz}} +\item{wnd}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_wnd.dat.gz}, areas originally including Antarctica are removed.} +\item{elv}{\url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/grid_10min_elv.dat.gz}, values are converted from kilometres to metres.} } This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. From 3804753a2a8e6df89525c45c09cf07e1f7a66587 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 14:06:32 +0800 Subject: [PATCH 20/60] alias functions with all lower case --- NAMESPACE | 4 ++++ R/create_CRU_df.R | 4 ++++ R/create_CRU_stack.R | 4 ++++ R/get_CRU_df.R | 4 ++++ R/get_CRU_stack.R | 4 ++++ codemeta.json | 2 +- man/create_CRU_df.Rd | 17 +++++++++++++++++ man/create_CRU_stack.Rd | 17 +++++++++++++++++ man/get_CRU_stack.Rd | 38 ++++++++++++++++++++++++++++++++++++-- 9 files changed, 91 insertions(+), 3 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 2ad4069..5b7fb1c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,8 +2,12 @@ export(create_CRU_df) export(create_CRU_stack) +export(create_cru_df) +export(create_cru_stack) export(get_CRU_df) export(get_CRU_stack) +export(get_cru_df) +export(get_cru_stack) export(manage_cache) importFrom(data.table,":=") importFrom(data.table,.BY) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index f4ab564..6b12e4a 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -136,3 +136,7 @@ create_CRU_df <- function(pre = FALSE, return(.create_df(tmn, tmx, tmp, dtr, pre, pre_cv, elv, files)) } + +#' @export +#' @rdname create_CRU_df +create_cru_df <- create_CRU_df diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index f1637f2..a7c29de 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -102,3 +102,7 @@ create_CRU_stack <- function(pre = FALSE, return(.create_stacks(tmn, tmx, tmp, dtr, pre, pre_cv, files)) } + +#' @export +#' @rdname create_CRU_stack +create_cru_stack <- create_CRU_stack diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 7d4b018..c416599 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -138,3 +138,7 @@ get_CRU_df <- function(pre = FALSE, return(.create_df(tmn, tmx, tmp, dtr, pre, pre_cv, elv, files)) } + +#' @export +#' @rdname get_CRU_stack +get_cru_df <- get_CRU_df diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index afbad61..1bff52e 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -102,3 +102,7 @@ get_CRU_stack <- return(.create_stacks(tmn, tmx, tmp, dtr, pre, pre_cv, files)) } + +#' @export +#' @rdname get_CRU_stack +get_cru_stack <- get_CRU_stack diff --git a/codemeta.json b/codemeta.json index 82b6072..80f50d4 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "918.578KB", + "fileSize": "920.186KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 0950841..e928ade 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/create_CRU_df.R \name{create_CRU_df} \alias{create_CRU_df} +\alias{create_cru_df} \title{Create a data.table of CRU CL v. 2.0 climatology elements from local disk files} \source{ \describe{ @@ -34,6 +35,22 @@ create_CRU_df( elv = FALSE, dsn ) + +create_cru_df( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + dsn +) } \arguments{ \item{pre}{Loads precipitation (millimetres/month) from server and diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 274e8df..d8a4de7 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/create_CRU_stack.R \name{create_CRU_stack} \alias{create_CRU_stack} +\alias{create_cru_stack} \title{Create a list of terra rast objects of CRU CL v. 2.0 climatology elements from local disk files} \source{ \describe{ @@ -34,6 +35,22 @@ create_CRU_stack( elv = FALSE, dsn ) + +create_cru_stack( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + dsn +) } \arguments{ \item{pre}{Loads precipitation (millimetres/month) from server and diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index c3acfd7..5103e1e 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -1,7 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/get_CRU_stack.R -\name{get_CRU_stack} +% Please edit documentation in R/get_CRU_df.R, R/get_CRU_stack.R +\name{get_cru_df} +\alias{get_cru_df} \alias{get_CRU_stack} +\alias{get_cru_stack} \title{Download and create a list of terra rast objects of CRU CL v. 2.0 climatology elements} \source{ \describe{ @@ -19,6 +21,22 @@ This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. } \usage{ +get_cru_df( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + cache = FALSE +) + get_CRU_stack( pre = FALSE, pre_cv = FALSE, @@ -34,6 +52,22 @@ get_CRU_stack( elv = FALSE, cache = FALSE ) + +get_cru_stack( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + cache = FALSE +) } \arguments{ \item{pre}{Fetches precipitation (millimetres/month) from server and From ce3ef7ea68deb12fc6aea991c92c09efcf1815c7 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 14:06:46 +0800 Subject: [PATCH 21/60] use \describe in list of functions --- R/manage_cached_files.R | 20 ++++++++++---------- man/manage_cache.Rd | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/R/manage_cached_files.R b/R/manage_cached_files.R index 739e63a..ee142a4 100644 --- a/R/manage_cached_files.R +++ b/R/manage_cached_files.R @@ -15,16 +15,16 @@ #' files, use `manage_cache$cache_delete` in an [base::lapply] type call. #' #' @section Useful user functions: -#' \itemize{ -#' \item `manage_cache$cache_path_get()` - get cache path -#' \item `manage_cache$cache_path_set()` - set cache path -#' \item `manage_cache$list()` - returns a character vector of full -#' path file names -#' \item `manage_cache$files()` - returns file objects with metadata -#' \item `manage_cache$details()` - returns files with details -#' \item `manage_cache$delete()` - delete specific files -#' \item `manage_cache$delete_all()` - delete all files, returns -#' nothing +#' \describe{ +#' \item{`manage_cache$cache_path_get()`}{get cache path} +#' \item{`manage_cache$cache_path_set()`}{set cache path} +#' \item{`manage_cache$list()`}{returns a character vector of full +#' path file names} +#' \item{`manage_cache$files()`}{returns file objects with metadata} +#' \item{`manage_cache$details()`}{returns files with details} +#' \item{`manage_cache$delete()`}{delete specific files} +#' \item{`manage_cache$delete_all()`}{delete all files, returns +#' nothing} #' } #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} diff --git a/man/manage_cache.Rd b/man/manage_cache.Rd index 96580dc..a180d36 100644 --- a/man/manage_cache.Rd +++ b/man/manage_cache.Rd @@ -18,16 +18,16 @@ files, use \code{manage_cache$cache_delete} in an \link[base:lapply]{base::lappl } \section{Useful user functions}{ -\itemize{ -\item \code{manage_cache$cache_path_get()} - get cache path -\item \code{manage_cache$cache_path_set()} - set cache path -\item \code{manage_cache$list()} - returns a character vector of full -path file names -\item \code{manage_cache$files()} - returns file objects with metadata -\item \code{manage_cache$details()} - returns files with details -\item \code{manage_cache$delete()} - delete specific files -\item \code{manage_cache$delete_all()} - delete all files, returns -nothing +\describe{ +\item{\code{manage_cache$cache_path_get()}}{get cache path} +\item{\code{manage_cache$cache_path_set()}}{set cache path} +\item{\code{manage_cache$list()}}{returns a character vector of full +path file names} +\item{\code{manage_cache$files()}}{returns file objects with metadata} +\item{\code{manage_cache$details()}}{returns files with details} +\item{\code{manage_cache$delete()}}{delete specific files} +\item{\code{manage_cache$delete_all()}}{delete all files, returns +nothing} } } From 3bc2a3edb95feebed1306362480b2e9211769db2 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 14:06:56 +0800 Subject: [PATCH 22/60] update NEWS --- NEWS.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NEWS.md b/NEWS.md index edffac6..3f5beff 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,13 @@ +# getCRUCLdata 1.0.2.9000 + +## Minor changes + +- Add source and references to documentation for data + +- Create function aliases that use all lower case, *e.g.*, `get_cru_stack()` vs `get_CRU_stack()` + +- Improved documentation with linting, ensuring consistency in units of measurement, etc. + # getCRUCLdata 1.0.2 ## Minor changes From d9083e63e8787f596685eeb373713625c8267eeb Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 14:27:14 +0800 Subject: [PATCH 23/60] Add citation to references along with the URL to PDF --- R/create_CRU_df.R | 4 +++- R/create_CRU_stack.R | 4 +++- R/get_CRU_df.R | 4 +++- R/get_CRU_stack.R | 4 +++- codemeta.json | 2 +- man/create_CRU_df.Rd | 2 ++ man/create_CRU_stack.Rd | 2 ++ man/get_CRU_df.Rd | 2 ++ man/get_CRU_stack.Rd | 2 ++ 9 files changed, 21 insertions(+), 5 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index 6b12e4a..4818045 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -75,7 +75,9 @@ #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. #' -#' @references +#' @references New, Mark, et al. "A high-resolution data set of surface climate +#' over global land areas." Climate research 21.1 (2002): 1-25. +#' #' #' @note #' This package automatically converts elevation values from kilometres to diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index a7c29de..b8b2942 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -44,7 +44,9 @@ #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. #' -#' @references +#' @references New, Mark, et al. "A high-resolution data set of surface climate +#' over global land areas." Climate research 21.1 (2002): 1-25. +#' #' #' @export create_CRU_stack diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index c416599..888a9b5 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -86,7 +86,9 @@ #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. #' -#' @references +#' @references New, Mark, et al. "A high-resolution data set of surface climate +#' over global land areas." Climate research 21.1 (2002): 1-25. +#' #' #' @export diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 1bff52e..739e086 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -40,7 +40,9 @@ #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. #' -#' @references +#' @references New, Mark, et al. "A high-resolution data set of surface climate +#' over global land areas." Climate research 21.1 (2002): 1-25. +#' #' #' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, #' xmin = -180, xmax = 180. Note that the original wind data include land area diff --git a/codemeta.json b/codemeta.json index 80f50d4..903e3fe 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "920.186KB", + "fileSize": "921.226KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index e928ade..86c9a79 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -147,6 +147,8 @@ CRU_tmp \dontshow{\}) # examplesIf} } \references{ +New, Mark, et al. "A high-resolution data set of surface climate +over global land areas." Climate research 21.1 (2002): 1-25. \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} } \seealso{ diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index d8a4de7..2271760 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -141,6 +141,8 @@ CRU_tmp \dontshow{\}) # examplesIf} } \references{ +New, Mark, et al. "A high-resolution data set of surface climate +over global land areas." Climate research 21.1 (2002): 1-25. \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} } \seealso{ diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index 44bdca1..95c277b 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -122,6 +122,8 @@ CRU_pre_tmp \dontshow{\}) # examplesIf} } \references{ +New, Mark, et al. "A high-resolution data set of surface climate +over global land areas." Climate research 21.1 (2002): 1-25. \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} } \seealso{ diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 5103e1e..f02b156 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -156,6 +156,8 @@ CRU_pre_tmp \dontshow{\}) # examplesIf} } \references{ +New, Mark, et al. "A high-resolution data set of surface climate +over global land areas." Climate research 21.1 (2002): 1-25. \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, From 83d822e719328f7cd156a222f07b9bc1aba4e656 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 15:00:34 +0800 Subject: [PATCH 24/60] remove redundant text --- R/create_CRU_df.R | 5 +---- R/create_CRU_stack.R | 2 +- R/get_CRU_stack.R | 5 ----- codemeta.json | 2 +- man/create_CRU_df.Rd | 4 ---- man/get_CRU_stack.Rd | 5 ----- 6 files changed, 3 insertions(+), 20 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index 4818045..5fbc43f 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -79,10 +79,7 @@ #' over global land areas." Climate research 21.1 (2002): 1-25. #' #' -#' @note -#' This package automatically converts elevation values from kilometres to -#' metres. -#' @export create_CRU_df +#' @export create_CRU_df <- function(pre = FALSE, pre_cv = FALSE, diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index b8b2942..4f0d9bd 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -48,7 +48,7 @@ #' over global land areas." Climate research 21.1 (2002): 1-25. #' #' -#' @export create_CRU_stack +#' @export create_CRU_stack <- function(pre = FALSE, pre_cv = FALSE, diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 739e086..9ef5504 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -44,11 +44,6 @@ #' over global land areas." Climate research 21.1 (2002): 1-25. #' #' -#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. Note that the original wind data include land area -#' for parts of Antarctica, these data are excluded in the \CRANpkg{terra} -#' [terra::rast] objects generated by this function. -#' #' @export get_CRU_stack get_CRU_stack <- diff --git a/codemeta.json b/codemeta.json index 903e3fe..0865032 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "921.226KB", + "fileSize": "920.424KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 86c9a79..25a05da 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -107,10 +107,6 @@ the data readme.txt file. This function can be useful if you have network connection issues that mean automated downloading of the files using \R does not work properly. } -\note{ -This package automatically converts elevation values from kilometres to -metres. -} \section{Nomenclature and Units}{ \describe{ diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index f02b156..0f70df6 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -159,11 +159,6 @@ CRU_pre_tmp New, Mark, et al. "A high-resolution data set of surface climate over global land areas." Climate research 21.1 (2002): 1-25. \url{https://crudata.uea.ac.uk/cru/data/hrg/tmc/new_et_al_10minute_climate_CR.pdf} - -This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -xmin = -180, xmax = 180. Note that the original wind data include land area -for parts of Antarctica, these data are excluded in the \CRANpkg{terra} -\link[terra:rast]{terra::rast} objects generated by this function. } \seealso{ \link{create_CRU_stack}, \link{manage_cache}. From dfe8523a9feb0af8b5d808b1b0dd228a48e72456 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 15:20:27 +0800 Subject: [PATCH 25/60] corrects invalid alias --- R/get_CRU_df.R | 2 +- man/get_CRU_df.Rd | 17 +++++++++++++++++ man/get_CRU_stack.Rd | 21 ++------------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 888a9b5..e338f36 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -142,5 +142,5 @@ get_CRU_df <- function(pre = FALSE, } #' @export -#' @rdname get_CRU_stack +#' @rdname get_CRU_df get_cru_df <- get_CRU_df diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index 95c277b..da5362a 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/get_CRU_df.R \name{get_CRU_df} \alias{get_CRU_df} +\alias{get_cru_df} \title{Download and create a data.table of CRU CL v. 2.0 climatology elements} \source{ \describe{ @@ -34,6 +35,22 @@ get_CRU_df( elv = FALSE, cache = FALSE ) + +get_cru_df( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + cache = FALSE +) } \arguments{ \item{pre}{Fetches precipitation (millimetres/month) from server and diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 0f70df6..466a772 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -1,7 +1,6 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/get_CRU_df.R, R/get_CRU_stack.R -\name{get_cru_df} -\alias{get_cru_df} +% Please edit documentation in R/get_CRU_stack.R +\name{get_CRU_stack} \alias{get_CRU_stack} \alias{get_cru_stack} \title{Download and create a list of terra rast objects of CRU CL v. 2.0 climatology elements} @@ -21,22 +20,6 @@ This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. } \usage{ -get_cru_df( - pre = FALSE, - pre_cv = FALSE, - rd0 = FALSE, - tmp = FALSE, - dtr = FALSE, - reh = FALSE, - tmn = FALSE, - tmx = FALSE, - sunp = FALSE, - frs = FALSE, - wnd = FALSE, - elv = FALSE, - cache = FALSE -) - get_CRU_stack( pre = FALSE, pre_cv = FALSE, From 67b06b8a59afb8c15b25bf31e2867493559c55ea Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 16:37:36 +0800 Subject: [PATCH 26/60] Remove an invalid terra fn from vignette --- codemeta.json | 2 +- vignettes/getCRUCLdata.Rmd | 58 ++++++++++++++++----------------- vignettes/getCRUCLdata.Rmd.orig | 2 +- vignettes/precompile.R | 1 + 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/codemeta.json b/codemeta.json index 0865032..765f739 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "920.424KB", + "fileSize": "920.313KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/vignettes/getCRUCLdata.Rmd b/vignettes/getCRUCLdata.Rmd index 659f467..e39b9ae 100644 --- a/vignettes/getCRUCLdata.Rmd +++ b/vignettes/getCRUCLdata.Rmd @@ -1,7 +1,7 @@ --- title: "getCRUCLdata" author: "Adam H. Sparks" -date: "2024-12-16" +date: "2024-12-17" output: rmarkdown::html_vignette: toc: true @@ -87,32 +87,32 @@ CRU_data <- get_CRU_df(pre = TRUE, elv = TRUE) CRU_data -#> lat lon month dtr frs pre pre_cv rd0 reh sun tmp wnd elv tmx -#> -#> 1: 30.917 35.417 NA NA NA NA NA NA NA NA NA -260 NA -#> 2: 31.083 35.417 NA NA NA NA NA NA NA NA NA -361 NA -#> 3: 31.250 35.417 NA NA NA NA NA NA NA NA NA -336 NA -#> 4: 31.417 35.417 NA NA NA NA NA NA NA NA NA -284 NA -#> 5: 31.750 35.583 NA NA NA NA NA NA NA NA NA -248 NA -#> --- -#> 6795146: 83.583 -30.083 dec 8.7 31 0.1 72.7 5.1 70.6 0 -31.3 5.6 283 -26.95 -#> 6795147: 83.583 -29.917 dec 8.6 31 0.1 72.8 4.9 70.6 0 -30.7 5.6 186 -26.40 -#> 6795148: 83.583 -29.750 dec 8.6 31 0.1 72.9 4.9 70.6 0 -30.8 5.6 195 -26.50 -#> 6795149: 83.583 -29.583 dec 8.6 31 0.1 73.0 5.0 70.6 0 -31.2 5.6 268 -26.90 -#> 6795150: 83.583 -29.417 dec 8.6 31 0.1 73.1 5.1 70.6 0 -31.5 5.6 328 -27.20 -#> tmn -#> -#> 1: NA -#> 2: NA -#> 3: NA -#> 4: NA -#> 5: NA -#> --- -#> 6795146: -35.65 -#> 6795147: -35.00 -#> 6795148: -35.10 -#> 6795149: -35.50 -#> 6795150: -35.80 +#> lat lon month dtr frs pre pre_cv rd0 reh sun tmp wnd elv +#> +#> 1: 30.917 35.417 NA NA NA NA NA NA NA NA NA -260 +#> 2: 31.083 35.417 NA NA NA NA NA NA NA NA NA -361 +#> 3: 31.250 35.417 NA NA NA NA NA NA NA NA NA -336 +#> 4: 31.417 35.417 NA NA NA NA NA NA NA NA NA -284 +#> 5: 31.750 35.583 NA NA NA NA NA NA NA NA NA -248 +#> --- +#> 6795146: 83.583 -30.083 dec 8.7 31 0.1 72.7 5.1 70.6 0 -31.3 5.6 283 +#> 6795147: 83.583 -29.917 dec 8.6 31 0.1 72.8 4.9 70.6 0 -30.7 5.6 186 +#> 6795148: 83.583 -29.750 dec 8.6 31 0.1 72.9 4.9 70.6 0 -30.8 5.6 195 +#> 6795149: 83.583 -29.583 dec 8.6 31 0.1 73.0 5.0 70.6 0 -31.2 5.6 268 +#> 6795150: 83.583 -29.417 dec 8.6 31 0.1 73.1 5.1 70.6 0 -31.5 5.6 328 +#> tmx tmn +#> +#> 1: NA NA +#> 2: NA NA +#> 3: NA NA +#> 4: NA NA +#> 5: NA NA +#> --- +#> 6795146: -26.95 -35.65 +#> 6795147: -26.40 -35.00 +#> 6795148: -26.50 -35.10 +#> 6795149: -26.90 -35.50 +#> 6795150: -27.20 -35.80 ``` Perhaps you only need one or two elements, it is easy to create a data frame of mean temperature only. @@ -252,7 +252,7 @@ CRU_stack #> resolution : 0.1666667, 0.1666667 (x, y) #> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) #> coord. ref. : lon/lat WGS 84 -#> source : spat_613232ecfe11_24882_GdaPwXHptgIOPSx.tif +#> source(s) : memory #> names : jan, feb, mar, apr, may, jun, ... #> min values : 0.0, 0.0, 0.0, 0.0, 0, 0.0, ... #> max values : 910.1, 824.3, 727.3, 741.3, 1100, 2512.6, ... @@ -367,7 +367,7 @@ plot(t[[8]]$jul) #### Saving terra objects to local disk -The terra rast stack objects can be saved to disk as geotiff files (others are available, see help for `terra::writeRaster()` and `terra::writeFormats()` for more options) on the `Data` directory with a tmn or tmx prefix to the month for a file name. +The [terra::rast()] objects can be saved to disk as geotiff files (others are available, see help for `terra::writeRaster()` for more options) on the `Data` directory with a tmn or tmx prefix to the month for a file name. ``` r diff --git a/vignettes/getCRUCLdata.Rmd.orig b/vignettes/getCRUCLdata.Rmd.orig index d00894a..6242244 100644 --- a/vignettes/getCRUCLdata.Rmd.orig +++ b/vignettes/getCRUCLdata.Rmd.orig @@ -196,7 +196,7 @@ plot(t[[8]]$jul) #### Saving terra objects to local disk -The terra rast stack objects can be saved to disk as geotiff files (others are available, see help for `terra::writeRaster()` and `terra::writeFormats()` for more options) on the `Data` directory with a tmn or tmx prefix to the month for a file name. +The [terra::rast()] objects can be saved to disk as geotiff files (others are available, see help for `terra::writeRaster()` for more options) on the `Data` directory with a tmn or tmx prefix to the month for a file name. ```{r save_stack, eval=FALSE} library(terra) diff --git a/vignettes/precompile.R b/vignettes/precompile.R index 8d60904..dac85ad 100644 --- a/vignettes/precompile.R +++ b/vignettes/precompile.R @@ -20,3 +20,4 @@ resources <- file.copy(from = resources, to = "doc", overwrite = TRUE) + From a7a97f8d5da5a0e7b2cea3c2671a81f312513030 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 16:38:17 +0800 Subject: [PATCH 27/60] style with {styler} --- R/zzz.R | 8 +++++--- codemeta.json | 2 +- tests/testthat/test-get_CRU.R | 11 +++++------ tests/testthat/test_caching.R | 16 ++++++++++------ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/R/zzz.R b/R/zzz.R index 11d64e6..c5d539e 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -8,9 +8,11 @@ manage_cache <- NULL # nocov start utils::globalVariables(c(".")) x <- hoardr::hoard() - x$cache_path_set(path = "getCRUCLdata", - prefix = "org.R-project.R/R", - type = "user_cache_dir") + x$cache_path_set( + path = "getCRUCLdata", + prefix = "org.R-project.R/R", + type = "user_cache_dir" + ) manage_cache <<- x } } diff --git a/codemeta.json b/codemeta.json index 765f739..839e3b6 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "920.313KB", + "fileSize": "920.18KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/tests/testthat/test-get_CRU.R b/tests/testthat/test-get_CRU.R index 095b521..4707316 100644 --- a/tests/testthat/test-get_CRU.R +++ b/tests/testthat/test-get_CRU.R @@ -7,7 +7,7 @@ test_that("get_CRU will retrieve only precipitation file when pre_cv TRUE", { )) skip_if_offline() - + .get_CRU( pre = FALSE, pre_cv = TRUE, @@ -36,7 +36,7 @@ test_that("get_CRU will retrieve only precipitation file when pre_cv TRUE", { test_that("get_CRU will retrieve diurnal tmp range & tmp files when tmn TRUE", { skip_if_offline() - + .get_CRU( pre = FALSE, pre_cv = FALSE, @@ -64,7 +64,7 @@ test_that("get_CRU will retrieve diurnal tmp range & tmp files when tmn TRUE", { # Test that get_CRU will retrieve diurnal tmp & tmp files when tmx TRUE -------- test_that("get_CRU will retrieve diurnal tmp range & tmp files when tmx TRUE", { skip_if_offline() - + unlink(list.files( path = tempdir(), pattern = ".dat.gz$", @@ -99,7 +99,7 @@ test_that("get_CRU will retrieve diurnal tmp range & tmp files when tmx TRUE", { test_that("get_CRU will set pre to TRUE if pre_cv is TRUE and pre is FALSE", { skip_if_offline() - + pre <- FALSE pre_cv <- TRUE @@ -117,9 +117,8 @@ test_that("get_CRU will set pre to TRUE if pre_cv is TRUE and pre is FALSE", { test_that("get_CRU will set tmp and dtr to TRUE if tmn or tmx is TRUE and either/both are false", { + skip_if_offline() - skip_if_offline() - tmp <- FALSE dtr <- FALSE tmn <- TRUE diff --git a/tests/testthat/test_caching.R b/tests/testthat/test_caching.R index 56d9f92..f0d3c00 100644 --- a/tests/testthat/test_caching.R +++ b/tests/testthat/test_caching.R @@ -4,9 +4,11 @@ test_that("test that set_cache creates a cache directory if none exists", { withr::local_envvar(R_USER_CACHE_DIR = tempdir()) temp_cache <- file.path(tempdir(), "R/getCRUCLdata/") manage_cache <- hoardr::hoard() - manage_cache$cache_path_set(path = "getCRUCLdata", - prefix = "org.R-project.R/R", - type = "user_cache_dir") + manage_cache$cache_path_set( + path = "getCRUCLdata", + prefix = "org.R-project.R/R", + type = "user_cache_dir" + ) cache <- TRUE .set_cache(cache) expect_true(file.exists(manage_cache$cache_path_get())) @@ -38,9 +40,11 @@ test_that("caching utils list files in cache and delete when asked", { withr::local_envvar(R_USER_CACHE_DIR = tempdir()) temp_cache <- file.path(tempdir(), "R/getCRUCLdata/") manage_cache <- hoardr::hoard() - manage_cache$cache_path_set(path = "getCRUCLdata", - prefix = "org.R-project.R/R", - type = "user_cache_dir") + manage_cache$cache_path_set( + path = "getCRUCLdata", + prefix = "org.R-project.R/R", + type = "user_cache_dir" + ) cache <- TRUE cache_dir <- .set_cache(cache) f <- From 57aa1f3454025509ec214136472039afceb5729e Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:26:47 +0800 Subject: [PATCH 28/60] line breaks --- R/get_CRU_stack.R | 6 +++--- man/get_CRU_stack.Rd | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 9ef5504..0249e8b 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -20,8 +20,8 @@ #' @seealso #' [create_CRU_stack], [manage_cache]. #' -#' @return A [base::list] of [terra::rast] objects of CRU CL v. 2.0 -#' climatology elements. +#' @return A [base::list] of [terra::rast] objects of CRU CL v. 2.0 climatology +#' elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' @@ -44,7 +44,7 @@ #' over global land areas." Climate research 21.1 (2002): 1-25. #' #' -#' @export get_CRU_stack +#' @export get_CRU_stack <- function(pre = FALSE, diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 466a772..44f1a72 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -97,8 +97,8 @@ To take advantage of cached files in future sessions, use \code{cache = TRUE} even after the initial download and caching. Defaults to \code{FALSE}.} } \value{ -A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of CRU CL v. 2.0 -climatology elements. +A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of CRU CL v. 2.0 climatology +elements. } \description{ This function automates downloading and importing CRU CL v. 2.0 From 3f9d91338b223455a0055593b765e831e11b60aa Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:27:04 +0800 Subject: [PATCH 29/60] add Curtin and AAGI/GRDC as cph --- DESCRIPTION | 19 ++++++++++++------- codemeta.json | 12 +++++++++++- man/getCRUCLdata-package.Rd | 6 ++++++ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index e308643..ee8a0b4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,16 +2,21 @@ Type: Package Package: getCRUCLdata Title: 'CRU' 'CL' v. 2.0 Climatology Client Version: 1.0.2 -Authors@R: +Authors@R: c( person("Adam H.", "Sparks", , "adamhsparks@gmail.com", role = c("aut", "cre"), - comment = c(ORCID = "0000-0002-0061-8359")) + comment = c(ORCID = "0000-0002-0061-8359")), + person("Curtin University of Technology", role = "cph", + comment = "Provided support through Adam Sparks's time."), + person("Grains Research and Development Corporation", role = c("cph"), + comment = "GRDC Project CUR2210-005OPX (AAGI-CU)") + ) Description: Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature - and maximum temperature and formats the data into a data.table object or a - list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a - gridded climatology of 1961-1990 monthly means released in 2002 and - cover all land areas (excluding Antarctica) at 10 arc minutes + and maximum temperature and formats the data into a data.table object + or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data + are a gridded climatology of 1961-1990 monthly means released in 2002 + and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit, @@ -46,13 +51,13 @@ VignetteBuilder: ByteCompile: TRUE Config/roxyglobals/filename: globals.R Config/roxyglobals/unique: FALSE +Config/roxylint: list(linters = roxylint::tidy) Config/testthat/edition: 3 Config/testthat/parallel: true Encoding: UTF-8 Language: en-US Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", "roxyglobals::global_roclet", "roxylint::roxylint")) -Config/roxylint: list(linters = roxylint::tidy) RoxygenNote: 7.3.2 X-schema.org-applicationCategory: Tools X-schema.org-isPartOf: https://ropensci.org diff --git a/codemeta.json b/codemeta.json index 839e3b6..66c53ea 100644 --- a/codemeta.json +++ b/codemeta.json @@ -24,6 +24,16 @@ "@id": "https://orcid.org/0000-0002-0061-8359" } ], + "copyrightHolder": [ + { + "@type": "Organization", + "name": "Curtin University of Technology" + }, + { + "@type": "Organization", + "name": "Grains Research and Development Corporation" + } + ], "maintainer": [ { "@type": "Person", @@ -244,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "920.18KB", + "fileSize": "920.69KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/getCRUCLdata-package.Rd b/man/getCRUCLdata-package.Rd index e95db91..3d8e446 100644 --- a/man/getCRUCLdata-package.Rd +++ b/man/getCRUCLdata-package.Rd @@ -20,5 +20,11 @@ Useful links: \author{ \strong{Maintainer}: Adam H. Sparks \email{adamhsparks@gmail.com} (\href{https://orcid.org/0000-0002-0061-8359}{ORCID}) +Other contributors: +\itemize{ + \item Curtin University of Technology (Provided support through Adam Sparks's time.) [copyright holder] + \item Grains Research and Development Corporation (GRDC Project CUR2210-005OPX (AAGI-CU)) [copyright holder] +} + } \keyword{internal} From 2b25a39068b2ee8f6abafa6586af5f3666aaca52 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:27:47 +0800 Subject: [PATCH 30/60] Update spelling list --- codemeta.json | 2 +- inst/WORDLIST | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index 66c53ea..f74b013 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "920.69KB", + "fileSize": "920.717KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/inst/WORDLIST b/inst/WORDLIST index 1bc77cb..5c8868d 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,11 +1,15 @@ +AAGI CMD CRU Centre +Curtin DOI +GRDC Hulme JOSS Makin NOTEs +OPX ORCID PURRR Precompile @@ -15,6 +19,7 @@ Reknit Reorganises Sri TJ +al arcminutes behaviour biogeochemical @@ -28,6 +33,7 @@ dplyr dsn dtr elv +et frs geotiff getCRUCL From ef66ecbf6774d2bcec5fc68ff83a13b471dce8e5 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:34:57 +0800 Subject: [PATCH 31/60] Provide a link to the CRU's readme.txt file for these data --- R/create_CRU_df.R | 10 ++++++---- R/create_CRU_stack.R | 9 ++++++--- R/get_CRU_df.R | 7 ++++--- R/get_CRU_stack.R | 5 +++-- codemeta.json | 2 +- man/create_CRU_df.Rd | 10 ++++++---- man/create_CRU_stack.Rd | 9 ++++++--- man/get_CRU_df.Rd | 7 ++++--- man/get_CRU_stack.Rd | 5 +++-- 9 files changed, 39 insertions(+), 25 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index 5fbc43f..ae0ead8 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -1,11 +1,13 @@ #' Create a data.table of CRU CL v. 2.0 climatology elements from local disk files #' #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology -#' data and creates a \CRANpkg{data.table} of the data. If requested, minimum +#' data and creates a \CRANpkg{data.table} of the data. If requested, minimum #' and maximum temperature may also be automatically calculated as described in -#' the data readme.txt file. This function can be useful if you have network -#' connection issues that mean automated downloading of the files using \R -#' does not work properly. +#' the data [readme.txt](https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt) +#' file. Data may be cached for later use by this function, saving time +#' downloading files in future using this function. This function can be useful +#' if you have network connection issues that mean automated downloading of the +#' files using \R does not work properly. #' #' @inheritSection get_CRU_df Nomenclature and Units #' diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index 4f0d9bd..564ceba 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -3,9 +3,12 @@ #' Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology #' data and creates a \CRANpkg{terra} [terra::rast] object of the #' data. If requested, minimum and maximum temperature may also be -#' automatically calculated as described in the data readme.txt file. This -#' function can be useful if you have network connection issues that mean -#' automated downloading of the files using \R does not work properly. +#' automatically calculated as described in the data +#' [readme.txt](https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt) file. +#' Data may be cached for later use by this function, saving time downloading +#' files in future using this function. This function can be useful if you have +#' network connection issues that mean automated downloading of the files using +#' \R does not work properly. #' #' @inheritSection get_CRU_df Nomenclature and Units #' @inheritParams create_CRU_df diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index e338f36..87c320a 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -3,9 +3,10 @@ #' This function automates downloading and importing \acronym{CRU} #' \acronym{CL} v. 2.0 climatology data and creates a \CRANpkg{data.table} of #' the data. If requested, minimum and maximum temperature may also be -#' automatically calculated as described in the data readme.txt file. Data may -#' be cached for later use by this function, saving time downloading files in -#' future use of this function. +#' automatically calculated as described in the data +#' [readme.txt](https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt) file. +#' Data may be cached for later use by this function, saving time downloading +#' files in future use of this function. #' #' @section Nomenclature and Units: #' \describe{ diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 0249e8b..5bcfe29 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -4,8 +4,9 @@ #' climatology data into \R and creates a list of \CRANpkg{terra} #' [terra::rast] objects of the data. If requested, minimum and maximum #' temperature may also be automatically calculated as described in the data -#' readme.txt file. Data may be cached for later use by this function, saving -#' time downloading files in future using this function. +#' [readme.txt](https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt) file. +#' Data may be cached for later use by this function, saving time downloading +#' files in future using this function. #' #' @inheritSection get_CRU_df Nomenclature and Units #' @inheritParams get_CRU_df diff --git a/codemeta.json b/codemeta.json index f74b013..5924514 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "920.717KB", + "fileSize": "921.658KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 25a05da..7edfdce 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -101,11 +101,13 @@ climatology elements. } \description{ Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology -data and creates a \CRANpkg{data.table} of the data. If requested, minimum +data and creates a \CRANpkg{data.table} of the data. If requested, minimum and maximum temperature may also be automatically calculated as described in -the data readme.txt file. This function can be useful if you have network -connection issues that mean automated downloading of the files using \R -does not work properly. +the data \href{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}{readme.txt} +file. Data may be cached for later use by this function, saving time +downloading files in future using this function. This function can be useful +if you have network connection issues that mean automated downloading of the +files using \R does not work properly. } \section{Nomenclature and Units}{ diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 2271760..6827d94 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -103,9 +103,12 @@ v. 2.0 climatology elements. Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology data and creates a \CRANpkg{terra} \link[terra:rast]{terra::rast} object of the data. If requested, minimum and maximum temperature may also be -automatically calculated as described in the data readme.txt file. This -function can be useful if you have network connection issues that mean -automated downloading of the files using \R does not work properly. +automatically calculated as described in the data +\href{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}{readme.txt} file. +Data may be cached for later use by this function, saving time downloading +files in future using this function. This function can be useful if you have +network connection issues that mean automated downloading of the files using +\R does not work properly. } \section{Nomenclature and Units}{ diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index da5362a..0f15410 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -104,9 +104,10 @@ climatology elements. This function automates downloading and importing \acronym{CRU} \acronym{CL} v. 2.0 climatology data and creates a \CRANpkg{data.table} of the data. If requested, minimum and maximum temperature may also be -automatically calculated as described in the data readme.txt file. Data may -be cached for later use by this function, saving time downloading files in -future use of this function. +automatically calculated as described in the data +\href{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}{readme.txt} file. +Data may be cached for later use by this function, saving time downloading +files in future use of this function. } \section{Nomenclature and Units}{ diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 44f1a72..edd4caa 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -105,8 +105,9 @@ This function automates downloading and importing CRU CL v. 2.0 climatology data into \R and creates a list of \CRANpkg{terra} \link[terra:rast]{terra::rast} objects of the data. If requested, minimum and maximum temperature may also be automatically calculated as described in the data -readme.txt file. Data may be cached for later use by this function, saving -time downloading files in future using this function. +\href{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}{readme.txt} file. +Data may be cached for later use by this function, saving time downloading +files in future using this function. } \section{Nomenclature and Units}{ From 2ab33a8fe0bc0eee1ea413c3f7dcb44be14a9b6e Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:36:55 +0800 Subject: [PATCH 32/60] linebreaks in example comment --- R/get_CRU_stack.R | 4 ++-- man/get_CRU_stack.Rd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 5bcfe29..d9c74c5 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -12,8 +12,8 @@ #' @inheritParams get_CRU_df #' @examplesIf interactive() #' -#' # Download data and create a {terra} `rast` -#' # object of precipitation and temperature without caching the data files +#' # Download data and create a {terra} `rast` object of precipitation and +#' # temperature without caching the data files #' CRU_pre_tmp <- get_CRU_stack(pre = TRUE, tmp = TRUE) #' #' CRU_pre_tmp diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index edd4caa..a3b6593 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -132,8 +132,8 @@ For more information see the description of the data provided by \examples{ \dontshow{if (interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} -# Download data and create a {terra} `rast` -# object of precipitation and temperature without caching the data files +# Download data and create a {terra} `rast` object of precipitation and +# temperature without caching the data files CRU_pre_tmp <- get_CRU_stack(pre = TRUE, tmp = TRUE) CRU_pre_tmp From 17cb70d66e46db21ff620e64b75213d104621da9 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:42:02 +0800 Subject: [PATCH 33/60] simplify Roxygen reuse source and references --- R/create_CRU_stack.R | 20 ++------------------ R/get_CRU_df.R | 20 ++------------------ R/get_CRU_stack.R | 21 ++------------------- codemeta.json | 2 +- 4 files changed, 7 insertions(+), 56 deletions(-) diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index 564ceba..29832c3 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -32,24 +32,8 @@ #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' -#' @source -#' \describe{ -#' \item{pre}{} -#' \item{rd0}{} -#' \item{tmp}{} -#' \item{dtr}{} -#' \item{reh}{} -#' \item{sunp}{} -#' \item{frs}{} -#' \item{wnd}{, areas originally including Antarctica are removed.} -#' \item{elv}{, values are converted from kilometres to metres.} -#' } -#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. -#' -#' @references New, Mark, et al. "A high-resolution data set of surface climate -#' over global land areas." Climate research 21.1 (2002): 1-25. -#' +#' @inherit create_CRU_df source +#' @inherit create_CRU_df references #' #' @export diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 87c320a..1504ba8 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -72,24 +72,8 @@ #' climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} -#' @source -#' \describe{ -#' \item{pre}{} -#' \item{rd0}{} -#' \item{tmp}{} -#' \item{dtr}{} -#' \item{reh}{} -#' \item{sunp}{} -#' \item{frs}{} -#' \item{wnd}{, areas originally including Antarctica are removed.} -#' \item{elv}{, values are converted from kilometres to metres.} -#' } -#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. -#' -#' @references New, Mark, et al. "A high-resolution data set of surface climate -#' over global land areas." Climate research 21.1 (2002): 1-25. -#' +#' @inherit create_CRU_df source +#' @inherit create_CRU_df references #' #' @export diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index d9c74c5..83cec9d 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -25,25 +25,8 @@ #' elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} -#' -#' @source -#' \describe{ -#' \item{pre}{} -#' \item{rd0}{} -#' \item{tmp}{} -#' \item{dtr}{} -#' \item{reh}{} -#' \item{sunp}{} -#' \item{frs}{} -#' \item{wnd}{, areas originally including Antarctica are removed.} -#' \item{elv}{, values are converted from kilometres to metres.} -#' } -#' This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, -#' xmin = -180, xmax = 180. -#' -#' @references New, Mark, et al. "A high-resolution data set of surface climate -#' over global land areas." Climate research 21.1 (2002): 1-25. -#' +#' @inherit create_CRU_df source +#' @inherit create_CRU_df references #' #' @export diff --git a/codemeta.json b/codemeta.json index 5924514..b72e833 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "921.658KB", + "fileSize": "918.205KB", "citation": [ { "@type": "ScholarlyArticle", From b729a856543233f84f1ab02633fbbe20d1dd1958 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:44:34 +0800 Subject: [PATCH 34/60] Clarify example code --- R/get_CRU_stack.R | 4 ++-- codemeta.json | 2 +- man/get_CRU_stack.Rd | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 83cec9d..507d1e0 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -12,8 +12,8 @@ #' @inheritParams get_CRU_df #' @examplesIf interactive() #' -#' # Download data and create a {terra} `rast` object of precipitation and -#' # temperature without caching the data files +#' # Download data and create a list of {terra} `rast` objects of precipitation +#' # and temperature without caching the data files #' CRU_pre_tmp <- get_CRU_stack(pre = TRUE, tmp = TRUE) #' #' CRU_pre_tmp diff --git a/codemeta.json b/codemeta.json index b72e833..dccb649 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "918.205KB", + "fileSize": "918.223KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index a3b6593..59cec81 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -132,8 +132,8 @@ For more information see the description of the data provided by \examples{ \dontshow{if (interactive()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} -# Download data and create a {terra} `rast` object of precipitation and -# temperature without caching the data files +# Download data and create a list of {terra} `rast` objects of precipitation +# and temperature without caching the data files CRU_pre_tmp <- get_CRU_stack(pre = TRUE, tmp = TRUE) CRU_pre_tmp From eec6c742fd5d9cc7c1671e858a815f8eac0e42f8 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:48:24 +0800 Subject: [PATCH 35/60] Use more inherited Roxygen tags --- R/create_CRU_df.R | 4 ++-- R/get_CRU_df.R | 4 +--- R/get_CRU_stack.R | 4 +--- codemeta.json | 2 +- man/create_CRU_df.Rd | 4 ++-- man/get_CRU_df.Rd | 4 ++-- man/get_CRU_stack.Rd | 4 ++-- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index ae0ead8..dd0053c 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -57,8 +57,8 @@ #' @seealso #' [get_CRU_df]. #' -#' @return A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -#' climatology elements. +#' @return A [data.table::data.table] object of \acronym{CRU} \acronym{CL} v. +#' 2.0 climatology elements. #' #' @author Adam H Sparks, \email{adamhsparks@@gmail.com} #' diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 1504ba8..bbc1245 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -68,12 +68,10 @@ #' @seealso #' [create_CRU_stack], [manage_cache]. #' -#' @return A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -#' climatology elements. -#' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' @inherit create_CRU_df source #' @inherit create_CRU_df references +#' @inherit create_CRU_df return #' #' @export diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 507d1e0..1d5491e 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -21,12 +21,10 @@ #' @seealso #' [create_CRU_stack], [manage_cache]. #' -#' @return A [base::list] of [terra::rast] objects of CRU CL v. 2.0 climatology -#' elements. -#' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' @inherit create_CRU_df source #' @inherit create_CRU_df references +#' @inherit create_CRU_stack return #' #' @export diff --git a/codemeta.json b/codemeta.json index dccb649..a916272 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "918.223KB", + "fileSize": "918.176KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 7edfdce..6801202 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -96,8 +96,8 @@ the data frame, \code{TRUE}. Defaults to \code{FALSE}.} files are located.} } \value{ -A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -climatology elements. +A \link[data.table:data.table]{data.table::data.table} object of \acronym{CRU} \acronym{CL} v. +2.0 climatology elements. } \description{ Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology diff --git a/man/get_CRU_df.Rd b/man/get_CRU_df.Rd index 0f15410..a4b3e7d 100644 --- a/man/get_CRU_df.Rd +++ b/man/get_CRU_df.Rd @@ -97,8 +97,8 @@ To take advantage of cached files in future sessions, use \code{cache = TRUE} even after the initial download and caching. Defaults to \code{FALSE}.} } \value{ -A \CRANpkg{data.table} object of \acronym{CRU} \acronym{CL} v. 2.0 -climatology elements. +A \link[data.table:data.table]{data.table::data.table} object of \acronym{CRU} \acronym{CL} v. +2.0 climatology elements. } \description{ This function automates downloading and importing \acronym{CRU} diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index 59cec81..f163261 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -97,8 +97,8 @@ To take advantage of cached files in future sessions, use \code{cache = TRUE} even after the initial download and caching. Defaults to \code{FALSE}.} } \value{ -A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of CRU CL v. 2.0 climatology -elements. +A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of \acronym{CRU} \acronym{CL} +v. 2.0 climatology elements. } \description{ This function automates downloading and importing CRU CL v. 2.0 From 2c70dc9b0ec22cdfbd399985d0d7f7eb8894f9be Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 17 Dec 2024 18:52:15 +0800 Subject: [PATCH 36/60] inherit author tag in Roxygen --- R/create_CRU_df.R | 2 +- R/create_CRU_stack.R | 9 ++++----- R/get_CRU_df.R | 2 +- R/get_CRU_stack.R | 10 +++++----- man/create_CRU_df.Rd | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index dd0053c..aad08e6 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -60,7 +60,7 @@ #' @return A [data.table::data.table] object of \acronym{CRU} \acronym{CL} v. #' 2.0 climatology elements. #' -#' @author Adam H Sparks, \email{adamhsparks@@gmail.com} +#' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} #' #' @source #' \describe{ diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index 29832c3..34e49a7 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -12,6 +12,10 @@ #' #' @inheritSection get_CRU_df Nomenclature and Units #' @inheritParams create_CRU_df +#' @inherit create_CRU_df author +#' @inherit create_CRU_df source +#' @inherit create_CRU_df references +#' @inherit create_CRU_stack return #' #' @examplesIf interactive() #' @@ -30,11 +34,6 @@ #' @return A [base::list] of [terra::rast] objects of \acronym{CRU} \acronym{CL} #' v. 2.0 climatology elements. #' -#' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} -#' -#' @inherit create_CRU_df source -#' @inherit create_CRU_df references -#' #' @export create_CRU_stack <- function(pre = FALSE, diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index bbc1245..527afb2 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -68,7 +68,7 @@ #' @seealso #' [create_CRU_stack], [manage_cache]. #' -#' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} +#' @inherit create_CRU_df author #' @inherit create_CRU_df source #' @inherit create_CRU_df references #' @inherit create_CRU_df return diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index 1d5491e..a935273 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -10,6 +10,11 @@ #' #' @inheritSection get_CRU_df Nomenclature and Units #' @inheritParams get_CRU_df +#' @inherit create_CRU_df author +#' @inherit create_CRU_df source +#' @inherit create_CRU_df references +#' @inherit create_CRU_stack return +#' #' @examplesIf interactive() #' #' # Download data and create a list of {terra} `rast` objects of precipitation @@ -21,11 +26,6 @@ #' @seealso #' [create_CRU_stack], [manage_cache]. #' -#' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} -#' @inherit create_CRU_df source -#' @inherit create_CRU_df references -#' @inherit create_CRU_stack return -#' #' @export get_CRU_stack <- diff --git a/man/create_CRU_df.Rd b/man/create_CRU_df.Rd index 6801202..cde1783 100644 --- a/man/create_CRU_df.Rd +++ b/man/create_CRU_df.Rd @@ -153,5 +153,5 @@ over global land areas." Climate research 21.1 (2002): 1-25. \link{get_CRU_df}. } \author{ -Adam H Sparks, \email{adamhsparks@gmail.com} +Adam H. Sparks, \email{adamhsparks@gmail.com} } From 5a5d2216224a147fb3692d4984fb5cb4bbc63b55 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Wed, 18 Dec 2024 08:02:20 +0800 Subject: [PATCH 37/60] lint README and remove revdepcheck infrastructure --- README.md | 42 +++++++++++++++++++++--------------------- codemeta.json | 2 +- revdep/README.md | 45 --------------------------------------------- revdep/check.R | 5 ----- revdep/checks.rds | Bin 748 -> 0 bytes revdep/cran.md | 7 ------- revdep/failures.md | 1 - revdep/problems.md | 1 - revdep/timing.md | 5 ----- 9 files changed, 22 insertions(+), 86 deletions(-) delete mode 100644 revdep/README.md delete mode 100644 revdep/check.R delete mode 100644 revdep/checks.rds delete mode 100644 revdep/cran.md delete mode 100644 revdep/failures.md delete mode 100644 revdep/problems.md delete mode 100644 revdep/timing.md diff --git a/README.md b/README.md index c411282..7a3c559 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ -getCRUCLdata: Use and Explore CRU CL v. 2.0 Climatology Elements in R -================ +# getCRUCLdata: Use and Explore CRU CL v. 2.0 Climatology Elements in R + [![R-CMD-check](https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.466812.svg)](https://doi.org/10.5281/zenodo.466812) [![JOSS status](http://joss.theoj.org/papers/10.21105/joss.00230/status.svg)](https://joss.theoj.org/papers/10.21105/joss.00230) [![](https://badges.ropensci.org/96_status.svg)](https://github.com/ropensci/software-review/issues/96) [![codecov](https://codecov.io/gh/ropensci/getCRUCLdata/graph/badge.svg?token=OZjFYcNGbS)](https://codecov.io/gh/ropensci/getCRUCLdata) + ## Introduction to {getCRUCLdata} @@ -31,7 +32,7 @@ Note that the original wind data include land area for parts of Antarctica. {getCRUCLdata} is not available from CRAN. You can install it from GitHub as follows. -``` r +```r if (!require("remotes")) { install.packages("remotes") } @@ -39,18 +40,18 @@ if (!require("remotes")) { install_github("ropensci/getCRUCLdata", build_vignettes = TRUE) ``` -Or you can install it from the rOpenSci Universe. +Or you can install it from the rOpenSci [R-universe](https://r-universe.dev/search?q=getCRUCLdata). -``` r -# Enable the rOpenSci universe +```r +# Enable the rOpenSci R-universe options(repos = c( rOpenSci = "https://ropensci.r-universe.dev", - CRAN = "https://cloud.r-project.org"")) + CRAN = "https://cloud.r-project.org")) # Install the package install.packages("getCRUCLdata") ``` ------ +--- # Documentation @@ -62,15 +63,15 @@ For complete documentation see the package website: Mark New (1,\*), David Lister (2), Mike Hulme (3), Ian Makin (4) -> A high-resolution data set of surface climate over global land areas +> A high-resolution data set of surface climate over global land areas > Climate Research, 2000, Vol 21, pg 1-25 -> 1) School of Geography and the Environment, University of Oxford, -> Mansfield Road, Oxford OX1 3TB, United Kingdom -> 2) Climatic Research Unit, and (3) Tyndall Centre for Climate Change +> 1. School of Geography and the Environment, University of Oxford, +> Mansfield Road, Oxford OX1 3TB, United Kingdom +> 2. Climatic Research Unit, and (3) Tyndall Centre for Climate Change > Research, both at School of Environmental Sciences, University of -> East Anglia, Norwich NR4 7TJ, United Kingdom -> 3) International Water Management Institute, PO Box 2075, Colombo, +> East Anglia, Norwich NR4 7TJ, United Kingdom +> 3. International Water Management Institute, PO Box 2075, Colombo, > Sri Lanka > **ABSTRACT:** We describe the construction of a 10-minute @@ -93,7 +94,6 @@ For complete documentation see the package website: @@ -167,12 +167,12 @@ All contributions to this project are gratefully acknowledged using the [`allcon ## Other - - Please [report any issues or - bugs](https://github.com/ropensci/getCRUCLdata/issues). +- Please [report any issues or + bugs](https://github.com/ropensci/getCRUCLdata/issues). - - License: MIT +- License: MIT - - Get citation information for _getCRUCLdata_ in R typing `citation(package = "getCRUCLdata")` +- Get citation information for _getCRUCLdata_ in R typing `citation(package = "getCRUCLdata")` - - Please note that this package is released with a [Contributor Code of Conduct](https://ropensci.org/code-of-conduct/). -By contributing to this project, you agree to abide by its terms. +- Please note that this package is released with a [Contributor Code of Conduct](https://ropensci.org/code-of-conduct/). + By contributing to this project, you agree to abide by its terms. diff --git a/codemeta.json b/codemeta.json index a916272..8e1ecc3 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "918.176KB", + "fileSize": "918.149KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/revdep/README.md b/revdep/README.md deleted file mode 100644 index d42e1bf..0000000 --- a/revdep/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Platform - -|field |value | -|:--------|:----------------------------| -|version |R version 4.0.3 (2020-10-10) | -|os |macOS Catalina 10.15.7 | -|system |x86_64, darwin17.0 | -|ui |RStudio | -|language |(EN) | -|collate |en_AU.UTF-8 | -|ctype |en_AU.UTF-8 | -|tz |Australia/Brisbane | -|date |2020-10-25 | - -# Dependencies - -|package |old |new |Δ | -|:------------|:------|:----------|:--| -|getCRUCLdata |0.3.1 |0.3.1.9000 |* | -|assertthat |0.2.1 |0.2.1 | | -|cli |2.1.0 |2.1.0 | | -|crayon |1.3.4 |1.3.4 | | -|curl |4.3 |4.3 | | -|data.table |1.13.2 |1.13.2 | | -|digest |0.6.27 |0.6.27 | | -|ellipsis |0.3.1 |0.3.1 | | -|fansi |0.4.1 |0.4.1 | | -|glue |1.4.2 |1.4.2 | | -|hoardr |0.5.2 |0.5.2 | | -|lifecycle |0.2.0 |0.2.0 | | -|magrittr |1.5 |1.5 | | -|pillar |1.4.6 |1.4.6 | | -|pkgconfig |2.0.3 |2.0.3 | | -|R6 |2.4.1 |2.4.1 | | -|rappdirs |0.3.1 |0.3.1 | | -|raster |3.3-13 |3.3-13 | | -|Rcpp |1.0.5 |1.0.5 | | -|rlang |0.4.8 |0.4.8 | | -|sp |1.4-4 |1.4-4 | | -|tibble |3.0.4 |3.0.4 | | -|utf8 |1.1.4 |1.1.4 | | -|vctrs |0.3.4 |0.3.4 | | - -# Revdeps - diff --git a/revdep/check.R b/revdep/check.R deleted file mode 100644 index e262948..0000000 --- a/revdep/check.R +++ /dev/null @@ -1,5 +0,0 @@ -library("devtools") - -revdep_check() -revdep_check_save_summary() -revdep_check_print_problems() diff --git a/revdep/checks.rds b/revdep/checks.rds deleted file mode 100644 index 0ad05039ae90a16691817f2bd1f9c55ee447383a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 748 zcmV)En) zi}Ofbuhq4q(0%oMf9b3+7lctK@IudbCeR15>rY)692>Up9^>dbntpUr#2*L+GcWRd z!{*K9cezXnb0)w8-Zboy3@2YMOzb75*JoGW)sL@kY^aXTmO^rr5%lRZC*lTCY*-v@ z5{_IDDfU52V^g%iqB0*<;HWCM5?_cXA@QP;21`<%_A*50OEkyYEn!)Pq!tJAm#!x* zP$O`XAt8)B$GP&qWqff>=q+n~61y@y(u@gPab28ZN1jACnT~9ydG@5$hjT2?FR#wO z6=piq`8>~Z+alX~x?s4-2rI**oj%+t_*z6&_Bng-^x_&9Jipa#y Date: Wed, 18 Dec 2024 10:33:34 +0800 Subject: [PATCH 38/60] Fix links with redirects --- README.md | 134 +++++----------------- codemeta.json | 4 +- vignettes/getCRUCLdata.Rmd | 189 +++----------------------------- vignettes/getCRUCLdata.Rmd.orig | 2 +- vignettes/precompile.R | 1 + 5 files changed, 52 insertions(+), 278 deletions(-) diff --git a/README.md b/README.md index 7a3c559..0d20e5f 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,7 @@ -[![R-CMD-check](https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml) -[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.466812.svg)](https://doi.org/10.5281/zenodo.466812) -[![JOSS status](http://joss.theoj.org/papers/10.21105/joss.00230/status.svg)](https://joss.theoj.org/papers/10.21105/joss.00230) -[![](https://badges.ropensci.org/96_status.svg)](https://github.com/ropensci/software-review/issues/96) -[![codecov](https://codecov.io/gh/ropensci/getCRUCLdata/graph/badge.svg?token=OZjFYcNGbS)](https://codecov.io/gh/ropensci/getCRUCLdata) +[![R-CMD-check](https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.466812.svg)](https://doi.org/10.5281/zenodo.466812) [![JOSS status](http://joss.theoj.org/papers/10.21105/joss.00230/status.svg)](https://joss.theoj.org/papers/10.21105/joss.00230) [![](https://badges.ropensci.org/96_status.svg)](https://github.com/ropensci/software-review/issues/96) [![codecov](https://codecov.io/gh/ropensci/getCRUCLdata/graph/badge.svg?token=OZjFYcNGbS)](https://app.codecov.io/gh/ropensci/getCRUCLdata) @@ -15,24 +10,21 @@ The {getCRUCLdata} package provides functions that automate importing CRU CL v. 2.0 climatology data into R, facilitates the calculation of minimum temperature and maximum temperature, and formats the data into a [data.table](https://CRAN.R-project.org/package=data.table) or a list of [terra::rast](https://CRAN.R-project.org/package=terra) objects for use. -CRU CL v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. -For more information see the description of the data provided by the University of East Anglia Climate Research Unit (CRU), . +CRU CL v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit (CRU), . ## Changes to original CRU CL v. 2.0 data This package automatically converts elevation values from kilometres to metres. -This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. -Note that the original wind data include land area for parts of Antarctica. +This package crops all spatial outputs to an extent of ymin = -60, ymax = 85, xmin = -180, xmax = 180. Note that the original wind data include land area for parts of Antarctica. # Quick Start ## Install -{getCRUCLdata} is not available from CRAN. -You can install it from GitHub as follows. +{getCRUCLdata} is not available from CRAN. You can install it from GitHub as follows. -```r +``` r if (!require("remotes")) { install.packages("remotes") } @@ -42,7 +34,7 @@ install_github("ropensci/getCRUCLdata", build_vignettes = TRUE) Or you can install it from the rOpenSci [R-universe](https://r-universe.dev/search?q=getCRUCLdata). -```r +``` r # Enable the rOpenSci R-universe options(repos = c( rOpenSci = "https://ropensci.r-universe.dev", @@ -51,7 +43,7 @@ options(repos = c( install.packages("getCRUCLdata") ``` ---- +------------------------------------------------------------------------ # Documentation @@ -63,116 +55,50 @@ For complete documentation see the package website: Mark New (1,\*), David Lister (2), Mike Hulme (3), Ian Makin (4) -> A high-resolution data set of surface climate over global land areas -> Climate Research, 2000, Vol 21, pg 1-25 - -> 1. School of Geography and the Environment, University of Oxford, -> Mansfield Road, Oxford OX1 3TB, United Kingdom -> 2. Climatic Research Unit, and (3) Tyndall Centre for Climate Change -> Research, both at School of Environmental Sciences, University of -> East Anglia, Norwich NR4 7TJ, United Kingdom -> 3. International Water Management Institute, PO Box 2075, Colombo, -> Sri Lanka - -> **ABSTRACT:** We describe the construction of a 10-minute -> latitude/longitude data set of mean monthly surface climate over -> global land areas, excluding Antarctica. The climatology includes 8 -> climate elements - precipitation, wet-day frequency, temperature, -> diurnal temperature range, relative humidity,sunshine duration, ground -> frost frequency and windspeed - and was interpolated from a data set -> of station means for the period centred on 1961 to 1990. Precipitation -> was first defined in terms of the parameters of the Gamma -> distribution, enabling the calculation of monthly precipitation at any -> given return period. The data are compared to an earlier data set at -> 0.5 degrees latitude/longitude resolution and show added value over -> most regions. The data will have many applications in applied -> climatology, biogeochemical modelling, hydrology and agricultural -> meteorology and are available through the School of Geography Oxford -> (), the International Water Management -> Institute “World Water and Climate Atlas” () and -> the Climatic Research Unit (). +> A high-resolution data set of surface climate over global land areas Climate Research, 2000, Vol 21, pg 1-25 + +> 1. School of Geography and the Environment, University of Oxford, Mansfield Road, Oxford OX1 3TB, United Kingdom +> 2. Climatic Research Unit, and (3) Tyndall Centre for Climate Change Research, both at School of Environmental Sciences, University of East Anglia, Norwich NR4 7TJ, United Kingdom +> 3. International Water Management Institute, PO Box 2075, Colombo, Sri Lanka + +> **ABSTRACT:** We describe the construction of a 10-minute latitude/longitude data set of mean monthly surface climate over global land areas, excluding Antarctica. The climatology includes 8 climate elements - precipitation, wet-day frequency, temperature, diurnal temperature range, relative humidity,sunshine duration, ground frost frequency and windspeed - and was interpolated from a data set of station means for the period centred on 1961 to 1990. Precipitation was first defined in terms of the parameters of the Gamma distribution, enabling the calculation of monthly precipitation at any given return period. The data are compared to an earlier data set at 0.5 degrees latitude/longitude resolution and show added value over most regions. The data will have many applications in applied climatology, biogeochemical modelling, hydrology and agricultural meteorology and are available through the School of Geography Oxford (), the International Water Management Institute “World Water and Climate Atlas” () and the Climatic Research Unit (). ## Contributors + + All contributions to this project are gratefully acknowledged using the [`allcontributors` package](https://github.com/ropensci/allcontributors) following the [all-contributors](https://allcontributors.org) specification. Contributions of any kind are welcome! ### Code - - - - - - - - - -
- - -
-adamhsparks -
- - -
-sckott -
- - -
-jeroen -
- - -
-karthik -
- ++------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+ +| [![](https://avatars.githubusercontent.com/u/3195906?v=4){alt=""} ](https://github.com/adamhsparks)\ | [![](https://avatars.githubusercontent.com/u/577668?v=4){alt=""} ](https://github.com/sckott)\ | [![](https://avatars.githubusercontent.com/u/216319?v=4){alt=""} ](https://github.com/jeroen)\ | [![](https://avatars.githubusercontent.com/u/138494?v=4){alt=""} ](https://github.com/karthik)\ | +| [adamhsparks](https://github.com/ropensci/getCRUCLdata/commits?author=adamhsparks) | [sckott](https://github.com/ropensci/getCRUCLdata/commits?author=sckott) | [jeroen](https://github.com/ropensci/getCRUCLdata/commits?author=jeroen) | [karthik](https://github.com/ropensci/getCRUCLdata/commits?author=karthik) | ++------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+ ### Issues - - - - - - - - -
- - -
-ivanhanigan -
- - -
-sunjj878 -
- - -
-mhesselbarth -
++-------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------+ +| [![](https://avatars.githubusercontent.com/u/1305767?u=151f7c98a1bb78ccceac6297d28750acb42ec877&v=4){alt=""} ](https://github.com/ivanhanigan)\ | [![](https://avatars.githubusercontent.com/u/77564290?v=4){alt=""} ](https://github.com/sunjj878)\ | [![](https://avatars.githubusercontent.com/u/29225293?u=326393156ff083af6e10548ff16a1c8e439ebdf9&v=4){alt=""} ](https://github.com/mhesselbarth)\ | +| [ivanhanigan](https://github.com/ropensci/getCRUCLdata/issues?q=is%3Aissue+author%3Aivanhanigan) | [sunjj878](https://github.com/ropensci/getCRUCLdata/issues?q=is%3Aissue+author%3Asunjj878) | [mhesselbarth](https://github.com/ropensci/getCRUCLdata/issues?q=is%3Aissue+author%3Amhesselbarth) | ++-------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------+ + + ## Other -- Please [report any issues or - bugs](https://github.com/ropensci/getCRUCLdata/issues). +- Please [report any issues or bugs](https://github.com/ropensci/getCRUCLdata/issues). -- License: MIT +- License: MIT -- Get citation information for _getCRUCLdata_ in R typing `citation(package = "getCRUCLdata")` +- Get citation information for *getCRUCLdata* in R typing `citation(package = "getCRUCLdata")` -- Please note that this package is released with a [Contributor Code of Conduct](https://ropensci.org/code-of-conduct/). - By contributing to this project, you agree to abide by its terms. +- Please note that this package is released with a [Contributor Code of Conduct](https://ropensci.org/code-of-conduct/). By contributing to this project, you agree to abide by its terms. diff --git a/codemeta.json b/codemeta.json index 8e1ecc3..b4b06a3 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "918.149KB", + "fileSize": "912.473KB", "citation": [ { "@type": "ScholarlyArticle", @@ -286,7 +286,7 @@ ], "releaseNotes": "https://github.com/ropensci/getCRUCLdata/blob/master/NEWS.md", "readme": "https://github.com/ropensci/getCRUCLdata/blob/main/README.md", - "contIntegration": ["https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml", "https://codecov.io/gh/ropensci/getCRUCLdata"], + "contIntegration": ["https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml", "https://app.codecov.io/gh/ropensci/getCRUCLdata"], "developmentStatus": "https://www.repostatus.org/", "review": { "@type": "Review", diff --git a/vignettes/getCRUCLdata.Rmd b/vignettes/getCRUCLdata.Rmd index e39b9ae..194466b 100644 --- a/vignettes/getCRUCLdata.Rmd +++ b/vignettes/getCRUCLdata.Rmd @@ -1,7 +1,7 @@ --- title: "getCRUCLdata" author: "Adam H. Sparks" -date: "2024-12-17" +date: "2024-12-18" output: rmarkdown::html_vignette: toc: true @@ -72,6 +72,7 @@ The `get_CRU_df()` function automates the download process and creates data fram ``` r library(getCRUCLdata) +#> Error in library(getCRUCLdata): there is no package called 'getCRUCLdata' CRU_data <- get_CRU_df(pre = TRUE, pre_cv = TRUE, @@ -85,34 +86,10 @@ CRU_data <- get_CRU_df(pre = TRUE, frs = TRUE, wnd = TRUE, elv = TRUE) +#> Error in get_CRU_df(pre = TRUE, pre_cv = TRUE, rd0 = TRUE, tmp = TRUE, : could not find function "get_CRU_df" CRU_data -#> lat lon month dtr frs pre pre_cv rd0 reh sun tmp wnd elv -#> -#> 1: 30.917 35.417 NA NA NA NA NA NA NA NA NA -260 -#> 2: 31.083 35.417 NA NA NA NA NA NA NA NA NA -361 -#> 3: 31.250 35.417 NA NA NA NA NA NA NA NA NA -336 -#> 4: 31.417 35.417 NA NA NA NA NA NA NA NA NA -284 -#> 5: 31.750 35.583 NA NA NA NA NA NA NA NA NA -248 -#> --- -#> 6795146: 83.583 -30.083 dec 8.7 31 0.1 72.7 5.1 70.6 0 -31.3 5.6 283 -#> 6795147: 83.583 -29.917 dec 8.6 31 0.1 72.8 4.9 70.6 0 -30.7 5.6 186 -#> 6795148: 83.583 -29.750 dec 8.6 31 0.1 72.9 4.9 70.6 0 -30.8 5.6 195 -#> 6795149: 83.583 -29.583 dec 8.6 31 0.1 73.0 5.0 70.6 0 -31.2 5.6 268 -#> 6795150: 83.583 -29.417 dec 8.6 31 0.1 73.1 5.1 70.6 0 -31.5 5.6 328 -#> tmx tmn -#> -#> 1: NA NA -#> 2: NA NA -#> 3: NA NA -#> 4: NA NA -#> 5: NA NA -#> --- -#> 6795146: -26.95 -35.65 -#> 6795147: -26.40 -35.00 -#> 6795148: -26.50 -35.10 -#> 6795149: -26.90 -35.50 -#> 6795150: -27.20 -35.80 +#> Error: object 'CRU_data' not found ``` Perhaps you only need one or two elements, it is easy to create a data frame of mean temperature only. @@ -120,21 +97,13 @@ Perhaps you only need one or two elements, it is easy to create a data frame of ``` r t <- get_CRU_df(tmp = TRUE) +#> Error in get_CRU_df(tmp = TRUE): could not find function "get_CRU_df" t -#> lat lon month tmp -#> -#> 1: -59.083 -26.583 jan 0.2 -#> 2: -58.417 -26.250 jan 0.6 -#> 3: -58.417 -26.417 jan 0.4 -#> 4: -55.917 -67.250 jan 8.0 -#> 5: -55.750 -67.250 jan 8.2 -#> --- -#> 6795140: 83.583 -36.083 dec -32.6 -#> 6795141: 83.583 -36.250 dec -33.0 -#> 6795142: 83.583 -36.417 dec -33.4 -#> 6795143: 83.583 -36.583 dec -33.3 -#> 6795144: 83.583 -36.750 dec -33.3 +#> function (x) +#> UseMethod("t") +#> +#> ``` #### Plotting data from the data frame @@ -152,13 +121,11 @@ ggplot(data = t, aes(x = lon, y = lat, fill = tmp)) + coord_quickmap() + ggtitle("Global Mean Monthly Temperatures 1961-1990") + facet_wrap( ~ month, nrow = 4) +#> Error in `ggplot()`: +#> ! `data` cannot be a function. +#> ℹ Have you misspelled the `data` argument in `ggplot()` ``` -
-Maps of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991. -

Maps of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991.

-
- We can also generate a violin plot of the same data to visualise how the temperatures change throughout the year. @@ -168,13 +135,11 @@ ggplot(data = t, aes(x = month, y = tmp)) + ylab("Temperature (˚C)") + labs(title = "Global Monthly Mean Land Surface Temperatures From 1960-1991", subtitle = "Excludes Antarctica") +#> Error in `ggplot()`: +#> ! `data` cannot be a function. +#> ℹ Have you misspelled the `data` argument in `ggplot()` ``` -
-Monthly values of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991. -

Monthly values of global temperatures from CRU CL v. 2.0 climatology covering the Earth's surface from ymin = -60, ymax = 85, xmin = -180, xmax = 180 degrees from 1960 to 1991.

-
- #### Saving the `data.frame` as a CSV (comma separated values file) locally Save the resulting `data.frame` to local disk as a comma separated (CSV) @@ -211,128 +176,10 @@ CRU_stack <- get_CRU_stack( wnd = TRUE, elv = TRUE ) +#> Error in get_CRU_stack(pre = TRUE, pre_cv = TRUE, rd0 = TRUE, tmp = TRUE, : could not find function "get_CRU_stack" CRU_stack -#> $dtr -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 2.3, 2.1, 2.2, 2.3, 1.8, 2.5, ... -#> max values : 22.7, 23.1, 23.5, 24.0, 24.0, 25.2, ... -#> -#> $elv -#> class : SpatRaster -#> dimensions : 870, 2160, 1 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> name : elv -#> min value : -361 -#> max value : 6486 -#> -#> $frs -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 0, 0.0, 0, 0, 0, 0, ... -#> max values : 31, 28.3, 31, 30, 31, 30, ... -#> -#> $pre -#> class : SpatRaster -#> dimensions : 870, 2160, 24 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 0.0, 0.0, 0.0, 0.0, 0, 0.0, ... -#> max values : 910.1, 824.3, 727.3, 741.3, 1100, 2512.6, ... -#> -#> $rd0 -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 0, 0.0, 0, 0, 0.0, 0, ... -#> max values : 31, 28.2, 31, 30, 30.7, 30, ... -#> -#> $reh -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 18.4, 14.6, 13.5, 13.4, 15.5, 10.2, ... -#> max values : 100.0, 100.0, 100.0, 100.0, 96.9, 95.1, ... -#> -#> $sun -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 0.0, 0, 3.3, 4.3, 8.1, 6.6, ... -#> max values : 92.8, 93, 90.2, 93.1, 94.0, 98.9, ... -#> -#> $tmp -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : -51.6, -47.6, -45.2, -36.6, -22.2, -16.3, ... -#> max values : 32.5, 32.1, 32.4, 34.3, 36.0, 38.3, ... -#> -#> $wnd -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : 0.1, 0.1, 0.3, 0.4, 0.3, 0.2, ... -#> max values : 9.8, 9.6, 9.4, 9.0, 8.7, 8.6, ... -#> -#> $tmn -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : -55.05, -52.95, -48.75, -41.35, -28, -21.40, ... -#> max values : 26.30, 26.25, 27.40, 27.50, 30, 30.65, ... -#> -#> $tmx -#> class : SpatRaster -#> dimensions : 870, 2160, 12 (nrow, ncol, nlyr) -#> resolution : 0.1666667, 0.1666667 (x, y) -#> extent : -180, 180, -60, 85 (xmin, xmax, ymin, ymax) -#> coord. ref. : lon/lat WGS 84 -#> source(s) : memory -#> names : jan, feb, mar, apr, may, jun, ... -#> min values : -48.2, -43.35, -41.65, -32.45, -17.55, -11.50, ... -#> max values : 39.7, 38.40, 40.25, 41.85, 43.60, 45.95, ... +#> Error: object 'CRU_stack' not found ``` The `create_CRU_stack()` function works in the same way with only one minor difference. @@ -413,5 +260,5 @@ and show added value over most regions. The data will have many applications in applied climatology, biogeochemical modelling, hydrology and agricultural meteorology and are available through the School of Geography Oxford (https://www.geog.ox.ac.uk), the International Water Management Institute -"World Water and Climate Atlas" (https://www.iwmi.cgiar.org/) and the Climatic +"World Water and Climate Atlas" (https://www.iwmi.org/) and the Climatic Research Unit (https://www.uea.ac.uk/groups-and-centres/climatic-research-unit). diff --git a/vignettes/getCRUCLdata.Rmd.orig b/vignettes/getCRUCLdata.Rmd.orig index 6242244..eb86aa2 100644 --- a/vignettes/getCRUCLdata.Rmd.orig +++ b/vignettes/getCRUCLdata.Rmd.orig @@ -241,5 +241,5 @@ and show added value over most regions. The data will have many applications in applied climatology, biogeochemical modelling, hydrology and agricultural meteorology and are available through the School of Geography Oxford (https://www.geog.ox.ac.uk), the International Water Management Institute -"World Water and Climate Atlas" (https://www.iwmi.cgiar.org/) and the Climatic +"World Water and Climate Atlas" (https://www.iwmi.org/) and the Climatic Research Unit (https://www.uea.ac.uk/groups-and-centres/climatic-research-unit). diff --git a/vignettes/precompile.R b/vignettes/precompile.R index dac85ad..e68c787 100644 --- a/vignettes/precompile.R +++ b/vignettes/precompile.R @@ -21,3 +21,4 @@ file.copy(from = resources, to = "doc", overwrite = TRUE) + From 11f3a5eb9be1b1cddde64f8d6d38dcc45253abc2 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Wed, 18 Dec 2024 10:42:14 +0800 Subject: [PATCH 39/60] update wordlist --- codemeta.json | 2 +- inst/WORDLIST | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index b4b06a3..a4caa27 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "912.473KB", + "fileSize": "912.538KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/inst/WORDLIST b/inst/WORDLIST index 5c8868d..16cfc1c 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -19,6 +19,7 @@ Reknit Reorganises Sri TJ +adamhsparks al arcminutes behaviour @@ -43,12 +44,16 @@ globals gridded gz hoardr +ivanhanigan +jeroen +karthik kilometres magrittr maintainer's md metre metres +mhesselbarth millimetres modelled modelling @@ -62,7 +67,9 @@ readme readr reh roxyglobals +sckott sp +sunjj sunp terra tibble From 1c43348381b8b50b1a7c9e0868d80fd86048ccef Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Wed, 18 Dec 2024 11:08:54 +0800 Subject: [PATCH 40/60] add cran-comments.md --- cran-comments.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 cran-comments.md diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..ab83bbb --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,17 @@ +## R CMD check results + +0 errors | 0 warnings | 2 notes + +## Fixes from previous CRAN version + +I had asked that the last version of this package on CRAN be removed, but the +notes indicate it was forcibly removed for "leaving things behind". + +Therefore, in this release, the caching capabilities now follow the new R +standard `tools::R_user_dir(package = "getCRUCLdata")` in spite of the default +behaviour of the underlying CRAN packages, {hoadr} and {rappdirs}, which have +been used since this package was first submitted to CRAN to proovide file +caching functionality in this package. I trust that this is sufficient to have +the {getCRUCLdata} package reinstated on CRAN. + +* This is a new release. From b75cbad8d5859bca20a8d48c6aa2ddb704c00103 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Wed, 18 Dec 2024 11:12:57 +0800 Subject: [PATCH 41/60] prep for CRAN re-release --- DESCRIPTION | 2 +- NEWS.md | 2 +- codemeta.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index ee8a0b4..8b0b2ef 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: getCRUCLdata Title: 'CRU' 'CL' v. 2.0 Climatology Client -Version: 1.0.2 +Version: 1.0.3 Authors@R: c( person("Adam H.", "Sparks", , "adamhsparks@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0061-8359")), diff --git a/NEWS.md b/NEWS.md index 3f5beff..4967a27 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# getCRUCLdata 1.0.2.9000 +# getCRUCLdata 1.0.3 ## Minor changes diff --git a/codemeta.json b/codemeta.json index a4caa27..f3c0335 100644 --- a/codemeta.json +++ b/codemeta.json @@ -8,7 +8,7 @@ "codeRepository": "https://github.com/ropensci/getCRUCLdata", "issueTracker": "https://github.com/ropensci/getCRUCLdata/issues", "license": "https://spdx.org/licenses/MIT", - "version": "1.0.2", + "version": "1.0.3", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "912.538KB", + "fileSize": "912.533KB", "citation": [ { "@type": "ScholarlyArticle", From 1529626aeaf0b90d91b09241fa22d32be7797fb0 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Wed, 5 Feb 2025 09:32:54 +0800 Subject: [PATCH 42/60] use {devtag} and fix @returns tag --- .Rbuildignore | 9 +++++ DESCRIPTION | 4 +- R/create_CRU_df.R | 2 +- R/create_CRU_stack.R | 11 ++--- R/internal_functions.R | 33 +++++++-------- codemeta.json | 2 +- man/create_CRU_stack.Rd | 11 ++--- man/dot-check_vars_FALSE.Rd | 81 +++++++++++++++++++++++++++++++++++++ man/dot-create_df.Rd | 28 +++++++++++++ man/dot-create_stack.Rd | 23 +++++++++++ man/dot-create_stacks.Rd | 30 ++++++++++++++ man/dot-get_local.Rd | 62 ++++++++++++++++++++++++++++ man/dot-read_cache.Rd | 17 ++++++++ man/dot-set_cache.Rd | 16 ++++++++ man/dot-tidy_df.Rd | 12 ++++++ man/dot-validate_dsn.Rd | 15 +++++++ man/get_CRU_stack.Rd | 4 +- 17 files changed, 325 insertions(+), 35 deletions(-) create mode 100644 man/dot-check_vars_FALSE.Rd create mode 100644 man/dot-create_df.Rd create mode 100644 man/dot-create_stack.Rd create mode 100644 man/dot-create_stacks.Rd create mode 100644 man/dot-get_local.Rd create mode 100644 man/dot-read_cache.Rd create mode 100644 man/dot-set_cache.Rd create mode 100644 man/dot-tidy_df.Rd create mode 100644 man/dot-validate_dsn.Rd diff --git a/.Rbuildignore b/.Rbuildignore index 43d8729..4c89960 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -21,3 +21,12 @@ # flint files ^flint$ +^man/dot-check_vars_FALSE\.Rd$ +^man/dot-validate_dsn\.Rd$ +^man/dot-create_df\.Rd$ +^man/dot-tidy_df\.Rd$ +^man/dot-read_cache\.Rd$ +^man/dot-create_stacks\.Rd$ +^man/dot-create_stack\.Rd$ +^man/dot-set_cache\.Rd$ +^man/dot-get_local\.Rd$ diff --git a/DESCRIPTION b/DESCRIPTION index 8b0b2ef..ecae0ea 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -56,11 +56,11 @@ Config/testthat/edition: 3 Config/testthat/parallel: true Encoding: UTF-8 Language: en-US -Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", - "roxyglobals::global_roclet", "roxylint::roxylint")) +Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", "roxyglobals::global_roclet", "roxylint::roxylint", "devtag::dev_roclet")) RoxygenNote: 7.3.2 X-schema.org-applicationCategory: Tools X-schema.org-isPartOf: https://ropensci.org X-schema.org-keywords: anglia-cru, climate-data, cru-cl2, temperature, rainfall, elevation, data-access, wind, relative-humidity, solar-radiation, diurnal-temperature, frost +Config/Needs/build: moodymudskipper/devtag diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index aad08e6..0535199 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -57,7 +57,7 @@ #' @seealso #' [get_CRU_df]. #' -#' @return A [data.table::data.table] object of \acronym{CRU} \acronym{CL} v. +#' @returns A [data.table::data.table] object of \acronym{CRU} \acronym{CL} v. #' 2.0 climatology elements. #' #' @author Adam H. Sparks, \email{adamhsparks@@gmail.com} diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index 34e49a7..b921d1c 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -6,9 +6,10 @@ #' automatically calculated as described in the data #' [readme.txt](https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt) file. #' Data may be cached for later use by this function, saving time downloading -#' files in future using this function. This function can be useful if you have -#' network connection issues that mean automated downloading of the files using -#' \R does not work properly. +#' files in future using this function. This function can be useful if you +#' have network connection issues that mean automated downloading of the files +#' using \R does not work properly or you have cached the files locally for +#' your own future use. #' #' @inheritSection get_CRU_df Nomenclature and Units #' @inheritParams create_CRU_df @@ -31,8 +32,8 @@ #' @seealso #' [get_CRU_stack]. #' -#' @return A [base::list] of [terra::rast] objects of \acronym{CRU} \acronym{CL} -#' v. 2.0 climatology elements. +#' @returns A [base::list] of [terra::rast] objects of \acronym{CRU} +#' \acronym{CL} v. 2.0 climatology elements. #' #' @export diff --git a/R/internal_functions.R b/R/internal_functions.R index 1def32e..3ac53e1 100644 --- a/R/internal_functions.R +++ b/R/internal_functions.R @@ -42,8 +42,8 @@ #' wnd, #' elv #' ) -#' @noRd -#' @keywords Internal +#' @dev + .check_vars_FALSE <- function(pre, pre_cv, @@ -68,8 +68,8 @@ #' Validates user entered dsn value #' #' @param dsn User provided value for checking. -#' @keywords Internal -#' @noRd + +#' @dev .validate_dsn <- function(dsn) { if (missing(dsn)) { cli::cli_abort( @@ -106,10 +106,9 @@ #' @param elv Is elv to be returned? Boolean. #' @param files File list to be used for creating data frame. #' -#' @return A \CRANpkg{data.table} of all requested values. -#' @keywords Internal +#' @returns A \CRANpkg{data.table} of all requested values. #' @autoglobal -#' @noRd +#' @dev .create_df <- function(tmn, tmx, tmp, dtr, pre, pre_cv, elv, files) { CRU_df <- @@ -141,8 +140,8 @@ } #' Read Files from Disk Directory and Tidy Them -#' @noRd -#' @keywords Internal +#' @dev + .tidy_df <- function(pre_cv, elv, tmn, tmx, .files) { # create list of tidied data frames ---------------------------------------- CRU_list <- @@ -187,9 +186,8 @@ #' @param .files a list of CRU CL2.0 files in local storage. #' @param .pre_cv `Boolean` return pre_cv in the data. #' -#' @keywords Internal #' @autoglobal -#' @noRd +#' @dev .read_cache <- function(.files, .pre_cv) { month_names <- @@ -282,9 +280,8 @@ #' `rast`, Boolean. #' @param files List. Files that are to be used in creating the `rast` object. #' -#' @keywords Internal #' @autoglobal -#' @noRd +#' @dev #' .create_stacks <- function(tmn, tmx, tmp, dtr, pre, pre_cv, files) { wrld <- @@ -360,8 +357,7 @@ #' @param pre_cv `Boolean` include preciptation cv. #' #' @autoglobal -#' @keywords Internal -#' @noRd +#' @dev .create_stack <- function(files, wrld, month_names, @@ -437,8 +433,8 @@ #' #' @param cache `Boolean` (create) and use local file cache. #' -#' @keywords Internal -#' @noRd + +#' @dev .set_cache <- function(cache) { manage_cache <- hoardr::hoard() manage_cache$cache_path_set( @@ -483,8 +479,7 @@ #' @param elv Boolean, loads elevation (converted to metres) and returns it in #' the data frame. #' -#' @keywords Internal -#' @noRd +#' @dev .get_local <- function(pre, pre_cv, rd0, diff --git a/codemeta.json b/codemeta.json index f3c0335..8672b8b 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "912.533KB", + "fileSize": "912.393KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/man/create_CRU_stack.Rd b/man/create_CRU_stack.Rd index 6827d94..a1a2e95 100644 --- a/man/create_CRU_stack.Rd +++ b/man/create_CRU_stack.Rd @@ -96,8 +96,8 @@ the data frame, \code{TRUE}. Defaults to \code{FALSE}.} files are located.} } \value{ -A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of \acronym{CRU} \acronym{CL} -v. 2.0 climatology elements. +A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of \acronym{CRU} +\acronym{CL} v. 2.0 climatology elements. } \description{ Automates importing \acronym{CRU} \acronym{CL} v.2.0 climatology @@ -106,9 +106,10 @@ data. If requested, minimum and maximum temperature may also be automatically calculated as described in the data \href{https://crudata.uea.ac.uk/cru/data/hrg/tmc/readme.txt}{readme.txt} file. Data may be cached for later use by this function, saving time downloading -files in future using this function. This function can be useful if you have -network connection issues that mean automated downloading of the files using -\R does not work properly. +files in future using this function. This function can be useful if you +have network connection issues that mean automated downloading of the files +using \R does not work properly or you have cached the files locally for +your own future use. } \section{Nomenclature and Units}{ diff --git a/man/dot-check_vars_FALSE.Rd b/man/dot-check_vars_FALSE.Rd new file mode 100644 index 0000000..ecccd12 --- /dev/null +++ b/man/dot-check_vars_FALSE.Rd @@ -0,0 +1,81 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.check_vars_FALSE} +\alias{.check_vars_FALSE} +\title{Check that at least one element is requested} +\usage{ +.check_vars_FALSE( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv +) +} +\arguments{ +\item{pre}{Fetches precipitation (millimetres/month) from server and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{pre_cv}{Fetches cv of precipitation (percent) from server and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}. Note, setting +this to \code{TRUE} will always results in \strong{pre} being set to \code{TRUE} and +returned as well.} + +\item{rd0}{Fetches wet-days (number days with >0.1 millimetres rain per +month) and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{tmp}{Fetches temperature (degrees Celsius) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{dtr}{Fetches mean diurnal temperature range (degrees Celsius) +and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{reh}{Fetches relative humidity and returns it in the data frame, +\code{TRUE}. Defaults to \code{FALSE}.} + +\item{tmn}{Calculates minimum temperature values (degrees Celsius) +and returns it in the data frame. Defaults to \code{FALSE}.} + +\item{tmx}{Boolean. Calculates maximum temperature (degrees Celsius) and +returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{sunp}{Fetches sunshine, percent of maximum possible (percent of +day length), and returns it in the data frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{frs}{Boolean. Fetches ground-frost records (number of days with +ground-frost per month) and returns it in data frame, \code{TRUE}. Defaults to +\code{FALSE}.} + +\item{wnd}{Fetches 10m wind speed (metres/second) and returns it in the data +frame, \code{TRUE}. Defaults to \code{FALSE}.} + +\item{elv}{Fetches elevation (converted to metres) and returns it in the +data frame, \code{TRUE}. Defaults to \code{FALSE}.} +} +\description{ +Check that at least one element is requested +} +\examples{ +.check_vars_FALSE( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv +) +} +\keyword{internal} diff --git a/man/dot-create_df.Rd b/man/dot-create_df.Rd new file mode 100644 index 0000000..1cba491 --- /dev/null +++ b/man/dot-create_df.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.create_df} +\alias{.create_df} +\title{Creates a data.table from the CRU data} +\usage{ +.create_df(tmn, tmx, tmp, dtr, pre, pre_cv, elv, files) +} +\arguments{ +\item{tmn}{Is tmx to be calculated? Boolean.} + +\item{dtr}{Is dtr to be returned? Boolean.} + +\item{pre}{Is pre to be returned? Boolean.} + +\item{pre_cv}{Is pre_cv to be returned? Boolean.} + +\item{elv}{Is elv to be returned? Boolean.} + +\item{files}{File list to be used for creating data frame.} +} +\value{ +A \CRANpkg{data.table} of all requested values. +} +\description{ +Creates a data.table from the CRU data +} +\keyword{internal} diff --git a/man/dot-create_stack.Rd b/man/dot-create_stack.Rd new file mode 100644 index 0000000..e5ad03d --- /dev/null +++ b/man/dot-create_stack.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.create_stack} +\alias{.create_stack} +\title{Helper Function Used in .create_stacks()} +\usage{ +.create_stack(files, wrld, month_names, pre, pre_cv) +} +\arguments{ +\item{files}{A list of files to use in creating \code{rast} objects.} + +\item{wrld}{An empty \link[terra:rast]{terra::rast} object for filling with values.} + +\item{month_names}{A vector of month names from jan -- dec.} + +\item{pre}{\code{Boolean} include precipitation.} + +\item{pre_cv}{\code{Boolean} include preciptation cv.} +} +\description{ +Helper Function Used in .create_stacks() +} +\keyword{internal} diff --git a/man/dot-create_stacks.Rd b/man/dot-create_stacks.Rd new file mode 100644 index 0000000..8e478ef --- /dev/null +++ b/man/dot-create_stacks.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.create_stacks} +\alias{.create_stacks} +\title{Create terra rast objects} +\usage{ +.create_stacks(tmn, tmx, tmp, dtr, pre, pre_cv, files) +} +\arguments{ +\item{tmn}{Return minimum temperature values (degrees Celsius) +in the \code{rast}, Boolean.} + +\item{tmx}{Return maximum temperature (degrees Celsius) in the +\code{rast}, Boolean.} + +\item{tmp}{Return temperature (degrees Celsius) in the \code{rast}, Boolean.} + +\item{dtr}{Return mean diurnal temperature range (degrees Celsius) +in the \code{rast}, Boolean.} + +\item{pre}{Return precipitation in the \code{rast}, Boolean.} + +\item{pre_cv}{Return cv of precipitation (percent) in the \code{rast}, Boolean.} + +\item{files}{List. Files that are to be used in creating the \code{rast} object.} +} +\description{ +Create terra rast objects +} +\keyword{internal} diff --git a/man/dot-get_local.Rd b/man/dot-get_local.Rd new file mode 100644 index 0000000..fca609d --- /dev/null +++ b/man/dot-get_local.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.get_local} +\alias{.get_local} +\title{Create a List of Locally Cached Files for Import} +\usage{ +.get_local( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv, + cache_dir +) +} +\arguments{ +\item{pre}{Boolean, loads precipitation (millimetres/month) from server and +returns in the data frame.} + +\item{pre_cv}{Boolean, loads cv of precipitation (percent) from server and +returns in the data frame.} + +\item{rd0}{Boolean, loads wet-days (number days with >0.1 millimetres rain +per month) and returns in the data frame.} + +\item{tmp}{Boolean, loads temperature (degrees Celsius) and returns it in +the data frame.} + +\item{dtr}{Boolean, loads mean diurnal temperature range (degrees Celsius) +and returns it in the data frame.} + +\item{reh}{Boolean, loads relative humidity and return it in the data frame.} + +\item{tmn}{Boolean, calculates minimum temperature values (degrees Celsius) +and returns it in the data frame.} + +\item{tmx}{Boolean, calculatex maximum temperature (degrees Celsius) and +returns it in the data frame.} + +\item{sunp}{Boolean, loads sunshine, percent of maximum possible (percent of +day length) and returns it in data frame.} + +\item{frs}{Boolean, loads ground-frost records (number of days with ground- +frost per month) and return it in data frame.} + +\item{wnd}{Boolean, loads 10m wind speed (metres/second) and returns it in +the data frame.} + +\item{elv}{Boolean, loads elevation (converted to metres) and returns it in +the data frame.} +} +\description{ +Create a List of Locally Cached Files for Import +} +\keyword{internal} diff --git a/man/dot-read_cache.Rd b/man/dot-read_cache.Rd new file mode 100644 index 0000000..3706fb9 --- /dev/null +++ b/man/dot-read_cache.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.read_cache} +\alias{.read_cache} +\title{Read Files From Local cache} +\usage{ +.read_cache(.files, .pre_cv) +} +\arguments{ +\item{.files}{a list of CRU CL2.0 files in local storage.} + +\item{.pre_cv}{\code{Boolean} return pre_cv in the data.} +} +\description{ +Read Files From Local cache +} +\keyword{internal} diff --git a/man/dot-set_cache.Rd b/man/dot-set_cache.Rd new file mode 100644 index 0000000..fa6068e --- /dev/null +++ b/man/dot-set_cache.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.set_cache} +\alias{.set_cache} +\title{Set Up User Cache} +\usage{ +.set_cache(cache) +} +\arguments{ +\item{cache}{\code{Boolean} (create) and use local file cache.} +} +\description{ +Creates local directory for caching and/or uses it for local caching or +uses the \R session \code{tempdir()}. +} +\keyword{internal} diff --git a/man/dot-tidy_df.Rd b/man/dot-tidy_df.Rd new file mode 100644 index 0000000..af8f61f --- /dev/null +++ b/man/dot-tidy_df.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.tidy_df} +\alias{.tidy_df} +\title{Read Files from Disk Directory and Tidy Them} +\usage{ +.tidy_df(pre_cv, elv, tmn, tmx, .files) +} +\description{ +Read Files from Disk Directory and Tidy Them +} +\keyword{internal} diff --git a/man/dot-validate_dsn.Rd b/man/dot-validate_dsn.Rd new file mode 100644 index 0000000..408ae7c --- /dev/null +++ b/man/dot-validate_dsn.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/internal_functions.R +\name{.validate_dsn} +\alias{.validate_dsn} +\title{Validates user entered dsn value} +\usage{ +.validate_dsn(dsn) +} +\arguments{ +\item{dsn}{User provided value for checking.} +} +\description{ +Validates user entered dsn value +} +\keyword{internal} diff --git a/man/get_CRU_stack.Rd b/man/get_CRU_stack.Rd index f163261..4f9c9d1 100644 --- a/man/get_CRU_stack.Rd +++ b/man/get_CRU_stack.Rd @@ -97,8 +97,8 @@ To take advantage of cached files in future sessions, use \code{cache = TRUE} even after the initial download and caching. Defaults to \code{FALSE}.} } \value{ -A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of \acronym{CRU} \acronym{CL} -v. 2.0 climatology elements. +A \link[base:list]{base::list} of \link[terra:rast]{terra::rast} objects of \acronym{CRU} +\acronym{CL} v. 2.0 climatology elements. } \description{ This function automates downloading and importing CRU CL v. 2.0 From 4a719dc9c798bf05b3d504c0369f22c9dbe56502 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Thu, 6 Feb 2025 11:30:01 +0800 Subject: [PATCH 43/60] update .gitignore and streamline precompile.R --- .gitignore | 4 +--- vignettes/precompile.R | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 30fdec5..a5c0d45 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,8 @@ .Rhistory .RData .Ruserdata -*.Rproj +.Rproj inst/doc -*.DS_Store - .DS_Store *.code-workspace docs/ diff --git a/vignettes/precompile.R b/vignettes/precompile.R index e68c787..b5a725d 100644 --- a/vignettes/precompile.R +++ b/vignettes/precompile.R @@ -1,7 +1,6 @@ # vignettes that depend on internet access need to be precompiled and take a # while to run -library("knitr") -knit("vignettes/getCRUCLdata.Rmd.orig", "vignettes/getCRUCLdata.Rmd") +knitr::knit("vignettes/getCRUCLdata.Rmd.orig", "vignettes/getCRUCLdata.Rmd") # remove file path such that vignettes will build with figures replace <- readLines("vignettes/getCRUCLdata.Rmd") @@ -11,8 +10,7 @@ writeLines(replace, fileConn) close(fileConn) # build vignettes -library("devtools") -build_vignettes() +devtools::build_vignettes() # move resource files to /doc resources <- From 621bbe1222b34b691dceace3ab93508a24ce08bf Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 15:48:48 +0800 Subject: [PATCH 44/60] document internal function --- R/get_CRU.R | 31 ++++++++++++++++++++---- man/dot-get_CRU.Rd | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 man/dot-get_CRU.Rd diff --git a/R/get_CRU.R b/R/get_CRU.R index 2e7d656..a2565ca 100644 --- a/R/get_CRU.R +++ b/R/get_CRU.R @@ -1,4 +1,25 @@ -#' @noRd +#' Downloads and formats CRU CL 2.0 data +#' +#' @param pre Logical. If TRUE, downloads precipitation data. +#' @param pre_cv Logical. If TRUE, downloads precipitation data. +#' @param rd0 Logical. If TRUE, downloads runoff data. +#' @param tmp Logical. If TRUE, downloads temperature data. +#' @param dtr Logical. If TRUE, downloads diurnal temperature range data. +#' @param reh Logical. If TRUE, downloads relative humidity data. +#' @param tmn Logical. If TRUE, downloads minimum temperature data. +#' @param tmx Logical. If TRUE, downloads maximum temperature data. +#' @param sunp Logical. If TRUE, downloads sunshine data. +#' @param frs Logical. If TRUE, downloads frost day frequency data. +#' @param wnd Logical. If TRUE, downloads wind speed data. +#' @param elv Logical. If TRUE, downloads elevation data. +#' @param cache_dir Character. Path to the cache directory. +#' +#' Handles the downloading of CRU CL 2.0 data. This function is called by +#' [get_cru_df] and [get_cru_stack]. It is not intended to be called directly. +#' +#' @returns A data.table with the requested data. +#' +#' @dev .get_CRU <- function(pre, pre_cv, @@ -23,7 +44,7 @@ frs_file <- "grid_10min_frs.dat.gz" rd0_file <- "grid_10min_rd0.dat.gz" - # check if pre_cv or tmx/tmn (derived) are true, make sure proper ---------- + # check if pre_cv or tmx/tmn (derived) are true, make sure proper --------- # parameters set TRUE if (pre_cv) { pre <- TRUE @@ -32,7 +53,7 @@ if (any(tmn, tmx)) { dtr <- tmp <- TRUE } - # create object list to filter downloads ----------------------------------- + # create object list to filter downloads ---------------------------------- object_list <- c(dtr, tmp, reh, elv, pre, sunp, wnd, frs, rd0) files <- @@ -61,7 +82,7 @@ "rd0_file" ) - # filter downloaded -------------------------------------------------------- + # filter downloaded ------------------------------------------------------- # which files are being requested? files <- files[which(object_list)] @@ -72,7 +93,7 @@ # which files requested need to be downloaded dl_files <- files[!(files %in% cache_dir_contents)] - # download files ----------------------------------------------------------- + # download files ---------------------------------------------------------- if (length(dl_files) > 0) { CRU_url <- "https://crudata.uea.ac.uk/cru/data/hrg/tmc/" dl_files <- as.list(paste0(CRU_url, dl_files)) diff --git a/man/dot-get_CRU.Rd b/man/dot-get_CRU.Rd new file mode 100644 index 0000000..8e09d24 --- /dev/null +++ b/man/dot-get_CRU.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_CRU.R +\name{.get_CRU} +\alias{.get_CRU} +\title{Fetches and Formats CRUL CL 2.0 Data} +\usage{ +.get_CRU( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv, + cache_dir +) +} +\arguments{ +\item{pre}{Logical. If TRUE, downloads precipitation data.} + +\item{pre_cv}{Logical. If TRUE, downloads precipitation data.} + +\item{rd0}{Logical. If TRUE, downloads runoff data.} + +\item{tmp}{Logical. If TRUE, downloads temperature data.} + +\item{dtr}{Logical. If TRUE, downloads diurnal temperature range data.} + +\item{reh}{Logical. If TRUE, downloads relative humidity data.} + +\item{tmn}{Logical. If TRUE, downloads minimum temperature data.} + +\item{tmx}{Logical. If TRUE, downloads maximum temperature data.} + +\item{sunp}{Logical. If TRUE, downloads sunshine data.} + +\item{frs}{Logical. If TRUE, downloads frost day frequency data.} + +\item{wnd}{Logical. If TRUE, downloads wind speed data.} + +\item{elv}{Logical. If TRUE, downloads elevation data.} + +\item{cache_dir}{Character. Path to the cache directory. + +Handles the downloading of CRU CL 2.0 data. This function is called by +\link{get_cru_df} and \link{get_cru_stack}. It is not intended to be called directly.} +} +\value{ +A data.table with the requested data. +} +\description{ +Fetches and Formats CRUL CL 2.0 Data +} +\keyword{internal} From babc498b1276b33d26e6bddf4fbba7467d2a1aac Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 15:49:05 +0800 Subject: [PATCH 45/60] update .Rbuildignore file --- .Rbuildignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.Rbuildignore b/.Rbuildignore index 4c89960..49ed843 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -21,6 +21,7 @@ # flint files ^flint$ +^man/dot-get_CRU\.Rd$ ^man/dot-check_vars_FALSE\.Rd$ ^man/dot-validate_dsn\.Rd$ ^man/dot-create_df\.Rd$ From 2857259b552b278c4c7e45f7c0ee96a8c644ec9d Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 15:49:15 +0800 Subject: [PATCH 46/60] update codemeta.json --- codemeta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index 8672b8b..26d0a39 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "912.393KB", + "fileSize": "913.57KB", "citation": [ { "@type": "ScholarlyArticle", From 4ba8467347c604e6de2a1249e1eb7cdf9743b1d3 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 15:49:23 +0800 Subject: [PATCH 47/60] update cran-comments.md --- cran-comments.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cran-comments.md b/cran-comments.md index ab83bbb..14eae13 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -10,8 +10,8 @@ notes indicate it was forcibly removed for "leaving things behind". Therefore, in this release, the caching capabilities now follow the new R standard `tools::R_user_dir(package = "getCRUCLdata")` in spite of the default behaviour of the underlying CRAN packages, {hoadr} and {rappdirs}, which have -been used since this package was first submitted to CRAN to proovide file +been used since this package was first submitted to CRAN to provide file caching functionality in this package. I trust that this is sufficient to have -the {getCRUCLdata} package reinstated on CRAN. +this package reinstated on CRAN. -* This is a new release. +- This is a new release. From 2118d07e032df64e22a1cc18eb4bd7c9d22c0a71 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 15:55:26 +0800 Subject: [PATCH 48/60] correct spelling --- R/internal_functions.R | 4 ++-- codemeta.json | 2 +- inst/WORDLIST | 2 ++ man/dot-create_stack.Rd | 2 +- man/dot-get_CRU.Rd | 4 ++-- man/dot-get_local.Rd | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/R/internal_functions.R b/R/internal_functions.R index 3ac53e1..ef6f8de 100644 --- a/R/internal_functions.R +++ b/R/internal_functions.R @@ -354,7 +354,7 @@ #' @param wrld An empty [terra::rast] object for filling with values. #' @param month_names A vector of month names from jan -- dec. #' @param pre `Boolean` include precipitation. -#' @param pre_cv `Boolean` include preciptation cv. +#' @param pre_cv `Boolean` include precipitation cv. #' #' @autoglobal #' @dev @@ -467,7 +467,7 @@ #' the data frame. #' @param tmn Boolean, calculates minimum temperature values (degrees Celsius) #' and returns it in the data frame. -#' @param tmx Boolean, calculatex maximum temperature (degrees Celsius) and +#' @param tmx Boolean, calculate maximum temperature (degrees Celsius) and #' returns it in the data frame. #' @param reh Boolean, loads relative humidity and return it in the data frame. #' @param sunp Boolean, loads sunshine, percent of maximum possible (percent of diff --git a/codemeta.json b/codemeta.json index 26d0a39..d72f5a6 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "913.57KB", + "fileSize": "913.578KB", "citation": [ { "@type": "ScholarlyArticle", diff --git a/inst/WORDLIST b/inst/WORDLIST index 16cfc1c..8c0a123 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -30,6 +30,7 @@ codecov colour cv dat +dec dplyr dsn dtr @@ -45,6 +46,7 @@ gridded gz hoardr ivanhanigan +jan jeroen karthik kilometres diff --git a/man/dot-create_stack.Rd b/man/dot-create_stack.Rd index e5ad03d..ae7c9bc 100644 --- a/man/dot-create_stack.Rd +++ b/man/dot-create_stack.Rd @@ -15,7 +15,7 @@ \item{pre}{\code{Boolean} include precipitation.} -\item{pre_cv}{\code{Boolean} include preciptation cv.} +\item{pre_cv}{\code{Boolean} include precipitation cv.} } \description{ Helper Function Used in .create_stacks() diff --git a/man/dot-get_CRU.Rd b/man/dot-get_CRU.Rd index 8e09d24..aee07a4 100644 --- a/man/dot-get_CRU.Rd +++ b/man/dot-get_CRU.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/get_CRU.R \name{.get_CRU} \alias{.get_CRU} -\title{Fetches and Formats CRUL CL 2.0 Data} +\title{Downloads and formats CRU CL 2.0 data} \usage{ .get_CRU( pre, @@ -54,6 +54,6 @@ Handles the downloading of CRU CL 2.0 data. This function is called by A data.table with the requested data. } \description{ -Fetches and Formats CRUL CL 2.0 Data +Downloads and formats CRU CL 2.0 data } \keyword{internal} diff --git a/man/dot-get_local.Rd b/man/dot-get_local.Rd index fca609d..b431817 100644 --- a/man/dot-get_local.Rd +++ b/man/dot-get_local.Rd @@ -41,7 +41,7 @@ and returns it in the data frame.} \item{tmn}{Boolean, calculates minimum temperature values (degrees Celsius) and returns it in the data frame.} -\item{tmx}{Boolean, calculatex maximum temperature (degrees Celsius) and +\item{tmx}{Boolean, calculate maximum temperature (degrees Celsius) and returns it in the data frame.} \item{sunp}{Boolean, loads sunshine, percent of maximum possible (percent of From ee7dc7c024f2304f5b6c7639536bf4fa0133dc52 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 15:55:35 +0800 Subject: [PATCH 49/60] update cran-comments.md --- cran-comments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cran-comments.md b/cran-comments.md index 14eae13..98bc0e7 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,4 +1,4 @@ -## R CMD check results +# R CMD check results 0 errors | 0 warnings | 2 notes From ddf702ce703001878bbecb823184e9bb0422c930 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 16:05:58 +0800 Subject: [PATCH 50/60] increment version number for CRAN release --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index ecae0ea..073decc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: getCRUCLdata Title: 'CRU' 'CL' v. 2.0 Climatology Client -Version: 1.0.3 +Version: 2.0.0 Authors@R: c( person("Adam H.", "Sparks", , "adamhsparks@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0061-8359")), From 608507d96a4cb37e87dcf52d9aa376abfdd96f66 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Fri, 7 Feb 2025 16:08:30 +0800 Subject: [PATCH 51/60] It IS v1.0.3 being released and a new major release on CRAN --- DESCRIPTION | 2 +- NEWS.md | 50 ++++++++++++++++++++++++------------------------ cran-comments.md | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 073decc..ecae0ea 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: getCRUCLdata Title: 'CRU' 'CL' v. 2.0 Climatology Client -Version: 2.0.0 +Version: 1.0.3 Authors@R: c( person("Adam H.", "Sparks", , "adamhsparks@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0061-8359")), diff --git a/NEWS.md b/NEWS.md index 4967a27..c610330 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,7 +4,7 @@ - Add source and references to documentation for data -- Create function aliases that use all lower case, *e.g.*, `get_cru_stack()` vs `get_CRU_stack()` +- Create function aliases that use all lower case, _e.g._, `get_cru_stack()` vs `get_CRU_stack()` - Improved documentation with linting, ensuring consistency in units of measurement, etc. @@ -32,7 +32,7 @@ ## Major changes -- The cache is now where ever `tools::R_user_dir(package = "getCRUCLdata", which = "cache")` is defined by R (>= 4.0.0) and *should* align with CRAN standards, so it *might* be possible to get this back on CRAN +- The cache is now where ever `tools::R_user_dir(package = "getCRUCLdata", which = "cache")` is defined by R (>= 4.0.0) and _should_ align with CRAN standards, so it _might_ be possible to get this back on CRAN - Depends on R (>= 4.0.0) @@ -105,14 +105,14 @@ - Removes startup message, instead placing information in CITATION file - Reorganises internal functions consolidating functions all in a single file -and following a standard naming scheme for all internal functions + and following a standard naming scheme for all internal functions # getCRUCLdata 0.2.4 ## Bug fixes - Fix bug where `tmp` and `dtr` could not be returned with `tmn` or `tmx` raster -stacks + stacks - Move `rappdirs` to SUGGESTS to fix NOTEs @@ -121,7 +121,7 @@ stacks - Fix documentation formatting issues - Enhance `stop` messages for user, just print message, not the function that -called it to clarify + called it to clarify # getCRUCLdata 0.2.3 @@ -154,9 +154,9 @@ called it to clarify - Use _hoardr_ for managing cached files - Fixed a bug where the file cache was not in the proper subdirectory. The file -cache has moved to the proper location in a `R/getCRUCLdata` location rather -than `getCRUCLdata`. You may wish to move files externally to R in order to keep -them in the cache where the package will find them + cache has moved to the proper location in a `R/getCRUCLdata` location rather + than `getCRUCLdata`. You may wish to move files externally to R in order to keep + them in the cache where the package will find them - Use `lapply` in place of `purrr::map`, _purrr_ is no longer imported @@ -178,7 +178,7 @@ them in the cache where the package will find them - Add startup message regarding data source, use and citation - Include Scott Chamberlain as copyright holder and contributor for file -caching functionality + caching functionality # getCRUCLdata 0.1.9 @@ -191,18 +191,18 @@ caching functionality ## Bug Fixes - Fix bug where `cache` was not specified in internal function, `.set_cache()`, -this caused either of the functions fetching data from CRU to fail + this caused either of the functions fetching data from CRU to fail - Fix bug where `cache` directory could not be created on Windows OS machines -- Fix bug where tmx was returned when *either* tmn *or* tmx was requested for -data frame, tmn now returned when requested and tmx now returned when requested. -Raster stacks were not affected by this bug +- Fix bug where tmx was returned when _either_ tmn _or_ tmx was requested for + data frame, tmn now returned when requested and tmx now returned when requested. + Raster stacks were not affected by this bug ## Minor Changes - Replaced `for f in 1:length()` with `for f in seq_along()` for better -programming practices + programming practices # getCRUCLdata 0.1.7 @@ -213,7 +213,7 @@ programming practices ## Bug Fixes - Fix bug where `rappdirs::user_config_dir()` was incorrectly used in place of -`rappdirs::user_cache_dir()` + `rappdirs::user_cache_dir()` # getCRUCLdata 0.1.6 @@ -236,27 +236,27 @@ programming practices ## Major Changes - `create_CRU_stack()` and `create_CRU_df()` now only work with locally - available files. If you need to fetch and create a data frame or raster stack - of the data, please use the new functions, `get_CRU_stack()` and - `get_CRU_stack()` + available files. If you need to fetch and create a data frame or raster stack + of the data, please use the new functions, `get_CRU_stack()` and + `get_CRU_stack()` - R >=3.2.0 now required - Data can be cached using either `get_CRU_stack()` or `get_CRU_df()` for later - use + use ## Minor Changes - Improved documentation with examples on mapping and graphing and more detail -regarding the data itself + regarding the data itself - Change the method in which files are downloaded to use `httr::GET()` - Ingest data using `data.table::fread` to decrease the amount of time necessary -to run the functions + to run the functions - Functions check to see if data file(s) have already been downloaded during -current R session, if so data file(s) are not requested for download again + current R session, if so data file(s) are not requested for download again - Months are returned as a factor object in the tidy data frame @@ -265,14 +265,14 @@ current R session, if so data file(s) are not requested for download again ## Minor Changes - Correct fix bug in data frame object generation where elevation was improperly -handled and function would stop + handled and function would stop # getCRUCLdata 0.1.3 ## Minor Changes - Correct fix bug in raster object generation where the objects were incorrectly -cropped + cropped - Update documentation with ROxygen 6.0.0 @@ -283,7 +283,7 @@ cropped ## Minor Changes - Correct documentation to read that the data resolution is 10 minute, not 10 -seconds + seconds - Correct URLs in DESCRIPTION file diff --git a/cran-comments.md b/cran-comments.md index 98bc0e7..87dd8b6 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -14,4 +14,4 @@ been used since this package was first submitted to CRAN to provide file caching functionality in this package. I trust that this is sufficient to have this package reinstated on CRAN. -- This is a new release. +- This is a new major release. From 64eadcafa3cfc4df2e7240fe1292be71072fcd8e Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sat, 8 Feb 2025 17:39:27 +0800 Subject: [PATCH 52/60] update codemeta.json --- codemeta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index d72f5a6..2d90592 100644 --- a/codemeta.json +++ b/codemeta.json @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "913.578KB", + "fileSize": "913.618KB", "citation": [ { "@type": "ScholarlyArticle", From 7415a36c32af316a15c4fa3a950811579e3aee16 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sat, 8 Feb 2025 20:09:03 +0800 Subject: [PATCH 53/60] update licence year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index b42b4ce..45f1016 100644 --- a/LICENSE +++ b/LICENSE @@ -1,2 +1,2 @@ -YEAR: 2017 +YEAR: 2025 COPYRIGHT HOLDER: Adam H. Sparks From e9620caeb7cf939da6b4e54c0a070ee26d476b85 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sat, 8 Feb 2025 20:09:27 +0800 Subject: [PATCH 54/60] Increment version number to 1.0.3 --- codemeta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index 2d90592..b45f3de 100644 --- a/codemeta.json +++ b/codemeta.json @@ -8,7 +8,7 @@ "codeRepository": "https://github.com/ropensci/getCRUCLdata", "issueTracker": "https://github.com/ropensci/getCRUCLdata/issues", "license": "https://spdx.org/licenses/MIT", - "version": "1.0.3", + "version": "1.0.2", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", From e53f149ae28a096405785cec0756a3b71c866f34 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 10 Feb 2025 12:51:56 +0800 Subject: [PATCH 55/60] delete cran-comments, there's no need any longer --- cran-comments.md | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 cran-comments.md diff --git a/cran-comments.md b/cran-comments.md deleted file mode 100644 index 87dd8b6..0000000 --- a/cran-comments.md +++ /dev/null @@ -1,17 +0,0 @@ -# R CMD check results - -0 errors | 0 warnings | 2 notes - -## Fixes from previous CRAN version - -I had asked that the last version of this package on CRAN be removed, but the -notes indicate it was forcibly removed for "leaving things behind". - -Therefore, in this release, the caching capabilities now follow the new R -standard `tools::R_user_dir(package = "getCRUCLdata")` in spite of the default -behaviour of the underlying CRAN packages, {hoadr} and {rappdirs}, which have -been used since this package was first submitted to CRAN to provide file -caching functionality in this package. I trust that this is sufficient to have -this package reinstated on CRAN. - -- This is a new major release. From fd66773d062ca5fb618d709a0f9c950927e9585d Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 3 Mar 2025 13:52:31 +0800 Subject: [PATCH 56/60] Format with Air and desc::desc_normalize() --- DESCRIPTION | 8 +- R/create_CRU_df.R | 31 +++--- R/create_CRU_stack.R | 31 +++--- R/get_CRU.R | 60 +++++------ R/get_CRU_df.R | 28 +++--- R/get_CRU_stack.R | 28 +++--- R/internal_functions.R | 132 +++++++++++++------------ R/zzz.R | 3 +- tests/spelling.R | 3 +- tests/testthat/test-create_CRU_stack.R | 44 +++------ tests/testthat/test-create_stack.R | 62 +++++------- tests/testthat/test-get_CRU.R | 1 - tests/testthat/test_caching.R | 8 +- tests/testthat/test_get_local.R | 12 +-- vignettes/precompile.R | 6 +- 15 files changed, 213 insertions(+), 244 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index ecae0ea..588e9e7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -7,7 +7,7 @@ Authors@R: c( comment = c(ORCID = "0000-0002-0061-8359")), person("Curtin University of Technology", role = "cph", comment = "Provided support through Adam Sparks's time."), - person("Grains Research and Development Corporation", role = c("cph"), + person("Grains Research and Development Corporation", role = "cph", comment = "GRDC Project CUR2210-005OPX (AAGI-CU)") ) Description: Provides functions that automate downloading and importing @@ -49,6 +49,7 @@ Suggests: VignetteBuilder: knitr ByteCompile: TRUE +Config/Needs/build: moodymudskipper/devtag Config/roxyglobals/filename: globals.R Config/roxyglobals/unique: FALSE Config/roxylint: list(linters = roxylint::tidy) @@ -56,11 +57,12 @@ Config/testthat/edition: 3 Config/testthat/parallel: true Encoding: UTF-8 Language: en-US -Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", "roxyglobals::global_roclet", "roxylint::roxylint", "devtag::dev_roclet")) +Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", + "roxyglobals::global_roclet", "roxylint::roxylint", + "devtag::dev_roclet")) RoxygenNote: 7.3.2 X-schema.org-applicationCategory: Tools X-schema.org-isPartOf: https://ropensci.org X-schema.org-keywords: anglia-cru, climate-data, cru-cl2, temperature, rainfall, elevation, data-access, wind, relative-humidity, solar-radiation, diurnal-temperature, frost -Config/Needs/build: moodymudskipper/devtag diff --git a/R/create_CRU_df.R b/R/create_CRU_df.R index 0535199..1c0ad4e 100644 --- a/R/create_CRU_df.R +++ b/R/create_CRU_df.R @@ -83,19 +83,21 @@ #' #' @export -create_CRU_df <- function(pre = FALSE, - pre_cv = FALSE, - rd0 = FALSE, - tmp = FALSE, - dtr = FALSE, - reh = FALSE, - tmn = FALSE, - tmx = FALSE, - sunp = FALSE, - frs = FALSE, - wnd = FALSE, - elv = FALSE, - dsn) { +create_CRU_df <- function( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + dsn +) { .check_vars_FALSE( pre, pre_cv, @@ -113,7 +115,8 @@ create_CRU_df <- function(pre = FALSE, .validate_dsn(dsn) - files <- .get_local(pre, + files <- .get_local( + pre, pre_cv, rd0, tmp, diff --git a/R/create_CRU_stack.R b/R/create_CRU_stack.R index b921d1c..cf16b95 100644 --- a/R/create_CRU_stack.R +++ b/R/create_CRU_stack.R @@ -37,19 +37,21 @@ #' #' @export -create_CRU_stack <- function(pre = FALSE, - pre_cv = FALSE, - rd0 = FALSE, - tmp = FALSE, - dtr = FALSE, - reh = FALSE, - tmn = FALSE, - tmx = FALSE, - sunp = FALSE, - frs = FALSE, - wnd = FALSE, - elv = FALSE, - dsn) { +create_CRU_stack <- function( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + dsn +) { .check_vars_FALSE( pre, pre_cv, @@ -67,7 +69,8 @@ create_CRU_stack <- function(pre = FALSE, .validate_dsn(dsn) - files <- .get_local(pre, + files <- .get_local( + pre, pre_cv, rd0, tmp, diff --git a/R/get_CRU.R b/R/get_CRU.R index a2565ca..d160423 100644 --- a/R/get_CRU.R +++ b/R/get_CRU.R @@ -21,19 +21,21 @@ #' #' @dev .get_CRU <- - function(pre, - pre_cv, - rd0, - tmp, - dtr, - reh, - tmn, - tmx, - sunp, - frs, - wnd, - elv, - cache_dir) { + function( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv, + cache_dir + ) { dtr_file <- "grid_10min_dtr.dat.gz" tmp_file <- "grid_10min_tmp.dat.gz" reh_file <- "grid_10min_reh.dat.gz" @@ -70,17 +72,17 @@ ) names(files) <- names(object_list) <- - c( - "dtr_file", - "tmp_file", - "reh_file", - "elv_file", - "pre_file", - "sun_file", - "wnd_file", - "frs_file", - "rd0_file" - ) + c( + "dtr_file", + "tmp_file", + "reh_file", + "elv_file", + "pre_file", + "sun_file", + "wnd_file", + "frs_file", + "rd0_file" + ) # filter downloaded ------------------------------------------------------- # which files are being requested? @@ -108,17 +110,17 @@ }, error = function(x) { manage_cache$delete_all() - cli::cli_abort("The file downloads have failed. - Please start the download again.") + cli::cli_abort( + "The file downloads have failed. + Please start the download again." + ) } ) } # filter files from cache directory in case there are local files for which # we do not want data - cache_dir_contents <- as.list(list.files(cache_dir, - pattern = ".dat.gz$" - )) + cache_dir_contents <- as.list(list.files(cache_dir, pattern = ".dat.gz$")) files <- cache_dir_contents[cache_dir_contents %in% files] diff --git a/R/get_CRU_df.R b/R/get_CRU_df.R index 527afb2..b330bf3 100644 --- a/R/get_CRU_df.R +++ b/R/get_CRU_df.R @@ -75,19 +75,21 @@ #' #' @export -get_CRU_df <- function(pre = FALSE, - pre_cv = FALSE, - rd0 = FALSE, - tmp = FALSE, - dtr = FALSE, - reh = FALSE, - tmn = FALSE, - tmx = FALSE, - sunp = FALSE, - frs = FALSE, - wnd = FALSE, - elv = FALSE, - cache = FALSE) { +get_CRU_df <- function( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + cache = FALSE +) { .check_vars_FALSE( pre, pre_cv, diff --git a/R/get_CRU_stack.R b/R/get_CRU_stack.R index a935273..4281f9c 100644 --- a/R/get_CRU_stack.R +++ b/R/get_CRU_stack.R @@ -29,19 +29,21 @@ #' @export get_CRU_stack <- - function(pre = FALSE, - pre_cv = FALSE, - rd0 = FALSE, - tmp = FALSE, - dtr = FALSE, - reh = FALSE, - tmn = FALSE, - tmx = FALSE, - sunp = FALSE, - frs = FALSE, - wnd = FALSE, - elv = FALSE, - cache = FALSE) { + function( + pre = FALSE, + pre_cv = FALSE, + rd0 = FALSE, + tmp = FALSE, + dtr = FALSE, + reh = FALSE, + tmn = FALSE, + tmx = FALSE, + sunp = FALSE, + frs = FALSE, + wnd = FALSE, + elv = FALSE, + cache = FALSE + ) { .check_vars_FALSE( pre, pre_cv, diff --git a/R/internal_functions.R b/R/internal_functions.R index ef6f8de..13635ce 100644 --- a/R/internal_functions.R +++ b/R/internal_functions.R @@ -44,19 +44,20 @@ #' ) #' @dev - -.check_vars_FALSE <- function(pre, - pre_cv, - rd0, - tmp, - dtr, - reh, - tmn, - tmx, - sunp, - frs, - wnd, - elv) { +.check_vars_FALSE <- function( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv +) { if (!any(pre, pre_cv, rd0, tmp, dtr, reh, tmn, tmx, sunp, frs, wnd, elv)) { cli::cli_abort( "You must select at least one element for download or import.", @@ -82,14 +83,17 @@ dsn <- trimws(dsn) if (substr(dsn, nchar(dsn) - 1, nchar(dsn)) == "//") { p <- substr(dsn, 1, nchar(dsn) - 2) - } else if (substr(dsn, nchar(dsn), nchar(dsn)) == "/" | - substr(dsn, nchar(dsn), nchar(dsn)) == "\\") { + } else if ( + substr(dsn, nchar(dsn), nchar(dsn)) == "/" | + substr(dsn, nchar(dsn), nchar(dsn)) == "\\" + ) { p <- substr(dsn, 1, nchar(dsn) - 1) } else { p <- dsn } if (!file.exists(p) || !file.exists(dsn)) { - cli::cli_abort("File directory does not exist: {.var dsn}.", + cli::cli_abort( + "File directory does not exist: {.var dsn}.", call = rlang::caller_env() ) } @@ -164,15 +168,21 @@ # lastly merge the data frames into one tidy (large) data frame -------------- if (isFALSE(elv)) { - CRU_df <- Reduce(function(...) { - merge(..., by = c("lat", "lon", "month")) - }, CRU_list) + CRU_df <- Reduce( + function(...) { + merge(..., by = c("lat", "lon", "month")) + }, + CRU_list + ) } else if (elv && length(CRU_list) > 1) { elv_df <- CRU_list[which(names(CRU_list) %in% "elv")] CRU_list[which(names(CRU_list) %in% "elv")] <- NULL - CRU_df <- Reduce(function(...) { - merge(..., by = c("lat", "lon", "month")) - }, CRU_list) + CRU_df <- Reduce( + function(...) { + merge(..., by = c("lat", "lon", "month")) + }, + CRU_list + ) CRU_df <- CRU_df[elv_df$elv, on = c("lat", "lon")] } else if (elv) { @@ -289,7 +299,8 @@ nrows = 930, ncols = 2160, ymin = -65, - ymax = 90, xmin = -180, + ymax = 90, + xmin = -180, xmax = 180 ) @@ -358,11 +369,7 @@ #' #' @autoglobal #' @dev -.create_stack <- function(files, - wrld, - month_names, - pre, - pre_cv) { +.create_stack <- function(files, wrld, month_names, pre, pre_cv) { wvar <- data.frame(data.table::fread( cmd = paste0("gzip -dc ", files[[1]]), @@ -417,12 +424,15 @@ names(y) <- "elv" } - y <- terra::crop(y, terra::ext( - -180, - 180, - -60, - 85 - )) + y <- terra::crop( + y, + terra::ext( + -180, + 180, + -60, + 85 + ) + ) return(y) } @@ -480,19 +490,21 @@ #' the data frame. #' #' @dev -.get_local <- function(pre, - pre_cv, - rd0, - tmp, - dtr, - reh, - tmn, - tmx, - sunp, - frs, - wnd, - elv, - cache_dir) { +.get_local <- function( + pre, + pre_cv, + rd0, + tmp, + dtr, + reh, + tmn, + tmx, + sunp, + frs, + wnd, + elv, + cache_dir +) { # check if pre_cv or tmx/tmn (derived) are true, make sure proper ------------ # parameters set TRUE if (pre_cv) { @@ -529,17 +541,17 @@ ) names(files) <- names(object_list) <- - c( - "dtr_file", - "tmp_file", - "reh_file", - "elv_file", - "pre_file", - "sun_file", - "wnd_file", - "frs_file", - "rd0_file" - ) + c( + "dtr_file", + "tmp_file", + "reh_file", + "elv_file", + "pre_file", + "sun_file", + "wnd_file", + "frs_file", + "rd0_file" + ) # filter files --------------------------------------------------------------- # which files are being requested? @@ -547,9 +559,7 @@ # filter files from cache directory in case there are local files for which # we do not want data - cache_dir_contents <- as.list(list.files(cache_dir, - pattern = ".dat.gz$" - )) + cache_dir_contents <- as.list(list.files(cache_dir, pattern = ".dat.gz$")) files <- cache_dir_contents[cache_dir_contents %in% files] diff --git a/R/zzz.R b/R/zzz.R index c5d539e..a6f992d 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,8 +1,7 @@ manage_cache <- NULL # nocov start .onLoad <- - function(libname = find.package("getCRUCLdata"), - pkgname = "getCRUCLdata") { + function(libname = find.package("getCRUCLdata"), pkgname = "getCRUCLdata") { # CRAN Note avoidance if (getRversion() >= "2.15.1") { utils::globalVariables(c(".")) diff --git a/tests/spelling.R b/tests/spelling.R index 13f77d9..d60e024 100644 --- a/tests/spelling.R +++ b/tests/spelling.R @@ -1,6 +1,7 @@ if (requireNamespace("spelling", quietly = TRUE)) { spelling::spell_check_test( - vignettes = TRUE, error = FALSE, + vignettes = TRUE, + error = FALSE, skip_on_cran = TRUE ) } diff --git a/tests/testthat/test-create_CRU_stack.R b/tests/testthat/test-create_CRU_stack.R index 9a6d4d9..82b7c2d 100644 --- a/tests/testthat/test-create_CRU_stack.R +++ b/tests/testthat/test-create_CRU_stack.R @@ -479,19 +479,11 @@ test_that("create_CRU_stack returns a list of terra rast objects", { ) ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_pre.dat.gz"), "w") - utils::write.table(pre_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(pre_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) gz1 <- gzfile(file.path(tempdir(), "grid_10min_tmp.dat.gz"), "w") - utils::write.table(tmp_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(tmp_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) dsn <- tempdir() @@ -837,19 +829,11 @@ test_that("Test that create_stack creates tmx if requested", { ) ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_dtr.dat.gz"), "w") - utils::write.table(dtr_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(dtr_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) gz1 <- gzfile(file.path(tempdir(), "grid_10min_tmp.dat.gz"), "w") - utils::write.table(tmp_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(tmp_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) pre_cv <- FALSE @@ -868,7 +852,9 @@ test_that("Test that create_stack creates tmx if requested", { .create_stacks(tmn, tmx, tmp, dtr, pre, pre_cv, files) expect_named(CRU_stack_list, c("tmx")) - expect_equal(terra::minmax(CRU_stack_list[[1]])[[2]][[1]], 12.9, + expect_equal( + terra::minmax(CRU_stack_list[[1]])[[2]][[1]], + 12.9, tolerance = 0.1 ) unlink(list.files( @@ -1206,19 +1192,11 @@ test_that("Test that create_stack creates tmn if requested", { ) ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_dtr.dat.gz"), "w") - utils::write.table(dtr_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(dtr_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) gz1 <- gzfile(file.path(tempdir(), "grid_10min_tmp.dat.gz"), "w") - utils::write.table(tmp_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(tmp_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) pre_cv <- FALSE @@ -1237,7 +1215,9 @@ test_that("Test that create_stack creates tmn if requested", { .create_stacks(tmn, tmx, tmp, dtr, pre, pre_cv, files) expect_named(CRU_stack_list, c("tmn")) - expect_equal(terra::minmax(CRU_stack_list[[1]])[[2]][[1]], 4.3, + expect_equal( + terra::minmax(CRU_stack_list[[1]])[[2]][[1]], + 4.3, tolerance = 0.1 ) unlink(list.files( diff --git a/tests/testthat/test-create_stack.R b/tests/testthat/test-create_stack.R index 46ee7b8..de7814b 100644 --- a/tests/testthat/test-create_stack.R +++ b/tests/testthat/test-create_stack.R @@ -484,19 +484,11 @@ test_that("create_CRU_stack creates a list of terra rast of pre and tmp", { ) ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_pre.dat.gz"), "w") - utils::write.table(pre_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(pre_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) gz1 <- gzfile(file.path(tempdir(), "grid_10min_tmp.dat.gz"), "w") - utils::write.table(tmp_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(tmp_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) pre_cv <- TRUE @@ -623,14 +615,9 @@ test_that("create_CRU_stack creates a list containing only elv", { ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_elv.dat.gz"), "w") - utils::write.table(elv_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(elv_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) - files <- list.files( path = tempdir(), pattern = ".dat.gz$", @@ -701,20 +688,23 @@ test_that("month names are appropriate", { "dec" ) - expect_identical(month_names, c( - "jan", - "feb", - "mar", - "apr", - "may", - "jun", - "jul", - "aug", - "sep", - "oct", - "nov", - "dec" - )) + expect_identical( + month_names, + c( + "jan", + "feb", + "mar", + "apr", + "may", + "jun", + "jul", + "aug", + "sep", + "oct", + "nov", + "dec" + ) + ) }) # Test that CRU_stack_list returns list of raster stacks with proper names ----- @@ -1174,19 +1164,11 @@ test_that("CRU_stack_list returns list of raster stacks with proper names", { ) ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_pre.dat.gz"), "w") - utils::write.table(pre_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(pre_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) gz1 <- gzfile(file.path(tempdir(), "grid_10min_tmp.dat.gz"), "w") - utils::write.table(tmp_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(tmp_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) files <- diff --git a/tests/testthat/test-get_CRU.R b/tests/testthat/test-get_CRU.R index 4707316..95a8b83 100644 --- a/tests/testthat/test-get_CRU.R +++ b/tests/testthat/test-get_CRU.R @@ -100,7 +100,6 @@ test_that("get_CRU will retrieve diurnal tmp range & tmp files when tmx TRUE", { test_that("get_CRU will set pre to TRUE if pre_cv is TRUE and pre is FALSE", { skip_if_offline() - pre <- FALSE pre_cv <- TRUE diff --git a/tests/testthat/test_caching.R b/tests/testthat/test_caching.R index f0d3c00..8e989b9 100644 --- a/tests/testthat/test_caching.R +++ b/tests/testthat/test_caching.R @@ -24,9 +24,7 @@ test_that("test that set_cache does not create a dir if cache == FALSE", { test_that("cache directory is created if necessary", { # if cache directory exists during testing, remove it - unlink(manage_cache$cache_path_get(), - recursive = TRUE - ) + unlink(manage_cache$cache_path_get(), recursive = TRUE) cache <- TRUE cache_dir <- .set_cache(cache) expect_true(dir.exists(manage_cache$cache_path_get())) @@ -34,9 +32,7 @@ test_that("cache directory is created if necessary", { test_that("caching utils list files in cache and delete when asked", { skip_if_offline() - unlink(list.files(manage_cache$cache_path_get()), - recursive = TRUE - ) + unlink(list.files(manage_cache$cache_path_get()), recursive = TRUE) withr::local_envvar(R_USER_CACHE_DIR = tempdir()) temp_cache <- file.path(tempdir(), "R/getCRUCLdata/") manage_cache <- hoardr::hoard() diff --git a/tests/testthat/test_get_local.R b/tests/testthat/test_get_local.R index d2083eb..db5ca6d 100644 --- a/tests/testthat/test_get_local.R +++ b/tests/testthat/test_get_local.R @@ -458,19 +458,11 @@ test_that("Test that .get_local lists local files", { ) ) gz1 <- gzfile(file.path(tempdir(), "grid_10min_pre.dat.gz"), "w") - utils::write.table(pre_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(pre_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) gz1 <- gzfile(file.path(tempdir(), "grid_10min_tmp.dat.gz"), "w") - utils::write.table(tmp_data, - file = gz1, - col.names = FALSE, - row.names = FALSE - ) + utils::write.table(tmp_data, file = gz1, col.names = FALSE, row.names = FALSE) close(gz1) pre <- TRUE diff --git a/vignettes/precompile.R b/vignettes/precompile.R index b5a725d..0d3040b 100644 --- a/vignettes/precompile.R +++ b/vignettes/precompile.R @@ -15,8 +15,4 @@ devtools::build_vignettes() # move resource files to /doc resources <- list.files("vignettes/", pattern = ".png$", full.names = TRUE) -file.copy(from = resources, - to = "doc", - overwrite = TRUE) - - +file.copy(from = resources, to = "doc", overwrite = TRUE) From 45aefba390d2fb242ea7e21b8c6b6738b0e1e6d1 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 3 Mar 2025 17:06:35 +0800 Subject: [PATCH 57/60] fix test that was rightfully not passing --- tests/testthat/test_caching.R | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test_caching.R b/tests/testthat/test_caching.R index 8e989b9..3d849b2 100644 --- a/tests/testthat/test_caching.R +++ b/tests/testthat/test_caching.R @@ -32,7 +32,6 @@ test_that("cache directory is created if necessary", { test_that("caching utils list files in cache and delete when asked", { skip_if_offline() - unlink(list.files(manage_cache$cache_path_get()), recursive = TRUE) withr::local_envvar(R_USER_CACHE_DIR = tempdir()) temp_cache <- file.path(tempdir(), "R/getCRUCLdata/") manage_cache <- hoardr::hoard() @@ -46,8 +45,10 @@ test_that("caching utils list files in cache and delete when asked", { f <- terra::rast(system.file("ex/test.grd", package = "terra")) cache_dir <- manage_cache$cache_path_get() - terra::writeRaster(f, file.path(cache_dir, "file1.asc")) - terra::writeRaster(f, file.path(cache_dir, "file2.asc")) + manage_cache$delete_all() + + terra::writeRaster(f, file.path(cache_dir, "file1.grd")) + terra::writeRaster(f, file.path(cache_dir, "file2.grd")) # test getCRUCLdata cache list k <- list.files(manage_cache$cache_path_get()) @@ -56,7 +57,7 @@ test_that("caching utils list files in cache and delete when asked", { # test delete one file expect_error(manage_cache$delete("file1.tif")) - manage_cache$delete("file1.asc") + manage_cache$delete("file1.grd") l <- list.files(manage_cache$cache_path_get()) expect_identical(basename(manage_cache$list()), l) From 72f654945d504ce45b56a05c23c509e31d4e410a Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 3 Mar 2025 17:07:02 +0800 Subject: [PATCH 58/60] update codemeta.json --- codemeta.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codemeta.json b/codemeta.json index b45f3de..f74219d 100644 --- a/codemeta.json +++ b/codemeta.json @@ -8,7 +8,7 @@ "codeRepository": "https://github.com/ropensci/getCRUCLdata", "issueTracker": "https://github.com/ropensci/getCRUCLdata/issues", "license": "https://spdx.org/licenses/MIT", - "version": "1.0.2", + "version": "1.0.3", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", @@ -254,7 +254,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "913.618KB", + "fileSize": "911.891KB", "citation": [ { "@type": "ScholarlyArticle", From bc711d2d6500d753c19e3fcb5863f95ff2f8af82 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Tue, 4 Mar 2025 20:10:24 +0800 Subject: [PATCH 59/60] update CONTRIBUTING.md --- .github/CONTRIBUTING.md | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index fbcc9e7..b5e92d8 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,56 +1,57 @@ -# CONTRIBUTING # +# CONTRIBUTING ### Fixing typos Small typos or grammatical errors in documentation may be edited directly using the GitHub web interface, so long as the changes are made in the _source_ file. -* YES: you edit a roxygen comment in a `.R` file below `R/`. -* NO: you edit an `.Rd` file below `man/`. +- YES: you edit a roxygen comment in a `.R` file below `R/`. +- NO: you edit an `.Rd` file below `man/`. ### Prerequisites Before you make a substantial pull request, you should always file an issue and make sure someone from the team agrees that it’s a problem. If you’ve found a -bug, create an associated issue and illustrate the bug with a minimal +bug, create an associated issue and illustrate the bug with a minimal [reprex](https://www.tidyverse.org/help/#reprex). ### Pull request process -* We recommend that you create a Git branch for each pull request (PR). -* Look at the Travis and AppVeyor build status before and after making changes. -The `README` should contain badges for any continuous integration services used -by the package. -* We recommend the tidyverse [style guide](http://style.tidyverse.org). -You can use the [styler](https://CRAN.R-project.org/package=styler) package to -apply these styles, but please don't restyle code that has nothing to do with -your PR. -* We use [roxygen2](https://cran.r-project.org/package=roxygen2). -* We use [testthat](https://cran.r-project.org/package=testthat). Contributions -with test cases included are easier to accept. -* For user-facing changes, add a bullet to the top of `NEWS.md` below the -current development version header describing the changes made followed by your -GitHub username, and links to relevant issue(s)/PR(s). +- We recommend that you create a Git branch for each pull request (PR). +- Look at the Travis and AppVeyor build status before and after making changes. + The `README` should contain badges for any continuous integration services used + by the package. +- We recommend the tidyverse [style guide](http://style.tidyverse.org). + You can use the [styler](https://CRAN.R-project.org/package=styler) package or + the [Air formatter](https://posit-dev.github.io/air/formatter.html) to apply + these styles, but please don't restyle code that has nothing to do with your PR. +- We use [roxygen2](https://cran.r-project.org/package=roxygen2). +- We use [testthat](https://cran.r-project.org/package=testthat). Contributions + with test cases included are easier to accept. +- For user-facing changes, add a bullet to the top of `NEWS.md` below the + current development version header describing the changes made followed by your + GitHub username, and links to relevant issue(s)/PR(s). ### Code of Conduct -Please note that the getCRUCLdata project is released with a +Please note that the nasapower project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this project you agree to abide by its terms. ### See rOpenSci [contributing guide](https://ropensci.github.io/dev_guide/contributingguide.html) + for further details. ### Discussion forum Check out our [discussion forum](https://discuss.ropensci.org) if you think your issue requires a longer form discussion. -### Prefer to Email? +### Prefer to Email? Email the person listed as maintainer in the `DESCRIPTION` file of this repo. Though note that private discussions over email don't help others - of course email is totally warranted if it's a sensitive problem of any kind. -### Thanks for contributing! +### Thanks for contributing -This contributing guide is adapted from the tidyverse contributing guide available at https://raw.githubusercontent.com/r-lib/usethis/master/inst/templates/tidy-contributing.md +This contributing guide is adapted from the tidyverse contributing guide available at From 1555031f739979bed196c923e2a3a261ea98c1ff Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Thu, 6 Mar 2025 16:12:13 +0800 Subject: [PATCH 60/60] set up flir --- .Rbuildignore | 4 + .github/workflows/flir.yaml | 37 +++++ flir/cache_file_state.rds | Bin 0 -> 44 bytes flir/config.yml | 51 +++++++ flir/rules/builtin/T_and_F_symbol.yml | 97 +++++++++++++ flir/rules/builtin/absolute_path.yml | 13 ++ flir/rules/builtin/any_duplicated.yml | 91 +++++++++++++ flir/rules/builtin/any_is_na.yml | 25 ++++ flir/rules/builtin/class_equals.yml | 42 ++++++ flir/rules/builtin/condition_message.yml | 23 ++++ flir/rules/builtin/double_assignment.yml | 23 ++++ flir/rules/builtin/duplicate_argument.yml | 46 +++++++ flir/rules/builtin/empty_assignment.yml | 15 +++ flir/rules/builtin/equal_assignment.yml | 10 ++ flir/rules/builtin/equals_na.yml | 37 +++++ flir/rules/builtin/expect_comparison.yml | 37 +++++ flir/rules/builtin/expect_identical.yml | 42 ++++++ flir/rules/builtin/expect_length.yml | 15 +++ flir/rules/builtin/expect_named.yml | 79 +++++++++++ flir/rules/builtin/expect_not.yml | 23 ++++ flir/rules/builtin/expect_null.yml | 22 +++ flir/rules/builtin/expect_true_false.yml | 28 ++++ flir/rules/builtin/expect_type.yml | 51 +++++++ flir/rules/builtin/for_loop_index.yml | 27 ++++ flir/rules/builtin/function_return.yml | 11 ++ flir/rules/builtin/implicit_assignment.yml | 69 ++++++++++ flir/rules/builtin/is_numeric.yml | 25 ++++ flir/rules/builtin/length_levels.yml | 7 + flir/rules/builtin/length_test.yml | 59 ++++++++ flir/rules/builtin/lengths.yml | 59 ++++++++ flir/rules/builtin/library_call.yml | 26 ++++ flir/rules/builtin/list_comparison.yml | 18 +++ flir/rules/builtin/literal_coercion.yml | 89 ++++++++++++ flir/rules/builtin/matrix_apply.yml | 142 ++++++++++++++++++++ flir/rules/builtin/missing_argument.yml | 44 ++++++ flir/rules/builtin/nested_ifelse.yml | 29 ++++ flir/rules/builtin/numeric_leading_zero.yml | 11 ++ flir/rules/builtin/outer_negation.yml | 29 ++++ flir/rules/builtin/package_hooks.yml | 127 +++++++++++++++++ flir/rules/builtin/paste.yml | 75 +++++++++++ flir/rules/builtin/redundant_equals.yml | 29 ++++ flir/rules/builtin/redundant_ifelse.yml | 67 +++++++++ flir/rules/builtin/rep_len.yml | 7 + flir/rules/builtin/right_assignment.yml | 10 ++ flir/rules/builtin/sample_int.yml | 43 ++++++ flir/rules/builtin/semicolon.yml | 10 ++ flir/rules/builtin/seq.yml | 121 +++++++++++++++++ flir/rules/builtin/sort.yml | 85 ++++++++++++ flir/rules/builtin/stopifnot_all.yml | 24 ++++ flir/rules/builtin/todo_comment.yml | 7 + flir/rules/builtin/undesirable_function.yml | 13 ++ flir/rules/builtin/undesirable_operator.yml | 29 ++++ flir/rules/builtin/unnecessary_nesting.yml | 36 +++++ flir/rules/builtin/unreachable_code.yml | 64 +++++++++ flir/rules/builtin/which_grepl.yml | 7 + getCRUCLdata.Rproj | 21 +++ 56 files changed, 2231 insertions(+) create mode 100644 .github/workflows/flir.yaml create mode 100644 flir/cache_file_state.rds create mode 100644 flir/config.yml create mode 100644 flir/rules/builtin/T_and_F_symbol.yml create mode 100644 flir/rules/builtin/absolute_path.yml create mode 100644 flir/rules/builtin/any_duplicated.yml create mode 100644 flir/rules/builtin/any_is_na.yml create mode 100644 flir/rules/builtin/class_equals.yml create mode 100644 flir/rules/builtin/condition_message.yml create mode 100644 flir/rules/builtin/double_assignment.yml create mode 100644 flir/rules/builtin/duplicate_argument.yml create mode 100644 flir/rules/builtin/empty_assignment.yml create mode 100644 flir/rules/builtin/equal_assignment.yml create mode 100644 flir/rules/builtin/equals_na.yml create mode 100644 flir/rules/builtin/expect_comparison.yml create mode 100644 flir/rules/builtin/expect_identical.yml create mode 100644 flir/rules/builtin/expect_length.yml create mode 100644 flir/rules/builtin/expect_named.yml create mode 100644 flir/rules/builtin/expect_not.yml create mode 100644 flir/rules/builtin/expect_null.yml create mode 100644 flir/rules/builtin/expect_true_false.yml create mode 100644 flir/rules/builtin/expect_type.yml create mode 100644 flir/rules/builtin/for_loop_index.yml create mode 100644 flir/rules/builtin/function_return.yml create mode 100644 flir/rules/builtin/implicit_assignment.yml create mode 100644 flir/rules/builtin/is_numeric.yml create mode 100644 flir/rules/builtin/length_levels.yml create mode 100644 flir/rules/builtin/length_test.yml create mode 100644 flir/rules/builtin/lengths.yml create mode 100644 flir/rules/builtin/library_call.yml create mode 100644 flir/rules/builtin/list_comparison.yml create mode 100644 flir/rules/builtin/literal_coercion.yml create mode 100644 flir/rules/builtin/matrix_apply.yml create mode 100644 flir/rules/builtin/missing_argument.yml create mode 100644 flir/rules/builtin/nested_ifelse.yml create mode 100644 flir/rules/builtin/numeric_leading_zero.yml create mode 100644 flir/rules/builtin/outer_negation.yml create mode 100644 flir/rules/builtin/package_hooks.yml create mode 100644 flir/rules/builtin/paste.yml create mode 100644 flir/rules/builtin/redundant_equals.yml create mode 100644 flir/rules/builtin/redundant_ifelse.yml create mode 100644 flir/rules/builtin/rep_len.yml create mode 100644 flir/rules/builtin/right_assignment.yml create mode 100644 flir/rules/builtin/sample_int.yml create mode 100644 flir/rules/builtin/semicolon.yml create mode 100644 flir/rules/builtin/seq.yml create mode 100644 flir/rules/builtin/sort.yml create mode 100644 flir/rules/builtin/stopifnot_all.yml create mode 100644 flir/rules/builtin/todo_comment.yml create mode 100644 flir/rules/builtin/undesirable_function.yml create mode 100644 flir/rules/builtin/undesirable_operator.yml create mode 100644 flir/rules/builtin/unnecessary_nesting.yml create mode 100644 flir/rules/builtin/unreachable_code.yml create mode 100644 flir/rules/builtin/which_grepl.yml create mode 100644 getCRUCLdata.Rproj diff --git a/.Rbuildignore b/.Rbuildignore index 49ed843..6901b71 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -31,3 +31,7 @@ ^man/dot-create_stack\.Rd$ ^man/dot-set_cache\.Rd$ ^man/dot-get_local\.Rd$ + + +# flir files +^flir$ diff --git a/.github/workflows/flir.yaml b/.github/workflows/flir.yaml new file mode 100644 index 0000000..a82408f --- /dev/null +++ b/.github/workflows/flir.yaml @@ -0,0 +1,37 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + release: + types: [published] + workflow_dispatch: + +name: flir + +jobs: + flir: + runs-on: macOS-latest + # Only restrict concurrency for non-PR jobs + concurrency: + group: flir-${{ github.event_name != 'pull_request' || github.run_id }} + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + + - name: Install flir + run: install.packages("flir", repos = c("https://etiennebacher.r-universe.dev/", getOption("repos"))) + shell: Rscript {0} + + - name: Run flir + run: flir::lint() + shell: Rscript {0} + env: + FLIR_ERROR_ON_LINT: true diff --git a/flir/cache_file_state.rds b/flir/cache_file_state.rds new file mode 100644 index 0000000000000000000000000000000000000000..b8cafa45bcdfa1d213bd233dd6c72780e7314417 GIT binary patch literal 44 vcmb2|=3oE==I#ec2?+^l35jWG32CfGk`d0%cS>{{dg>Xr@2!@Q1}Xvo3Mve= literal 0 HcmV?d00001 diff --git a/flir/config.yml b/flir/config.yml new file mode 100644 index 0000000..6909752 --- /dev/null +++ b/flir/config.yml @@ -0,0 +1,51 @@ +keep: + - any_duplicated + - any_is_na + - class_equals + - condition_message + - double_assignment + - duplicate_argument + - empty_assignment + - equal_assignment + - equals_na + - expect_comparison + - expect_identical + - expect_length + - expect_named + - expect_not + - expect_null + - expect_true_false + - expect_type + - for_loop_index + - function_return + - implicit_assignment + - is_numeric + - length_levels + - length_test + - lengths + - library_call + - list_comparison + - literal_coercion + - matrix_apply + - missing_argument + - nested_ifelse + - numeric_leading_zero + - outer_negation + - package_hooks + - paste + - redundant_equals + - redundant_ifelse + - rep_len + - right_assignment + - sample_int + - semicolon + - seq + - sort + - stopifnot_all + - T_and_F_symbol + - todo_comment + - undesirable_function + - undesirable_operator + - unnecessary_nesting + - unreachable_code + - which_grepl diff --git a/flir/rules/builtin/T_and_F_symbol.yml b/flir/rules/builtin/T_and_F_symbol.yml new file mode 100644 index 0000000..ebe54ba --- /dev/null +++ b/flir/rules/builtin/T_and_F_symbol.yml @@ -0,0 +1,97 @@ +id: true_false_symbol +language: r +severity: warning +rule: + pattern: T + kind: identifier + not: + any: + - precedes: + any: + - pattern: <- + - pattern: = + - regex: ^~$ + - follows: + any: + - pattern: $ + - regex: ^~$ + - inside: + any: + - kind: parameter + - kind: call + - kind: binary_operator + follows: + regex: ^~$ + stopBy: end + stopBy: + kind: + argument +fix: TRUE +message: Use TRUE instead of the symbol T. + +--- + +id: true_false_symbol-2 +language: r +severity: warning +rule: + pattern: F + kind: identifier + not: + any: + - precedes: + any: + - pattern: <- + - pattern: = + - regex: ^~$ + - follows: + any: + - pattern: $ + - regex: ^~$ + - inside: + any: + - kind: parameter + - kind: call + - kind: binary_operator + follows: + regex: ^~$ + stopBy: end + stopBy: + kind: + argument +fix: FALSE +message: Use FALSE instead of the symbol F. + +--- + +id: true_false_symbol-3 +language: r +severity: warning +rule: + pattern: T + kind: identifier + precedes: + any: + - pattern: <- + - pattern: = + not: + inside: + kind: argument +message: Don't use T as a variable name, as it can break code relying on T being TRUE. + +--- + +id: true_false_symbol-4 +language: r +severity: warning +rule: + pattern: F + kind: identifier + precedes: + any: + - pattern: <- + - pattern: = + not: + inside: + kind: argument +message: Don't use F as a variable name, as it can break code relying on F being FALSE. diff --git a/flir/rules/builtin/absolute_path.yml b/flir/rules/builtin/absolute_path.yml new file mode 100644 index 0000000..2c5bb3d --- /dev/null +++ b/flir/rules/builtin/absolute_path.yml @@ -0,0 +1,13 @@ +# id: absolute_path-1 +# language: r +# severity: warning +# rule: +# kind: string_content +# any: +# - regex: '^~[[:alpha:]]' +# - regex: '^~/[[:alpha:]]' +# - regex: '^[[:alpha:]]:' +# - regex: '^(/|~)$' +# - regex: '^/[[:alpha:]]' +# - regex: '^\\' +# message: Do not use absolute paths. diff --git a/flir/rules/builtin/any_duplicated.yml b/flir/rules/builtin/any_duplicated.yml new file mode 100644 index 0000000..514b028 --- /dev/null +++ b/flir/rules/builtin/any_duplicated.yml @@ -0,0 +1,91 @@ +id: any_duplicated-1 +language: r +severity: warning +rule: + pattern: any($$$ duplicated($MYVAR) $$$) +fix: anyDuplicated(~~MYVAR~~) > 0 +message: anyDuplicated(x, ...) > 0 is better than any(duplicated(x), ...). + +--- + +id: any_duplicated-2 +language: r +severity: warning +rule: + any: + - pattern: length(unique($MYVAR)) == length($MYVAR) + - pattern: length($MYVAR) == length(unique($MYVAR)) +fix: anyDuplicated(~~MYVAR~~) == 0L +message: anyDuplicated(x) == 0L is better than length(unique(x)) == length(x). + +--- + +id: any_duplicated-3 +language: r +severity: warning +rule: + pattern: length(unique($MYVAR)) != length($MYVAR) +fix: anyDuplicated(~~MYVAR~~) != 0L +message: | + Use anyDuplicated(x) != 0L (or > or <) instead of length(unique(x)) != length(x) + (or > or <). + +--- + +id: any_duplicated-4 +language: r +severity: warning +rule: + any: + - pattern: nrow($DATA) != length(unique($DATA$µCOL)) + - pattern: length(unique($DATA$µCOL)) != nrow($DATA) +fix: anyDuplicated(~~DATA~~$~~COL~~) != 0L +message: | + anyDuplicated(DF$col) != 0L is better than length(unique(DF$col)) != nrow(DF) + +--- + +# id: any_duplicated-5 +# language: r +# severity: warning +# rule: +# any: +# - pattern: +# context: nrow($DATA) != length(unique($DATA[["µCOL"]])) +# strictness: ast +# - pattern: +# context: length(unique($DATA[["µCOL"]])) != nrow($DATA) +# strictness: ast +# fix: anyDuplicated(~~DATA~~[["~~COL~~"]]) != 0L +# message: | +# anyDuplicated(DF[["col"]]) != 0L is better than length(unique(DF[["col"]])) != nrow(DF) +# +# --- + +id: any_duplicated-6 +language: r +severity: warning +rule: + any: + - pattern: nrow($DATA) == length(unique($DATA$µCOL)) + - pattern: length(unique($DATA$µCOL)) == nrow($DATA) +fix: anyDuplicated(~~DATA~~$~~COL~~) == 0L +message: | + anyDuplicated(DF$col) == 0L is better than length(unique(DF$col)) == nrow(DF) + +# --- +# +# id: any_duplicated-7 +# language: r +# severity: warning +# rule: +# any: +# - pattern: +# context: nrow($DATA) == length(unique($DATA[["µCOL"]])) +# strictness: ast +# - pattern: +# context: length(unique($DATA[["µCOL"]])) == nrow($DATA) +# strictness: ast +# fix: anyDuplicated(~~DATA~~[["~~COL~~"]]) == 0L +# message: | +# anyDuplicated(DF[["col"]]) == 0L is better than length(unique(DF[["col"]])) == nrow(DF) diff --git a/flir/rules/builtin/any_is_na.yml b/flir/rules/builtin/any_is_na.yml new file mode 100644 index 0000000..68acfae --- /dev/null +++ b/flir/rules/builtin/any_is_na.yml @@ -0,0 +1,25 @@ +id: any_na-1 +language: r +severity: warning +rule: + any: + - pattern: any(is.na($MYVAR)) + - pattern: any(na.rm = $NARM, is.na($MYVAR)) + - pattern: any(is.na($MYVAR), na.rm = $NARM) +fix: anyNA(~~MYVAR~~) +message: anyNA(x) is better than any(is.na(x)). + +--- + +id: any_na-2 +language: r +severity: warning +rule: + any: + - pattern: NA %in% $ELEM + - pattern: NA_real_ %in% $ELEM + - pattern: NA_logical_ %in% $ELEM + - pattern: NA_character_ %in% $ELEM + - pattern: NA_complex_ %in% $ELEM +fix: anyNA(~~ELEM~~) +message: anyNA(x) is better than NA %in% x. diff --git a/flir/rules/builtin/class_equals.yml b/flir/rules/builtin/class_equals.yml new file mode 100644 index 0000000..2b7eb4c --- /dev/null +++ b/flir/rules/builtin/class_equals.yml @@ -0,0 +1,42 @@ +id: class_equals-1 +language: r +severity: warning +rule: + any: + - pattern: class($VAR) == $CLASSNAME + - pattern: $CLASSNAME == class($VAR) + not: + inside: + kind: argument +fix: inherits(~~VAR~~, ~~CLASSNAME~~) +message: Instead of comparing class(x) with ==, use inherits(x, 'class-name') or is. or is(x, 'class') + +--- + +id: class_equals-2 +language: r +severity: warning +rule: + any: + - pattern: class($VAR) != $CLASSNAME + - pattern: $CLASSNAME != class($VAR) + not: + inside: + kind: argument +fix: "!inherits(~~VAR~~, ~~CLASSNAME~~)" +message: "Instead of comparing class(x) with !=, use !inherits(x, 'class-name') or is. or is(x, 'class')" + +--- + +id: class_equals-3 +language: r +severity: warning +rule: + any: + - pattern: $CLASSNAME %in% class($VAR) + - pattern: class($VAR) %in% $CLASSNAME +constraints: + CLASSNAME: + kind: string +fix: inherits(~~VAR~~, ~~CLASSNAME~~) +message: Instead of comparing class(x) with %in%, use inherits(x, 'class-name') or is. or is(x, 'class') diff --git a/flir/rules/builtin/condition_message.yml b/flir/rules/builtin/condition_message.yml new file mode 100644 index 0000000..eb32466 --- /dev/null +++ b/flir/rules/builtin/condition_message.yml @@ -0,0 +1,23 @@ +id: condition_message-1 +language: r +severity: warning +rule: + pattern: $FUN($$$ paste0($$$MSG) $$$) + kind: call + not: + any: + - has: + kind: extract_operator + - has: + stopBy: end + kind: argument + has: + field: name + regex: "^collapse|recycle0$" + stopBy: end +constraints: + FUN: + regex: "^(packageStartupMessage|stop|warning)$" +fix: ~~FUN~~(~~MSG~~) +message: | + ~~FUN~~(paste0(...)) can be rewritten as ~~FUN~~(...). diff --git a/flir/rules/builtin/double_assignment.yml b/flir/rules/builtin/double_assignment.yml new file mode 100644 index 0000000..60a04e2 --- /dev/null +++ b/flir/rules/builtin/double_assignment.yml @@ -0,0 +1,23 @@ +id: right_double_assignment +language: r +severity: hint +rule: + pattern: $RHS ->> $LHS + has: + field: rhs + kind: identifier +message: ->> can have hard-to-predict behavior; prefer assigning to a + specific environment instead (with assign() or <-). + +--- + +id: left_double_assignment +language: r +severity: hint +rule: + pattern: $LHS <<- $RHS + has: + field: lhs + kind: identifier +message: <<- can have hard-to-predict behavior; prefer assigning to a + specific environment instead (with assign() or <-). diff --git a/flir/rules/builtin/duplicate_argument.yml b/flir/rules/builtin/duplicate_argument.yml new file mode 100644 index 0000000..415b9ff --- /dev/null +++ b/flir/rules/builtin/duplicate_argument.yml @@ -0,0 +1,46 @@ +id: duplicate_argument-1 +language: r +severity: warning +rule: + # Look for a function argument... + kind: argument + any: + - has: + kind: identifier + field: name + pattern: $OBJ + - has: + kind: string_content + pattern: $OBJ + stopBy: end + + # ... that follows other argument(s) with the same name... + follows: + kind: argument + stopBy: end + has: + stopBy: end + kind: identifier + field: name + pattern: $OBJ + + # ... inside a function call (or a subset environment for data.table)... + inside: + kind: arguments + follows: + any: + - kind: identifier + pattern: $FUN + - kind: string + inside: + any: + - kind: call + - kind: subset + +# ... that is not a function listed below. +constraints: + FUN: + not: + regex: ^(mutate|transmute)$ + +message: Avoid duplicate arguments in function calls. diff --git a/flir/rules/builtin/empty_assignment.yml b/flir/rules/builtin/empty_assignment.yml new file mode 100644 index 0000000..ccc995f --- /dev/null +++ b/flir/rules/builtin/empty_assignment.yml @@ -0,0 +1,15 @@ +id: empty_assignment-1 +language: r +severity: warning +rule: + any: + - pattern: $OBJ <- {} + - pattern: $OBJ <- {$CONTENT} + - pattern: $OBJ = {} + - pattern: $OBJ = {$CONTENT} +constraints: + CONTENT: + regex: ^\s+$ +message: | + Assign NULL explicitly or, whenever possible, allocate the empty object with + the right type and size. diff --git a/flir/rules/builtin/equal_assignment.yml b/flir/rules/builtin/equal_assignment.yml new file mode 100644 index 0000000..77074fe --- /dev/null +++ b/flir/rules/builtin/equal_assignment.yml @@ -0,0 +1,10 @@ +id: equal_assignment +language: r +severity: hint +rule: + pattern: $LHS = $RHS + has: + field: lhs + kind: identifier +fix: ~~LHS~~ <- ~~RHS~~ +message: Use <-, not =, for assignment. diff --git a/flir/rules/builtin/equals_na.yml b/flir/rules/builtin/equals_na.yml new file mode 100644 index 0000000..64e7454 --- /dev/null +++ b/flir/rules/builtin/equals_na.yml @@ -0,0 +1,37 @@ +id: equals_na +language: r +severity: warning +rule: + any: + - pattern: $MYVAR == NA + - pattern: $MYVAR == NA_integer_ + - pattern: $MYVAR == NA_real_ + - pattern: $MYVAR == NA_complex_ + - pattern: $MYVAR == NA_character_ + - pattern: NA == $MYVAR + - pattern: NA_integer_ == $MYVAR + - pattern: NA_real_ == $MYVAR + - pattern: NA_complex_ == $MYVAR + - pattern: NA_character_ == $MYVAR +fix: is.na(~~MYVAR~~) +message: Use is.na for comparisons to NA (not == or !=). + +--- + +id: equals_na-2 +language: r +severity: warning +rule: + any: + - pattern: $MYVAR != NA + - pattern: $MYVAR != NA_integer_ + - pattern: $MYVAR != NA_real_ + - pattern: $MYVAR != NA_complex_ + - pattern: $MYVAR != NA_character_ + - pattern: NA != $MYVAR + - pattern: NA_integer_ != $MYVAR + - pattern: NA_real_ != $MYVAR + - pattern: NA_complex_ != $MYVAR + - pattern: NA_character_ != $MYVAR +fix: is.na(~~MYVAR~~) +message: Use is.na for comparisons to NA (not == or !=). diff --git a/flir/rules/builtin/expect_comparison.yml b/flir/rules/builtin/expect_comparison.yml new file mode 100644 index 0000000..6af9bb1 --- /dev/null +++ b/flir/rules/builtin/expect_comparison.yml @@ -0,0 +1,37 @@ +id: expect_comparison-1 +language: r +severity: warning +rule: + pattern: expect_true($X > $Y) +fix: expect_gt(~~X~~, ~~Y~~) +message: expect_gt(x, y) is better than expect_true(x > y). + +--- + +id: expect_comparison-2 +language: r +severity: warning +rule: + pattern: expect_true($X >= $Y) +fix: expect_gte(~~X~~, ~~Y~~) +message: expect_gte(x, y) is better than expect_true(x >= y). + +--- + +id: expect_comparison-3 +language: r +severity: warning +rule: + pattern: expect_true($X < $Y) +fix: expect_lt(~~X~~, ~~Y~~) +message: expect_lt(x, y) is better than expect_true(x < y). + +--- + +id: expect_comparison-4 +language: r +severity: warning +rule: + pattern: expect_true($X <= $Y) +fix: expect_lte(~~X~~, ~~Y~~) +message: expect_lte(x, y) is better than expect_true(x <= y). diff --git a/flir/rules/builtin/expect_identical.yml b/flir/rules/builtin/expect_identical.yml new file mode 100644 index 0000000..3af5a85 --- /dev/null +++ b/flir/rules/builtin/expect_identical.yml @@ -0,0 +1,42 @@ +id: expect_identical-1 +language: r +severity: warning +rule: + pattern: expect_true(identical($VAL1, $VAL2)) +fix: expect_identical(~~VAL1~~, ~~VAL2~~) +message: Use expect_identical(x, y) instead of expect_true(identical(x, y)). + +--- + +id: expect_identical-2 +language: r +severity: warning +rule: + pattern: expect_equal($VAL1, $VAL2) +fix: expect_identical(~~VAL1~~, ~~VAL2~~) +constraints: + VAL1: + all: + - not: + has: + stopBy: end + kind: float + regex: \. + - not: + regex: ^typeof + - not: + pattern: NULL + VAL2: + all: + - not: + has: + stopBy: end + kind: float + regex: \. + - not: + regex: ^typeof + - not: + pattern: NULL +message: | + Use expect_identical(x, y) by default; resort to expect_equal() only when + needed, e.g. when setting ignore_attr= or tolerance=. diff --git a/flir/rules/builtin/expect_length.yml b/flir/rules/builtin/expect_length.yml new file mode 100644 index 0000000..fe233a7 --- /dev/null +++ b/flir/rules/builtin/expect_length.yml @@ -0,0 +1,15 @@ +id: expect_length-1 +language: r +severity: warning +rule: + any: + - pattern: $FUN(length($OBJ), $VALUE) + - pattern: $FUN($VALUE, length($OBJ)) +constraints: + FUN: + regex: ^(expect_identical|expect_equal)$ + VALUE: + not: + regex: length\( +fix: expect_length(~~OBJ~~, ~~VALUE~~) +message: expect_length(x, n) is better than ~~FUN~~(length(x), n). diff --git a/flir/rules/builtin/expect_named.yml b/flir/rules/builtin/expect_named.yml new file mode 100644 index 0000000..7d0691e --- /dev/null +++ b/flir/rules/builtin/expect_named.yml @@ -0,0 +1,79 @@ +id: expect_named-1 +language: r +severity: warning +rule: + any: + - pattern: + context: expect_identical(names($OBJ), $VALUES) + strictness: ast + - pattern: + context: expect_identical($VALUES, names($OBJ)) + strictness: ast +constraints: + VALUES: + not: + regex: ^(colnames\(|rownames\(|dimnames\(|NULL|names\() + has: + kind: null +fix: expect_named(~~OBJ~~, ~~VALUES~~) +message: expect_named(x, n) is better than expect_identical(names(x), n). + +--- + +id: expect_named-2 +language: r +severity: warning +rule: + any: + - pattern: + context: expect_equal(names($OBJ), $VALUES) + strictness: ast + - pattern: + context: expect_equal($VALUES, names($OBJ)) + strictness: ast +constraints: + VALUES: + not: + regex: ^(colnames\(|rownames\(|dimnames\(|NULL|names\() +fix: expect_named(~~OBJ~~, ~~VALUES~~) +message: expect_named(x, n) is better than expect_equal(names(x), n). + +--- + +id: expect_named-3 +language: r +severity: warning +rule: + any: + - pattern: + context: testthat::expect_identical(names($OBJ), $VALUES) + strictness: ast + - pattern: + context: testthat::expect_identical($VALUES, names($OBJ)) + strictness: ast +constraints: + VALUES: + not: + regex: ^(colnames\(|rownames\(|dimnames\(|NULL|names\() +fix: testthat::expect_named(~~OBJ~~, ~~VALUES~~) +message: expect_named(x, n) is better than expect_identical(names(x), n). + +--- + +id: expect_named-4 +language: r +severity: warning +rule: + any: + - pattern: + context: testthat::expect_equal(names($OBJ), $VALUES) + strictness: ast + - pattern: + context: testthat::expect_equal($VALUES, names($OBJ)) + strictness: ast +constraints: + VALUES: + not: + regex: ^(colnames\(|rownames\(|dimnames\(|NULL|names\() +fix: testthat::expect_named(~~OBJ~~, ~~VALUES~~) +message: expect_named(x, n) is better than expect_equal(names(x), n). diff --git a/flir/rules/builtin/expect_not.yml b/flir/rules/builtin/expect_not.yml new file mode 100644 index 0000000..3a23e9f --- /dev/null +++ b/flir/rules/builtin/expect_not.yml @@ -0,0 +1,23 @@ +id: expect_not-1 +language: r +severity: warning +rule: + all: + - pattern: expect_true(!$COND) + - not: + regex: '^expect_true\(!!' +fix: expect_false(~~COND~~) +message: expect_false(x) is better than expect_true(!x), and vice versa. + +--- + +id: expect_not-2 +language: r +severity: warning +rule: + all: + - pattern: expect_false(!$COND) + - not: + regex: '^expect_false\(!!' +fix: expect_true(~~COND~~) +message: expect_false(x) is better than expect_true(!x), and vice versa. diff --git a/flir/rules/builtin/expect_null.yml b/flir/rules/builtin/expect_null.yml new file mode 100644 index 0000000..7888fdb --- /dev/null +++ b/flir/rules/builtin/expect_null.yml @@ -0,0 +1,22 @@ +id: expect_null-1 +language: r +severity: warning +rule: + any: + - pattern: $FUN(NULL, $VALUES) + - pattern: $FUN($VALUES, NULL) +constraints: + FUN: + regex: ^(expect_identical|expect_equal)$ +fix: expect_null(~~VALUES~~) +message: expect_null(x) is better than ~~FUN~~(x, NULL). + +--- + +id: expect_null-2 +language: r +severity: warning +rule: + pattern: expect_true(is.null($VALUES)) +fix: expect_null(~~VALUES~~) +message: expect_null(x) is better than expect_true(is.null(x)). diff --git a/flir/rules/builtin/expect_true_false.yml b/flir/rules/builtin/expect_true_false.yml new file mode 100644 index 0000000..784843d --- /dev/null +++ b/flir/rules/builtin/expect_true_false.yml @@ -0,0 +1,28 @@ +id: expect_true_false-1 +language: r +severity: warning +rule: + any: + - pattern: $FUN(TRUE, $VALUES) + - pattern: $FUN($VALUES, TRUE) +constraints: + FUN: + regex: ^(expect_identical|expect_equal)$ +fix: expect_true(~~VALUES~~) +message: expect_true(x) is better than ~~FUN~~(x, TRUE). + +--- + +id: expect_true_false-2 +language: r +severity: warning +rule: + any: + - pattern: $FUN(FALSE, $VALUES) + - pattern: $FUN($VALUES, FALSE) +constraints: + FUN: + regex: ^(expect_identical|expect_equal)$ +fix: expect_false(~~VALUES~~) +message: expect_false(x) is better than ~~FUN~~(x, FALSE). + diff --git a/flir/rules/builtin/expect_type.yml b/flir/rules/builtin/expect_type.yml new file mode 100644 index 0000000..1ab20ec --- /dev/null +++ b/flir/rules/builtin/expect_type.yml @@ -0,0 +1,51 @@ +id: expect_type-1 +language: r +severity: warning +rule: + any: + - pattern: + context: expect_identical(typeof($OBJ), $VALUES) + strictness: ast + - pattern: + context: expect_identical($VALUES, typeof($OBJ)) + strictness: ast +constraints: + VALUES: + not: + regex: typeof +fix: expect_type(~~OBJ~~, ~~VALUES~~) +message: expect_type(x, t) is better than expect_identical(typeof(x), t). + +--- + +id: expect_type-2 +language: r +severity: warning +rule: + any: + - pattern: + context: expect_equal(typeof($OBJ), $VALUES) + strictness: ast + - pattern: + context: expect_equal($VALUES, typeof($OBJ)) + strictness: ast +constraints: + VALUES: + not: + regex: typeof +fix: expect_type(~~OBJ~~, ~~VALUES~~) +message: expect_type(x, t) is better than expect_equal(typeof(x), t). + +--- + +id: expect_type-3 +language: r +severity: warning +rule: + pattern: expect_true($FUN($OBJ)) +constraints: + FUN: + regex: ^is\. + not: + regex: data\.frame$ +message: expect_type(x, t) is better than expect_true(is.(x)). diff --git a/flir/rules/builtin/for_loop_index.yml b/flir/rules/builtin/for_loop_index.yml new file mode 100644 index 0000000..e5b28b4 --- /dev/null +++ b/flir/rules/builtin/for_loop_index.yml @@ -0,0 +1,27 @@ +id: for_loop_index-1 +language: r +severity: warning +rule: + pattern: for ($IDX in $IDX) +message: Don't re-use any sequence symbols as the index symbol in a for loop. + +--- + +id: for_loop_index-2 +language: r +severity: warning +rule: + pattern: for ($IDX in $SEQ) +constraints: + SEQ: + kind: call + has: + kind: arguments + has: + kind: argument + stopBy: end + has: + kind: identifier + field: value + pattern: $IDX +message: Don't re-use any sequence symbols as the index symbol in a for loop. diff --git a/flir/rules/builtin/function_return.yml b/flir/rules/builtin/function_return.yml new file mode 100644 index 0000000..31ba46b --- /dev/null +++ b/flir/rules/builtin/function_return.yml @@ -0,0 +1,11 @@ +id: function_return-1 +language: r +severity: warning +rule: + any: + - pattern: return($OBJ <- $VAL) + - pattern: return($OBJ <<- $VAL) + - pattern: return($VAL -> $OBJ) + - pattern: return($VAL ->> $OBJ) +message: | + Move the assignment outside of the return() clause, or skip assignment altogether. diff --git a/flir/rules/builtin/implicit_assignment.yml b/flir/rules/builtin/implicit_assignment.yml new file mode 100644 index 0000000..133a40e --- /dev/null +++ b/flir/rules/builtin/implicit_assignment.yml @@ -0,0 +1,69 @@ +id: implicit_assignment-1 +language: r +severity: warning +rule: + any: + - pattern: $RECEIVER <- $VALUE + - pattern: $RECEIVER <<- $VALUE + - pattern: $VALUE -> $RECEIVER + - pattern: $VALUE ->> $RECEIVER + inside: + any: + - kind: if_statement + - kind: while_statement + field: condition + stopBy: end + strictness: cst +message: | + Avoid implicit assignments in function calls. For example, instead of + `if (x <- 1L) { ... }`, write `x <- 1L; if (x) { ... }`. + +--- + +id: implicit_assignment-2 +language: r +severity: warning +rule: + any: + - pattern: $RECEIVER <- $VALUE + - pattern: $RECEIVER <<- $VALUE + - pattern: $VALUE -> $RECEIVER + - pattern: $VALUE ->> $RECEIVER + inside: + kind: for_statement + field: sequence + stopBy: end + strictness: cst +message: | + Avoid implicit assignments in function calls. For example, instead of + `if (x <- 1L) { ... }`, write `x <- 1L; if (x) { ... }`. + +# --- +# +# id: implicit_assignment-3 +# language: r +# severity: warning +# rule: +# any: +# - pattern: $RECEIVER <- $VALUE +# - pattern: $RECEIVER <<- $VALUE +# - pattern: $VALUE -> $RECEIVER +# - pattern: $VALUE ->> $RECEIVER +# inside: +# kind: argument +# field: value +# strictness: cst +# stopBy: end +# not: +# inside: +# kind: call +# field: function +# has: +# kind: identifier +# regex: ^(lapply)$ +# stopBy: end +# strictness: cst +# message: | +# Avoid implicit assignments in function calls. For example, instead of +# `if (x <- 1L) { ... }`, write `x <- 1L; if (x) { ... }`. + diff --git a/flir/rules/builtin/is_numeric.yml b/flir/rules/builtin/is_numeric.yml new file mode 100644 index 0000000..0a76b08 --- /dev/null +++ b/flir/rules/builtin/is_numeric.yml @@ -0,0 +1,25 @@ +id: is_numeric-1 +language: r +severity: warning +rule: + any: + - pattern: is.numeric($VAR) || is.integer($VAR) + - pattern: is.integer($VAR) || is.numeric($VAR) +message: is.numeric(x) || is.integer(x) can be simplified to is.numeric(x). Use + is.double(x) to test for objects stored as 64-bit floating point. + +--- + +id: is_numeric-2 +language: r +severity: warning +rule: + any: + - pattern: + context: class($VAR) %in% c("numeric", "integer") + strictness: ast + - pattern: + context: class($VAR) %in% c("integer", "numeric") + strictness: ast +message: class(x) %in% c("numeric", "integer") can be simplified to is.numeric(x). Use + is.double(x) to test for objects stored as 64-bit floating point. diff --git a/flir/rules/builtin/length_levels.yml b/flir/rules/builtin/length_levels.yml new file mode 100644 index 0000000..8e02978 --- /dev/null +++ b/flir/rules/builtin/length_levels.yml @@ -0,0 +1,7 @@ +id: length_levels-1 +language: r +severity: warning +rule: + pattern: length(levels($VAR)) +fix: nlevels(~~VAR~~) +message: nlevels(x) is better than length(levels(x)). df diff --git a/flir/rules/builtin/length_test.yml b/flir/rules/builtin/length_test.yml new file mode 100644 index 0000000..f9ba9ed --- /dev/null +++ b/flir/rules/builtin/length_test.yml @@ -0,0 +1,59 @@ +# Strangely, having something like pattern: length($VAR $OP $VAR2) doesn't work + +id: length_test-1 +language: r +severity: warning +rule: + pattern: length($VAR == $VAR2) +fix: length(~~VAR~~) == ~~VAR2~~ +message: Checking the length of a logical vector is likely a mistake. + +--- + +id: length_test-2 +language: r +severity: warning +rule: + pattern: length($VAR != $VAR2) +fix: length(~~VAR~~) != ~~VAR2~~ +message: Checking the length of a logical vector is likely a mistake. + +--- + +id: length_test-3 +language: r +severity: warning +rule: + pattern: length($VAR > $VAR2) +fix: length(~~VAR~~) > ~~VAR2~~ +message: Checking the length of a logical vector is likely a mistake. + +--- + +id: length_test-4 +language: r +severity: warning +rule: + pattern: length($VAR >= $VAR2) +fix: length(~~VAR~~) >= ~~VAR2~~ +message: Checking the length of a logical vector is likely a mistake. + +--- + +id: length_test-5 +language: r +severity: warning +rule: + pattern: length($VAR < $VAR2) +fix: length(~~VAR~~) < ~~VAR2~~ +message: Checking the length of a logical vector is likely a mistake. + +--- + +id: length_test-6 +language: r +severity: warning +rule: + pattern: length($VAR <= $VAR2) +fix: length(~~VAR~~) <= ~~VAR2~~ +message: Checking the length of a logical vector is likely a mistake. diff --git a/flir/rules/builtin/lengths.yml b/flir/rules/builtin/lengths.yml new file mode 100644 index 0000000..a416440 --- /dev/null +++ b/flir/rules/builtin/lengths.yml @@ -0,0 +1,59 @@ +id: sapply_lengths-1 +language: r +severity: warning +rule: + any: + - pattern: sapply($MYVAR, length) + - pattern: sapply(FUN = length, $MYVAR) + - pattern: sapply($MYVAR, FUN = length) + - pattern: vapply($MYVAR, length $$$) + + - pattern: map_dbl($MYVAR, length) + - pattern: map_dbl($MYVAR, .f = length) + - pattern: map_dbl(.f = length, $MYVAR) + - pattern: map_int($MYVAR, length) + - pattern: map_int($MYVAR, .f = length) + - pattern: map_int(.f = length, $MYVAR) + + - pattern: purrr::map_dbl($MYVAR, length) + - pattern: purrr::map_dbl($MYVAR, .f = length) + - pattern: purrr::map_dbl(.f = length, $MYVAR) + - pattern: purrr::map_int($MYVAR, length) + - pattern: purrr::map_int($MYVAR, .f = length) + - pattern: purrr::map_int(.f = length, $MYVAR) +fix: lengths(~~MYVAR~~) +message: Use lengths() to find the length of each element in a list. + +--- + +id: sapply_lengths-2 +language: r +severity: warning +rule: + any: + - pattern: $MYVAR |> sapply(length) + - pattern: $MYVAR |> sapply(FUN = length) + - pattern: $MYVAR |> vapply(length $$$) + - pattern: $MYVAR |> map_int(length) + - pattern: $MYVAR |> map_int(length $$$) + - pattern: $MYVAR |> purrr::map_int(length) + - pattern: $MYVAR |> purrr::map_int(length $$$) +fix: ~~MYVAR~~ |> lengths() +message: Use lengths() to find the length of each element in a list. + +--- + +id: sapply_lengths-3 +language: r +severity: warning +rule: + any: + - pattern: $MYVAR %>% sapply(length) + - pattern: $MYVAR %>% sapply(FUN = length) + - pattern: $MYVAR %>% vapply(length $$$) + - pattern: $MYVAR %>% map_int(length) + - pattern: $MYVAR %>% map_int(length $$$) + - pattern: $MYVAR %>% purrr::map_int(length) + - pattern: $MYVAR %>% purrr::map_int(length $$$) +fix: ~~MYVAR~~ %>% lengths() +message: Use lengths() to find the length of each element in a list. diff --git a/flir/rules/builtin/library_call.yml b/flir/rules/builtin/library_call.yml new file mode 100644 index 0000000..4b578fe --- /dev/null +++ b/flir/rules/builtin/library_call.yml @@ -0,0 +1,26 @@ +id: library_call +language: r +severity: warning +rule: + kind: call + has: + regex: ^library|require$ + kind: identifier + follows: + not: + any: + - kind: call + has: + regex: ^library|require$ + kind: identifier + - kind: comment + not: + inside: + stopBy: end + any: + - kind: function_definition + - kind: call + has: + pattern: suppressPackageStartupMessages + kind: identifier +message: Move all library/require calls to the top of the script. diff --git a/flir/rules/builtin/list_comparison.yml b/flir/rules/builtin/list_comparison.yml new file mode 100644 index 0000000..772d433 --- /dev/null +++ b/flir/rules/builtin/list_comparison.yml @@ -0,0 +1,18 @@ +id: list_comparison-1 +language: r +severity: warning +rule: + any: + - pattern: $FUN($$$) > $$$ + - pattern: $FUN($$$) >= $$$ + - pattern: $FUN($$$) < $$$ + - pattern: $FUN($$$) <= $$$ + - pattern: $FUN($$$) == $$$ + - pattern: $FUN($$$) != $$$ +constraints: + FUN: + regex: ^(lapply|map|Map|\.mapply)$ +message: | + The output of ~~FUN~~(), a list, is being coerced for comparison. + Instead, use a mapper that generates a vector with the correct type directly, + for example vapply(x, FUN, character(1L)) if the output is a string. diff --git a/flir/rules/builtin/literal_coercion.yml b/flir/rules/builtin/literal_coercion.yml new file mode 100644 index 0000000..e61fb24 --- /dev/null +++ b/flir/rules/builtin/literal_coercion.yml @@ -0,0 +1,89 @@ +id: literal_coercion-1 +language: r +severity: warning +rule: + pattern: $FUN($VALUE) +constraints: + VALUE: + kind: argument + has: + kind: float + not: + regex: 'e' + FUN: + regex: ^(int|as\.integer)$ +fix: ~~VALUE~~L +message: | + Use ~~VALUE~~L instead of ~~FUN~~(~~VALUE~~), i.e., use literals directly + where possible, instead of coercion. + +--- + +id: literal_coercion-2 +language: r +severity: warning +rule: + pattern: as.character(NA) +fix: NA_character_ +message: | + Use NA_character_ instead of as.character(NA), i.e., use literals directly + where possible, instead of coercion. + +--- + +id: literal_coercion-3 +language: r +severity: warning +rule: + pattern: as.logical($VAR) +constraints: + VAR: + kind: argument + has: + any: + - regex: ^1L$ + - regex: ^1$ + - regex: 'true' +fix: TRUE +message: Use TRUE instead of as.logical(~~VAR~~). + +--- + +id: literal_coercion-4 +language: r +severity: warning +rule: + pattern: $FUN($VAR) +constraints: + VAR: + kind: argument + has: + kind: float + FUN: + regex: ^(as\.numeric|as\.double)$ +fix: ~~VAR~~ +message: Use ~~VAR~~ instead of ~~FUN~~(~~VAR~~). + +--- + +id: literal_coercion-5 +language: r +severity: warning +rule: + pattern: as.integer(NA) +fix: NA_integer_ +message: Use NA_integer_ instead of as.integer(NA). + +--- + +id: literal_coercion-6 +language: r +severity: warning +rule: + pattern: $FUN(NA) +constraints: + FUN: + regex: ^(as\.numeric|as\.double)$ +fix: NA_real_ +message: Use NA_real_ instead of ~~FUN~~(NA). + diff --git a/flir/rules/builtin/matrix_apply.yml b/flir/rules/builtin/matrix_apply.yml new file mode 100644 index 0000000..7eaa40c --- /dev/null +++ b/flir/rules/builtin/matrix_apply.yml @@ -0,0 +1,142 @@ +id: matrix_apply-1 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, sum) + - pattern: apply($INPUT, MARGIN = $MARG, sum) + - pattern: apply($INPUT, $MARG, FUN = sum) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = sum) +constraints: + MARG: + has: + regex: ^(2|2L)$ +fix: colSums(~~INPUT~~) +message: Use colSums(x) rather than apply(x, 2, sum) + +--- + +id: matrix_apply-2 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, sum, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, sum, na.rm = $NARM) + - pattern: apply($INPUT, $MARG, FUN = sum, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = sum, na.rm = $NARM) +constraints: + MARG: + has: + regex: ^(2|2L)$ +fix: colSums(~~INPUT~~, na.rm = ~~NARM~~) +message: Use colSums(x, na.rm = ~~NARM~~) rather than apply(x, 2, sum, na.rm = ~~NARM~~). + +--- + +id: matrix_apply-3 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, sum) + - pattern: apply($INPUT, MARGIN = $MARG, sum) + - pattern: apply($INPUT, $MARG, FUN = sum) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = sum) +constraints: + MARG: + has: + regex: ^(1|1L)$ +fix: rowSums(~~INPUT~~) +message: Use rowSums(x) rather than apply(x, 1, sum) + +--- + +id: matrix_apply-4 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, sum, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, sum, na.rm = $NARM) + - pattern: apply($INPUT, $MARG, FUN = sum, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = sum, na.rm = $NARM) +constraints: + MARG: + has: + regex: ^(1|1L)$ +fix: rowSums(~~INPUT~~, na.rm = ~~NARM~~) +message: Use rowSums(x, na.rm = ~~NARM~~) rather than apply(x, 1, sum, na.rm = ~~NARM~~). + +--- + +id: matrix_apply-5 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, mean) + - pattern: apply($INPUT, MARGIN = $MARG, mean) + - pattern: apply($INPUT, $MARG, FUN = mean) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = mean) +constraints: + MARG: + has: + regex: ^(1|1L)$ +fix: rowMeans(~~INPUT~~) +message: Use rowMeans(x) rather than apply(x, 1, mean). + +--- + +id: matrix_apply-6 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, mean, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, mean, na.rm = $NARM) + - pattern: apply($INPUT, $MARG, FUN = mean, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = mean, na.rm = $NARM) +constraints: + MARG: + has: + regex: ^(1|1L)$ +fix: rowMeans(~~INPUT~~, na.rm = ~~NARM~~) +message: Use rowMeans(x, na.rm = ~~NARM~~) rather than apply(x, 1, mean, na.rm = ~~NARM~~). + +--- + +id: matrix_apply-7 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, mean) + - pattern: apply($INPUT, MARGIN = $MARG, mean) + - pattern: apply($INPUT, $MARG, FUN = mean) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = mean) +constraints: + MARG: + has: + regex: ^(2|2L)$ +fix: colMeans(~~INPUT~~) +message: Use colMeans(x) rather than apply(x, 2, mean). + +--- + +id: matrix_apply-8 +language: r +severity: warning +rule: + any: + - pattern: apply($INPUT, $MARG, mean, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, mean, na.rm = $NARM) + - pattern: apply($INPUT, $MARG, FUN = mean, na.rm = $NARM) + - pattern: apply($INPUT, MARGIN = $MARG, FUN = mean, na.rm = $NARM) +constraints: + MARG: + has: + regex: ^(2|2L)$ +fix: colMeans(~~INPUT~~, na.rm = ~~NARM~~) +message: Use colMeans(x, na.rm = ~~NARM~~) rather than apply(x, 2, mean, na.rm = ~~NARM~~). + diff --git a/flir/rules/builtin/missing_argument.yml b/flir/rules/builtin/missing_argument.yml new file mode 100644 index 0000000..9f47d17 --- /dev/null +++ b/flir/rules/builtin/missing_argument.yml @@ -0,0 +1,44 @@ +id: missing_argument-1 +language: r +severity: warning +rule: + kind: arguments + has: + kind: comma + any: + - precedes: + stopBy: neighbor + any: + - regex: '^\)$' + - kind: comma + - follows: + any: + - regex: '^\($' + - kind: argument + regex: '=$' + follows: + kind: identifier + not: + regex: '^(quote|switch|alist)$' + inside: + kind: call +message: Missing argument in function call. + +--- + +id: missing_argument-2 +language: r +severity: warning +rule: + kind: arguments + regex: '=(\s+|)\)$' + follows: + any: + - kind: identifier + - kind: extract_operator + - kind: namespace_operator + not: + regex: '^(quote|switch|alist)$' + inside: + kind: call +message: Missing argument in function call. diff --git a/flir/rules/builtin/nested_ifelse.yml b/flir/rules/builtin/nested_ifelse.yml new file mode 100644 index 0000000..64dcb08 --- /dev/null +++ b/flir/rules/builtin/nested_ifelse.yml @@ -0,0 +1,29 @@ +id: nested_ifelse-1 +language: r +severity: warning +rule: + pattern: $FUN($COND, $TRUE, $FALSE) +constraints: + FALSE: + regex: ^(ifelse|if_else|fifelse) + FUN: + regex: ^(ifelse|if_else|fifelse) +message: | + Don't use nested ~~FUN~~() calls; instead, try (1) data.table::fcase; + (2) dplyr::case_when; or (3) using a lookup table. + +--- + +id: nested_ifelse-2 +language: r +severity: warning +rule: + pattern: $FUN($COND, $TRUE, $FALSE) +constraints: + TRUE: + regex: ^(ifelse|if_else|fifelse) + FUN: + regex: ^(ifelse|if_else|fifelse) +message: | + Don't use nested ~~FUN~~() calls; instead, try (1) data.table::fcase; + (2) dplyr::case_when; or (3) using a lookup table. diff --git a/flir/rules/builtin/numeric_leading_zero.yml b/flir/rules/builtin/numeric_leading_zero.yml new file mode 100644 index 0000000..1d6762d --- /dev/null +++ b/flir/rules/builtin/numeric_leading_zero.yml @@ -0,0 +1,11 @@ +id: numeric_leading_zero-1 +language: r +severity: warning +rule: + pattern: $VALUE + any: + - kind: float + - kind: identifier + regex: ^\.[0-9] +fix: 0~~VALUE~~ +message: Include the leading zero for fractional numeric constants. diff --git a/flir/rules/builtin/outer_negation.yml b/flir/rules/builtin/outer_negation.yml new file mode 100644 index 0000000..ca377de --- /dev/null +++ b/flir/rules/builtin/outer_negation.yml @@ -0,0 +1,29 @@ +id: outer_negation-1 +language: r +severity: warning +rule: + pattern: all(!$VAR) +constraints: + VAR: + not: + regex: '^!' +fix: '!any(~~VAR~~)' +message: | + !any(x) is better than all(!x). The former applies negation only once after + aggregation instead of many times for each element of x. + +--- + +id: outer_negation-2 +language: r +severity: warning +rule: + pattern: any(! $VAR) +constraints: + VAR: + not: + regex: '^!' +fix: '!all(~~VAR~~)' +message: | + !all(x) is better than any(!x). The former applies negation only once after + aggregation instead of many times for each element of x. diff --git a/flir/rules/builtin/package_hooks.yml b/flir/rules/builtin/package_hooks.yml new file mode 100644 index 0000000..f4dfa75 --- /dev/null +++ b/flir/rules/builtin/package_hooks.yml @@ -0,0 +1,127 @@ +id: package_hooks-1 +language: r +severity: warning +rule: + pattern: packageStartupMessage($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: .onLoad +message: Put packageStartupMessage() calls in .onAttach(), not .onLoad(). + +--- + +id: package_hooks-2 +language: r +severity: warning +rule: + pattern: library.dynam($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: .onAttach +message: Put library.dynam() calls in .onLoad(), not .onAttach(). + +--- + +id: package_hooks-3 +language: r +severity: warning +rule: + pattern: $FN($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: .onLoad +constraints: + FN: + regex: '^(cat|installed.packages|message|packageStartupMessage|print|writeLines)$' +message: Don't use ~~FN~~() in .onLoad(). + +--- + +id: package_hooks-4 +language: r +severity: warning +rule: + pattern: $FN($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: .onAttach +constraints: + FN: + # library.dynam already has its own linter + regex: '^(cat|installed.packages|message|print|writeLines)$' +message: Don't use ~~FN~~() in .onAttach(). + +--- + +id: package_hooks-5 +language: r +severity: warning +rule: + pattern: $FN($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: $LOAD +constraints: + LOAD: + regex: '^(\.onAttach|\.onLoad)$' + FN: + regex: '^(require|library)$' +message: Don't alter the search() path in ~~LOAD~~() by calling ~~FN~~(). + +--- + +id: package_hooks-6 +language: r +severity: warning +rule: + pattern: installed.packages($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: $LOAD +constraints: + LOAD: + regex: '^(\.onAttach|\.onLoad)$' +message: Don't slow down package load by running installed.packages() in ~~LOAD~~(). + +--- + +id: package_hooks-7 +language: r +severity: warning +rule: + pattern: library.dynam.unload($$$) + inside: + stopBy: end + kind: binary_operator + has: + stopBy: end + field: lhs + pattern: $LOAD +constraints: + LOAD: + regex: '^(\.onDetach|\.Last\.lib)$' +message: Use library.dynam.unload() calls in .onUnload(), not ~~LOAD~~(). diff --git a/flir/rules/builtin/paste.yml b/flir/rules/builtin/paste.yml new file mode 100644 index 0000000..800b676 --- /dev/null +++ b/flir/rules/builtin/paste.yml @@ -0,0 +1,75 @@ +id: paste-1 +language: r +severity: warning +rule: + pattern: + context: paste($$$CONTENT sep = "" $$$CONTENT2) + strictness: ast +# fix: paste0($$$CONTENT) +message: paste0(...) is better than paste(..., sep = ""). + +--- + +id: paste-2 +language: r +severity: warning +rule: + any: + - pattern: + context: paste($CONTENT, collapse = ", ") + strictness: ast + - pattern: + context: paste(collapse = ", ", $CONTENT) + strictness: ast +# fix: paste0($$$CONTENT) +message: toString(.) is more expressive than paste(., collapse = ", "). + +--- + +id: paste-3 +language: r +severity: warning +rule: + pattern: + context: paste0($$$CONTENT sep = $USELESS $$$CONTENT2) + strictness: ast +# fix: paste0($$$CONTENT) +message: | + sep= is not a formal argument to paste0(); did you mean to use paste(), or + collapse=? + +--- + +id: paste-4 +language: r +severity: warning +rule: + any: + - pattern: + context: paste0($CONTENT, collapse = $FOO) + strictness: ast + - pattern: + context: paste0(collapse = $FOO, $CONTENT) + strictness: ast + not: + has: + regex: sep + kind: argument +# fix: paste0($$$CONTENT) +message: | + Use paste(), not paste0(), to collapse a character vector when sep= is not used. + +# --- +# +# id: paste-5 +# language: r +# severity: warning +# rule: +# pattern: +# context: paste0(rep($VAR, $TIMES), collapse = "") +# strictness: ast +# constraints: +# VAR: +# kind: string +# fix: strrep(~~VAR~~, ~~TIMES~~) +# message: strrep(x, times) is better than paste0(rep(x, times), collapse = ""). diff --git a/flir/rules/builtin/redundant_equals.yml b/flir/rules/builtin/redundant_equals.yml new file mode 100644 index 0000000..79a6abc --- /dev/null +++ b/flir/rules/builtin/redundant_equals.yml @@ -0,0 +1,29 @@ +id: redundant_equals-1 +language: r +severity: warning +rule: + any: + - pattern: $VAR == TRUE + - pattern: TRUE == $VAR + - pattern: $VAR == FALSE + - pattern: FALSE == $VAR +message: | + Using == on a logical vector is redundant. Well-named logical vectors can be + used directly in filtering. For data.table's `i` argument, wrap the column + name in (), like `DT[(is_treatment)]`. + +--- + +id: redundant_equals-2 +language: r +severity: warning +rule: + any: + - pattern: $VAR != TRUE + - pattern: TRUE != $VAR + - pattern: $VAR != FALSE + - pattern: FALSE != $VAR +message: | + Using != on a logical vector is redundant. Well-named logical vectors can be + used directly in filtering. For data.table's `i` argument, wrap the column + name in (), like `DT[(is_treatment)]`. diff --git a/flir/rules/builtin/redundant_ifelse.yml b/flir/rules/builtin/redundant_ifelse.yml new file mode 100644 index 0000000..8f252e6 --- /dev/null +++ b/flir/rules/builtin/redundant_ifelse.yml @@ -0,0 +1,67 @@ +id: redundant_ifelse-1 +language: r +severity: warning +rule: + pattern: $FUN($COND, $VAL1, $VAL2) +constraints: + VAL1: + regex: ^TRUE$ + VAL2: + regex: ^FALSE$ + FUN: + regex: ^(ifelse|fifelse|if_else)$ +fix: ~~COND~~ +message: | + Use ~~COND~~ directly instead of calling ~~FUN~~(~~COND~~, TRUE, FALSE). + +--- + +id: redundant_ifelse-2 +language: r +severity: warning +rule: + pattern: $FUN($COND, $VAL1, $VAL2) +constraints: + VAL1: + regex: ^FALSE$ + VAL2: + regex: ^TRUE$ + FUN: + regex: ^(ifelse|fifelse|if_else)$ +fix: '!(~~COND~~)' +message: | + Use !(~~COND~~) directly instead of calling ~~FUN~~(~~COND~~, FALSE, TRUE). + +--- + +id: redundant_ifelse-3 +language: r +severity: warning +rule: + pattern: $FUN($COND, $VAL1, $VAL2) +constraints: + VAL1: + regex: ^(1|1L)$ + VAL2: + regex: ^(0|0L)$ + FUN: + regex: ^(ifelse|fifelse|if_else)$ +fix: as.integer(~~COND~~) +message: Prefer as.integer(~~COND~~) to ~~FUN~~(~~COND~~, ~~VAL1~~, ~~VAL2~~). + +--- + +id: redundant_ifelse-4 +language: r +severity: warning +rule: + pattern: $FUN($COND, $VAL1, $VAL2) +constraints: + VAL1: + regex: ^(0|0L)$ + VAL2: + regex: ^(1|1L)$ + FUN: + regex: ^(ifelse|fifelse|if_else)$ +fix: as.integer(!(~~COND~~)) +message: Prefer as.integer(!(~~COND~~)) to ~~FUN~~(~~COND~~, ~~VAL1~~, ~~VAL2~~). diff --git a/flir/rules/builtin/rep_len.yml b/flir/rules/builtin/rep_len.yml new file mode 100644 index 0000000..d4d78e5 --- /dev/null +++ b/flir/rules/builtin/rep_len.yml @@ -0,0 +1,7 @@ +id: rep_len-1 +language: r +severity: warning +rule: + pattern: rep($OBJ, length.out = $LEN) +fix: rep_len(~~OBJ~~, ~~LEN~~) +message: Use rep_len(x, n) instead of rep(x, length.out = n). diff --git a/flir/rules/builtin/right_assignment.yml b/flir/rules/builtin/right_assignment.yml new file mode 100644 index 0000000..76b736e --- /dev/null +++ b/flir/rules/builtin/right_assignment.yml @@ -0,0 +1,10 @@ +id: right_assignment +language: r +severity: hint +rule: + pattern: $RHS -> $LHS + has: + field: rhs + kind: identifier +fix: ~~LHS~~<- ~~RHS~~ +message: Use <-, not ->, for assignment. diff --git a/flir/rules/builtin/sample_int.yml b/flir/rules/builtin/sample_int.yml new file mode 100644 index 0000000..091825c --- /dev/null +++ b/flir/rules/builtin/sample_int.yml @@ -0,0 +1,43 @@ +id: sample_int-1 +language: r +severity: warning +rule: + any: + - pattern: sample(1:$N, $$$OTHER) + - pattern: sample(1L:$N, $$$OTHER) +fix: sample.int(~~N~~, ~~OTHER~~) +message: sample.int(n, m, ...) is preferable to sample(1:n, m, ...). + +--- + +id: sample_int-2 +language: r +severity: warning +rule: + pattern: sample(seq($N), $$$OTHER) +fix: sample.int(~~N~~, ~~OTHER~~) +message: sample.int(n, m, ...) is preferable to sample(seq(n), m, ...). + +--- + +id: sample_int-3 +language: r +severity: warning +rule: + pattern: sample(seq_len($N), $$$OTHER) +fix: sample.int(~~N~~, ~~OTHER~~) +message: sample.int(n, m, ...) is preferable to sample(seq_len(n), m, ...). + +--- + +# Strangely this panicks if I rename FIRST to N +id: sample_int-4 +language: r +severity: warning +rule: + pattern: sample($FIRST, $$$OTHER) +constraints: + FIRST: + regex: ^\d+(L|)$ +fix: sample.int(~~N~~, ~~OTHER~~) +message: sample.int(n, m, ...) is preferable to sample(n, m, ...). diff --git a/flir/rules/builtin/semicolon.yml b/flir/rules/builtin/semicolon.yml new file mode 100644 index 0000000..fb5dd75 --- /dev/null +++ b/flir/rules/builtin/semicolon.yml @@ -0,0 +1,10 @@ +id: semicolon-1 +language: r +severity: warning +rule: + regex: ;\s+$ + not: + inside: + kind: string + stopBy: end +message: Trailing semicolons are not needed. diff --git a/flir/rules/builtin/seq.yml b/flir/rules/builtin/seq.yml new file mode 100644 index 0000000..c199c5d --- /dev/null +++ b/flir/rules/builtin/seq.yml @@ -0,0 +1,121 @@ +id: seq-1 +language: r +severity: warning +rule: + pattern: seq(length($VAR)) +fix: seq_along(~~VAR~~) +message: | + seq(length(...)) is likely to be wrong in the empty edge case. Use seq_along(...) instead. + +--- + +id: seq-2 +language: r +severity: warning +rule: + any: + - pattern: 1:nrow($VAR) + - pattern: 1L:nrow($VAR) + regex: ^1 +fix: seq_len(nrow(~~VAR~~)) +message: | + 1:nrow(...) is likely to be wrong in the empty edge case. Use seq_len(nrow(...)) instead. + +--- + +id: seq-3 +language: r +severity: warning +rule: + any: + - pattern: 1:n() + - pattern: 1L:n() + regex: ^1 +fix: seq_len(n()) +message: | + 1:n() is likely to be wrong in the empty edge case. Use seq_len(n()) instead. + +--- + +id: seq-4 +language: r +severity: warning +rule: + pattern: seq(nrow($VAR)) +fix: seq_len(nrow(~~VAR~~)) +message: | + seq(nrow(...)) is likely to be wrong in the empty edge case. Use seq_len(nrow(...)) instead. + +--- + +id: seq-5 +language: r +severity: warning +rule: + any: + - pattern: 1:length($VAR) + - pattern: 1L:length($VAR) + regex: ^1 +fix: seq_along(~~VAR~~) +message: | + 1:length(...) is likely to be wrong in the empty edge case. Use seq_along(...) instead. + +--- + +id: seq-6 +language: r +severity: warning +rule: + any: + - pattern: 1:ncol($VAR) + - pattern: 1L:ncol($VAR) + regex: ^1 +fix: seq_len(ncol(~~VAR~~)) +message: | + 1:ncol(...) is likely to be wrong in the empty edge case. Use seq_len(ncol(...)) instead. + +--- + +id: seq-7 +language: r +severity: warning +rule: + any: + - pattern: 1:NCOL($VAR) + - pattern: 1L:NCOL($VAR) + regex: ^1 +fix: seq_len(NCOL(~~VAR~~)) +message: | + 1:NCOL(...) is likely to be wrong in the empty edge case. Use seq_len(NCOL(...)) instead. + +--- + +id: seq-8 +language: r +severity: warning +rule: + any: + - pattern: 1:NROW($VAR) + - pattern: 1L:NROW($VAR) + regex: ^1 +fix: seq_len(NROW(~~VAR~~)) +message: | + 1:NROW(...) is likely to be wrong in the empty edge case. Use seq_len(NROW(...)) instead. + + +--- + +id: seq-9 +language: r +severity: warning +rule: + pattern: seq(1, $VAL) + not: + pattern: seq(1, 0) +constraints: + VAL: + regex: ^\d+(|L)$ +fix: seq_len(~~VAL~~) +message: seq_len(~~VAL~~) is more efficient than seq(1, ~~VAL~~). + + diff --git a/flir/rules/builtin/sort.yml b/flir/rules/builtin/sort.yml new file mode 100644 index 0000000..930f5c6 --- /dev/null +++ b/flir/rules/builtin/sort.yml @@ -0,0 +1,85 @@ +id: sort-1 +language: r +severity: warning +rule: + pattern: $OBJ[order($OBJ)] +fix: sort(~~OBJ~~, na.last = TRUE) +message: sort(~~OBJ~~, na.last = TRUE) is better than ~~OBJ~~[order(~~OBJ~~)]. + +--- + +id: sort-2 +language: r +severity: warning +rule: + any: + - pattern: $OBJ[order($OBJ, decreasing = $DECREASING)] + - pattern: $OBJ[order(decreasing = $DECREASING, $OBJ)] +constraints: + DECREASING: + regex: ^(TRUE|FALSE)$ +fix: sort(~~OBJ~~, decreasing = ~~DECREASING~~, na.last = TRUE) +message: | + sort(~~OBJ~~, decreasing = ~~DECREASING~~, na.last = TRUE) is better than + ~~OBJ~~[order(~~OBJ~~, decreasing = ~~DECREASING~~)]. + +--- + +id: sort-3 +language: r +severity: warning +rule: + any: + - pattern: $OBJ[order($OBJ, na.last = $NALAST)] + - pattern: $OBJ[order(na.last = $NALAST, $OBJ)] +constraints: + NALAST: + regex: ^(TRUE|FALSE)$ +fix: sort(~~OBJ~~, na.last = ~~NALAST~~, na.last = TRUE) +message: | + sort(~~OBJ~~, na.last = ~~NALAST~~, na.last = TRUE) is better than + ~~OBJ~~[order(~~OBJ~~, na.last = ~~NALAST~~)]. + +--- + +id: sort-4 +language: r +severity: warning +rule: + any: + - pattern: $OBJ[order($OBJ, decreasing = TRUE, na.last = FALSE)] + - pattern: $OBJ[order($OBJ, na.last = FALSE, decreasing = TRUE)] + - pattern: $OBJ[order(decreasing = TRUE, $OBJ, na.last = FALSE)] + - pattern: $OBJ[order(decreasing = TRUE, na.last = FALSE, $OBJ)] + - pattern: $OBJ[order(na.last = FALSE, decreasing = TRUE, $OBJ)] + - pattern: $OBJ[order(na.last = FALSE, $OBJ, decreasing = TRUE)] +fix: sort(~~OBJ~~, decreasing = TRUE, na.last = FALSE) +message: | + sort(~~OBJ~~, decreasing = TRUE, na.last = FALSE) is better than + ~~OBJ~~[order(~~OBJ~~, na.last = FALSE, decreasing = TRUE)]. + +--- + +id: sort-5 +language: r +severity: warning +rule: + any: + - pattern: sort($OBJ) == $OBJ + - pattern: $OBJ == sort($OBJ) +fix: !is.unsorted(~~OBJ~~) +message: | + Use !is.unsorted(~~OBJ~~) to test the sortedness of a vector. + +--- + +id: sort-6 +language: r +severity: warning +rule: + any: + - pattern: sort($OBJ) != $OBJ + - pattern: $OBJ != sort($OBJ) +fix: is.unsorted(~~OBJ~~) +message: | + Use is.unsorted(~~OBJ~~) to test the unsortedness of a vector. diff --git a/flir/rules/builtin/stopifnot_all.yml b/flir/rules/builtin/stopifnot_all.yml new file mode 100644 index 0000000..6f6619b --- /dev/null +++ b/flir/rules/builtin/stopifnot_all.yml @@ -0,0 +1,24 @@ +id: stopifnot_all-1 +language: r +severity: warning +rule: + pattern: stopifnot(all($$$CODE)) +fix: stopifnot(~~CODE~~) +message: | + Use stopifnot(x) instead of stopifnot(all(x)). stopifnot(x) runs all() 'under + the hood' and provides a better error message in case of failure. + +--- + +id: stopifnot_all-2 +language: r +severity: warning +rule: + pattern: stopifnot(exprs = { all($$$CODE) }) +fix: | + stopifnot(exprs = { + ~~CODE~~ + }) +message: | + Use stopifnot(x) instead of stopifnot(all(x)). stopifnot(x) runs all() 'under + the hood' and provides a better error message in case of failure. diff --git a/flir/rules/builtin/todo_comment.yml b/flir/rules/builtin/todo_comment.yml new file mode 100644 index 0000000..83d86ed --- /dev/null +++ b/flir/rules/builtin/todo_comment.yml @@ -0,0 +1,7 @@ +id: todo_comment-1 +language: r +severity: warning +rule: + kind: comment + regex: '(?i)#(|\s+)\b(todo|fixme)\b' +message: Remove TODO comments. diff --git a/flir/rules/builtin/undesirable_function.yml b/flir/rules/builtin/undesirable_function.yml new file mode 100644 index 0000000..c9b1756 --- /dev/null +++ b/flir/rules/builtin/undesirable_function.yml @@ -0,0 +1,13 @@ +id: undesirable_function-1 +language: r +severity: warning +rule: + pattern: $FUN + kind: identifier + not: + inside: + kind: argument +constraints: + FUN: + regex: ^(\.libPaths|attach|browser|debug|debugcall|debugonce|detach|par|setwd|structure|Sys\.setenv|Sys\.setlocale|trace|undebug|untrace)$ +message: Function "~~FUN~~()" is undesirable. diff --git a/flir/rules/builtin/undesirable_operator.yml b/flir/rules/builtin/undesirable_operator.yml new file mode 100644 index 0000000..7d63513 --- /dev/null +++ b/flir/rules/builtin/undesirable_operator.yml @@ -0,0 +1,29 @@ +id: undesirable_operator-1 +language: r +severity: warning +rule: + any: + - pattern: $X <<- $Y + - pattern: $X ->> $Y +message: | + Avoid undesirable operators `<<-` and `->>`. They assign outside the current + environment in a way that can be hard to reason about. Prefer fully-encapsulated + functions wherever possible, or, if necessary, assign to a specific environment + with assign(). Recall that you can create an environment at the desired scope + with new.env(). + +--- + +id: undesirable_operator-2 +language: r +severity: warning +rule: + kind: namespace_operator + has: + pattern: ':::' +message: | + Operator `:::` is undesirable. It accesses non-exported functions inside + packages. Code relying on these is likely to break in future versions of the + package because the functions are not part of the public interface and may be + changed or removed by the maintainers without notice. Use public functions + via :: instead. diff --git a/flir/rules/builtin/unnecessary_nesting.yml b/flir/rules/builtin/unnecessary_nesting.yml new file mode 100644 index 0000000..b56b467 --- /dev/null +++ b/flir/rules/builtin/unnecessary_nesting.yml @@ -0,0 +1,36 @@ +id: unnecessary_nesting-1 +language: r +severity: warning +rule: + kind: if_statement + any: + - has: + kind: 'braced_expression' + field: consequence + has: + kind: if_statement + stopBy: neighbor + not: + has: + kind: 'braced_expression' + field: alternative + stopBy: end + not: + any: + - has: + nthChild: 2 + - precedes: + regex: "^else$" + - has: + kind: if_statement + field: consequence + stopBy: neighbor + # Can be in if(), but not else if() + not: + inside: + field: alternative + kind: if_statement +message: | + Don't use nested `if` statements, where a single `if` with the combined + conditional expression will do. For example, instead of `if (x) { if (y) { ... }}`, + use `if (x && y) { ... }`. diff --git a/flir/rules/builtin/unreachable_code.yml b/flir/rules/builtin/unreachable_code.yml new file mode 100644 index 0000000..56eb497 --- /dev/null +++ b/flir/rules/builtin/unreachable_code.yml @@ -0,0 +1,64 @@ +id: unreachable_code-1 +language: r +severity: warning +rule: + regex: '[^}]+' + not: + regex: 'else' + follows: + any: + - pattern: return($$$A) + - pattern: stop($$$A) + not: + precedes: + regex: 'else' + stopBy: end +message: Code and comments coming after a return() or stop() should be removed. + +--- + +id: unreachable_code-2 +language: r +severity: warning +rule: + regex: '[^}]+' + not: + regex: 'else' + follows: + any: + - pattern: next + - pattern: break + stopBy: end +message: Remove code and comments coming after `next` or `break` + +--- + +id: unreachable_code-3 +language: r +severity: warning +rule: + inside: + any: + - kind: if_statement + pattern: if (FALSE) + - kind: while_statement + pattern: while (FALSE) + stopBy: end +message: Remove code inside a conditional loop with a deterministically false condition. + +--- + +id: unreachable_code-4 +language: r +severity: warning +rule: + inside: + any: + - kind: if_statement + pattern: if (TRUE) + - kind: while_statement + pattern: while (TRUE) + stopBy: end +message: | + One branch has a a deterministically true condition. The other branches can + be removed. diff --git a/flir/rules/builtin/which_grepl.yml b/flir/rules/builtin/which_grepl.yml new file mode 100644 index 0000000..81e30f2 --- /dev/null +++ b/flir/rules/builtin/which_grepl.yml @@ -0,0 +1,7 @@ +id: which_grepl-1 +language: r +severity: warning +rule: + pattern: which(grepl($$$ARGS)) +fix: grep(~~ARGS~~) +message: grep(pattern, x) is better than which(grepl(pattern, x)). diff --git a/getCRUCLdata.Rproj b/getCRUCLdata.Rproj new file mode 100644 index 0000000..25074f7 --- /dev/null +++ b/getCRUCLdata.Rproj @@ -0,0 +1,21 @@ +Version: 1.0 +ProjectId: b876aac1-663c-4e95-b4b7-a129e578fd9b + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source

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 From f147d80ffef1ec2558807d8dc048287b9168557a Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sun, 15 Dec 2024 17:35:56 +0800 Subject: [PATCH 02/60] update codemeta.json --- codemeta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codemeta.json b/codemeta.json index 9abb12b..e5b60fa 100644 --- a/codemeta.json +++ b/codemeta.json @@ -243,7 +243,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "800.224KB", + "fileSize": "909.623KB", "citation": [ { "@type": "ScholarlyArticle", From e1ba872f11c346aa255aa025155c2e307b93cecb Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sun, 15 Dec 2024 17:39:01 +0800 Subject: [PATCH 03/60] prep for v1.0.2 --- DESCRIPTION | 2 +- NEWS.md | 6 ++++++ codemeta.json | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index be8761e..6a7cadb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: getCRUCLdata Title: 'CRU' 'CL' v. 2.0 Climatology Client -Version: 1.0.1 +Version: 1.0.2 Authors@R: person("Adam H.", "Sparks", , "adamhsparks@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0061-8359")) diff --git a/NEWS.md b/NEWS.md index ef21644..edffac6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# getCRUCLdata 1.0.2 + +## Minor changes + +- Reknit vignette with proper values + # getCRUCLdata 1.0.1 ## Minor changes diff --git a/codemeta.json b/codemeta.json index e5b60fa..bcc649d 100644 --- a/codemeta.json +++ b/codemeta.json @@ -7,7 +7,7 @@ "codeRepository": "https://github.com/ropensci/getCRUCLdata", "issueTracker": "https://github.com/ropensci/getCRUCLdata/issues", "license": "https://spdx.org/licenses/MIT", - "version": "1.0.1", + "version": "1.0.2", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", @@ -243,7 +243,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "909.623KB", + "fileSize": "909.701KB", "citation": [ { "@type": "ScholarlyArticle", From b59c0bfbb0259bad763fa07690e42dfb606d5513 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Sun, 15 Dec 2024 17:56:32 +0800 Subject: [PATCH 04/60] Add link to repo in DESCRIPTION --- DESCRIPTION | 7 ++++--- codemeta.json | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6a7cadb..9fa85c8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,8 @@ Description: Provides functions that automate downloading and importing Climate Research Unit, . License: MIT + file LICENSE -URL: https://docs.ropensci.org/getCRUCLdata/ +URL: https://github.com/ropensci/getCRUCLdata, + https://docs.ropensci.org/getCRUCLdata/ BugReports: https://github.com/ropensci/getCRUCLdata/issues Depends: R (>= 4.0.0) @@ -43,6 +44,8 @@ Suggests: VignetteBuilder: knitr ByteCompile: TRUE +Config/roxyglobals/filename: globals.R +Config/roxyglobals/unique: FALSE Config/testthat/edition: 3 Config/testthat/parallel: true Encoding: UTF-8 @@ -55,5 +58,3 @@ X-schema.org-isPartOf: https://ropensci.org X-schema.org-keywords: anglia-cru, climate-data, cru-cl2, temperature, rainfall, elevation, data-access, wind, relative-humidity, solar-radiation, diurnal-temperature, frost -Config/roxyglobals/filename: globals.R -Config/roxyglobals/unique: FALSE diff --git a/codemeta.json b/codemeta.json index bcc649d..0eb1901 100644 --- a/codemeta.json +++ b/codemeta.json @@ -4,6 +4,7 @@ "identifier": "getCRUCLdata", "description": "Provides functions that automate downloading and importing University of East Anglia Climate Research Unit ('CRU') 'CL' v. 2.0 climatology data, facilitates the calculation of minimum temperature and maximum temperature and formats the data into a data frame or a list of 'terra' 'rast' objects for use. 'CRU' 'CL' v. 2.0 data are a gridded climatology of 1961-1990 monthly means released in 2002 and cover all land areas (excluding Antarctica) at 10 arc minutes (0.1666667 degree) resolution. For more information see the description of the data provided by the University of East Anglia Climate Research Unit, .", "name": "getCRUCLdata: 'CRU' 'CL' v. 2.0 Climatology Client", + "relatedLink": "https://docs.ropensci.org/getCRUCLdata/", "codeRepository": "https://github.com/ropensci/getCRUCLdata", "issueTracker": "https://github.com/ropensci/getCRUCLdata/issues", "license": "https://spdx.org/licenses/MIT", @@ -243,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "909.701KB", + "fileSize": "909.747KB", "citation": [ { "@type": "ScholarlyArticle", @@ -273,7 +274,6 @@ } } ], - "relatedLink": "https://docs.ropensci.org/getCRUCLdata/", "releaseNotes": "https://github.com/ropensci/getCRUCLdata/blob/master/NEWS.md", "readme": "https://github.com/ropensci/getCRUCLdata/blob/main/README.md", "contIntegration": ["https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml", "https://app.codecov.io/gh/ropensci/getCRUCLdata"], From 50eab86c13bb4a14747ba54914f0d312f26725b3 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 16 Dec 2024 18:12:54 +0800 Subject: [PATCH 05/60] Update documentation --- man/getCRUCLdata-package.Rd | 1 + 1 file changed, 1 insertion(+) diff --git a/man/getCRUCLdata-package.Rd b/man/getCRUCLdata-package.Rd index 275c873..ec5cf3c 100644 --- a/man/getCRUCLdata-package.Rd +++ b/man/getCRUCLdata-package.Rd @@ -11,6 +11,7 @@ Provides functions that automate downloading and importing University of East An \seealso{ Useful links: \itemize{ + \item \url{https://github.com/ropensci/getCRUCLdata} \item \url{https://docs.ropensci.org/getCRUCLdata/} \item Report bugs at \url{https://github.com/ropensci/getCRUCLdata/issues} } From 51a2d66bde16731d5e2f0f7696c52a608bf74559 Mon Sep 17 00:00:00 2001 From: "Adam H. Sparks" Date: Mon, 16 Dec 2024 19:13:19 +0800 Subject: [PATCH 06/60] Polish vignette --- codemeta.json | 4 ++-- vignettes/getCRUCLdata.Rmd | 30 ++++++++++++++---------------- vignettes/getCRUCLdata.Rmd.orig | 18 ++++++++++-------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/codemeta.json b/codemeta.json index 0eb1901..f9f5622 100644 --- a/codemeta.json +++ b/codemeta.json @@ -244,7 +244,7 @@ "applicationCategory": "Tools", "isPartOf": "https://ropensci.org", "keywords": ["anglia-cru", "climate-data", "cru-cl2", "temperature", "rainfall", "elevation", "data-access", "wind", "relative-humidity", "solar-radiation", "diurnal-temperature", "frost", "cru", "r", "rstats", "r-package", "peer-reviewed"], - "fileSize": "909.747KB", + "fileSize": "910.679KB", "citation": [ { "@type": "ScholarlyArticle", @@ -276,7 +276,7 @@ ], "releaseNotes": "https://github.com/ropensci/getCRUCLdata/blob/master/NEWS.md", "readme": "https://github.com/ropensci/getCRUCLdata/blob/main/README.md", - "contIntegration": ["https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml", "https://app.codecov.io/gh/ropensci/getCRUCLdata"], + "contIntegration": ["https://github.com/ropensci/getCRUCLdata/actions/workflows/R-CMD-check.yaml", "https://codecov.io/gh/ropensci/getCRUCLdata"], "developmentStatus": "https://www.repostatus.org/", "review": { "@type": "Review", diff --git a/vignettes/getCRUCLdata.Rmd b/vignettes/getCRUCLdata.Rmd index f5a13ff..659f467 100644 --- a/vignettes/getCRUCLdata.Rmd +++ b/vignettes/getCRUCLdata.Rmd @@ -1,7 +1,7 @@ --- title: "getCRUCLdata" author: "Adam H. Sparks" -date: "2024-12-15" +date: "2024-12-16" output: rmarkdown::html_vignette: toc: true @@ -12,6 +12,7 @@ vignette: > %\VignetteDepends{terra} %\VignetteDepends{ggplot2} %\VignetteDepends{viridis} + %\VignetteDepends{data.table} --- @@ -64,7 +65,7 @@ The arguments for selecting the climatology elements for importing are: - **dsn** *For `create_CRU_stack()`* and *`create_CRU_df()`* only. Local file path where CRU CL v. 2.0 .dat.gz files are located. -### Creating tidy data frames for use in R +### Creating data frames for use in R The `get_CRU_df()` function automates the download process and creates data frames of the climatology elements. @@ -114,7 +115,7 @@ CRU_data #> 6795150: -35.80 ``` -Perhaps you only need one or two elements, it is easy to create a tidy data frame of mean temperature only. +Perhaps you only need one or two elements, it is easy to create a data frame of mean temperature only. ``` r @@ -136,7 +137,7 @@ t #> 6795144: 83.583 -36.750 dec -33.3 ``` -#### Plotting data from the tidy dataframe +#### Plotting data from the data frame Now that we have the data, we can plot it easily using _ggplot2_ and the _viridis_ package for the colour scale. @@ -154,8 +155,8 @@ ggplot(data = t, aes(x = lon, y = lat, fill = tmp)) + ```