Run Matlab function (*.m) in subdir / path of file stands in variable - matlab

I want to run a function "folder/test.m". This path stands in a variable "var_path". How do I run the function with parameters?

You can use system command.
For example:
sys_com = ['C:\path\to\matlab.exe ', var_path, ' ', parameter1, ' ', parameter2];
system(sys_com);
First line creates a command as a string (parameters should be strings). Second line executes that string.

you can either change dir to var_path and then run test as a regular funciton.
Alternatively, you can add var_path to your path and run test.

Matlab does not allow including function files (like in C/C++, for example). There are two possbilities to achieve something similar:
Change the folder during script execution
Change the search path to make the function file visible to the Matlab interpreter
Example for 1:
cur_dir = pwd; % save current directory
cd(var_path); % change to directory containing the function
test(a, b);
cd(pwd); % change back to original directory
This can have unwanted side effects of course, e.g. if your script relies on other files in the current directory or if you write to files.
Example for 2:
cur_path = path(); % save current path variable
addpath(var_path); % add function path to Matlab path
test(a, b);
setpath(cur_path); % restore original path variable

Related

Matlab: set current working directory as top priority in path

In one of my projects, I have a Matlab function called eom.m. When I try to call it, I get errors. I have realised this is because Matlab calls a simulink file, eom.slx, instead, which is in one of the toolboxes.
I would prefer not to rename the function, so I was wondering how I could change the order in the Matlab path so that the folder I call Matlab from always has top priority. That is to say how I can ensure that the files in my current working directory are always those that are called in fact.
Thank you for the help!
You can do it programmatically using addpath with the '-begin' option.
You can use command syntax:
addpath c:/path/you/want -begin
Enclose with quotes if the path contains spaces:
addpath 'c:/path /you/ want' -begin
Alternatively, you can use function syntax:
addpath('c:/path/you/want', '-begin')
This allows having the path stored in a variable:
p = 'c:/path/you/want';
addpath(p, '-begin')

Shortcut for saving file in current directory with correct name?

Is there any shortcut for saving an open file into the current directory with the current name? If I download multiple files with the same name they go into my Downloads folder and they end up with names like function (1).m instead of function.m.
At this point it's easy to open the file and see the contents by opening the file from my web browser- MATLAB sees the file extension and opens it. However, if it's a function, I have to Save As and move/rename the file before I'm able to use the code.
Edit: Since MATLAB insists that the file name be the same as the function name I'm hoping that there's a shortcut that saves an open file directly to the current MATLAB path and names it appropriately.
Since MATLAB convention is that the file name is the same as the function name I'm hoping that there's a shortcut that saves an open file directly to the current MATLAB path and names it according to the function name specified in the file.
You will need a directory which is always on the Matlab path. This can be achieved by adding one in the startup.m script.
Then you should save the below function savefunc.m to that directory, so you can always call it.
function savefunc(FuncName, Directory)
% Set directory if not given, default is working directory
if nargin < 2; Directory = pwd; end
% Get active document
ActiveDoc = matlab.desktop.editor.getActive;
% Set FuncName if not given, or if FuncName was empty string
if nargin < 1 || strcmp(FuncName, '');
% Get function name
FuncName = ActiveDoc.Text; % Entire text of document
% Could use indexing to only take first n characters,
% and not load entire string of long function into variable.
% FuncName = ActiveDoc.Text(1:min(numel(ActiveDoc.Text), n));
FuncName = strsplit(FuncName, '('); % Split on parenthesis
FuncName = FuncName{1}; % First item is "function [a,b,c] = myFunc"
FuncName = strsplit(FuncName, ' '); % Split on space (functions don't always have equals)
FuncName = strtrim(FuncName{end}); % Last item (without whitespace) is "myFunc"
end
% Save the file
saveAs(ActiveDoc, fullfile(Directory, [FuncName, '.m']));
end
Now, say you have just created the following Untitled.m:
function [a,b,c] = mytest()
a = 1; b = 1; c = 1;
end
The shortcut: just have Untitled.m open, and type into the Command Window
savefunc()
Untitled.m will be saved as mytest.m in the current working directory. Notice you can also pass a different function name and save-as directory if you wish, making this useful for other occasions.
You can pass an empty string as the FuncName if you want to specify the directory but use the auto-naming.
You could extend this using matlab.desktop.editor.getAll to get all open documents, then loop through them for saving.
For more info, type help matlab.desktop.editor in the Command Window, online documentation seems lacking.
matlab.desktop.editor: Programmatically access the MATLAB Editor to open, change, save, or close
documents.
Finally, note there is no need for a "Save successful" type message, since you will see the file name change, and also receive an error if it fails (from the saveAs docs):
If any error occurs during the saveAs operation, MATLAB throws a MATLAB:Editor:Document:SaveAsFailed exception. If the operation returns without an exception being thrown, assume that the operation succeeded.

MATLAB: Save figure with default name

I am running a matlab-script that produces a figure. To save this figure I use:
print(h_f,'-dpng','-r600','filename.png')
What this means is that if I don't change filename for each time I run the script, the figure filename.png will be overwritten.
Is there a way to save a figure to a default name, e.g. untitled.png, and then when the script is run twice it will make a new figure untitled(1).png instead of overwriting the original one?
You could create a new filename based on the number of existing files
defaultName = 'untitled';
fileName = sprintf('%s_%d.png', defaultName, ...
length(dir([defaultName '_*.png'])));
print(h_f,'-dpng','-r600', fileName)
Add a folder path to your dir search path if the files aren't located in your current working directory.
This will create a 0-index file name list
untitled_0.png
untitled_1.png
untitled_2.png
untitled_3.png
...
You could also use tempname to generate a long random name for each iteration. Unique for most cases, see section Limitations.
print(h_f,'-dpng','-r600', [tempname(pwd) '.png'])
The input argument (pwd in the example) is needed if you do not want to save the files in your TEMPDIR
You can try something like this:
for jj=1:N
name_image=sscanf('filename','%s') ;
ext=sscanf('.png','%s') ;
%%do your stuff
filename=strcat(name_image,num2str(jj),ext);
print(h_f,'-dpng','-r600',filename)
end
If you want to execute your script multiple time (because you don't want to use a "for") just declare a variable (for example jjthat will be incremented at the end of the script:
jj=jj+1;
Be careful to don't delete this variable and, when you start again your script, you will use the next value of jj to compose the name of the new image.
This is just an idea

Run callback to change to current directory when opening files

When I open MATLAB, it defaults to open to /home/myUser. Whenever I open a file interactively (say I run Simulink and click "Open...") the dialog will start in /home/myUser. Then I might go into /home/myUser/myDir1/myDir2/ before clicking on myModel.mdl.
If I open a different Simulink file with the "Open..." dialog again, it'll kick me back to /home/myUser. Note that this is regardless of file, I'm just using Simulink as an example. I would like to keep it in /home/myUser/myDir1/myDir2, meaning I should be in the same directory as the last file I just opened (or saved).
Programatically, I would set up a callback to cd into whatever directory the file I chose was in after selecting the file using uigetfile. Is this possible to do just with MATLAB's own "Open" or "Save As" commands?
There is a wrapper for uigetfile that remembers the last director on the file exchange. You can get wrappers for the other file dialogs as well from the same author.
EDIT
How to overload the built-in uigetdir etc.
(1) Rename uigetdir2 to uigetdir, and make sure it's in a path that has precedence over the path for the built-in function (this should be the case by default).
(2) Use BUILTIN to ensure that the new function doesn't call itself.
(2) Since uigetdir is implemented as a .m-file, as opposed to being compiled (like sum), the builtin command doesn't work for it. Thus, open uigetdir, find the private function uigetdir_helper (which is private, so we can't call it), and finally uncover the java method (that turns out to have changed from R2011a to R2011b. Yay.). This allows us to finally overload uigetdir at the cost of having to parse the input ourselves.
Here's lines 37 to 67 from the modified uigetdir
%% Check passed arguments and load saved directory
% if start path is specified and not empty call uigetdir with arguments
% from user, if no arguments are passed or start path is empty load saved
% directory from mat file
% parse inputs
parserObj = inputParser;
parserObj.FunctionName = 'uigetdir';
parserObj.addOptional('startPath',[],#(x)exist(x,'dir'));
parserObj.addOptional('dialogTitle','Please choose directory',#ischar);
parserObj.parse(varargin{:});
inputList = parserObj.Results;
% create directory dialog instance - this has changed from 2011a to 2011b
if verLessThan('matlab','7.13')
dirdlg = UiDialog.UiDirDialog();
else
dirdlg = matlab.ui.internal.dialog.FolderChooser();
end
dirdlg.InitialPathName = inputList.startPath;
dirdlg.Title = inputList.dialogTitle;
if nargin > 0 && ~isempty(inputList.startPath)
% call dirdlg instead of uigetdir to avoid infinite recursion
dirdlg.show();
% if dirname empty, return 0 for uigetdir.
directory_name = dirdlg.SelectedFolder;
else
% set default dialog open directory to the present working directory
lastDir = pwd;
% load last data directory
if exist(lastDirMat, 'file') ~= 0
% lastDirMat mat file exists, load it
load('-mat', lastDirMat)
% check if lastDataDir variable exists and contains a valid path
if (exist('lastUsedDir', 'var') == 1) && ...
(exist(lastUsedDir, 'dir') == 7)
% set default dialog open directory
lastDir = lastUsedDir;
end
end
dirdlg.InitialPathName = lastDir;
% call dirdlg instead of uigetdir to avoid infinite recursion
dirdlg.show();
% if dirname empty, return 0 for uigetdir.
directory_name = dirdlg.SelectedFolder;
end

How to include the general file name, taken as function argument in Matlab, in the path location?

BRIEF SUMMARY OF WHAT I WANT: If I take a file name as argument of a function, how do I include that file name in the path location such that the name of the file in the path location is the one user enters. If you didn't understand what I am saying, then read below for explanation:
SECONDARY EXPLANATION:
I am making a general function which requires calling a software called CMG. The software needs a .dat file, whose name I am taking as argument in the function with general name in the argument as ReservoirModel_CMGBuilder. As you can see in the partial code below, this ReservoirModel_CMGBuilder file is kept in a folder whose path location I have entered. However the problem is since the file name is in quotes, so it does not identify the file name in the code. What I want is I take name of the .dat file name, needed for CMG, from the user and store it in name ReservoirModel_CMGBuilder, and then use this name in the path location to pick up that file.
Similarly I want to do this thing for Reportq_rwd and Reportq_rwo. How can I do this?
function [q_yearly,Swav_yearly]=q_from_CMG_general(nModel,nCell,T,ReservoirModel_CMGBuilder,poro_models_gslib_file,perm_models_gslib_file,Reportq)
ReservoirModel_CMGBuilder=[ReservoirModel_CMGBuilder '.dat']; % string concatenation
Reportq_rwd=[Reportq '.rwd'];
Reportq_rwo=[Reportq '.rwo'];
poro_models=gslib_file_to_matlab_var(nModel,nCell,poro_models_gslib_file);
perm_models=gslib_file_to_matlab_var(nModel,nCell,perm_models_gslib_file);
%% loop to run all nModel
for model_no=1:nModel
%% Writing the porosity and permeability model one at a time in .inc file, which will be read and will work as input to porosity and permeability models in CMG
dlmwrite('poro_model.inc',poro_models(:,model_no),'delimiter','\n');
dlmwrite('perm_model.inc',perm_models(:,model_no),'delimiter','\n');
%% Prior to driling an exploratory well or acquiring a seismic with just 5 producing wells
%# Calls CMG
system('mx200810.exe -f "C:\Documents and Settings\HSingh2\Desktop\Work\Model - SGEMS, CMG and MATLAB\ReservoirModel_CMGBuilder"') % Calls CMG
%# Calls parameter report file and generates output file
system('report.exe /f Reportq_rwd /o Reportq_rwo')
If you concatenate something like this:
['foo"' bar '"baz']
you get a string like this: foo"bar"baz
So for your question:
system(['mx200810.exe -f "C:\Documents and Settings\HSingh2\Desktop\Work\Model - SGEMS, CMG and MATLAB\' ReservoirModel_CMGBuilder '"']) % Calls CMG
%# Calls parameter report file and generates output file
system(['report.exe /f "' Reportq_rwd '" /o "' Reportq_rwo '"'])
It might be easier to use sprintf:
system(sprintf('mx200810.exe -f "%s"', ...
fullfile('c:', 'Documents and Settings', 'HSingh2', ...
'Desktop', 'Work', 'Model - SGEMS, CMG and MATLAB', ...
ReservoirModel_CMGBuilder)));
Also not the use of fullfile to construct the path name -- it'll automatically insert the right kind of path separator. Note if you want to use a \ in sprintf you need to escape it with a backslash.