run matlab and pass integer parameter from command line - matlab

I have a matlab function and I was able to run it from command line. Now I want to pass a parameter to the file from command line. The parameter is a integer. It seems when I pass from command line, it is always taken as a "char".
Here is how I run the command
matlab -nodesktop -nosplash -r "mycommand 3"
For example, if I have a function as
function [ ] = mycommand( a )
a = a+3;
disp(a)
end
it prints 54 instead of 6.
Is there a way to work around this? I don't want to check the type of the variable in my code.
Thanks

You need to execute the function as you would in the matlab interpreter:
matlab -nodesktop -nosplash -r "mycommand(3)"
(Notice the parenthesis around the 3)

MarkD gave a good answer. Although you mentioned you might be unhappy doing this (I'm sure for good reasons), another option would be to put a little extra code in to the beginning of your function, which would convert character inputs to numerical if the command were called via matlab -r:
if ischar(a)
a = str2num(a);
end

Related

Undefined function or variable in Matlab when calling a function from cmd

I have a function in Matlab like this:
function func(v1)
v1
end
and I want to call it from cmd.
so when I call it in cmd with command like
matlab -nodisplay -r "func("hello");"
I face an error:
Undefined function or variable 'hello'.
but I just want to have string "hello" in my function.
when I try a function which has not any argument, it works properly. but the error occurs when I want to pass argument to the function.
any help will be appreciated.
You want to use single quotes here:
matlab -nodisplay -r "func('hello');"

Get command line arguments in matlab

This is probably too easy, but I cannot google the answer for this: how can I get command line arguments in matlab script.
I run matlab as matlab -nodisplay -r "run('script.m')" and I want to return all arguments as a list. Something similar to python sys.argv. How can I do this?
I'm using Linux Mint and MATLAB 2015a.
I came up with a simple function that works on both Windows and Linux (Ubuntu):
function args = GetCommandLineArgs()
if isunix
fid = fopen(['/proc/' num2str(feature('getpid')) '/cmdline'], 'r');
args = textscan(fid, '%s', 'Delimiter', char(0));
fclose(fid);
else
kernel32WasAlreadyLoaded = libisloaded('kernel32');
if ~kernel32WasAlreadyLoaded
temporaryHeaderName = [gettempfolder '\GetCommandLineA.h'];
dlmwrite(temporaryHeaderName, 'char* __stdcall GetCommandLineA(void);', '');
loadlibrary('kernel32', temporaryHeaderName);
delete(temporaryHeaderName);
end
args = textscan(calllib('kernel32', 'GetCommandLineA'), '%q');
if ~kernel32WasAlreadyLoaded
unloadlibrary kernel32;
end
end
args = args{1};
On your sample call, it would return this:
>> GetCommandLineArgs
args =
'/[path-to-matlab-home-folder]/'
'-nodisplay'
'-r'
'run('script.m')'
It returns a cell array of strings, where the first string is the path to MATLAB home folder (on Linux) or the full path to MATLAB executable (on Windows) and the others are the program arguments (if any).
How it works:
On Linux: the function gets the current Matlab process ID using the feature function (be aware it's an undocumented feature). And reads the /proc/[PID]/cmdline file, which on Linux gives the command line arguments of any process. The values are separated by the null character \0, hence the textscan with delimiter = char(0).
On Windows: the function calls GetCommandLineA, which returns the command line arguments on a string. Then it uses textscan to split the arguments on individual strings. The GetCommandLineA function is called using MATLAB's calllib. It requires a header file. Since we only want to use one function, it creates the header file on the fly on the temporary folder and deletes it after it's no longer needed. Also the function takes care not to unload the library in case it was already loaded (for example, if the calling script already loads it for some other purpose).
I am not aware of a direction solution (like an inbuilt function).
However, you can use one of the following workarounds:
1. method
This only works in Linux:
Create a file pid_wrapper.m with the following contents:
function [] = pid_wrapper( parent_pid )
[~, matlab_pid] = system(['pgrep -P' num2str(parent_pid)]);
matlab_pid = strtrim(matlab_pid);
[~, matlab_args] = system(['ps -h -ocommand ' num2str(matlab_pid)]);
matlab_args = strsplit(strtrim(matlab_args));
disp(matlab_args);
% call your script with the extracted arguments in matlab_args
% ...
end
Invoke MATLAB like this:
matlab -nodisplay -r "pid_wrapper($$)"
This will pass the process id of MATLAB's parent process (i.e. the shell which launches MATLAB) to wrapper. This can then be used to find out the child MATLAB process and its command line arguments which you then can access in matlab_args.
2. method
This method is OS independent and does not really find out the command line arguments, but since your goal is to pass additional parameters to a script, it might work for you.
Create a file vararg_wrapper.m with the following contents:
function [] = wrapper( varargin )
% all parameters can be accessed in varargin
for i=1:nargin
disp(varargin{i});
end
% call your script with the supplied parameters
% ...
end
Invoke MATLAB like this:
matlab -nodisplay -r "vararg_wrapper('first_param', 'second_param')"
This will pass {'first_param', 'second_param'} to vararg_wrapper which you can then forward to your script.

Sending commands to FWTools via Matlab?

I am trying to use Matlab to send commands to FWTools in order to project a bunch of .shp files.
I am able to start FWTools from Matlab but I cant figure out how to send it commands without my interaction.
So far FWTools starts and my matlab command window and acts like the FWTools shell. I type commands and it will run, but I want to be able to send them in my .m file. Once FWTools starts up, my script will not continue to the next line of code.
My code so far:
cmd = 'ogr2ogr -s_srs "EPSG:4326" -t_srs "EPSG:3006" out_sweref99tm.shp in_wgs84.shp';
system('C:\Windows\system32\cmd.exe \K "d:\FWTools2.4.7\setfw.bat" ')
sprintf('%s',cmd) % try to send cmd to matlab command window aka FWTools
I also tried to put the cmd into my system call but that returned an error since it appears that I am trying to call FWTools with a super long string afterwards :(
cmd = 'ogr2ogr -s_srs "EPSG:4326" -t_srs "EPSG:3006" out_sweref99tm.shp in_wgs84.shp';
system(['C:\Windows\system32\cmd.exe \K "d:\FWTools2.4.7\setfw.bat" ',cmd])
The reason I am using FWTools is that I am projecting from WGS84 to SWEREF99TM and (from my understanding) its not easy to get the final projection via Matlab's mapping toolbox. Please correct me if I am wrong as I would love to keep it to Matlab.
And if possible, I would like to stay in Matlab and not move to Python.
Thanks.
Norris
The call of C:\Windows\system32\cmd.exe is not necessary.
Try this:
cmd = 'ogr2ogr -s_srs "EPSG:4326" -t_srs "EPSG:3006" out_sweref99tm.shp in_wgs84.shp';
system(['d: && cd d:\FWTools2.4.7\ && setfw.bat ',cmd])
or if you actually need to pass your parameters after the first call and not with:
system(['d: && cd d:\FWTools2.4.7\ && setfw.bat && ',cmd])
Maybe you can post a screenshot of how it looks like when you do it manually.
requested explanation:
The && operator is implicating that the following command is executed "in the next line". It's like you press enter in the cmd window and then you have to type the next command.
For example cd d:\FWTools2.4.7\ does never work directly, as the default is usually "c:". So firstly have to type d: and in the next step you change to your folder cd d:\FWTools2.4.7\

Running a matlab program with arguments

I have a matlab file that takes in a file. I would like to run that program in the matlab shell, such as prog. I need to implement it so that it takes a number of arguments, such as "prog filename.txt 1 2 which would mean that i can use filename.txt and 1 2 as variables in my program.
Thank you!
In order to make a script accept arguments from the command line, you must first turn it into a function that will get the arguments you want, i.e if your script is named prog.m, put as the first line
function []=prog(arg1, arg2)
and add an end at the end (assuming that the file has only one function). It's very important that you call the function the same name as the file.
The next thing is that you need to make sure that the script file is located at the same place from where you call the script, or it's located at the Matlab working path, otherwise it'll not be able to recognize your script.
Finally, to execute the script you use
matlab -r "prog arg1 arg2"
which is equivalent to calling
prog(arg1,arg2)
from inside Matlab.
*- tested in Windows and Linux environments
Once your function is written in a separate file, as discussed by the other answer you can call it with a slightly more complicated setup to make it easier to catch errors etc.
There is useful advice in this thread about ensuring that Matlab doesn't launch the graphical interface and quits after finishing the script, and reports the error nicely if there is one.
For example:
matlab -nodisplay -nosplash -r "try, prog(1, 'file.txt'), catch me, fprintf('%s / %s\n',me.identifier,me.message), exit(1), end, exit(0)"
The script given to Matlab would read as follows if line spaces were added:
% Try running the script
try
prog(1, 'file.txt')
catch me
% On error, print error message and exit with failure
fprintf('%s / %s\n',me.identifier,me.message)
exit(1)
end
% Else, exit with success
exit(0)

suppress start message of Matlab

I want to call matlab in bash non-interactively and use its result outside Matlab.
For example, I have a script test.m
rand(3,4)
quit
When I execute in bash
$ matlab -nosplash -nodesktop -nodisplay -r test
Warning: No window system found. Java option 'MWT' ignored
< M A T L A B (R) >
Copyright 1984-2008 The MathWorks, Inc.
Version 7.7.0.471 (R2008b)
September 17, 2008
To get started, type one of these: helpwin, helpdesk, or demo.
For product information, visit www.mathworks.com.
ans =
0.8147 0.9134 0.2785 0.9649
0.9058 0.6324 0.5469 0.1576
0.1270 0.0975 0.9575 0.9706
Is it possible to suppress the start message of Matlab and only show the results also without "ans=".
Note I am asking a general question not just for this example.
Thanks and regards!
Try using the -logfile command line option:
-logfile log - Make a copy of any output to the command window
in file log. This includes all crash reports.
Then you can easily remove the first few lines using any way you want (sed for example). Example:
matlab.exe -nosplash -nodesktop -nojvm -logfile out.log -r 'rand(3,3), exit'
sed '1,5d' out.log
Also if you are running from a script where you need it to finish running before continuing, use the -wait option:
-wait - MATLAB is started by a separate starter program
which normally launches MATLAB and then immediately
quits. Using the -wait option tells the starter
program not to quit until MATLAB has terminated.
This option is useful when you need to process the
the results from MATLAB in a script. The call to
MATLAB with this option will block the script from
continuing until the results are generated.
More info on MATLAB startup options can be found here, or in the matlab executable reference pages: Windows/Unix
You could use the Unix command "tail +n" to remove the first n lines of output. That header looks like 10 lines, so this will strip it.
$ matlab -nosplash -nodesktop -nodisplay -r test | tail +10
This is a little fragile, though, since warnings (like that "no window system") will get stripped, and the header size will vary depending on what warnings happen (and those warnings are useful diagnostics). Also, that warning might be on STDERR instead of STDOUT, so "tail +9" might be what you need.
A more robust approach could be to modify the Matlab script to write to a separate file using fopen/fprintf/fclose. That way the header, warnings, errors, etc from Matlab will be separated from the formatted output you want. To get the "disp" output to go to that separate file handle, you can capture it using evalc. The outfile could be specified using an argument to test() in the -r message, and the $$ env variable (the bash process's PID) incorporated in the file name to prevent collisions in a multiprocess environment.
function test(ppid)
outfile = sprintf('outfile-%d.tmp', ppid);
fh = fopen(outfile, 'w');
myvar = rand(3,4);
str = evalc('disp(myvar)');
fprintf(fh, '%s', str);
fclose(fh);
To invoke it from bash, use this calling form. (May be minor syntax problems here; I don't have a Unix box to test on right now.)
% matlab -nosplash -nodisplay -r "test($$)" -logfile matlab-log-$$.tmp
Let's say your bash PID is 1234. Now you've got your output in outfile-1234.tmp and a Matlab log in matlab-log-1234.tmp. Stick them in /tmp if you don't want to be dependent on pwd. You could extend this to create multiple output files from a single matlab invocation, saving the startup costs if you need to compute multiple things.
I'd recommend saving the output to a file, and then reading in that file. This approach is slightly more complicated, but less fragile as formats change etc. It gives you much more control. You'll find plenty of scripts on the web to transform Matlab files to a different host language.
Example:
A = randn(3, 2);
save temp_output.mat A
# Later, read temp_output.mat in whichever language you desire.
To suppress the display of ans =, you can use the DISP function:
disp(rand(3,4));
To suppress that first warning message, you can try adding in the option -nojvm to see if that helps.
To suppress everything else, you can try this solution from a MathWorks Newsgroup thread that addresses the same problem.
Calling MATLAB like this
matlab -nodisplay <test.m &>matlab.output
will dump all of the startup messages and other displayed output into the matlab.output file (which can be named anything you want). If you then (following Peter's suggestion) have test.m save the result that you need to a file using
csvwrite('temp_output.txt',A)
or another appropriate output function you can then read in this file and proceed.