diff --git a/bin/dwifslpreproc b/bin/dwifslpreproc index d7efcae9cc..4cf91ba83e 100755 --- a/bin/dwifslpreproc +++ b/bin/dwifslpreproc @@ -1203,7 +1203,7 @@ def execute(): #pylint: disable=unused-variable # Also grab any files generated by the eddy qc tool QUAD if os.path.isdir('dwi_post_eddy.qc'): if app.FORCE_OVERWRITE and os.path.exists(os.path.join(eddyqc_path, 'quad')): - run.function(shutil.rmtree(os.path.join(eddyqc_path, 'quad'))) + run.function(shutil.rmtree, os.path.join(eddyqc_path, 'quad')) run.function(shutil.copytree, 'dwi_post_eddy.qc', os.path.join(eddyqc_path, 'quad')) # Also grab the brain mask that was provided to eddy if -eddyqc_all was specified if app.ARGS.eddyqc_all: diff --git a/cmd/mrconvert.cpp b/cmd/mrconvert.cpp index 48ad7272b3..2ea5f06389 100644 --- a/cmd/mrconvert.cpp +++ b/cmd/mrconvert.cpp @@ -63,7 +63,7 @@ void usage () + "The -vox option is used to change the size of the voxels in the output " "image as reported in the image header; note however that this does not " "re-sample the image based on a new voxel size (that is done using the " - "mrresize command)." + "mrgrid command)." + "By default, the intensity scaling parameters in the input image header " "are passed through to the output image header when writing to an integer " diff --git a/cmd/mrthreshold.cpp b/cmd/mrthreshold.cpp index 08224e7ef0..1dcb9d286f 100644 --- a/cmd/mrthreshold.cpp +++ b/cmd/mrthreshold.cpp @@ -200,8 +200,7 @@ default_type calculate (Image& in, const default_type percentile, const ssize_t bottom, const ssize_t top, - const bool ignore_zero, - const bool to_cout) + const bool ignore_zero) { if (std::isfinite (abs)) { @@ -249,9 +248,6 @@ default_type calculate (Image& in, } else { // No explicit mechanism option: do automatic thresholding - std::unique_ptr latch; - if (to_cout) - latch.reset (new LogLevelLatch (App::log_level - 1)); if (max_axis < in.ndim()) { // Need to extract just the current 3D volume @@ -302,14 +298,8 @@ void apply (Image& in, const size_t max_axis, const value_type threshold, const operator_type comp, - const bool mask_out, - const bool to_cout) + const bool mask_out) { - if (to_cout) { - std::cout << threshold; - return; - } - const T true_value = std::is_floating_point::value ? 1.0 : true; const T false_value = std::is_floating_point::value ? NaN : false; @@ -335,7 +325,9 @@ void apply (Image& in, - +// TODO Don't write directly to std::cout; +// will get hidden by /r of progress bar +// Alternatively, withhold progress bar if writing to std::cout template void execute (Image& in, Image& mask, @@ -363,19 +355,27 @@ void execute (Image& in, // Do one volume at a time // If writing to cout, also add a newline between each volume - bool is_first_loop = true; - for (auto l = Loop("Determining and applying per-volume thresholds", 3, in.ndim()) (in); l; ++l) { - if (to_cout) { + if (to_cout) { + LogLevelLatch latch (App::log_level - 1); + bool is_first_loop = true; + for (auto l = Loop(3, in.ndim()) (in); l; ++l) { if (is_first_loop) is_first_loop = false; else std::cout << "\n"; + const default_type threshold = calculate (in, mask, 3, abs, percentile, bottom, top, ignore_zero); + std::cout << threshold; } - LogLevelLatch latch (App::log_level - 1); - const default_type threshold = calculate (in, mask, 3, abs, percentile, bottom, top, ignore_zero, to_cout); - if (out.valid()) + + } else { + + for (auto l = Loop("Determining and applying per-volume thresholds", 3, in.ndim()) (in); l; ++l) { + LogLevelLatch latch (App::log_level - 1); + const default_type threshold = calculate (in, mask, 3, abs, percentile, bottom, top, ignore_zero); assign_pos_of (in, 3).to (out); - apply (in, mask, out, 3, value_type(threshold), op, mask_out, to_cout); + apply (in, mask, out, 3, value_type(threshold), op, mask_out); + } + } return; @@ -385,8 +385,11 @@ void execute (Image& in, } // Process whole input image as a single block - const default_type threshold = calculate (in, mask, in.ndim(), abs, percentile, bottom, top, ignore_zero, to_cout); - apply (in, mask, out, in.ndim(), value_type(threshold), op, mask_out, to_cout); + const default_type threshold = calculate (in, mask, in.ndim(), abs, percentile, bottom, top, ignore_zero); + if (to_cout) + std::cout << threshold; + else + apply (in, mask, out, in.ndim(), value_type(threshold), op, mask_out); } diff --git a/core/dwi/gradient.cpp b/core/dwi/gradient.cpp index b0c6b6badf..249e9aedd6 100644 --- a/core/dwi/gradient.cpp +++ b/core/dwi/gradient.cpp @@ -288,7 +288,8 @@ namespace MR // write the scheme as interpreted back into the header if: // - vector normalisation effect is large, regardless of whether or not b-value scaling was applied // - gradient information was pulled from file - if (exceeds_single_precision || get_options ("grad").size() || get_options ("fslgrad").size()) + // - explicit b-value scaling is requested + if (exceeds_single_precision || get_options ("grad").size() || get_options ("fslgrad").size() || bvalue_scaling != BValueScalingBehaviour::Auto) set_DW_scheme (const_cast (header), grad); INFO ("found " + str (grad.rows()) + "x" + str (grad.cols()) + " diffusion gradient table"); diff --git a/docs/fixel_based_analysis/mt_fibre_density_cross-section.rst b/docs/fixel_based_analysis/mt_fibre_density_cross-section.rst index ccb32b7840..8ac0f1f561 100644 --- a/docs/fixel_based_analysis/mt_fibre_density_cross-section.rst +++ b/docs/fixel_based_analysis/mt_fibre_density_cross-section.rst @@ -64,7 +64,7 @@ There is however no strict requirement for the final set of response functions t ^^^^^^^^^^^^^^^^^^^^^^^ Upsampling DWI data *before* computing FODs increases anatomical contrast and improves downstream template building, registration, tractography and statistics. We recommend upsampling to an isotropic voxel size of 1.25 mm for human brains (if your original resolution is already higher, you can skip this step):: - for_each * : mrresize IN/dwi_denoised_unringed_preproc_unbiased.mif -vox 1.25 IN/dwi_denoised_unringed_preproc_unbiased_upsampled.mif + for_each * : mrgrid IN/dwi_denoised_unringed_preproc_unbiased.mif regrid -vox 1.25 IN/dwi_denoised_unringed_preproc_unbiased_upsampled.mif 6. Compute upsampled brain mask images diff --git a/docs/fixel_based_analysis/st_fibre_density_cross-section.rst b/docs/fixel_based_analysis/st_fibre_density_cross-section.rst index d006353825..abde0cf643 100644 --- a/docs/fixel_based_analysis/st_fibre_density_cross-section.rst +++ b/docs/fixel_based_analysis/st_fibre_density_cross-section.rst @@ -107,7 +107,7 @@ There is however no strict requirement for the (one) final response function to ^^^^^^^^^^^^^^^^^^^^^^^ Upsampling DWI data *before* computing FODs can increase anatomical contrast and improve downstream template building, registration, tractography and statistics. We recommend upsampling to an isotropic voxel size of 1.25 mm for human brains (if your original resolution is already higher, you can skip this step):: - for_each * : mrresize IN/dwi_denoised_unringed_preproc_unbiased_normalised.mif -vox 1.25 IN/dwi_denoised_unringed_preproc_unbiased_normalised_upsampled.mif + for_each * : mrgrid IN/dwi_denoised_unringed_preproc_unbiased_normalised.mif regrid -vox 1.25 IN/dwi_denoised_unringed_preproc_unbiased_normalised_upsampled.mif 8. Compute upsampled brain mask images ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/quantitative_structural_connectivity/ismrm_hcp_tutorial.rst b/docs/quantitative_structural_connectivity/ismrm_hcp_tutorial.rst index b09fc35c2a..1a1781777b 100644 --- a/docs/quantitative_structural_connectivity/ismrm_hcp_tutorial.rst +++ b/docs/quantitative_structural_connectivity/ismrm_hcp_tutorial.rst @@ -161,7 +161,7 @@ image and provide this alternative FOD image to SIFT (this should have little influence on the outcome of the algorithm, but will greatly reduce memory consumption): -``mrresize WM_FODs.mif FOD_downsampled.mif -scale 0.5 -interp sinc`` +``mrgrid WM_FODs.mif regrid FOD_downsampled.mif -scale 0.5 -interp sinc`` If this still does not adequately reduce RAM usage, you will need to reduce the number of input streamlines to a level where your processing diff --git a/docs/reference/commands/mrconvert.rst b/docs/reference/commands/mrconvert.rst index 8fab484415..5aeaba3926 100644 --- a/docs/reference/commands/mrconvert.rst +++ b/docs/reference/commands/mrconvert.rst @@ -27,7 +27,7 @@ Note that for both the -coord and -axes options, indexing starts from 0 rather t Additionally, for the second input to the -coord option and the -axes option, you can use any valid number sequence in the selection, as well as the 'end' keyword (see the main documentation for details); this can be particularly useful to select multiple coordinates. -The -vox option is used to change the size of the voxels in the output image as reported in the image header; note however that this does not re-sample the image based on a new voxel size (that is done using the mrresize command). +The -vox option is used to change the size of the voxels in the output image as reported in the image header; note however that this does not re-sample the image based on a new voxel size (that is done using the mrgrid command). By default, the intensity scaling parameters in the input image header are passed through to the output image header when writing to an integer image, and reset to 0,1 (i.e. no scaling) for floating-point and binary images. Note that the -scaling option will therefore have no effect for floating-point or binary output images. diff --git a/matlab/write_mrtrix.m b/matlab/write_mrtrix.m index 9ee308caac..28155e3fe3 100644 --- a/matlab/write_mrtrix.m +++ b/matlab/write_mrtrix.m @@ -142,9 +142,9 @@ function write_mrtrix (image, filename) if strcmp(filename(end-3:end), '.mif') dataoffset = ftell (fid) + 18; - dataoffset += mod((4 - mod(dataoffset, 4)), 4); + dataoffset = dataoffset + mod((4 - mod(dataoffset, 4)), 4); fprintf (fid, '. %d\nEND\n ', dataoffset); - fseek (fid, dataoffset); + fseek (fid, dataoffset, 'bof'); elseif strcmp(filename(end-3:end), '.mih') datafile = [ filename(1:end-4) '.dat' ]; fprintf (fid, '%s 0\nEND\n', datafile); diff --git a/run_tests b/run_tests index 3ba7711de6..12dd312ef0 100755 --- a/run_tests +++ b/run_tests @@ -82,13 +82,17 @@ EOD if [ ! -z $datadir ]; then - echo -n "fetching requisite test data... " + echo -n "checking for requisite test data... " git submodule update --init $datadir >> $LOGFILE 2>&1 if [ $? != 0 ]; then - echo ERROR! - exit 1 + if [[ -e $datadir && ! -z $(ls -A $datadir) ]]; then + echo "Found; UNABLE TO VERIFY VERSION MATCH" + else + echo "ERROR!" + exit 1 + fi else - echo OK + echo "Synchronized OK" fi fi diff --git a/share/mrtrix3/labelconvert/fs2lobes_cinginc_convert.txt b/share/mrtrix3/labelconvert/fs2lobes_cinginc_convert.txt index 9bd1eec552..2d6772c243 100644 --- a/share/mrtrix3/labelconvert/fs2lobes_cinginc_convert.txt +++ b/share/mrtrix3/labelconvert/fs2lobes_cinginc_convert.txt @@ -58,6 +58,7 @@ 5 Left-Cerebellum-Cortex +6 Left-Thalamus 6 Left-Thalamus-Proper 6 Left-Caudate 6 Left-Putamen @@ -66,6 +67,7 @@ 6 Left-Amygdala 6 Left-Accumbens-area +7 Right-Thalamus 7 Right-Thalamus-Proper 7 Right-Caudate 7 Right-Putamen diff --git a/share/mrtrix3/labelconvert/fs2lobes_cingsep_convert.txt b/share/mrtrix3/labelconvert/fs2lobes_cingsep_convert.txt index 8fcbb1f1bd..595de53cd1 100644 --- a/share/mrtrix3/labelconvert/fs2lobes_cingsep_convert.txt +++ b/share/mrtrix3/labelconvert/fs2lobes_cingsep_convert.txt @@ -58,6 +58,7 @@ 6 Left-Cerebellum-Cortex +7 Left-Thalamus 7 Left-Thalamus-Proper 7 Left-Caudate 7 Left-Putamen @@ -66,6 +67,7 @@ 7 Left-Amygdala 7 Left-Accumbens-area +8 Right-Thalamus 8 Right-Thalamus-Proper 8 Right-Caudate 8 Right-Putamen diff --git a/share/mrtrix3/labelconvert/fs_a2009s.txt b/share/mrtrix3/labelconvert/fs_a2009s.txt index b1e6ad44ff..2eaca4db96 100644 --- a/share/mrtrix3/labelconvert/fs_a2009s.txt +++ b/share/mrtrix3/labelconvert/fs_a2009s.txt @@ -94,6 +94,7 @@ 75 Left-Cerebellum-Cortex 230 148 34 255 +76 Left-Thalamus 0 118 14 255 76 Left-Thalamus-Proper 0 118 14 255 77 Left-Caudate 122 186 220 255 78 Left-Putamen 236 13 176 255 @@ -102,6 +103,7 @@ 81 Left-Amygdala 103 255 255 255 82 Left-Accumbens-area 255 165 0 255 +83 Right-Thalamus 0 118 14 255 83 Right-Thalamus-Proper 0 118 14 255 84 Right-Caudate 122 186 220 255 85 Right-Putamen 236 13 176 255 diff --git a/share/mrtrix3/labelconvert/fs_default.txt b/share/mrtrix3/labelconvert/fs_default.txt index c4e8e02b20..4219d3904b 100644 --- a/share/mrtrix3/labelconvert/fs_default.txt +++ b/share/mrtrix3/labelconvert/fs_default.txt @@ -54,6 +54,7 @@ 35 L.CER Left-Cerebellum-Cortex 230 148 34 255 +36 L.TH Left-Thalamus 0 118 14 255 36 L.TH Left-Thalamus-Proper 0 118 14 255 37 L.CA Left-Caudate 122 186 220 255 38 L.PU Left-Putamen 236 13 176 255 @@ -62,6 +63,7 @@ 41 L.AM Left-Amygdala 103 255 255 255 42 L.AC Left-Accumbens-area 255 165 0 255 +43 R.TH Right-Thalamus 0 118 14 255 43 R.TH Right-Thalamus-Proper 0 118 14 255 44 R.CA Right-Caudate 122 186 220 255 45 R.PU Right-Putamen 236 13 176 255 diff --git a/src/gui/mrview/tool/connectome/connectome.cpp b/src/gui/mrview/tool/connectome/connectome.cpp index a8732379e5..cd1be37f3c 100644 --- a/src/gui/mrview/tool/connectome/connectome.cpp +++ b/src/gui/mrview/tool/connectome/connectome.cpp @@ -2268,6 +2268,8 @@ namespace MR for (node_t n = 1; n <= max_index; ++n) node_coms[n] *= (1.0f / float(node_volumes[n])); + selected_nodes.resize (max_index+1); + nodes.clear(); const size_t pixheight = dynamic_cast(node_list->tool)->row_height(); @@ -2317,8 +2319,6 @@ namespace MR node_overlay.reset (new NodeOverlay (std::move (H_overlay))); update_node_overlay(); - selected_nodes.resize (num_nodes()+1); - dynamic_cast(node_list->tool)->initialize(); } @@ -2755,14 +2755,45 @@ namespace MR } else { // Load the node names from the LUT // Other properties will only be pulled from the LUT if requested + // Permit two indices to have a duplicate entry without warning + // (so that using new FreeSurfer tables will not raise a warning); + // if more than two node indices has a duplicate entry, issue the + // user with a warning, as they may have selected the incorrect + // LUT file + for (node_t node_index = 1; node_index <= num_nodes(); ++node_index) + nodes[node_index].set_name (""); + size_t duplicate_entry_count = 0; for (node_t node_index = 1; node_index <= num_nodes(); ++node_index) { const size_t count = lut.count (node_index); - if (count) { - if (count > 1) - throw Exception ("Duplicate entries in lookup table file for index " + str(node_index)); + if (count == 1) { nodes[node_index].set_name (lut.find(node_index)->second.get_name()); + } else if (count > 1) { + ++duplicate_entry_count; + vector names; + const auto range = lut.equal_range (node_index); + for (auto i = range.first; i != range.second; ++i) + names.push_back (i->second.get_name()); + std::nth_element (names.begin(), names.begin(), names.end()); + nodes[node_index].set_name (names.front()); + } + } + if (duplicate_entry_count > 2) { + WARN("Lookup table file contains " + str(duplicate_entry_count) + " indices with duplicate entries; " + "file may be intended for use in conversion rather than visualisation"); + } + size_t absent_entry_count = 0; + for (node_t node_index = 1; node_index <= num_nodes(); ++node_index) { + if (nodes[node_index].get_volume() && !nodes[node_index].get_name().size()) { + const std::string name = "Node " + str(node_index); + nodes[node_index].set_name (name); + lut.insert (std::make_pair (node_index, MR::Connectome::LUT_node (name))); + ++absent_entry_count; } } + if (absent_entry_count) { + WARN(str(absent_entry_count) + " indices present in parcellation image with no entry in lookup table; " + "lookup table file and parcellation image may not match"); + } } calculate_node_visibility(); diff --git a/src/gui/mrview/tool/tractography/track_scalar_file.cpp b/src/gui/mrview/tool/tractography/track_scalar_file.cpp index 4c7bb1071a..1980d9953d 100644 --- a/src/gui/mrview/tool/tractography/track_scalar_file.cpp +++ b/src/gui/mrview/tool/tractography/track_scalar_file.cpp @@ -180,24 +180,6 @@ namespace MR min_entry->setValue (tractogram->scaling_min()); max_entry->setValue (tractogram->scaling_max()); - threshold_lower_box->setEnabled (true); - if (tractogram->use_discard_lower()) { - threshold_lower_box->setChecked(true); - threshold_lower->setEnabled (true); - } else { - threshold_lower->setEnabled (false); - threshold_lower_box->setChecked(false); - } - threshold_upper_box->setEnabled (true); - if (tractogram->use_discard_upper()) { - threshold_upper_box->setChecked (true); - threshold_upper->setEnabled (true); - } else { - threshold_upper->setEnabled (false); - threshold_upper_box->setChecked (false); - } - threshold_lower->setRate (tractogram->scaling_rate()); - colourmap_menu->setEnabled (true); colourmap_actions[tractogram->colourmap]->setChecked (true); show_colour_bar->setChecked (tractogram->show_colour_bar); @@ -242,9 +224,9 @@ namespace MR threshold_lower ->setEnabled (tractogram->use_discard_lower()); threshold_upper_box->setChecked (tractogram->use_discard_upper()); threshold_upper ->setEnabled (tractogram->use_discard_upper()); - threshold_lower->setRate (tractogram->scaling_rate()); + threshold_lower->setRate (tractogram->get_threshold_rate()); threshold_lower->setValue (tractogram->lessthan); - threshold_upper->setRate (tractogram->scaling_rate()); + threshold_upper->setRate (tractogram->get_threshold_rate()); threshold_upper->setValue (tractogram->greaterthan); } } diff --git a/src/gui/mrview/tool/tractography/tractogram.cpp b/src/gui/mrview/tool/tractography/tractogram.cpp index 545fd93eb0..4eec74535f 100644 --- a/src/gui/mrview/tool/tractography/tractogram.cpp +++ b/src/gui/mrview/tool/tractography/tractogram.cpp @@ -520,12 +520,12 @@ namespace MR case TrackColourType::Ends: gl::BindBuffer (gl::ARRAY_BUFFER, colour_buffers[buf]); gl::EnableVertexAttribArray (3); - gl::VertexAttribPointer (3, 3, gl::FLOAT, gl::FALSE_, 3 * sample_stride * sizeof(float), (void*)0); + gl::VertexAttribPointer (3, 3, gl::FLOAT, gl::FALSE_, 3 * sample_stride * sizeof(float), (void*)(3*sample_stride*sizeof(float))); break; case TrackColourType::ScalarFile: gl::BindBuffer (gl::ARRAY_BUFFER, intensity_scalar_buffers[buf]); gl::EnableVertexAttribArray (3); - gl::VertexAttribPointer (3, 1, gl::FLOAT, gl::FALSE_, sample_stride * sizeof(float), (void*)0); + gl::VertexAttribPointer (3, 1, gl::FLOAT, gl::FALSE_, sample_stride * sizeof(float), (void*)(sample_stride*sizeof(float))); break; default: break; @@ -534,7 +534,7 @@ namespace MR if (threshold_type == TrackThresholdType::SeparateFile) { gl::BindBuffer (gl::ARRAY_BUFFER, threshold_scalar_buffers[buf]); gl::EnableVertexAttribArray (4); - gl::VertexAttribPointer (4, 1, gl::FLOAT, gl::FALSE_, sample_stride * sizeof(float), (void*)0); + gl::VertexAttribPointer (4, 1, gl::FLOAT, gl::FALSE_, sample_stride * sizeof(float), (void*)(sample_stride*sizeof(float))); } gl::BindBuffer (gl::ARRAY_BUFFER, vertex_buffers[buf]); @@ -811,7 +811,7 @@ namespace MR while (file (tck_scalar)) { const size_t tck_size = tck_scalar.size(); - assert (tck_size == size_t(original_track_sizes[intensity_scalar_buffers.size()][tck_count])); + assert (tck_size == size_t(original_track_sizes[threshold_scalar_buffers.size()][tck_count])); if (!tck_size) continue;