MRtrix3 / mrtrix3

MRtrix3 provides a set of tools to perform various advanced diffusion MRI analyses, including constrained spherical deconvolution (CSD), probabilistic tractography, track-density imaging, and apparent fibre density
http://www.mrtrix.org
Mozilla Public License 2.0
293 stars 180 forks source link

mrview Connectome tool surface visualisation issues #1311

Closed Lestropie closed 6 years ago

Lestropie commented 6 years ago

Two separate but perhaps related issues on the forum in short succession: Connectome node mesh visualisation problem Visualising edges as streamlines / streamtubes

What these two functionalities share is that they either import or internally generate triangular polygon data.

There may be some association of the issue with Mac OSX systems, particularly the streamtubes, but it's unclear at this point. If any dev can reproduce either of these faults please let me know, as otherwise I have no starting point.

jdtournier commented 6 years ago

Any chance you could share some data and instructions that ought to replicate the user's issues...?

Also, do you have access to a system with an ATI/AMD card? Their drivers tend to be a lot pickier than the NVIDIA ones, regardless of the OS - could explain at least some of these issues (assuming they are indeed running on ATI hardware)...

Lestropie commented 6 years ago

At least one of the users is on NVIDIA, so can't be purely an ATI thing.

Example data:

Lestropie commented 6 years ago

Some updates on the node mesh visualisation issue on forum. Seems at least one source of problems is the mismatch in locale conformity between functions used to save (MRtrix3's str()) and load (sscanf()) floating-point data to/from the .obj text file; these should preferable be either a << / >> pair (i.e. str() and to()) or a C function pair (i.e. sprintf() / sscanf()). I haven't been able to find anything on the .obj format regarding how locale differences should be handled in that context specifically.

Within MRtrix3, both str() and to() are based on fresh instances of std::*stringstream, which will by default take the current C++ global locale. We're not making a std::locale::global(std::locale("")); call anywhere, which would set the C++ global locale to be the system default. In the absence of such a call, the C++ global locale is equivalent to std::locale::classic() (an immutable C++-compatible version of the C global locale), which is "the classic C locale semantics": the universal "simplest" locale. This is why our own converters "ignore the locale" as stated by @jdtournier on the forum.

(There's a secondary debate to be had here about whether or not stdin / stdout / stderr should be imbued with the system locale globally across MRtrix3)

This however doesn't explain why there would be issues in saving & loading .obj files entirely within MRtrix3: the C locale assumed by sscanf() and the C++ default locale assumed by str() should match... I could understand if the file were modified by some third-party software, and our own reader should ideally be as robust as possible against this, but it's not quite clicking for me why this is the source of the problem.

Nevertheless, if this specific instance is causing issues, it can be changed and tested. However while I initially had the idea of replacing & then forbidding all use of sscanf() and similar C functions via the check_syntax script, I then recalled having an issue with parsing of lookup table files using split() rather than sscanf(), specifically because I've seen at least one atlas lookup table in the wild that uses double-inverted-commas to encapsulate parcel names that contain spaces, which results in erroneous results from split(). So I'd need to improve upon #1281 by writing some kind of tokenize() function to complement split() before going full nuclear on scanf(); std::quoted would help, but that's C++14.

It's also worth noting that if this is indeed the source of the problem with node mesh visualisation, then the issue with streamtube visualisation would in fact not be related, contrary to the initial hypothesis of this issue.

jdtournier commented 6 years ago

Good bit of detective work on locale handling... I must admit I've never looked into it all that closely. But given the issues, it seems to be that it would be safer to set both the C and C++ locales to the default C early on in the init() call. That would require the fewest changes and lead to the most robust solution long term (since we can't guarantee what future devs might choose to use). What do you think?

jdtournier commented 6 years ago

OK, I had a look into this. It's a bit of a mess...

Pull request to follow shortly...

jdtournier commented 6 years ago

See pull request in #1323. I'd set LC_ALL=hr_HR.UTF-8 for testing, which reproduces the issue. This seems to fix it for me...

Lestropie commented 6 years ago

Can't reproduce on Windows at home, so will need to have a look at work next week.

I think I agree forcing both c and c++ to classic locale semantics universally, for both GUI and non-GUI, is going to be the way to go. Thought about trying to set just cerr to use native encoding so that terminal feedback would be native, but anything that goes through str() rather than straight to operator<< would still not get that native encoding (at least unless e.g. str() took a bool argument to specify which encoding to use).

jdtournier commented 6 years ago

Checks out OK on my Windows 10 system. Compiles and runs fine, but then I couldn't reproduce the problem anyway... I think locale issues are handled differently on Windows... Anyway, I think we're good to merge.

Thought about trying to set just cerr to use native encoding so that terminal feedback would be native, but anything that goes through str() rather than straight to operator<< would still not get that native encoding (at least unless e.g. str() took a bool argument to specify which encoding to use).

Yes, this is really tricky to handle. We have to be able to distinguish direct user input/output from uses where the input/output is to files, where it's important to stick to the standard C locale to avoid funny issues when reading back the values on a different system (i.e. anywhere interoperability is possible). And it's not even that clear-cut, since terminal output can be redirected to file, which makes it a bit of a grey area. Personally, I think we have to force all locales to default to avoid any issues like this...

Lestropie commented 6 years ago
$ LC_ALL=hr_HR.UTF-8 mrview anat/vis.mif -connectome.init parc/nodes_fix_int.mif -connectome.load connectome.csv 

(process:6484): Gtk-WARNING **: 11:55:16.850: Locale not supported by C library.
    Using the fallback 'C' locale.

:man_facepalming: :rofl:

Lestropie commented 6 years ago

Okay, confirm this fixes the issue. Also confirm that the locale does not affect file write in any way (done here via str()), but a modified locale prevents correct file read via sscanf().

Lestropie commented 6 years ago

Closed by #1323; re-listing streamtube visualisation issue in #1330 as that will not be fixed by the localisation handling changes in #1323.

jdtournier commented 6 years ago

(process:6484): Gtk-WARNING **: 11:55:16.850: Locale not supported by C library.

Yes, this depends on how your system is set up. On my Arch Linux box, only the locales I've set up are available. I had to enable that particular one for testing... I guess the locales installed by default, and the process for generating additional ones, will be distro-dependent.