• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

neurospin-deepinsight / brainprep / 15466399122

05 Jun 2025 11:57AM UTC coverage: 35.744% (-0.2%) from 35.977%
15466399122

Pull #19

github

web-flow
Merge 2f8a6cef3 into 2f230a9ce
Pull Request #19: Automatic brain mask computation in quasi raw + bug fixed for software version

13 of 54 new or added lines in 3 files covered. (24.07%)

3 existing lines in 1 file now uncovered.

692 of 1936 relevant lines covered (35.74%)

0.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.12
/brainprep/spatial.py
1
# -*- coding: utf-8 -*-
2
##########################################################################
3
# NSAp - Copyright (C) CEA, 2021
4
# Distributed under the terms of the CeCILL-B license, as published by
5
# the CEA-CNRS-INRIA. Refer to the LICENSE file or to
6
# http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
7
# for details.
8
##########################################################################
9

10
"""
11
Common functions to spatialy normalize the data.
12
"""
13

14
# Imports
15
import os
1✔
16
import nibabel
1✔
17
import numpy as np
1✔
18
from .utils import check_version, check_command, execute_command
1✔
19

20

21
def scale(imfile, scaledfile, scale, check_pkg_version=False):
1✔
22
    """ Resample the MRI image to a new isotropic voxel size.
23

24
    .. note:: This function is based on FSL.
25

26
    Parameters
27
    ----------
28
    imfile: str
29
        the input image.
30
    scaledfile: str
31
        the path to the scaled input image.
32
    scale: int
33
        Desired isotropic voxel size in mm.
34
    check_pkg_version: bool, default False
35
        optionally check the package version using dpkg.
36

37
    Returns
38
    -------
39
    scaledfile, trffile: str
40
        the generated files.
41
    """
42
    check_version("fsl", check_pkg_version)
1✔
43
    check_command("flirt")
1✔
44
    trffile = scaledfile.split(".")[0] + ".txt"
1✔
45
    cmd = ["flirt", "-in", imfile, "-ref", imfile, "-out",
1✔
46
           scaledfile, "-applyisoxfm", str(scale), "-omat", trffile]
47
    execute_command(cmd)
1✔
48
    return scaledfile, trffile
1✔
49

50

51
def bet2(imfile, brainfile, frac=0.5, cleanup=True, save_brain_mask=True, check_pkg_version=False):
1✔
52
    """ Skull stripped the MRI image.
53

54
    .. note:: This function is based on FSL.
55

56
    Parameters
57
    ----------
58
    imfile: str
59
        the input image.
60
    brainfile: str
61
        the path to the output brain image file (with masked applied).
62
    frac: float, default=0.5
63
        fractional intensity threshold (0->1);smaller values give larger brain
64
        outline estimates
65
    cleanup: bool, default=True
66
        optionnally add bias field & neck cleanup.
67
    save_brain_mask: bool, default=True
68
        optionnally save the brain mask with suffix "_mask.nii.gz".
69
    check_pkg_version: bool, default=False
70
        optionally check the package version using dpkg.
71

72
    Returns
73
    -------
74
    brainfile, maskfile: str, str or None
75
        the generated files. 
76
        If `save_brain_mask` is False, the maskfile will be None
77
    """
78
    check_version("fsl", check_pkg_version)
1✔
79
    check_command("bet")
1✔
80
    cmd = ["bet", imfile, brainfile, "-f", str(frac), "-R"]
1✔
81
    maskfile = None
1✔
82
    if save_brain_mask:
1✔
83
        cmd.append("-m")
1✔
84
        maskfile = brainfile.split(".")[0] + "_mask.nii.gz"
1✔
85
    if cleanup:
1✔
86
        cmd.append("-B")
1✔
87
    execute_command(cmd)
1✔
88
    return brainfile, maskfile
1✔
89

90
def synthstrip(imfile, brainfile, save_brain_mask=True):
1✔
91
    """
92
    Skull strip the MRI image using SynthStrip (FreeSurfer).
93

94
    Parameters
95
    ----------
96
    imfile: str
97
        Input image (T1, T2, FLAIR, etc.)
98
    brainfile: str
99
        Output skull-stripped brain image file path.
100
    save_brain_mask: bool, default=True
101
        Optionally save the brain mask with suffix '_mask.nii.gz'.
102

103
    Returns
104
    -------
105
    brainfile, maskfile: str, str or None
106
        The skull-stripped image and mask file paths.
107
        If `save_brain_mask` is False, maskfile is None.
108
    """
NEW
109
    check_command("mri_synthstrip")
×
110
    
NEW
111
    cmd = [
×
112
        "mri_synthstrip",
113
        "-i", imfile,
114
        "-o", brainfile,
115
        "--no-csf"
116
    ]
NEW
117
    maskfile = None
×
NEW
118
    if save_brain_mask:
×
NEW
119
        maskfile = brainfile.split(".")[0] + "_mask.nii.gz"
