Skip to content

Commit 11e2f55

Browse files
committed
0.8.1: updates to freeview and qdecr_snap
1 parent 08ae63b commit 11e2f55

File tree

5 files changed

+197
-59
lines changed

5 files changed

+197
-59
lines changed

NEWS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
## New features
1010
* Added `cwp_thr` argument to `qdecr_fastlm` and `qdecr` to set the further cluster-wise p-value adjustment (default is 0.025 due to having 2 hemispheres, thus 0.05 / 2).
11-
* Automatically output two extra files: "significant_clusters.txt" (the output of `summary(vw, annot = TRUE)`) and "stack_names.txt" (the output of `stacks(vw)` and the corresponding stack numbers)
11+
* Automatically output two extra files: "significant_clusters.txt" (the output of `summary(vw, annot = TRUE)`) and "stack_names.txt" (the output of `stacks(vw)` and the corresponding stack numbers).
12+
* Modified `freeview` and `qdecr_snap`. The `mask` argument is now called `sig`. Furthermore, the ranges for the overlay colors are determined dynamically. Finally, users can now set any arguments to Freeview for manipulating surface files (see `freeview --help` on the command line).
1213

1314
# QDECR 0.8.0: Momo
1415

R/plotting.R

Lines changed: 140 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,123 @@
88
#'
99
#'@param vw The output object of a qdecr call (e.g. qdecr_fastlm)
1010
#'@param stack Either a numeric or a string for your variable (use `stacks(vw)`)
11-
#'@param mask Logical; if TRUE, only the significant clusters are shown
11+
#'@param type The type of map to plot (currently for OLS). Default is `coef`, others are `se`, `t` and `p`
12+
#'@param sig Logical; if TRUE (default), only the significant clusters are shown
13+
#'@param ... any arguments that freeview (on command line) normally takes for manipulating surface files
1214
#'@return NULL
1315
#'@export
1416

