Standalone compiled with Matlab compiler doesn't work

22 views (last 30 days)
Sam Y.
Sam Y. on 30 Apr 2022
Commented: Sam Y. on 1 May 2022
I have compiled a .exe file of MRiLab (https://se.mathworks.com/matlabcentral/fileexchange/45456-mrilab-v1-2-1) using Matlab compiler.
The program is an excellent MRI-Simulator with which you can, for example, load different phantoms and image them with different MRI sequences and imaging parameters.However, the compiled exe from MRiLab does not work as it does in Matlab. Standalone application of program starts but does not work fully. For example, when I select an MRI sequence the program gives an error message (when the exe is started in Matlab):
Error using DoParseXML (line 60)
Failed to read XML file C:\Users\sylisiur\AppData\Local\Temp\sylisiur\mcrCache9.9\MRiLab1\MRiLab\PSD\3D\FastSpinEcho\PSD_FSE3D\PSD_FSE3D.xml.
Error in SeqList>Seq_listbox_Callback (line 272)
Error in gui_mainfcn (line 95)
Error in SeqList (line 94)
Error in matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)SeqList('Seq_listbox_Callback',hObject,eventdata,guidata(hObject))
Error using waitforallfiguresclosed (line 16)
Error while evaluating UIControl Callback.
Sometimes the program lets you select some of a sequences, but when I then press the scan button it gives a new error message:
To correct the error, I have tried e.g. change the MCR_CACHE_ROOT to another path that also did not help or delete the mcrcache9.9 folder and run the program again. The versions of Matlab (R2020b) and Runtime (v9.9) also match. Apparently the problem, I think, is with the DoParseXML function (code below)?
I have been trying for a long time to solve the problem and I would be very grateful if someone could help?
BR: S.Y
function theStruct = DoParseXML(dnode)
%DoParseXML(XML_filename)
%convert XML file to a MATLAB structure.
try
tree = xmlread(dnode);
catch me
error('Failed to read XML file %s.',dnode);
end
% Recurse over child nodes. This could run into problems
% with very deeply nested trees.
theStruct = parseChildNodes(tree);
theStruct.current=1;
% ----- Subfunction PARSECHILDNODES -----
function children = parseChildNodes(theNode)
% Recurse over node children.
children = [];
if theNode.hasChildNodes
childNodes = theNode.getChildNodes;
numChildNodes = childNodes.getLength;
allocCell = cell(1, numChildNodes);
children = struct('Name', allocCell,...
'Attributes', allocCell,...
'Data', allocCell,...
'Children', allocCell,...
'current', allocCell);
i=0;
for count = 1:numChildNodes
theChild = childNodes.item(count-1);
c = makeStructFromNode(theChild);
if isempty(c)
i=i+1;
else
children(count-i) = c;
end
end
if i>0
children(numChildNodes-i+1:numChildNodes)=[];
end
end
% ----- Subfunction MAKESTRUCTFROMNODE -----
function nodeStruct = makeStructFromNode(theNode)
% Create structure of node info.
PC=parseChildNodes(theNode);
nodeStruct = struct('Name', char(theNode.getNodeName),...
'Attributes', parseAttributes(theNode),...
'Data', '',...
'Children', PC,...
'current',0);
if any(strcmp(methods(theNode), 'getData'))
nodeStruct.Data = char(theNode.getData);
else
nodeStruct.Data = '';
end
if strcmp(nodeStruct.Name,'#text')
nodeStruct=[];
end
% ----- Subfunction PARSEATTRIBUTES -----
function attributes = parseAttributes(theNode)
% Create attributes structure.
attributes = [];
if theNode.hasAttributes
theAttributes = theNode.getAttributes;
numAttributes = theAttributes.getLength;
allocCell = cell(1, numAttributes);
attributes = struct('Name', allocCell,...
'Value', allocCell);
for count = 1:numAttributes
attrib = theAttributes.item(count-1);
attributes(count).Name = char(attrib.getName);
attributes(count).Value = char(attrib.getValue);
end
end

Accepted Answer

Bruno Luong
Bruno Luong on 30 Apr 2022
Have you include PSD_FSE3D.xml in the packaging?
Do you take into account the path of the file is different when you run in standalone mode?

More Answers (3)