×
NEW
120
        cmd.extend(["-m", maskfile])
×
NEW
121
    execute_command(cmd)
×
NEW
122
    return brainfile, maskfile
×
123

124
def reorient2std(imfile, stdfile, check_pkg_version=False):
1✔
125
    """ Reorient the MRI image to match the approximate orientation of the
126
    standard template images (MNI152).
127

128
    .. note:: This function is based on FSL.
129

130
    Parameters
131
    ----------
132
    imfile: str
133
        the input image.
134
    stdfile: str
135
        the reoriented image file.
136
    check_pkg_version: bool, default False
137
        optionally check the package version using dpkg.
138

139
    Returns
140
    -------
141
    stdfile: str
142
        the generated file.
143
    """
144
    check_version("fsl", check_pkg_version)
1✔
145
    check_command("fslreorient2std")
1✔
146
    cmd = ["fslreorient2std", imfile, stdfile]
1✔
147
    execute_command(cmd)
1✔
148
    return stdfile
1✔
149

150

151
def biasfield(imfile, bfcfile, maskfile=None, nb_iterations=50,
1✔
152
              convergence_threshold=0.001, bspline_grid=(1, 1, 1),
153
              shrink_factor=1, bspline_order=3,
154
              histogram_sharpening=(0.15, 0.01, 200), check_pkg_version=False):
155
    """ Perform MRI bias field correction using N4 algorithm.
156

157
    .. note:: This function is based on ANTS.
158

159
    Parameters
160
    ----------
161
    imfile: str
162
        the input image.
163
    bfcfile: str
164
        the bias fieled corrected file.
165
    maskfile: str, default None
166
        the brain mask image.
167
    nb_iterations: int, default 50
168
        Maximum number of iterations at each level of resolution. Larger
169
        values will increase execution time, but may lead to better results.
170
    convergence_threshold: float, default 0.001
171
        Stopping criterion for the iterative bias estimation. Larger values
172
        will lead to smaller execution time.
173
    bspline_grid: int, default (1, 1, 1)
174
        Resolution of the initial bspline grid defined as a sequence of three
175
        numbers. The actual resolution will be defined by adding the bspline
176
        order (default is 3) to the resolution in each dimension specified
177
        here. For example, 1,1,1 will result in a 4x4x4 grid of control points.
178
        This parameter may need to be adjusted based on your input image.
179
        In the multi-resolution N4 framework, the resolution of the bspline
180
        grid at subsequent iterations will be doubled. The number of
181
        resolutions is implicitly defined by Number of iterations parameter
182
        (the size of this list is the number of resolutions).
183
    shrink_factor: int, default 1
184
        Defines how much the image should be upsampled before estimating the
185
        inhomogeneity field. Increase if you want to reduce the execution
186
        time. 1 corresponds to the original resolution. Larger values will
187
        significantly reduce the computation time.
188
    bspline_order: int, default 3
189
        Order of B-spline used in the approximation. Larger values will lead
190
        to longer execution times, may result in overfitting and poor result.
191
    histogram_sharpening: 3-uplate, default (0.15, 0.01, 200)
192
        A vector of up to three values. Non-zero values correspond to Bias
193
        Field Full Width at Half Maximum, Wiener filter noise, and Number of
194
        histogram bins.
195
    check_pkg_version: bool, default False
196
        optionally check the package version using dpkg.
197

198
    Returns
199
    -------
200
    bfcfile, bffile: str
201
        the generatedd files.
202
    """
203
    check_version("ants", check_pkg_version)
1✔
204
    check_command("N4BiasFieldCorrection")
1✔
205
    ndim = 3
1✔
206
    bspline_grid = [str(e) for e in bspline_grid]
1✔
207
    histogram_sharpening = [str(e) for e in histogram_sharpening]
1✔
208
    bffile = bfcfile.split(".")[0] + "_field.nii.gz"
1✔
209
    cmd = [
1✔
210
        "N4BiasFieldCorrection",
211
        "-d", str(ndim),
212
        "-i", imfile,
213
        "-s", str(shrink_factor),
214
        "-b", "[{0},{1}]".format("x".join(bspline_grid), bspline_order),
215
        "-c", "[{0},{1}]".format(
216
            "x".join([str(nb_iterations)] * 4), convergence_threshold),
217
        "-t", "[{0}]".format(", ".join(histogram_sharpening)),
218
        "-o", "[{0},{1}]".format(bfcfile, bffile),
219
        "-v"]
220
    if maskfile is not None:
1✔
221
        cmd += ["-x", maskfile]
1✔
222
    try:
1✔
223
        execute_command(cmd)
1✔
NEW
224
    except Exception as e:
×
NEW
225
        print(f"Error occurred while executing command: {e}")
×
NEW
226
        cmd = ["cp", imfile, bfcfile]
×
NEW
227
        execute_command(cmd)
×
NEW
228
        print("Using the original image as the bias field corrected image.")
×
229
    return bfcfile, bffile
