-
-
Notifications
You must be signed in to change notification settings - Fork 664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: BUG: Fixed issue with 4th component in FreeSurfer ASCII mesh #3781
base: master
Are you sure you want to change the base?
Conversation
Video to demonstrate the issues with ascii (1 min 45 sec) https://youtu.be/Pylza3ePZTs |
Not sure how to handle arbitrary extension for binary data. Is it legal to have in constructor: this->AddSupportedWriteExtension(".fsb");
this->AddSupportedWriteExtension(".fcv"); and bool FreeSurferBinaryMeshIO::CanWriteFile(const char * fileName)
{
return true;
} or maybe additionally exclude in CanWriteFile extensions supported by FreeSurfer:
? |
I think it is. @blowekamp do you agree? BUT, that format will be used by almost all writes, instead of other formats. Let's say I want to create new mesh IO module which will support
This is fine for a FreeSurfer tool, not quite for a general purpose library such as ITK. I suggest to have just a few extensions for FreeSurfer, and return false for all other cases in |
Does the MeshIO automatically determine the IO class for reading and writing like the ImageIO? If so accepting all files for CanWrite would cause priority difficulties depending on the order of the MeshIO registered. For example if *.vtk is supported by freesurfer and meshvtk, then the order the factories are registered will determine which meshIO is used. Worse if freesurfer cannot read the file, when it says it can it could take higher priority that IOs which can actually read the file. I'd recommend just using the "supported" extensions for the CanWrite method. If the freesurfer IO is wanted to be used for another format it can be explicitly test as the MeshIO for the reader/writer. |
Thanks. Yes. I will not change CanWrite. |
Sorry for the delay. Thanks for having investigated all issues and proposing a fix to them @issakomi 💯. I'm not an expert on FS file formats 😔. For the current state of things:
In the mid term:
In the longer run:
|
@hjmjohnson @seanm @gdevenyi do you know anyone from https://github.com/freesurfer/freesurfer? It would be good if someone more familiar with the file format would provide some feedback. |
the template is protected, probably there is no API change from user perspective
cell components are indices, float, double, long double don't make sense and will crash FreeView. |
I have reduced the PR to ASCII mesh. So there is no need to discuss curvature files now (related methods are empty).
I have reverted this to simplify the discussion.
Another test (itkMeshFileReadWriteTest) invokes the methods internally, in the correct order. Edit: If you wish to repair itkFreeSurferMeshIOTestBinary, don't change defaults to true and use only in this order ReadMeshInformation, ReadPoints, ReadCells and WriteMeshInformation, WritePoints, WriteCells. Or Update. We don't have a test file to test ReadPointData and WritePointData. @jhlegarreta let me know if you wish to work on that test, i can remove it from the PR |
@issakomi thanks again for the effort.
Rather than the write methods themselves, when saying that I was more concerned about calling the e.g.
OK. For now, I think it is enough in order to move forward. We can improve the test and the coverage in separate PRs. It's better to fix the class itself. I get the point about the default flag and the relevance of the order. 👌 thanks Mikhail.
I'm fine with the changes. I would need more time to work on it, and I will not be able to set aside some time for it before some weeks. So whenever you feel the current PR is ready to go, mark is as ready to review (as the issue will still not be completely addressed, you may want to remove the Again, thanks for having investigated all this. Edit: We will also be willing to clarify the cell vs. point distinction, and the mentioned order in the documentation so that the class methods are called appropriately. Can definitely be done in a separate PR. |
AFAIK, Update seems to work. Probably it is the recommended way: just set file name, (input) for mesh reader/writer and Update, BTW. |
d4a9c68
to
6228662
Compare
The class is backward compatible with old buggy files with wrong 4th components e.g. Tested by converting to #include "itkMesh.h"
#include "itkMeshFileReader.h"
#include "itkMeshFileWriter.h"
#include "itkTestingMacros.h"
int main(int argc, char ** argv)
{
using MeshType = itk::Mesh<float, 3>;
using MeshFileReaderType = itk::MeshFileReader<MeshType>;
using MeshFileWriterType = itk::MeshFileWriter<MeshType>;
MeshFileReaderType::Pointer reader = MeshFileReaderType::New();
reader->SetFileName(argv[1]);
ITK_TRY_EXPECT_NO_EXCEPTION(reader->Update());
MeshFileWriterType::Pointer writer = MeshFileWriterType::New();
writer->SetInput(reader->GetOutput());
writer->SetFileName("out.obj");
ITK_TRY_EXPECT_NO_EXCEPTION(writer->Update());
return 0;
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I shall check |
@issakomi you're right, my mistake. Added it back. Got confused by the focus on the ASCII files and the commit and PR messages not mentioning that the method calls in the test were modified to fix the issue. |
Maybe we should separate the fix to the memory leak in the test and fixing the ASCII format? That way at least the fix to the leak will be eventually merged without being blocked by the fix to the ASCII format. What do you think @issakomi ? |
If you like. I stuck a little with the PR. There are many things I don't like in both classes, e.g. switches over data types that can not work, this 'curvature data' stuff (where is cell type?). Also MeshIOBase could be a little bit bloated with cell/point pixel (?) types like RGBA, tensor, etc. But i don't want to step into this stuff and make so many big changes. |
I think best is to split, have the memory leak issue resolved and merged, and then go to tackle the other issues incrementally. As you found the fix, I'd prefer if you would submit it to credit you as the author. |
S. #3796 |
Use correct 4th component for points and cells. Updated tests. The class is backward compatible with files written with incorrect 4th components.
The Valgrind defect is gone: I have updated this PR to only change 4th component now. Didn't change extension. |
This is fantastic @issakomi ! A big thank you.
I see your feeling, but when we feel the changes needed are big, and we do not have time to properly do them all at once, or have a somewhat incomplete picture, if possible, it is better to split them and do small steps towards the solution. e.g. you also did some changes to the binary FS mesh IO class in an earlier commit: If you are more confident with these, can they be put to a separate PR, and make the appropriate changes to the test data/files so that the difference gets tested, fixed and merged independently? Thanks for all this effort. I know tracking down some stuff can consume a lot of time and energy. |
The only significant change in binary class was the modification of CanReadFile to use magic number instead of extension if (fileTypeIdentifier == (-2 & 0x00ffffff))
{
// The input file is FreeSurfer binary surface file
ok = true;
}
else if (fileTypeIdentifier == (-1 & 0x00ffffff))
{
// The input file is FreeSurfer binary curvature file
ok = true;
} The problem is I think that a curvature file is something very special. In ASCII format it looks like:
I am not sure that it can be used standalone at all. I don't think that binary mesh class works for such files (but works well with surfaces), not sure, it reads numbers of points and cells (?), the numbers are different, how it could be? What kind of cell it should be? Only Read/WritePointData methods are used. So i decided to do no changes in binary class at all. I am playing with FreeSurfer. It is interesting. Shortly, it works like this (after installation, licensing and setting the environment) |
👍, but we all agree that this is an
OK, but this is separate from the above binary format improvement.
I am not very familiar with mesh files. Maybe the curvature file is always accompanied by a vertex file? @PranjalSahu has been working on mesh files lately. Maybe he can cast some light on this.
I see, but we agree that the magic number change is independent of the curvature/point/cell data issue, right?
I know FS does a lot of processing and generates a lot of files, and that it requires several hours of computation for a single subject. But these people have worked hard to develop the tool and make it available. I have not played with FastSurfer, and IDK if it computes the same features/generates the exact same number of files, but might be an option if we want to get the output fast for experimenting with the files. |
Yes, it can not be used standalone. There are just float values, one per vertex. In fact there are different types: curvature, thickness, weights, etc. In Slicer's FreeSurfer importer plugin it is called overlay file. Also binary and ASCII formats are different, binary has a kind of header: magic number, number of points, number of cells (unused), number of components (always 1) and a float array of values. I don't know how it is supposed to be used in binary mesh class standalone, it is not a mesh, probably there could be a method, something like SetOverlayFile. In ASCII class it is not available, the related methods (for point data) are empty. Generally ASCII files are not native, FreeSurfer doesn't produce them, actually they can be only created with |
Looks like this is loosely related: InsightSoftwareConsortium/ITKIOMeshSTL#44 |
S. explanation #3772 (comment).
Fixed 4th element.
Tested with FreeSurfer 7.3.2, 2022/08/04