I have a Matlab .m file that I usually run interactively. I would like to run some jobs overnight, WITHOUT re-writing the .m file to remove the interactive queries for input. I used to be able to do this with Fortran or C or VB executables by running a batch file from the OS's command line. Is this possible with Matlab? (Also, I don't have the Matlab compiler. But I can have Matlab open the whole time.)
Skeleton of Program:
Input variable1 from keyboard;
Input variable2 from keyboard;
Long calculation;
Save results to file;
Stop
But, if I make a "batch" .m file to run Program, like this:
Program
0.2
0.47
Program
1.2
2.4
then Program just sits there forever waiting for my input from the keyboard. Is there a way to run Program so that it gets its interactive inputs from the calling .m file?
What environment/operating system are you working on? You refer to a batch file which leads one to think you are working in Windows. If you are working in Linux, you can use the echo command and pipe the results into your program. For example:
#my_bash_script.sh
echo "0.2
0.47
" | Program
Perhaps you can do something similar if you are working with Windows batch files. Check out this as one resource:
https://ss64.com/nt/syntax-redirection.html
This is a workaround, not an answer, but it is too long for a comment. After researching this for a while, I don't think Matlab can do what the question requests. (Not without compiling the Matlab code into an executable.) I got around it by writing a function (call it Meta) that reads the entire "batch" file of responses and returns them as a string array. I gave Program two extra input parameters: a flag for interactive/batch running (FlagBatch), and a string for the batch filename (BatchName). If FlagBatch is 1, Program uses Meta to read BatchName and generate ResponseArray, which is used to provide responses to any requests from Program. Kludgey, but it works, with minimal reprogramming of Program. (Of course, I had to have access to Program's code, but if I'd only had an executable from someone else, then I wouldn't have had this problem in the first place!)
Another workaround. Define myinput (see below), and use that everywhere to replace input. As in my other workaround, you give Program two extra input parameters: a flag for interactive/batch running (FlagBatch), and a string for the batch filename (BatchName). Also have
if FlagBatch==1, fid=open(BatchName); end
near top of Program. This approach is nice when you have dozens of input statements scattered all over Program (and various subroutines/functions).
function A=myinput(fileID,prompt,formatSpec,sizeA)
% A=myinput(fileID,prompt,formatSpec);
% Function myinput will read from either stdin (keyboard) or from a file,
% allowing programs' inputs to be entered interactively or from a file.
% Use it instead of Matlab's built-in functions input and fscanf.
% fileID = file ID (fid) of the opened file, or 0 for keyboard input.
% prompt = the prompt string (not used for file input)
% formatSpec = string containing Matlab format spec;
% not used for keyboard input
% sizeA = size of A; basically specifies how many times to use formatSpec;
% not used for keyboard input
%
% Example Uses in Program (where fid would have been set earlier):
% NumOrcs=myinput(fid,'Enter # of orcs','%i',1);
% MapFile=myinput(fid,'Enter filename for LotR map','s',1);
% [Sgimli,Slegolas]=myinput(fid,'Strengths of Gimli and Legolas?','%g',2);
%
if fileID==0
if formatSpec=='%s'
A=input(prompt,'s');
else
A=input(prompt);
end
else
A = fscanf(fileID,formatSpec, sizeA);
end
return
Related
I'm looking for a command to get a general file path in MATLAB. I'm looking to be able to run my code across multiple computers.
Example
fullfile('','C:','users','XXXXXX','Desktop','Matlab Data')
Is it possible to get this fullfile location off of where the MATLAB code is stored so that it can be used later in the code for file execution, regardless of what computer it's executing it?
From within a function called foo:
function x = foo( )
x=fullfile(fileparts(mfilename('fullpath')),'lorem','ipsum');
% fun stuff
end
This should work regardless of your current working directory.
Background
Say I compile the following simple function in MATLAB
function foo(path_to_m_file)
disp([' Running ' path_to_m_file])
run(path_to_m_file);
end
The function foo just takes a path to an .m file and tries to run it.
However, when I actually try to run foo after compiling it:
./run_foo.sh $path_to_run_time $path_to_m_file
where path_to_m_file is a simple .m file with a statement such as:
a = 2;
I get the following error:
Error using ==> run
MATLAB:run:FileNotFound
However, I know that foo gets the correct path. For example, if I try replacing the line with run by the following two lines in foo
fID = fopen(conf_file, 'rt');
first_line = textscan(fID, '%s', Inf, 'Delimiter', '\n');
foo reads the corresponding line of the .m file. So the .m file is there, and the MATLAB engine can "see" it. Indeed I can even run eval on strings read with textscan.
So my questions are:
Why do I get the error above? Why doesn't foo run the .m file?
Update: See #strictlyrude27's answer below for what seems to be an answer to this question.
If the above doesn't work. Is there a way to get a MATLAB-compiled function to run an .m file that may have changed after compiling the original function?
The motivation for my second question:
I would like to have the ability to "update" an .m file that is part of the project without having to re-compile the full project. Any ideas for this would be greatly appreciated.
From the MATLAB Compiler's documentaton:
Compiled Applications Do Not Process MATLAB Files at Runtime
The MATLAB Compiler was designed so that you can deploy locked down functionality. Deployable MATLAB files are suspended or frozen at the time MATLAB Compiler encrypts them—they do not change from that point onward. This does not mean that you cannot deploy a flexible application—it means that you must design your application with flexibility in mind. If you want the end user to be able to choose between two different methods, for example, they both must be compiled in.
The MCR only works on MATLAB code that was encrypted when the component was built. Any function or process that dynamically generates new MATLAB code will not work against the MCR.
Some MATLAB toolboxes, such as the Neural Network Toolbox™ product, generate MATLAB code dynamically. Because the MCR only executes encrypted MATLAB files, and the Neural Network Toolbox generates unencrypted MATLAB files, some functions in the Neural Network Toolbox cannot be deployed.
Similarly, functions that need to examine the contents of a MATLAB function file cannot be deployed. HELP, for example, is dynamic and not available in deployed mode. You can use LOADLIBRARY in deployed mode if you provide it with a MATLAB function prototype.
Instead of compiling the function that generates the MATLAB code and attempting to deploy it, perform the following tasks:
Run the code once in MATLAB to obtain your generated function.
Compile the MATLAB code with MATLAB Compiler, including the generated function.
Tip: Another alternative to using EVAL or FEVAL is using anonymous function handles.
If you require the ability to create MATLAB code for dynamic run time processing, your end users must have an installed copy of MATLAB.
You can read read an m file, line by line and execute each line with the eval() function. There are restrictions on the format of the m file (no line breaks for example, each line must contain a complete MATLAB statement) but it does work and can add to your run time environment inside the compiled application. I use this technique to allow users to define configuration and data files for a compiled application I have developed.
Clearly, if your end user provides a poorly formed m file to evaluate, you will end up with difficult to resolve bugs.
I have two Matlab sessions runs parallel.
To be handy, I just change the parameters that are hard-coded into the scripts for each run.
So my question is, can I change the script when the first Matlab session is running that script? After I changed and saved that very script, will the first Matlab session run according to the original version of the script?
I have multiple scripts that call each other. Will it be more complicated in this situation?
If the answer is YES, it will appear to me that for each run, Matlab will make a ad-hoc copy of all the scripts and run that copy regardless of the hard-disk changes.
MATLAB's first step after you press "run" is to parse all the script/function's M-code and all of its dependencies into something akin to "byte code". That means that whatever MATLAB is running, is entirely in memory and thus not coupled anymore to what's in the M-file(s).
Therefore, you may indeed use another MATLAB session to change parameters in an M-file, save it, and run it in the new session, without affecting what the outcomes of the first session are.
Be sure to save or print the values of those variables though; working this way is a sure way to forget what values of those parameters belong to which session again :)
Note that this is NOT true for:
data files, or other files explicitly read during runtime
MEX files
A better workflow would be to convert those scripts into modular functions that receive configurable parameters as input, as opposed to hardcoding the values in the code.
That way you call the same function in each MATLAB session without making any changes to the M-files, only each session passes different input arguments as needed.
To learn more about how MATLAB detects changes in M-files, run the following:
>> help changeNotification
>> help changeNotificationAdvanced
You also might also wanna read about the following functions: rehash and clear functions
EDIT:
One way to find out which scripts/functions are currently "loaded in memory" is to use inmem. Say for example we have the following script saved in a file available on the path (the same works for functions):
testScript.m
x = 10;
disp(x)
Now starting with a clean session, the script is initially not loaded. After calling the script, the file is loaded and remains in memory:
% initially not loaded
>> ismember('testScript', inmem())
ans =
0
% execute script
>> testScript
10
% file is cached in memory
>> ismember('testScript', inmem())
ans =
1
Immediately continuing with the same session, make an edit to the file (for example change x to 99). By checking the list of loaded functions/scripts again, you will see that MATLAB has already detected the change, and invalidated the cached version by removing it from memory:
>> % .. make changes to testScript.m file
% file is automatically unloaded
>> ismember('testScript', inmem())
ans =
0
% execute the new script
>> testScript
99
% the result is cached once more
>> ismember('testScript', inmem())
ans =
1
I tested the above on my Windows machine, but I can't guarantee this behavior is cross-platform, you'll have to test it on Mac/Linux and see if works the same...
The script can definately be altered without influencing an ongoing run. However, if your flow gets more complicated it can be problematic to depend on what will happen:
Here are some flows you will not likely want:
main1 calls sub
sub is edited
main2 calls sub
main1 continues to run and calls sub for a second time
In the above case I would expect the second run of main1 to be calling the altered version of sub, but I would not depend on it.
main1 calls sub
sub is edited
sub called by main1 hits a breakpoint
I am not even sure what will happen, but I believe that you will stop on the original line, but will see the edited code. So the line you find may not even be the line with the breakpoint anymore.
So to conclude: Don't alter your script frequently to change the output, rather give it inputs that will determine the output.
Background
Say I compile the following simple function in MATLAB
function foo(path_to_m_file)
disp([' Running ' path_to_m_file])
run(path_to_m_file);
end
The function foo just takes a path to an .m file and tries to run it.
However, when I actually try to run foo after compiling it:
./run_foo.sh $path_to_run_time $path_to_m_file
where path_to_m_file is a simple .m file with a statement such as:
a = 2;
I get the following error:
Error using ==> run
MATLAB:run:FileNotFound
However, I know that foo gets the correct path. For example, if I try replacing the line with run by the following two lines in foo
fID = fopen(conf_file, 'rt');
first_line = textscan(fID, '%s', Inf, 'Delimiter', '\n');
foo reads the corresponding line of the .m file. So the .m file is there, and the MATLAB engine can "see" it. Indeed I can even run eval on strings read with textscan.
So my questions are:
Why do I get the error above? Why doesn't foo run the .m file?
Update: See #strictlyrude27's answer below for what seems to be an answer to this question.
If the above doesn't work. Is there a way to get a MATLAB-compiled function to run an .m file that may have changed after compiling the original function?
The motivation for my second question:
I would like to have the ability to "update" an .m file that is part of the project without having to re-compile the full project. Any ideas for this would be greatly appreciated.
From the MATLAB Compiler's documentaton:
Compiled Applications Do Not Process MATLAB Files at Runtime
The MATLAB Compiler was designed so that you can deploy locked down functionality. Deployable MATLAB files are suspended or frozen at the time MATLAB Compiler encrypts them—they do not change from that point onward. This does not mean that you cannot deploy a flexible application—it means that you must design your application with flexibility in mind. If you want the end user to be able to choose between two different methods, for example, they both must be compiled in.
The MCR only works on MATLAB code that was encrypted when the component was built. Any function or process that dynamically generates new MATLAB code will not work against the MCR.
Some MATLAB toolboxes, such as the Neural Network Toolbox™ product, generate MATLAB code dynamically. Because the MCR only executes encrypted MATLAB files, and the Neural Network Toolbox generates unencrypted MATLAB files, some functions in the Neural Network Toolbox cannot be deployed.
Similarly, functions that need to examine the contents of a MATLAB function file cannot be deployed. HELP, for example, is dynamic and not available in deployed mode. You can use LOADLIBRARY in deployed mode if you provide it with a MATLAB function prototype.
Instead of compiling the function that generates the MATLAB code and attempting to deploy it, perform the following tasks:
Run the code once in MATLAB to obtain your generated function.
Compile the MATLAB code with MATLAB Compiler, including the generated function.
Tip: Another alternative to using EVAL or FEVAL is using anonymous function handles.
If you require the ability to create MATLAB code for dynamic run time processing, your end users must have an installed copy of MATLAB.
You can read read an m file, line by line and execute each line with the eval() function. There are restrictions on the format of the m file (no line breaks for example, each line must contain a complete MATLAB statement) but it does work and can add to your run time environment inside the compiled application. I use this technique to allow users to define configuration and data files for a compiled application I have developed.
Clearly, if your end user provides a poorly formed m file to evaluate, you will end up with difficult to resolve bugs.
I have 'inherited' Matlab code (A) that uses another compiled Matlab code (B). I do not have the source of B. B requires user intervention ('Hit return to continue'), and I need to use A in a loop. I need to do something so I would not need to hit Return each and every time until the loop is done.
The command I use in the loop is:
str='!start "Code_B" /low "c:\Code_B\bin\Code.exe" r';
eval(str)
Are there any other switches that I can use to suppress the call to 'Hit return' ?
Thanks
Katto
One way you could do this is to create a batch file that:
Starts the compiled Matlab program
Waits for the program to run (fixed delay?)
Uses a utility to send the program an Enter key
There are many (free) utilities that let you send keystrokes to a program.
Instead of calling Program B, you would call this batch file.
You can create a text file, let's say autoreturn.txt, with many empty lines (just end of line characters), over the number of loops you expect. Then add redirection of input from this at the end of your string:
str='!start "Code_B" /low "c:\Code_B\bin\Code.exe" r < autoreturn.txt';