Sam Y.
Sam Y. on 30 Apr 2022
Yes, I added PSD_FSE3D.xml to the package. The path can be a problem. I've been wondering how to add a path to the code in terms of standalone so that it works on different computers. Now, the main file (MRiLab.m) reads the path as follows
[pathstr,name,ext]=fileparts(mfilename('fullpath'));
which is input to the SimuPanel function which opens the program's user interface
SimuPanel(pathstr);
Simupanel contains an opening function that reads the path to its own variable (MRiLabPath):
function varargout = SimuPanel(varargin)
% SIMUPANEL M-file for SimuPanel.fig
% SIMUPANEL, by itself, creates a new SIMUPANEL or raises the existing
% singleton*.
%
% H = SIMUPANEL returns the handle to a new SIMUPANEL or the handle to
% the existing singleton*.
%
% SIMUPANEL('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in SIMUPANEL.M with the given input arguments.
%
% SIMUPANEL('Property','Value',...) creates a new SIMUPANEL or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before SimuPanel_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to SimuPanel_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help SimuPanel
% Last Modified by GUIDE v2.5 26-Feb-2014 17:07:31
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @SimuPanel_OpeningFcn, ...
'gui_OutputFcn', @SimuPanel_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before SimuPanel is made visible.
function SimuPanel_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to SimuPanel (see VARARGIN)
%MALab('Welcome')
% clc;
disp( ' _______ ');
disp( '_________________________________________ / _____ \ ');
disp( ' . . |---- (OO)| ___ | | | | | ');
disp( ' /\ /\ |__ | || | / \ |___ |_| |_| ');
disp( ' / \/ \ | \ || | \___/ | \ |S| |N| ');
disp( ' / || \ | \_ || |____| \ |___/ MRI Simulator ');
disp( '_________________________________________ ');
disp( 'Version 1.2 - https://sourceforge.net/projects/mrilab/ ');
fprintf('\n');
%MRiLab path
handles.MRiLabPath=varargin{1};
% Check MEX existence
fpath = [handles.MRiLabPath filesep 'Lib' filesep 'bin'];
if exist([fpath filesep 'DoScanAtCPU.mexw64'], 'file')
% MEX exist, do nothing
else
try
fileUrl = ['http://mrilab.sourceforge.net/bin/MRiLab1.2Bin.zip'];
zipFileName = fullfile(fpath,'MRiLab1.2Bin.zip');
disp('Downloading core MEX files from MRiLab website http://sourceforge.net/projects/mrilab/');
urlwrite(fileUrl,zipFileName);
disp('Unzip files ...');
unzip(zipFileName,fpath);
rehash;
catch me
error_msg{1,1}='Some core MEX files for running MRiLab can not be configured.';
error_msg{2,1}='Please download MRiLab full version with all MEX configured from';
error_msg{3,1}='http://sourceforge.net/projects/mrilab/';
errordlg(error_msg);
return;
end
end
%System Seperator
if isunix
sep='/';
elseif ispc
sep='\';
end
handles.Sep=sep;
%Output Dir
time=clock;
OutputDir=[handles.MRiLabPath handles.Sep 'Output' handles.Sep num2str(time(1)) num2str(time(2)) num2str(time(3)) '-' num2str(time(4)) '-' num2str(time(5))];
if ~isdir(OutputDir)
mkdir(OutputDir);
handles.OutputDir=OutputDir;
else
handles.OutputDir=OutputDir;
end
%System Hardware Check
try
handles.CPUInfo=DoCPUOSChk;
if ~isempty(handles.CPUInfo)
handles.CPU_uimenu=uimenu(handles.SelectPU_uimenu,'Label',handles.CPUInfo.Name);
set(handles.CPU_uimenu,'Callback',{@Uimenu_ChkFunction, handles.CPU_uimenu});
set(handles.CPU_uimenu,'Checked','on');
end
catch me
handles.CPUInfo.NumThreads = 8; % Open up to 8 threads as default if CPU model is unknown
handles.CPU_uimenu=uimenu(handles.SelectPU_uimenu,'Label','unknown CPU model');
set(handles.CPU_uimenu,'Callback',{@Uimenu_ChkFunction, handles.CPU_uimenu});
set(handles.CPU_uimenu,'Checked','on');
error_msg{1,1}='Detecting local CPU infomation failed!';
error_msg{2,1}=me.message;
warndlg(error_msg);
end
try
handles.GPUCount=gpuDeviceCount;
if handles.GPUCount~=0
for i=1:handles.GPUCount
handles.GPUInfo=gpuDevice(i);
GPU_flag = ['GPU' num2str(i) '_uimenu'];
handles.(GPU_flag)=uimenu(handles.SelectPU_uimenu,'Label',['nVIDIA(R) ' handles.GPUInfo.Name]);
set(handles.(GPU_flag),'Callback',{@Uimenu_ChkFunction, handles.(GPU_flag)});
set(handles.(GPU_flag),'Checked','on');
end
Uimenu_ChkFunction([],[],handles.GPU1_uimenu); % Set first GPU as default processing unit
else
handles.GPU1_uimenu=uimenu(handles.SelectPU_uimenu,'Label','No GPU or unknown GPU model');
set(handles.GPU1_uimenu,'Callback',{@Uimenu_ChkFunction, handles.GPU1_uimenu});
error_msg{1,1}='Detecting local GPU infomation failed!';
warndlg(error_msg);
end
% handles.GPUInfo=gpuDevice;
% if ~isempty(handles.GPUInfo)
% % handles.GPU_uimenu=uimenu(handles.SelectPU_uimenu,'Label',['nVIDIA(R) ' handles.GPUInfo.Name ' GPU' char(ones(1,12)*32) '@ ' num2str(handles.GPUInfo.ClockRateKHz/1048576,'%3.2f') 'GHz']);
% handles.GPU_uimenu=uimenu(handles.SelectPU_uimenu,'Label',['nVIDIA(R) ' handles.GPUInfo.Name]);
% set(handles.GPU_uimenu,'Callback',{@Uimenu_ChkFunction, handles.GPU_uimenu});
% set(handles.GPU_uimenu,'Checked','on');
% Uimenu_ChkFunction([],[],handles.GPU_uimenu); % Set GPU as default processing unit
% end
catch me
handles.GPU1_uimenu=uimenu(handles.SelectPU_uimenu,'Label','No GPU or unknown GPU model');
set(handles.GPU1_uimenu,'Callback',{@Uimenu_ChkFunction, handles.GPU1_uimenu});
error_msg{1,1}='Detecting local GPU infomation failed!';
error_msg{2,1}=me.message;
warndlg(error_msg);
end
%Global Variables
global VObj; VObj=[];
global VCtl; VCtl=[];
global VMag; VMag=[];
global VCoi; VCoi=[];
global VMot; VMot=[];
global VVar; VVar=[];
try
handles.SimuAttrStruct=DoParseXML([handles.MRiLabPath handles.Sep 'PSD' handles.Sep '3D' handles.Sep 'SimuAttr.xml']);
catch ME
DoUpdateInfo(handles,'SimuAttr.xml file is missing or can not be loaded.');
% Choose default command line output for SimuPanel
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
close(hObject);
return;
end
handles.Setting_tabgroup=uitabgroup(handles.Setting_uipanel);
guidata(hObject, handles);
for i=1:length(handles.SimuAttrStruct.Children)
eval(['handles.' handles.SimuAttrStruct.Children(i).Name '_tab=uitab( handles.Setting_tabgroup,' '''title'',''' handles.SimuAttrStruct.Children(i).Name ''',''Units'',''normalized'');']);
eval(['DoEditValue(handles,handles.' handles.SimuAttrStruct.Children(i).Name '_tab,handles.SimuAttrStruct.Children(' num2str(i) ').Attributes,1,[0.2,0.12,0.01,0.1,0.1,0.05]);']);
handles=guidata(hObject);
end
% Disable scan button when change settings
fieldname=fieldnames(handles.Attrh1);
for i=1:length(fieldname)/2
set(handles.Attrh1.(fieldname{i*2}),'Callback',{@DoDisableButton,handles});
end
% Turn off uitab warning
% warning('off', 'last');
handles.CoilSel_tabgroup=uitabgroup(handles.CoilSel_uipanel);
handles.CoilTx_tab=uitab( handles.CoilSel_tabgroup, 'title', 'Tx');
handles.CoilRx_tab=uitab( handles.CoilSel_tabgroup, 'title', 'Rx');
% Choose default command line output for SimuPanel
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);

Sam Y.
Sam Y. on 30 Apr 2022
Edited: Sam Y. on 30 Apr 2022
So currently the program reads the path according to the MRiLab folders.
Do I need to program standalone code for compilation with an absolute path reference that I know is located on the target machine?
  4 Comments
Sam Y.
Sam Y. on 1 May 2022
Thank you very much Bruno! I now got a standalone to work on my two different computers. I took advantage of your getcurrentdir code and added the folders contained in the MRiLab program to the standalone folder, which the program utilizes (picture below). This was a great help to me!
BR, SY

Sign in to comment.


Image Analyst
Image Analyst on 30 Apr 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by