1✔
230

231

232
def register_affine(imfile, targetfile, regfile, mask=None, cost="normmi",
1✔
233
                    bins=256, interp="spline", dof=9, check_pkg_version=False):
234
    """ Register the MRI image to a target image using an affine transform
235
    with 9 dofs.
236

237
    .. note:: This function is based on FSL.
238

239
    Parameters
240
    ----------
241
    imfile: str
242
        the input image.
243
    targetfile: str
244
        the target image.
245
    regfile: str
246
        the registered file.
247
    mask: str, default None
248
        the white matter mask image needed by the bbr cost function.
249
    cost: str, default 'normmi'
250
        Choose the most appropriate metric: 'mutualinfo', 'corratio',
251
        'normcorr', 'normmi', 'leastsq', 'labeldiff', 'bbr'.
252
    bins: int, default 256
253
        Number of histogram bins
254
    interp: str, default 'spline'
255
        Choose the most appropriate interpolation method: 'trilinear',
256
        'nearestneighbour', 'sinc', 'spline'.
257
    dof: int, default 9
258
        Number of affine transform dofs.
259
    check_pkg_version: bool, default False
260
        optionally check the package version using dpkg.
261

262
    Returns
263
    -------
264
    regfile, trffile: str
265
        the generated files.
266
    """
267
    check_version("fsl", check_pkg_version)
1✔
268
    check_command("flirt")
1✔
269
    trffile = regfile.split(".")[0] + ".txt"
1✔
270
    cmd = ["flirt",
1✔
271
           "-in", imfile,
272
           "-ref", targetfile,
273
           "-cost", cost,
274
           "-searchcost", cost,
275
           "-anglerep", "euler",
276
           "-bins", str(bins),
277
           "-interp", interp,
278
           "-dof", str(dof),
279
           "-out", regfile,
280
           "-omat", trffile,
281
           "-verbose", "1"]
282
    if cost == "bbr":
1✔
283
        if mask is None:
×
284
            raise ValueError("A white matter mask image is needed by the "
×
285
                             "bbr cost function.")
286
        cmd += ["-wmseg", mask]
×
287
    execute_command(cmd)
1✔
288
    return regfile, trffile
1✔
289

290

291
def apply_affine(imfile, targetfile, regfile, affines, interp="spline",
1✔
292
                 check_pkg_version=False):
293
    """ Apply affine transformations to an image.
294

295
    .. note:: This function is based on FSL.
296

297
    Parameters
298
    ----------
299
    imfile: nibabel.Nifti1Image
300
        the input image.
301
    targetfile: nibabel.Nifti1Image
302
        the target image.
303
    regfile: str
304
        the registered file.
305
    affines: str or list of str
306
        the affine transforms to be applied. If multiple transforms are
307
        specified, they are first composed.
308
    interp: str, default 'spline'
309
        Choose the most appropriate interpolation method: 'trilinear',
310
        'nearestneighbour', 'sinc', 'spline'.
311
    check_pkg_version: bool, default False
312
        optionally check the package version using dpkg.
313

314
    Returns
315
    -------
316
    regfile, trffile: str
317
        the generated files.
318
    """
319
    check_version("fsl", check_pkg_version)
1✔
320
    check_command("flirt")
1✔
321
    if not isinstance(affines, list):
1✔
UNCOV
322
        affines = [affines]
×
323
    elif len(affines) == 0:
1✔
UNCOV
324
        raise ValueError("No transform specified.")
×
325
    trffile = regfile.split(".")[0] + ".txt"
1✔
326
    affines = [np.loadtxt(path) for path in affines][::-1]
1✔
327
    affine = affines[0]
1✔
328
    for matrix in affines[1:]:
1✔
UNCOV
329
        affine = np.dot(matrix, affine)
×
330
    np.savetxt(trffile, affine)
1✔
331
    cmd = ["flirt",
1✔
332
           "-in", imfile,
333
           "-ref", targetfile,
334
           "-init", trffile,
335
           "-interp", interp,
336
           "-applyxfm",
337
           "-out", regfile]
338
    execute_command(cmd)
1✔
339
    return regfile, trffile
1✔
340

341

342
def apply_mask(imfile, maskfile, genfile):
1✔
343
    """ Apply brain mask.
344

345
    Parameters
346
    ----------
347
    imfile: str
348
        the input image.
349
    maskfile: str
350
        the mask image.
351
    genfile: str
352
        the input masked file.
353

354
    Returns
355
    -------
356
    genfile: str
357
        the generated file.
358
    """
359
    im = nibabel.load(imfile)
1✔
360
    mask_im = nibabel.load(maskfile)
1✔
361
    arr = im.get_fdata()
1✔
362
    arr[mask_im.get_fdata() == 0] = 0
1✔
363
    gen_im = nibabel.Nifti1Image(arr, im.affine)
1✔
364
    nibabel.save(gen_im, genfile)
1✔
365
    return genfile
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc