Skip to content

Commit 442e89e

Browse files
authored
Merge pull request #2406 from MRtrix3/dev_update
dev update
2 parents d834024 + dee1511 commit 442e89e

21 files changed

Lines changed: 111 additions & 41 deletions

File tree

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Please provide the following information:
3434
**Advanced debugging information (if applicable)**
3535

3636
- In case of a critical error such as "segmentation fault", please generate
37-
and report the backtrace as described [here](https://mrtrix.readthedocs.io/en/latest/troubleshooting/advanced_debugging.html).
37+
and report the backtrace as described [here](https://community.mrtrix.org/t/advanced-debugging-of-mrtrix3-binaries).
3838

3939
- For issues with `mrview`, please provide:
4040

CONTRIBUTING.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,17 @@ to be provided in subsequent sections of this document.
145145
146146
- If only making changes to the *MRtrix3* *documentation*, then the
147147
appropriate base branch will depend upon the nature of the changes
148-
being proposed and the urgency of the update. In this scenario,
149-
please generate an [Issue](https://github.com/MRtrix3/mrtrix3/issues)
150-
to facilitate communication with the core development team.
148+
being proposed and the urgency of the update. For instance, if providing
149+
a minor correction to spelling / grammar, or fixing an erroneous
150+
hyperlink, then a direct merge to `master` is likely appropriate.
151+
Conversely, if the changes are non-trivial, and it makes more sense for
152+
the changes to be made as part of an *MRtrix3* update rather than
153+
immediately, then `dev` may be the more appropriate base branch. If
154+
the answer to this question in the context of your proposed changes is
155+
unclear to you, then please generate an [Issue](https://github.com/MRtrix3/mrtrix3/issues)
156+
to facilitate direct discussion with the *MRtrix3* core development
157+
team (ideally before commencing the implementation of changes, as
158+
incorrect selection can sometimes be laborious to resolve later).
151159
152160
1. Generate one or more Git commits that apply your proposed changes to
153161
the repository.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# MRtrix
22

33
[![Build Status](https://github.com/MRtrix3/mrtrix3/workflows/checks/badge.svg)](https://github.com/MRtrix3/mrtrix3/actions)
4+
[![@MRtrix3](http://img.shields.io/twitter/follow/MRtrix3.svg?style=social)](https://twitter.com/MRtrix3)
45

56
*MRtrix3* can be installed / run through multiple avenues:
67
- [Direct download](https://www.mrtrix.org/download/) through mechanisms tailored for different OS platforms;

bin/blend

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import sys
2020

2121
if len(sys.argv) <= 1:
2222
sys.stderr.write('A script to blend two sets of movie frames together with a desired overlap.\n')
23-
sys.stderr.write('The input arguments are two folders containing the movie frames (eg. output from the MRview screenshot tool), and the desired number of overlapping frames.\n')
23+
sys.stderr.write('The input arguments are two folders containing the movie frames '
24+
'(eg. output from the MRview screenshot tool), and the desired number '
25+
'of overlapping frames.\n')
2426
sys.stderr.write('eg: blend folder1 folder2 20 output_folder\n')
2527
sys.exit(1)
2628

@@ -42,7 +44,9 @@ for i in range(NUM_OUTPUT_FRAMES):
4244
if len(FILE_LIST_1) - NUM_OVERLAP < i < len(FILE_LIST_1):
4345
i2 = i - (len(FILE_LIST_1) - NUM_OVERLAP) - 1
4446
blend_amount = 100 * float(i2 + 1) / float(NUM_OVERLAP)
45-
os.system('convert ' + INPUT_FOLDER_1 + '/' + FILE_LIST_1[i] + ' ' + INPUT_FOLDER_2 + '/' + FILE_LIST_2[i2] + ' -alpha on -compose blend -define compose:args=' + str(blend_amount) + ' -gravity South -composite ' + OUTPUT_FOLDER + '/' + file_name)
47+
os.system('convert ' + INPUT_FOLDER_1 + '/' + FILE_LIST_1[i] + ' ' + INPUT_FOLDER_2 \
48+
+ '/' + FILE_LIST_2[i2] + ' -alpha on -compose blend -define compose:args=' \
49+
+ str(blend_amount) + ' -gravity South -composite ' + OUTPUT_FOLDER + '/' + file_name)
4650
if i >= (len(FILE_LIST_1)):
4751
i2 = i - (len(FILE_LIST_1) - NUM_OVERLAP) - 1
4852
os.system('cp -L ' + INPUT_FOLDER_2 + '/' + FILE_LIST_2[i2] + ' ' + OUTPUT_FOLDER + '/' + file_name)

bin/dwi2response

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,20 @@ def execute(): #pylint: disable=unused-variable
103103

104104
app.goto_scratch_dir()
105105

106-
if app.ARGS.mask:
107-
# Check that the brain mask is appropriate
108-
mask_header = image.Header('mask.mif')
109-
if mask_header.size()[:3] != image.Header('dwi.mif').size()[:3]:
110-
raise MRtrixError('Dimensions of provided mask image do not match DWI')
111-
if not (len(mask_header.size()) == 3 or (len(mask_header.size()) == 4 and mask_header.size()[3] == 1)):
112-
raise MRtrixError('Provided mask image needs to be a 3D image')
113-
else:
114-
app.console('Computing brain mask (dwi2mask)...')
115-
run.command('dwi2mask ' + CONFIG.get('Dwi2maskAlgorithm', 'legacy') + ' dwi.mif mask.mif', show=False)
116-
117-
if not image.statistics('mask.mif', mask='mask.mif').count:
118-
raise MRtrixError(('Provided' if app.ARGS.mask else 'Generated') + ' mask image does not contain any voxels')
106+
if alg.supports_mask():
107+
if app.ARGS.mask:
108+
# Check that the brain mask is appropriate
109+
mask_header = image.Header('mask.mif')
110+
if mask_header.size()[:3] != image.Header('dwi.mif').size()[:3]:
111+
raise MRtrixError('Dimensions of provided mask image do not match DWI')
112+
if not (len(mask_header.size()) == 3 or (len(mask_header.size()) == 4 and mask_header.size()[3] == 1)):
113+
raise MRtrixError('Provided mask image needs to be a 3D image')
114+
else:
115+
app.console('Computing brain mask (dwi2mask)...')
116+
run.command('dwi2mask ' + CONFIG.get('Dwi2maskAlgorithm', 'legacy') + ' dwi.mif mask.mif', show=False)
117+
118+
if not image.statistics('mask.mif', mask='mask.mif').count:
119+
raise MRtrixError(('Provided' if app.ARGS.mask else 'Generated') + ' mask image does not contain any voxels')
119120

120121
# From here, the script splits depending on what estimation algorithm is being used
121122
alg.execute()

bin/dwicat

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818

1919

20-
import json
20+
import json, shutil
2121

2222

2323

@@ -36,7 +36,7 @@ def usage(cmdline): #pylint: disable=unused-variable
3636

3737

3838
def execute(): #pylint: disable=unused-variable
39-
from mrtrix3 import MRtrixError #pylint: disable=no-name-in-module, import-outside-toplevel
39+
from mrtrix3 import CONFIG, MRtrixError #pylint: disable=no-name-in-module, import-outside-toplevel
4040
from mrtrix3 import app, image, path, run #pylint: disable=no-name-in-module, import-outside-toplevel
4141

4242
num_inputs = len(app.ARGS.inputs)
@@ -45,13 +45,26 @@ def execute(): #pylint: disable=unused-variable
4545

4646
# check input data
4747
def check_header(header):
48-
if len(header.size()) != 4:
49-
raise MRtrixError('Image "' + header.name() + '" is not a 4D image series')
48+
if len(header.size()) > 4:
49+
raise MRtrixError('Image "' + header.name() + '" contains more than 4 dimensions')
5050
if not 'dw_scheme' in header.keyval():
5151
raise MRtrixError('Image "' + header.name() + '" does not contain a gradient table')
52-
num_grad_lines = len(header.keyval()['dw_scheme'])
53-
if num_grad_lines != header.size()[3]:
54-
raise MRtrixError('Number of lines in gradient table for image "' + header.name() + '" (' + str(num_grad_lines) + ') does not match number of volumes (' + str(header.size()[3]) + ')')
52+
dw_scheme = header.keyval()['dw_scheme']
53+
try:
54+
if isinstance(dw_scheme[0], list):
55+
num_grad_lines = len(dw_scheme)
56+
elif (isinstance(dw_scheme[0], ( int, float))) and len(dw_scheme) >= 4:
57+
num_grad_lines = 1
58+
else:
59+
raise MRtrixError
60+
except (IndexError, MRtrixError):
61+
raise MRtrixError('Image "' + header.name() + '" contains gradient table of unknown format') # pylint: disable=raise-missing-from
62+
if len(header.size()) == 4:
63+
num_volumes = header.size()[3]
64+
if num_grad_lines != num_volumes:
65+
raise MRtrixError('Number of lines in gradient table for image "' + header.name() + '" (' + str(num_grad_lines) + ') does not match number of volumes (' + str(num_volumes) + ')')
66+
elif not (num_grad_lines == 1 and len(dw_scheme) >= 4 and dw_scheme[3] <= float(CONFIG.get('BZeroThreshold', 10.0))):
67+
raise MRtrixError('Image "' + header.name() + '" is 3D, and cannot be validated as a b=0 volume')
5568

5669
first_header = image.Header(path.from_user(app.ARGS.inputs[0], False))
5770
check_header(first_header)
@@ -87,7 +100,12 @@ def execute(): #pylint: disable=unused-variable
87100

88101
# extract b=0 volumes within each input series
89102
for index in range(0, num_inputs):
90-
run.command('dwiextract ' + str(index) + 'in.mif ' + str(index) + 'b0.mif -bzero')
103+
infile = str(index) + 'in.mif'
104+
outfile = str(index) + 'b0.mif'
105+
if len(image.Header(infile).size()) > 3:
106+
run.command('dwiextract ' + infile + ' ' + outfile + ' -bzero')
107+
else:
108+
run.function(shutil.copyfile, infile, outfile)
91109

92110
mask_option = ' -mask_input mask.mif -mask_target mask.mif' if app.ARGS.mask else ''
93111

bin/dwifslpreproc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ def execute(): #pylint: disable=unused-variable
847847
app.cleanup(se_epi_path)
848848
se_epi_path = new_se_epi_path
849849
new_dwi_path = os.path.splitext(dwi_path)[0] + '_pad' + str(axis) + '.mif'
850-
run.command('mrconvert ' + dwi_path + ' -coord ' + str(axis) + ' ' + str(axis_size-1) + ' - | mrcat ' + dwi_path + ' - ' + new_dwi_path + ' -axis ' + str(axis))
850+
run.command('mrconvert ' + dwi_path + ' -coord ' + str(axis) + ' ' + str(axis_size-1) + ' -clear dw_scheme - | mrcat ' + dwi_path + ' - ' + new_dwi_path + ' -axis ' + str(axis))
851851
app.cleanup(dwi_path)
852852
dwi_path = new_dwi_path
853853
dwi_post_eddy_crop_option += ' -coord ' + str(axis) + ' 0:' + str(axis_size-1)

build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,8 @@ cpp = cpp_flags = ld = ld_flags = ld_lib = ld_lib_flags = eigen_cflags = qt_cfla
534534

535535
try:
536536
log ('reading configuration from "' + config_file + '"...' + os.linesep)
537-
exec (codecs.open (config_file, mode='r', encoding='utf-8').read()) # pylint: disable=exec-used,consider-using-with
537+
with codecs.open (config_file, mode='r', encoding='utf-8') as f:
538+
exec (f.read()) # pylint: disable=exec-used
538539
except IOError:
539540
fail ('''no configuration file found!
540541
please run "./configure" prior to invoking this script

cmd/dwiextract.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ void usage ()
6767
void run()
6868
{
6969
auto input_image = Image<float>::open (argument[0]);
70+
if (input_image.ndim() < 4)
71+
throw Exception ("Epected input image to contain more than three dimensions");
7072
auto grad = DWI::get_DW_scheme (input_image);
7173

7274
// Want to support non-shell-like data if it's just a straight extraction

configure

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,8 @@ class TempFile:
344344
def __exit__(self, exception_type, value, traceback):
345345
try:
346346
os.unlink (self.name)
347-
except OSError as excp: # pylint: disable=redefined-outer-name
348-
log ('error deleting temporary file "' + self.name + '": ' + excp.strerror)
347+
except OSError as excp_local:
348+
log ('error deleting temporary file "' + self.name + '": ' + excp_local.strerror)
349349

350350

351351

@@ -359,8 +359,8 @@ class DeleteAfter:
359359
def __exit__(self, exception_type, value, traceback):
360360
try:
361361
os.unlink (self.name)
362-
except OSError as excp: # pylint: disable=redefined-outer-name
363-
log ('error deleting temporary file "' + self.name + '": ' + excp.strerror)
362+
except OSError as excp_local:
363+
log ('error deleting temporary file "' + self.name + '": ' + excp_local.strerror)
364364

365365

366366
class TempDir:
@@ -380,8 +380,8 @@ class TempDir:
380380
os.unlink (fullpath)
381381
os.rmdir (self.name)
382382

383-
except OSError as excp: # pylint: disable=redefined-outer-name
384-
log ('error deleting temporary folder "' + self.name + '": ' + excp.strerror)
383+
except OSError as excp_local:
384+
log ('error deleting temporary folder "' + self.name + '": ' + excp_local.strerror)
385385

386386

387387

@@ -522,7 +522,8 @@ def execute (cmd, exception, raise_on_non_zero_exit_code = True, cwd = None):
522522
log ('error invoking command "' + cmd[0] + '": ' + excp_local.strerror + '\n>>\n\n')
523523
raise exception from excp_local
524524
except Exception as excp_local:
525-
error ('unexpected exception of type ' + type(excp_local).__name__ + ': ' + str(excp_local) + configure_log_hint)
525+
error ('unexpected exception of type ' + type(excp_local).__name__ + ': ' + str(excp_local) + configure_log_hint)
526+
raise exception from excp_local
526527
else:
527528
if raise_on_non_zero_exit_code and process.returncode != 0:
528529
raise exception (stderr)
@@ -663,8 +664,8 @@ def compile_check (full_name, name, cflags, ldflags, code, cflags_env=None, cfla
663664
error ('''runtime error!
664665
665666
Unable to configure ''' + name + configure_log_hint)
666-
except Exception as excp: # pylint: disable=redefined-outer-name
667-
error ('unexpected exception of type ' + type(excp).__name__ + ': ' + str(excp) + configure_log_hint)
667+
except Exception as excp_local:
668+
error ('unexpected exception of type ' + type(excp_local).__name__ + ': ' + str(excp_local) + configure_log_hint)
668669

669670

670671

0 commit comments

Comments
 (0)