Skip to content

Commit ccb1cac

Browse files
committed
Update ScriptLocation + Small fixes
1 parent 2bcd777 commit ccb1cac

13 files changed

+189
-133
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Package: IASDT.R
33
Title: Modelling the distribution of invasive alien plant species in
44
Europe
55
Version: 0.1.03
6-
Date: 2025-03-13
6+
Date: 2025-03-14
77
Authors@R:
88
person("Ahmed", "El-Gabbas", , "ahmed.el-gabbas@ufz.de", role = c("aut", "cre"),
99
comment = c(ORCID = "0000-0003-2225-088X"))

R/General_CatTime.R

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ CatTime <- function(
5656
AllArgs,
5757
function(x) get(x, envir = parent.env(env = environment()))) %>%
5858
stats::setNames(AllArgs)
59-
IASDT.R::CheckArgs(
60-
AllArgs = AllArgs, Type = "character", Args = "Text")
6159
IASDT.R::CheckArgs(
6260
AllArgs = AllArgs, Type = "logical",
6361
Args = c("Time", "Bold", "Red", "Date"))

R/General_Package_RemoteSha.R

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,58 @@
22
# Package_RemoteSha ----
33
## |------------------------------------------------------------------------| #
44

5-
#' Get the remote SHA of an R packages
5+
#' Get the remote SHA of R packages
66
#'
77
#' This function retrieves the remote SHA (Secure Hash Algorithm) reference for
8-
#' one or more specified R packages. It is useful for tracking the exact version
9-
#' of a package's source code.
8+
#' one or more specified R packages from their remote repositories. The SHA
9+
#' uniquely identifies the version of a package's source code, useful for
10+
#' reproducibility and version tracking.
11+
#'
1012
#' @name Package_RemoteSha
11-
#' @param ... Character. Names of one or more R packages for which to retrieve
12-
#' the remote SHA.
13+
#' @param ... Character. Names of one or more R packages (quoted or unquoted)
14+
#' for which to retrieve the remote SHA.
1315
#' @return A named character vector where names are the package names and values
14-
#' are the corresponding remote SHAs.
16+
#' are the corresponding remote SHAs. If a package is not found or has no
17+
#' remote SHA, the value will be `NA`.
1518
#' @export
1619
#' @author Ahmed El-Gabbas
20+
#' @details The function uses `pak::lib_status()` to query the status of
21+
#' installed packages and extract their remote SHAs. It supports packages
22+
#' installed from GitHub, GitLab, or other remote sources via `pak`. If a
23+
#' package is installed from CRAN or locally without a remote SHA, the result
24+
#' will be `NA`.
1725
#' @examples
18-
#' Package_RemoteSha(IASDT.R, devtools)
26+
#' Package_RemoteSha(Hmsc, IASDT.R, "nonexistent")
1927

2028
Package_RemoteSha <- function(...) {
2129

22-
Pk <- rlang::ensyms(...) %>%
30+
# Capture package names as symbols and convert to character strings
31+
Pk <- rlang::ensyms(...) %>%
2332
purrr::map_chr(.f = rlang::as_string)
2433

34+
# Retrieve library status once for efficiency and map over packages
35+
lib_status <- IASDT.R::AddMissingCols(
36+
pak::lib_status(), NA_character_, "remotesha")
37+
2538
Out <- purrr::map_chr(
2639
.x = Pk,
2740
.f = ~{
28-
pak::lib_status() %>%
29-
dplyr::filter(package == .x) %>%
41+
42+
# Filter library status for the current package
43+
sha <- dplyr::filter(lib_status, package == .x) %>%
3044
dplyr::pull("remotesha")
45+
46+
# Return the SHA if found, otherwise NA
47+
if (length(sha) > 0) {
48+
sha
49+
} else {
50+
NA_character_
51+
}
52+
3153
}) %>%
54+
# Name the output vector with package names
3255
stats::setNames(Pk)
3356

57+
# Return the named vector of SHAs
3458
return(Out)
3559
}

R/General_ScriptLocation.R

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,102 @@
11
## |------------------------------------------------------------------------| #
22
# ScriptLocation ----
33
## |------------------------------------------------------------------------| #
4-
#
4+
55
#' Retrieve the location of the current R script.
66
#'
7-
#' This function attempts to find the location of the currently running R
8-
#' script. It first tries to identify the script's location based on the command
9-
#' line arguments used to start the script. If the script is being run in an
10-
#' interactive session within RStudio, it falls back to using the `rstudioapi`
11-
#' to find the file path of the script in the source editor. If the location
12-
#' cannot be determined, it returns `NA`.
7+
#' This function determines the file path of the currently executing R script.
8+
#' It checks command line arguments (e.g., via `Rscript`) for the script path,
9+
#' then in interactive sessions, it examines the call stack for the most
10+
#' recently sourced file, falling back to `rstudioapi` (if available and RStudio
11+
#' is running) when no sourcing context exists. If the location cannot be
12+
#' determined, it returns `NA`.
13+
#'
1314
#' @return A character string representing the file path of the current R
14-
#' script, or `NA` if the path cannot be determined.
15+
#' script, or `NA_character_` if the path cannot be determined (e.g., in an
16+
#' unsourced interactive session without a script context).
17+
#'
18+
#' @details The function follows this priority order:
19+
#' - Command line arguments (`--file`) when executed via `Rscript`.
20+
#' - The most recent `ofile` attribute from the call stack when sourced
21+
#' interactively in any R environment, supporting nested sourcing scenarios.
22+
#' - RStudio's active editor context via `rstudioapi` if available, RStudio is
23+
#' running, and no sourcing context is found.
24+
#' - Returns `NA_character_` for unsourced interactive sessions or
25+
#' non-interactive execution without a script path.
26+
#'
1527
#' @name ScriptLocation
16-
#' @source The source code of this function was taken from this
28+
#' @source The source code of this function was adapted from this
1729
#' [stackoverflow](https://stackoverflow.com/questions/47044068/) question.
1830
#' @importFrom rlang .data
1931
#' @export
2032
#' @examples
21-
#' # ScriptLocation()
33+
#' \dontrun{
34+
#' # Save as "myscript.R": ScriptLocation()
35+
#' # Run: Rscript myscript.R
36+
#' # Output: [1] "myscript.R" (or full path depending on Rscript invocation)
37+
#' }
2238

2339
ScriptLocation <- function() {
40+
# Attempt to extract the script path from command line arguments (e.g.,
41+
# Rscript)
2442
this_file <- commandArgs() %>%
43+
# Convert to a tibble with a single column 'value'
2544
tibble::enframe(name = NULL) %>%
45+
# Split each argument at '=' into 'key' and 'value'
2646
tidyr::separate(
27-
col = .data$value, into = c("key", "value"), sep = "=",
28-
fill = "right") %>%
47+
col = .data$value, into = c("key", "value"),
48+
sep = "=", fill = "right") %>%
49+
# Keep only the '--file' argument
2950
dplyr::filter(.data$key == "--file") %>%
51+
# Extract the value (file path)
3052
dplyr::pull(.data$value)
3153

32-
if (length(this_file) == 0) {
33-
this_file <- rstudioapi::getSourceEditorContext()$path
54+
if (length(this_file) > 0) {
55+
# If a command-line file path is found (e.g., from Rscript), use it. This
56+
# handles cases like 'Rscript myscript.R'
57+
this_file <- this_file
58+
} else if (interactive()) {
59+
# If running interactively (R console, RStudio, etc.), check the call stack
60+
# for sourced script paths
61+
frame_files <- lapply(
62+
X = sys.frames(),
63+
FUN = function(x) {
64+
# For each frame, check if 'ofile' exists (set by source()) and retrieve
65+
# it
66+
if (exists("ofile", envir = x)) {
67+
get("ofile", envir = x)
68+
} else {
69+
NULL
70+
}
71+
})
72+
73+
# Flatten the list, removing NULLs
74+
valid_files <- unlist(frame_files)
75+
if (length(valid_files) > 0 && any(nzchar(valid_files))) {
76+
# If valid file paths are found, take the most recent one (last in stack).
77+
# This ensures nested sourcing returns the innermost script (e.g., TT2.R)
78+
this_file <- utils::tail(valid_files[nzchar(valid_files)], 1)
79+
} else if (requireNamespace("rstudioapi", quietly = TRUE) &&
80+
rstudioapi::isAvailable()) {
81+
# If no sourced files are found and RStudio is available, use the active
82+
# editor context as a fallback (useful for unsourced code in RStudio)
83+
this_file <- tryCatch(
84+
# Get path of active script in RStudio
85+
rstudioapi::getSourceEditorContext()$path,
86+
# Return NA if RStudio call fails
87+
error = function(e) NA_character_)
88+
} else {
89+
# No sourced files and not in RStudio: return NA (e.g., console without
90+
# source)
91+
this_file <- NA_character_
92+
}
3493
} else {
94+
# Non-interactive session without command-line args (unlikely case): return
95+
# NA
3596
this_file <- NA_character_
3697
}
3798

99+
# Return the determined file path or NA
38100
return(this_file)
101+
39102
}

R/General_git_log.R

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232
#' @author Ahmed El-Gabbas
3333
#' @export
3434
#' @examples
35-
#' # not a git repo
36-
#' git_log(Path = "C:/")
37-
#'
3835
#' # Show the most recent commit
3936
#' git_log(Num = 1)
4037
#'
@@ -47,6 +44,12 @@
4744
#' length(Log)
4845
#'
4946
#' head(Log, 8)
47+
#'
48+
#' \dontrun{
49+
#' # not a git repo
50+
#' git_log(Path = "C:/")
51+
#' # #> Error: The provided path does not exist.
52+
#' }
5053

5154
git_log <- function(Path = ".", Num = NULL, ReturnLog = FALSE) {
5255

R/Mod_GetCV.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Mod_GetCV <- function(
130130
# # 1. CV using large blocks -----
131131
# # |||||||||||||||||||||||||||||||||||
132132

133-
IASDT.R::CatTime("1. CV_Large", Level = 1)
133+
IASDT.R::CatTime("1. CV_Large", Level = 1, Time = FALSE)
134134
CV_Large <- blockCV::cv_spatial(
135135
x = XY_sf, r = DT_R, hexagon = FALSE, iteration = 1000, k = CV_NFolds,
136136
rows_cols = c(CV_NR, CV_NC), plot = FALSE, progress = FALSE, report = FALSE)
@@ -139,7 +139,7 @@ Mod_GetCV <- function(
139139
# # 2. CV based on number of grid cells -----
140140
# # |||||||||||||||||||||||||||||||||||
141141

142-
IASDT.R::CatTime("2. CV_Dist", Level = 1)
142+
IASDT.R::CatTime("2. CV_Dist", Level = 1, Time = FALSE)
143143
CV_Dist <- blockCV::cv_spatial(
144144
x = XY_sf, r = DT_R, hexagon = FALSE, iteration = 1000, k = CV_NFolds,
145145
size = CV_NGrids * raster::res(DT_R)[1], plot = FALSE, progress = FALSE,

R/Mod_Prep4HPC.R

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -148,39 +148,6 @@
148148
#' @order 1
149149
#' @importFrom rlang .data
150150
#' @author Ahmed El-Gabbas
151-
#' @details The current models are fitted for 8 habitat types see [Pysek et
152-
#' al.](https://doi.org/10.23855/preslia.2022.447):
153-
#' - **1. Forests** -- closed vegetation dominated by deciduous or evergreen
154-
#' trees
155-
#' - **2. Open forests** -- woodlands with canopy openings created by
156-
#' environmental stress or disturbance, including forest edges
157-
#' - **3. Scrub** -- shrublands maintained by environmental stress (aridity) or
158-
#' disturbance
159-
#' - **4a. Natural grasslands** -- grasslands maintained by climate (aridity,
160-
#' unevenly distributed precipitation), herbivores or environmental stress
161-
#' (aridity, instability or toxicity of substrate)
162-
#' - **4b. Human-maintained grasslands** -- grasslands dependent on regular
163-
#' human-induced management (mowing, grazing by livestock, artificial burning)
164-
#' - **10. Wetland** -- sites with the permanent or seasonal influence of
165-
#' moisture, ranging from oligotrophic to eutrophic
166-
#' - **12a. Ruderal habitats** -- anthropogenically disturbed or eutrophicated
167-
#' sites, where the anthropogenic disturbance or fertilization is typically a
168-
#' side-product and not the aim of the management
169-
#' - **12b. Agricultural habitats** -- synanthropic habitats directly
170-
#' associated with growing of agricultural products, thus dependent on
171-
#' specific type of management (ploughing, fertilization)
172-
#'
173-
#' <br/>The following habitat types are excluded from the analysis:
174-
#' - **5. Sandy** -- dunes and other habitats on unstable sandy substrate,
175-
#' stressed by low nutrients, drought and disturbed by sand movement
176-
#' - **6. Rocky** -- cliffs and rock outcrops with very shallow or no soil
177-
#' - **7. Dryland** -- habitats in which drought stress limits vegetation
178-
#' development
179-
#' - **8. Saline** -- habitats stressed by high soil salinity
180-
#' - **9. Riparian** -- a mosaic of wetlands, grasslands, tall-forb stands,
181-
#' scrub and open forests in stream corridors
182-
#' - **11. Aquatic** -- water bodies and streams with submerged and floating
183-
#' plant species
184151

185152
Mod_Prep4HPC <- function(
186153
Hab_Abb = NULL, DirName = NULL,
@@ -649,9 +616,9 @@ Mod_Prep4HPC <- function(
649616
IASDT.R::CatTime("Response - Y matrix")
650617
DT_y <- dplyr::select(DT_All, tidyselect::starts_with("Sp_")) %>%
651618
as.data.frame()
652-
IASDT.R::CatTime(paste0(ncol(DT_y), " species"), Level = 1)
619+
IASDT.R::CatTime(paste0(ncol(DT_y), " species"), Level = 1, Time = FALSE)
653620

654-
IASDT.R::CatTime("Save species summary", Level = 1)
621+
IASDT.R::CatTime("Save species summary", Level = 1, Time = FALSE)
655622
SpSummary <- IASDT.R::Path(Path_PA, "Sp_PA_Summary_DF.RData")
656623
if (!file.exists(SpSummary)) {
657624
stop(SpSummary, " file does not exist", call. = FALSE)
@@ -682,22 +649,25 @@ Mod_Prep4HPC <- function(
682649
IASDT.R::CatTime(
683650
paste0(
684651
"Models will be fitted using ", length(XVars), " predictors: ",
685-
paste(XVars, collapse = " + ")), Level = 1)
652+
paste(XVars, collapse = " + ")), Level = 1, Time = FALSE)
686653
} else {
687654
OnlyLinear <- setdiff(XVars, QuadraticVars)
688655
FormVars <- c(
689656
OnlyLinear,
690657
paste0("stats::poly(", QuadraticVars, ", degree = 2, raw = TRUE)"))
691658

692-
IASDT.R::CatTime("Models will be fitted using:", Level = 1)
659+
IASDT.R::CatTime("Models will be fitted using:", Level = 1, Time = FALSE)
693660

694-
IASDT.R::CatTime(paste0(length(OnlyLinear), " linear effect: "), Level = 2)
695-
IASDT.R::CatTime(paste(OnlyLinear, collapse = " + "), Level = 3)
661+
IASDT.R::CatTime(
662+
paste0(length(OnlyLinear), " linear effect: "), Level = 2, Time = FALSE)
663+
IASDT.R::CatTime(
664+
paste(OnlyLinear, collapse = " + "), Level = 3, Time = FALSE)
696665

697666
IASDT.R::CatTime(
698667
paste0(length(QuadraticVars), " linear and quadratic effects: "),
699668
Level = 2)
700-
IASDT.R::CatTime(paste(QuadraticVars, collapse = " + "), Level = 3)
669+
IASDT.R::CatTime(
670+
paste(QuadraticVars, collapse = " + "), Level = 3, Time = FALSE)
701671

702672
}
703673

@@ -738,7 +708,7 @@ Mod_Prep4HPC <- function(
738708

739709
IASDT.R::CatTime(
740710
paste0("Models will be fitted using ", paste(Tree, collapse = " & ")),
741-
Level = 1)
711+
Level = 1, Time = FALSE)
742712

743713
## # ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
744714

@@ -763,7 +733,7 @@ Mod_Prep4HPC <- function(
763733

764734
IASDT.R::CatTime(
765735
paste0("Prepare working on parallel using ", NCores_GPP, " cores."),
766-
Level = 1)
736+
Level = 2, Time = FALSE)
767737

768738
withr::local_options(
769739
future.globals.maxSize = 8000 * 1024^2, future.gc = TRUE,
@@ -792,7 +762,7 @@ Mod_Prep4HPC <- function(
792762

793763
} else {
794764

795-
IASDT.R::CatTime("Working sequentially")
765+
IASDT.R::CatTime("Working sequentially", Time = FALSE, Level = 2)
796766

797767
GPP_Knots <- purrr::map(
798768
.x = GPP_Dists * 1000,
@@ -1250,7 +1220,8 @@ Mod_Prep4HPC <- function(
12501220
IASDT.R::CatTime(
12511221
"Save model fitting commands for batch SLURM jobs", Level = 1)
12521222
IASDT.R::CatTime(
1253-
paste0("Models will be fitted in ", NSplits, " SLURM job(s)"), Level = 2)
1223+
paste0("Models will be fitted in ", NSplits, " SLURM job(s)"),
1224+
Level = 2, Time = FALSE)
12541225

12551226
purrr::walk(
12561227
.x = seq_len(NSplits),
@@ -1445,7 +1416,8 @@ Mod_Prep4HPC <- function(
14451416

14461417
## # ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
14471418

1448-
IASDT.R::CatDiff(InitTime = .StartTime)
1419+
IASDT.R::CatDiff(
1420+
Prefix = "Processing modelling data took ", InitTime = .StartTime)
14491421

14501422
return(invisible(NULL))
14511423
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ If you use the `IASDT.R` package, please cite it as:
7474
> <a href="https://biodt.eu" target="_blank">https://biodt.eu</a>.
7575
7676
<span style=" color: grey !important;">Last update:
77-
2025-03-13</span>
77+
2025-03-14</span>

inst/WORDLIST

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,6 @@ sbatch
212212
Warton
213213
unevaluated
214214
Unevaluated
215+
RStudio's
216+
RStudio
217+
unsourced

0 commit comments

Comments
 (0)