|
a |
|
b/R/deepbleed.R |
|
|
1 |
#' DeepBleed Model |
|
|
2 |
#' |
|
|
3 |
#' @param outdir Output directory for `DeepBleed` model |
|
|
4 |
#' |
|
|
5 |
#' @note \url{https://github.com/muschellij2/deepbleed} |
|
|
6 |
#' |
|
|
7 |
#' @return A list of the output images and predictions. |
|
|
8 |
#' @export |
|
|
9 |
#' @rdname deepbleed |
|
|
10 |
#' |
|
|
11 |
#' @examples |
|
|
12 |
#' \donttest{ |
|
|
13 |
#' destfile = file.path(tempdir(), "01.tar.xz") |
|
|
14 |
#' dl = download.file( |
|
|
15 |
#' "https://archive.data.jhu.edu/api/access/datafile/1311?gbrecs=true", |
|
|
16 |
#' destfile = destfile) |
|
|
17 |
#' res = untar(tarfile = destfile, exdir = tempdir()) |
|
|
18 |
#' fname = file.path(tempdir(), "01", "BRAIN_1_Anonymized.nii.gz") |
|
|
19 |
#' mask = file.path(tempdir(), "01", "BRAIN_1_Anonymized_Mask.nii.gz") |
|
|
20 |
#' tdir = tempfile() |
|
|
21 |
#' dir.create(tdir) |
|
|
22 |
#' download_deepbleed_model(outdir = tdir) |
|
|
23 |
#' mod = load_deepbleed_model(outdir = tdir) |
|
|
24 |
#' predict_deepbleed(fname, mask = mask, outdir = tdir) |
|
|
25 |
#' } |
|
|
26 |
download_deepbleed_model = function(outdir = NULL) { |
|
|
27 |
if (is.null(outdir)) { |
|
|
28 |
outdir = system.file(package = "ichseg") |
|
|
29 |
} |
|
|
30 |
fnames = c("_index", "_data-00000-of-00002", |
|
|
31 |
"checkpoint", "_data-00001-of-00002") |
|
|
32 |
real_fnames = sub("_", ".", fnames) |
|
|
33 |
|
|
|
34 |
outfiles = file.path(outdir, real_fnames) |
|
|
35 |
if (!all(file.exists(outfiles))) { |
|
|
36 |
url = paste0("https://www.dropbox.com/s/v2ptd9mfpo13gcb/", |
|
|
37 |
"mistie_2-20200122T175000Z-001.zip?dl=1") |
|
|
38 |
tfile = tempfile(fileext = ".zip") |
|
|
39 |
dl = utils::download.file(url, destfile = tfile) |
|
|
40 |
|
|
|
41 |
ofiles_list = utils::unzip( |
|
|
42 |
tfile, |
|
|
43 |
exdir = outdir, |
|
|
44 |
list = TRUE, |
|
|
45 |
junkpaths = TRUE) |
|
|
46 |
ofiles = utils::unzip(tfile, exdir = outdir, junkpaths = TRUE) |
|
|
47 |
stopifnot(all(basename(ofiles) == fnames)) |
|
|
48 |
file.rename(ofiles, outfiles) |
|
|
49 |
} |
|
|
50 |
stopifnot(all(file.exists(outfiles))) |
|
|
51 |
|
|
|
52 |
outdir = path.expand(outdir) |
|
|
53 |
outdir = normalizePath(outdir) |
|
|
54 |
if (!grepl("/$", outdir)) { |
|
|
55 |
outdir = paste0(outdir, "/") |
|
|
56 |
} |
|
|
57 |
return(outdir) |
|
|
58 |
} |
|
|
59 |
|
|
|
60 |
#' @rdname deepbleed |
|
|
61 |
#' @export |
|
|
62 |
load_deepbleed_model = function(outdir = NULL) { |
|
|
63 |
outdir = download_deepbleed_model(outdir) |
|
|
64 |
path = system.file("deepbleed", package = "ichseg") |
|
|
65 |
if (!requireNamespace("reticulate", quietly = TRUE)) { |
|
|
66 |
stop("You need the reticulate package for deepbleed") |
|
|
67 |
} |
|
|
68 |
model = reticulate::import_from_path("models.vnet", path) |
|
|
69 |
vnet = model$VNet() |
|
|
70 |
vnet$load_weights(outdir) |
|
|
71 |
vnet |
|
|
72 |
} |
|
|
73 |
|
|
|
74 |
#' @rdname deepbleed |
|
|
75 |
#' @param image image to segment using `DeepBleed` model |
|
|
76 |
#' @param mask brain mask image |
|
|
77 |
#' @param verbose print diagnostic messages |
|
|
78 |
#' @param ... additional arguments to send to |
|
|
79 |
#' \code{\link{CT_Skull_Stripper_mask}} |
|
|
80 |
#' @export |
|
|
81 |
predict_deepbleed = function(image, |
|
|
82 |
mask = NULL, |
|
|
83 |
verbose = TRUE, |
|
|
84 |
..., |
|
|
85 |
outdir = NULL) { |
|
|
86 |
|
|
|
87 |
if (verbose) { |
|
|
88 |
message("Loading DeepBleed Model") |
|
|
89 |
} |
|
|
90 |
L = register_deepbleed( |
|
|
91 |
image = image, |
|
|
92 |
mask = mask, |
|
|
93 |
verbose = verbose, |
|
|
94 |
...) |
|
|
95 |
image = L$template_space |
|
|
96 |
reg = L$registration |
|
|
97 |
ss = L$skull_stripped |
|
|
98 |
image = array(image, dim = c(1L, dim(image), 1L)) |
|
|
99 |
|
|
|
100 |
|
|
|
101 |
vnet = load_deepbleed_model(outdir = outdir) |
|
|
102 |
if (verbose) { |
|
|
103 |
message("Prediction") |
|
|
104 |
} |
|
|
105 |
|
|
|
106 |
prediction = vnet$predict(image) |
|
|
107 |
|
|
|
108 |
arr = drop(prediction) |
|
|
109 |
arr = neurobase::copyNIfTIHeader(arr = arr, img = L$template_space) |
|
|
110 |
if (verbose) { |
|
|
111 |
message("Projecting back into Native Space") |
|
|
112 |
} |
|
|
113 |
native = extrantsr::ants_apply_transforms( |
|
|
114 |
fixed = ss, |
|
|
115 |
moving = arr, |
|
|
116 |
interpolator = "nearestNeighbor", |
|
|
117 |
transformlist = reg$invtransforms, |
|
|
118 |
verbose = verbose > 1, |
|
|
119 |
whichtoinvert = 1) |
|
|
120 |
L$registration_matrix = reg$fwdtransforms |
|
|
121 |
L$registration = NULL |
|
|
122 |
L$native_prediction = native |
|
|
123 |
L$template_prediction = arr |
|
|
124 |
return(L) |
|
|
125 |
|
|
|
126 |
} |
|
|
127 |
|
|
|
128 |
#' @rdname deepbleed |
|
|
129 |
#' @param interpolator interpolation done for antsApplyTransforms |
|
|
130 |
#' @export |
|
|
131 |
register_deepbleed = function( |
|
|
132 |
image, |
|
|
133 |
mask = NULL, |
|
|
134 |
verbose = TRUE, |
|
|
135 |
interpolator = "Linear", |
|
|
136 |
...) { |
|
|
137 |
|
|
|
138 |
image = check_nifti(image) |
|
|
139 |
if (is.null(mask)) { |
|
|
140 |
if (verbose) { |
|
|
141 |
message("Skull Stripping") |
|
|
142 |
} |
|
|
143 |
mask = CT_Skull_Stripper_mask(image, verbose = verbose, ...) |
|
|
144 |
mask = mask$mask |
|
|
145 |
} |
|
|
146 |
mask = check_nifti(mask) |
|
|
147 |
if (verbose) { |
|
|
148 |
message("Masking Image") |
|
|
149 |
} |
|
|
150 |
ss = mask_img(image, mask) |
|
|
151 |
template.file = system.file( |
|
|
152 |
'scct_unsmooth_SS_0.01_128x128x128.nii.gz', |
|
|
153 |
package = 'ichseg') |
|
|
154 |
if (verbose) { |
|
|
155 |
message("Registration") |
|
|
156 |
} |
|
|
157 |
reg = extrantsr::registration( |
|
|
158 |
ss, |
|
|
159 |
template.file = template.file, |
|
|
160 |
typeofTransform = "Rigid", |
|
|
161 |
affSampling = 64, |
|
|
162 |
interpolator = interpolator, |
|
|
163 |
verbose = verbose > 1) |
|
|
164 |
temp_space = reg$outfile |
|
|
165 |
|
|
|
166 |
L = list( |
|
|
167 |
skull_stripped = ss, |
|
|
168 |
brain_mask = mask, |
|
|
169 |
template_space = temp_space, |
|
|
170 |
registration = reg |
|
|
171 |
) |
|
|
172 |
} |