15-
freeview <- function(vw, stack = NULL, mask = TRUE) {
17+
freeview <- function(vw, stack = NULL, type = c("coef", "se", "t", "p"), sig = TRUE, ...) {
1618
if (is.null(stack)) stop("`stack` not defined. Please choose: ", paste(stacks(vw), collapse = ", "))
1719
if (length(stack) > 1) stop("More than 1 stack specified.")
1820
if(is.character(stack)) stack <- which(stacks(vw) == stack)
1921
if(is.null(stack) || stack > length(stacks(vw))) stop("specified `stack` is not present in this dataset. Please choose: ", paste(stacks(vw), collapse = ", "))
22+
type <- match.arg(type)
23+
empty_val <- if(type == "p") 1 else 0
24+
25+
read_fun <- switch(type,
26+
coef = qdecr_read_coef,
27+
se = qdecr_read_se,
28+
t = qdecr_read_t,
29+
p = qdecr_read_p)
2030

21-
temp_mgh <- qdecr_read_coef(vw, stack)
22-
if (mask) temp_mgh$x <- temp_mgh$x %MASK% qdecr_read_ocn_mask(vw, stack)
23-
if (all(temp_mgh$x == 0)) stop("Stack does not contain information (e.g. because of no significant findings), aborting plot.")
31+
temp_mgh <- read_fun(vw, stack)
32+
if (all(temp_mgh$x == empty_val)) stop("Stack does not contain information (e.g. because of no significant findings), aborting plot.")
33+
if (sig) {
34+
p_mgh <- qdecr_read_ocn_mask(vw, stack)
35+
temp_mgh$x[!p_mgh] <- empty_val
36+
if (all(temp_mgh$x == empty_val)) stop("No information in the stack passed the threshold (i.e. `p_thr` was set too strict), aborting plot.")
37+
}
38+
2439
temp_mgh_file <- paste0(vw$paths$dir_tmp2, ".stack", stack, ".temp_mgh.mgh")
2540
save.mgh(temp_mgh, temp_mgh_file)
2641
on.exit(file.remove(temp_mgh_file), add = TRUE)
2742

28-
cmdStr <- paste0("freeview --surface ", vw$paths$dir_subj, "/fsaverage/surf/", vw$input$hemi, ".inflated:overlay=", temp_mgh_file)
29-
system(cmdStr)
43+
surface <- paste0("--surface ", vw$paths$dir_subj, "/fsaverage/surf/", vw$input$hemi, ".inflated")
44+
45+
freeview_args <- list(...)
46+
freeview_args$surface <- surface
47+
freeview_args$overlay <- temp_mgh_file
48+
49+
if (is.null(freeview_args$overlay_method)) {
50+
freeview_args$overlay_method <- "linearopaque"
51+
temp_vals <- temp_mgh$x[temp_mgh$x != empty_val]
52+
freeview_args$overlay_threshold <- c(min(abs(temp_vals)), max(abs(temp_vals)))
53+
}
54+
55+
surf_cmd <- do.call(freeview_surf_cmd, freeview_args)
56+
cmd_str <- paste("freeview", surf_cmd)
57+
cat("Opening Freeview on the command line. Pop-up incoming.\nCall:", cmd_str, "\n")
58+
system(cmd_str)
3059

3160
invisible(NULL)
3261
}
3362

63+
freeview_surf_cmd <- function(surface,
64+
curvature = NULL,
65+
curvature_method = NULL,
66+
overlay = NULL,
67+
overlay_reg = NULL,
68+
overlay_method = NULL,
69+
overlay_color = NULL,
70+
overlay_threshold = NULL,
71+
overlay_frame = NULL,
72+
correlation = NULL,
73+
color = NULL,
74+
edgecolor = NULL,
75+
edgethickness = NULL,
76+
annot = NULL,
77+
annot_outline = NULL,
78+
name = NULL,
79+
offset = NULL,
80+
visible = NULL,
81+
vector = NULL,
82+
target_surf = NULL,
83+
label = NULL,
84+
label_outline = NULL,
85+
label_color = NULL,
86+
label_centroid = NULL,
87+
label_visible = NULL,
88+
spline = NULL,
89+
vertex = NULL,
90+
vertexcolor = NULL,
91+
goto = NULL,
92+
hide_in_3d = NULL,
93+
all = NULL) {
94+
string <- surface
95+
if(!is.null(curvature)) string <- paste0(string, ":curvature=", curvature)
96+
if(!is.null(curvature_method)) string <- paste0(string, ":curvature_method=", curvature_method)
97+
if(!is.null(overlay)) string <- paste0(string, ":overlay=", overlay)
98+
if(!is.null(overlay_reg)) string <- paste0(string, ":overlay_reg=", overlay_reg)
99+
if(!is.null(overlay_method)) string <- paste0(string, ":overlay_method=", overlay_method)
100+
if(!is.null(overlay_color)) string <- paste0(string, ":overlay_color=", collapse(overlay_color, collapse = ","))
101+
if(!is.null(overlay_threshold)) string <- paste0(string, ":overlay_threshold=", collapse(overlay_threshold, collapse = ","))
102+
if(!is.null(overlay_frame)) string <- paste0(string, ":overlay_frame=", overlay_frame)
103+
if(!is.null(correlation)) string <- paste0(string, ":correlation=", correlation)
104+
if(!is.null(color)) string <- paste0(string, ":color=", collapse(color, collapse = ","))
105+
if(!is.null(edgecolor)) string <- paste0(string, ":edgecolor=", collapse(edgecolor, collapse = ","))
106+
if(!is.null(edgethickness)) string <- paste0(string, ":edgethickness=", edgethickness)
107+
if(!is.null(annot)) string <- paste0(string, ":annot=", annot)
108+
if(!is.null(annot_outline)) string <- paste0(string, ":annot_outline=", annot_outline)
109+
if(!is.null(name)) string <- paste0(string, ":name=", name)
110+
if(!is.null(offset)) string <- paste0(string, ":offset=", collapse(offset, collapse = ","))
111+
if(!is.null(visible)) string <- paste0(string, ":visible=", visible)
112+
if(!is.null(vector)) string <- paste0(string, ":vector=", vector)
113+
if(!is.null(target_surf)) string <- paste0(string, ":target_surf=", target_surf)
114+
if(!is.null(label)) string <- paste0(string, ":label=", label)
115+
if(!is.null(label_outline)) string <- paste0(string, ":label_outline=", label_outline)
116+
if(!is.null(label_color)) string <- paste0(string, ":label_color=", label_color)
117+
if(!is.null(label_centroid)) string <- paste0(string, ":label_centroid=", label_centroid)
118+
if(!is.null(label_visible)) string <- paste0(string, ":label_visible=", label_visible)
119+
if(!is.null(spline)) string <- paste0(string, ":spline=", spline)
120+
if(!is.null(vertex)) string <- paste0(string, ":vertex=", vertex)
121+
if(!is.null(vertexcolor)) string <- paste0(string, ":vertexcolor=", collapse(vertexcolor, collapse = ","))
122+
if(!is.null(goto)) string <- paste0(string, ":goto=", goto)
123+
if(!is.null(hide_in_3d)) string <- paste0(string, ":hide_in_3d=", hide_in_3d)
124+
if(!is.null(all)) string <- paste0(string, ":all=", all)
125+
string
126+
}
127+
34128
#'Histograms of the vertex measures
35129
#'
36130
#'Plots a histogram of the mean vertex measure, either by vertex or by subject
@@ -64,16 +158,18 @@ hist.vw <- function(vw, qtype = c("vertex", "subject"), xlab = NULL, main = NULL
64158
#'
65159
#'@param vw The output object of a qdecr call (e.g. qdecr_fastlm)
66160
#'@param stack Either a numeric or a string for your variable (use `stacks(vw)`)
161+
#'@param type The type of map to plot (currently for OLS). Default is `coef`, others are `se`, `t` and `p`
67162
#'@param ext Extension of the image files that will be stored on disk
68163
#'@param zoom Float that determines how far the brains are zoomed in
69164
#'@param compose Logical; if TRUE, a single compiled image will be made (requires Magick++)
70165
#'@param plot_brain Logical; if TRUE, returns a graphical device with the composed images
71166
#'@param save_plot Logical; if TRUE, saves the composed image
72-
#'@param mask Logical; if TRUE, only the significant clusters are shown
167+
#'@param sig Logical; if TRUE, only the significant clusters are shown
168+
#'@param ... any arguments that freeview (on command line) normally takes for manipulating surface files
73169
#'@return NULL
74170
#'@export
75171

76-
qdecr_snap <- function(vw, stack = NULL, ext = ".tiff", zoom = 1, compose = TRUE, plot_brain = TRUE, save_plot = TRUE, mask = TRUE) {
172+
qdecr_snap <- function(vw, stack = NULL, type = c("coef", "se", "t", "p"), ext = ".tiff", zoom = 1, compose = TRUE, plot_brain = TRUE, save_plot = TRUE, sig = TRUE, ...) {
77173
if (is.null(stack)) stop("`stack` not defined. Please choose: ", paste(stacks(vw), collapse = ", "))
78174
if (length(stack) > 1) stop("More than 1 stack specified.")
79175
if(is.character(stack)) stack <- which(stacks(vw) == stack)
@@ -98,19 +194,48 @@ qdecr_snap <- function(vw, stack = NULL, ext = ".tiff", zoom = 1, compose = TRUE
98194
qsnap_e(180),
99195
qsnap(snap_names[4]),
100196
"--quit")
101-
tfile <- file.path(vw$paths$dir_tmp, "tmp_snapshot_qdecr.txt")
197+
tfile <- file.path(vw$paths$dir_tmp, "tmp_snapshot_qdecr.txt")
102198
write.table(snap_cmd, tfile, quote = F, row.names = F, col.names = F)
103199
on.exit(file.remove(tfile))
104200

105-
temp_mgh <- qdecr_read_coef(vw, stack)
106-
if (mask) temp_mgh$x <- temp_mgh$x %MASK% qdecr_read_ocn_mask(vw, stack)
107-
if (all(temp_mgh$x == 0)) stop("Stack does not contain information (e.g. because of no significant findings), aborting plot.")
201+
type <- match.arg(type)
202+
empty_val <- if(type == "p") 1 else 0
203+
204+
read_fun <- switch(type,
205+
coef = qdecr_read_coef,
206+
se = qdecr_read_se,
207+
t = qdecr_read_t,
208+
p = qdecr_read_p)
209+
210+
temp_mgh <- read_fun(vw, stack)
211+
if (all(temp_mgh$x == empty_val)) stop("Stack does not contain information (e.g. because of no significant findings), aborting plot.")
212+
if (sig) {
213+
p_mgh <- qdecr_read_ocn_mask(vw, stack)
214+
temp_mgh$x[!p_mgh] <- empty_val
215+
if (all(temp_mgh$x == empty_val)) stop("No information in the stack passed the threshold (i.e. `p_thr` was set too strict), aborting plot.")
216+
}
217+
108218
temp_mgh_file <- paste0(vw$paths$dir_tmp2, ".stack", stack, ".temp_mgh.mgh")
109219
save.mgh(temp_mgh, temp_mgh_file)
110220
on.exit(file.remove(temp_mgh_file), add = TRUE)
111221

112-
cmdStr <- paste0("freeview --surface ", vw$paths$dir_subj, "/", vw$input$target, "/surf/", vw$input$hemi, ".inflated:overlay=", temp_mgh_file, " -cmd ", tfile)
113-
system(cmdStr)
222+
surface <- paste0("--surface ", vw$paths$dir_subj, "/fsaverage/surf/", vw$input$hemi, ".inflated")
223+
224+
freeview_args <- list(...)
225+
freeview_args$surface <- surface
226+
freeview_args$overlay <- temp_mgh_file
227+
228+
if (is.null(freeview_args$overlay_method)) {
229+
freeview_args$overlay_method <- "linearopaque"
230+
temp_vals <- temp_mgh$x[temp_mgh$x != empty_val]
231+
freeview_args$overlay_threshold <- c(min(abs(temp_vals)), max(abs(temp_vals)))
232+
}
233+
234+
surf_cmd <- do.call(freeview_surf_cmd, freeview_args)
235+
cmd_str <- paste("freeview", surf_cmd, "-cmd", tfile)
236+
cat("Opening Freeview on the command line. Pop-up incoming.\nCall:", cmd_str, "\n")
237+
cat(tfile, "contains:", snap_cmd, "\n")
238+
system(cmd_str)
114239

115240
if (compose) {
116241
if (!requireNamespace("magick", quietly = TRUE)) {

R/qdecr_utility.R

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,40 @@
1-
#' \code{message} function with verbose option
2-
#'
3-
#' This is a wrapper for \code{message}. It calls \code{message} if \code{verbose}
4-
#' is set to true.
5-
#'
6-
#' @param verbose Logical. If TRUE, \code{message} is called.
7-
#' @param ... Any input for \code{message}
8-
9-
catprompt <- function(string, n = 60, base = "-", center = TRUE, addSpace = TRUE, start = 5, verbose = TRUE){
10-
if(addSpace) string <- paste0(" ", string, " ")
11-
ns <- nchar(string)
12-
if(ns > n) n <- ns
13-
phase <- n - ns
14-
if (center) {
15-
start <- end <- phase / 2
16-
} else {
17-
if (phase < start) n <- n + (start - phase)
18-
phase <- ns - n
19-
end <- n - start - ns
20-
}
21-
22-
br1 <- paste0("\n", paste(rep(base, n), collapse = ""))
23-
sr <- paste(rep(base, start), collapse = "")
24-
er <- paste(rep(base, end), collapse = "")
25-
main <- paste0(sr, string, er)
26-
if (nchar(main) < n) main <- paste0(main, rep(base, n - nchar(main)))
27-
br2 <- paste(rep(base, n), collapse = "")
28-
29-
cat(br1, "\n")
30-
cat(main, "\n")
31-
cat(br2, "\n\n")
32-
}
33-
34-
message2 <- function(..., verbose = TRUE) {
35-
if (verbose) message(...)
36-
invisible()
37-
}
38-
1+
#' \code{message} function with verbose option
2+
#'
3+
#' This is a wrapper for \code{message}. It calls \code{message} if \code{verbose}
4+
#' is set to true.
5+
#'
6+
#' @param verbose Logical. If TRUE, \code{message} is called.
7+
#' @param ... Any input for \code{message}
8+
9+
catprompt <- function(string, n = 60, base = "-", center = TRUE, addSpace = TRUE, start = 5, verbose = TRUE){
10+
if(addSpace) string <- paste0(" ", string, " ")
11+
ns <- nchar(string)
12+
if(ns > n) n <- ns
13+
phase <- n - ns
14+
if (center) {
15+
start <- end <- phase / 2
16+
} else {
17+
if (phase < start) n <- n + (start - phase)
18+
phase <- ns - n
19+
end <- n - start - ns
20+
}
21+
22+
br1 <- paste0("\n", paste(rep(base, n), collapse = ""))
23+
sr <- paste(rep(base, start), collapse = "")
24+
er <- paste(rep(base, end), collapse = "")
25+
main <- paste0(sr, string, er)
26+
if (nchar(main) < n) main <- paste0(main, rep(base, n - nchar(main)))
27+
br2 <- paste(rep(base, n), collapse = "")
28+
29+
cat(br1, "\n")
30+
cat(main, "\n")
31+
cat(br2, "\n\n")
32+
}
33+
34+
message2 <- function(..., verbose = TRUE) {
35+
if (verbose) message(...)
36+
invisible()
37+
}
38+
39+
collapse <- function(..., collapse = NULL) paste(..., collapse = collapse)
40+

man/freeview.Rd

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/qdecr_snap.Rd

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)