-
Notifications
You must be signed in to change notification settings - Fork 75
Technical programming notes
(This section was spawned from this email sent to the gerardus-user mailing list)
Our MatlabImportFilter
can read vectors as input parameters directly from Matlab, and pass them to ITK without intermediate steps. For example, in the itk::VotingBinaryIterativeHoleFillingImageFilter
https://github.com/vigente/gerardus/blob/master/matlab/ItkToolbox/ItkImFilter.cpp#L529
// The variance for the discrete Gaussian kernel. Sets the
// variance independently for each dimension. The default is 0.0
// in each dimension (ITK)
typename FilterType::ArrayType defVariance;
defVariance.Fill(0.0);
filter->SetVariance(matlabImport->
GetRowVectorArgument<typename FilterType::ArrayType::ValueType,
typename FilterType::ArrayType,
VImageDimension>(2, "VAR", defVariance));
The method GetRowVectorArgument() is declared here
https://github.com/vigente/gerardus/blob/master/matlab/MatlabImportFilter.h#L239
Because we may want to read Matlab vectors into very different classes, e.g. itk::Size<Dimension>
vs. CGAL::Direction_3<CGAL::Simple_cartesian<double> >
, the definition of this method relies heavily on the idea of a vector wrapper,
https://github.com/vigente/gerardus/blob/master/matlab/MatlabImportFilter.hxx#L443
VectorWrapper<VectorValueType, VectorType, mxLogical, VectorSize> paramWrap;
That is, we have a class VectorWrapper that provides a common interface from Matlab to different sorts of vectors. For the moment, by default we assume that the output vector is
https://github.com/vigente/gerardus/blob/master/matlab/VectorWrapper.h#L75
std::vector
but we have partial specialisations to deal with
https://github.com/vigente/gerardus/blob/master/matlab/VectorWrapper.h#L118
itk::Size<Dimension>
itk::FixedArray<ValueType, Dimension>
https://github.com/vigente/gerardus/blob/master/matlab/VectorWrapper.h#L250
CGAL::Point_3<CGAL::Simple_cartesian<ValueType> >
CGAL::Direction_3<CGAL::Simple_cartesian<ValueType> >
For ITK this already covers quite a bit of possibilities, because many types get reduced to the two above. For example, the itk::BoxFilterType<...,...>::RadiusType
used in the Median filter is actually an itk::FixedArray<double, Dimension>
.
https://github.com/vigente/gerardus/blob/master/matlab/ItkToolbox/ItkImFilter.cpp#L816
These are notes of what we did to get the Boost libraries code into Gerardus.
-
Go to the Boost C++ Libraries and click on the current release link (1.53.0 at the time of this writing)
-
Download the tarball with the whole project, e.g.
boost_1_53_0.tar.bz2
-
Extract
boost_1_53_0
togerardus/cpp/src/third-party
. This takes up 456M, which is too much to distribute with Gerardus -
Change to the boost source code directory
cd `gerardus/cpp/src/third-party/boost_1_53_0`
-
Delete documentation, tests and examples to reduce the size to 144M
find . -name test | xargs rm -rf find . -name doc | xargs rm -rf find . -name examples | xargs rm -rf find . -name example | xargs rm -rf
-
Add and commit the boost source code to the gerardus repository
cd .. svn add boost_1_53_0 svn ci boost_1_53_0
MEX files in Windows are DLLs that can link to other DLLs. Sometimes a MEX file may not run giving the error
Invalid MEX-file <mexfilename>:
The specified module could not be found.
As explained in Mathworks support page "Invalid MEX-File Error", in Windows one can install the program Dependency Walker, and run it within Matlab to figure out whether all DLLs the MEX file depends on are visible, e.g.
>> !"C:\Program Files\depends22_x64\depends.exe" ..\ItkToolbox\itk_imfilter.mexw64
To make a DLL visible, its has to be in the same directory as the MEX file, or it's directory has to be in the system path (which is different from the Matlab toolbox path). In Gerardus, we solve this problem in the script add_gerardus_paths.m with the code
%% System paths to DLLs for Windows
if ~isempty(strfind(getenv('OS'), 'Windows'))
% full paths to directories with DLLs
pathsToDlls = {cd(cd('..\lib')), cd(cd('..\lib\bin')), cd(cd('..\cpp\src\third-party\CGAL-4.2\auxiliary\gmp\lib'))};
% get system paths
systemPath = getenv('PATH');
% add paths to directories with DLLs unless they are already in the
% system path
for I = 1:length(pathsToDlls)
if isempty(strfind(lower(systemPath), lower(pathsToDlls{I})))
disp(['Adding ' pathsToDlls{I} ' to system path'])
systemPath = [pathsToDlls{I} ';' systemPath];
end
end
setenv('PATH', systemPath);
end
This code searches the system path, and adds any DLL directory that is missing.