0

I've inherited an m-file that calls the function:

function conditions(varargin)

This requires me to type a series of names when running the m-file. E.g.,:

conditions('c01','c02','c03')

I also have a text file (conditions.txt) that contains all conditions names, one conditions per line. e.g.,:

'c01'
'c02'
'c03'
etc...

Is there a way to automate conditions.m through the Bash shell by running through each line of the text file, one line at a time?

pomodoro
  • 297
  • 3
  • 12
  • 1
    Why Bash? Just use MATLAB to read the file and call `conditions()`, easier, no? – Ander Biguri Jul 23 '18 at 09:23
  • 1
    I'd like to not need to leave Bash. – pomodoro Jul 23 '18 at 09:27
  • Could you explain why you’d like to not leave Bash? Do you want to not have to learn how to do this in MATLAB, or do you have some other constraints? Doing this in MATLAB would be a lot easier, and a lot more efficient. It’s hard for me to recommend a solution to a problem I think is the wrong one... – Cris Luengo Jul 23 '18 at 13:51
  • It's part of an analysis pipeline that is largely automated through Bash script, and I'm more familiar with Bash. I didn't want to change the M-file. But if it is much easier doing this through matlab I'm happy to take all suggestions. – pomodoro Jul 24 '18 at 02:33

2 Answers2

1

Since you're happy to take other suggestions as well, I'm going to suggest you do this through a simple MATLAB script. MATLAB takes a while to start up, so it is quite inefficient to start MATLAB anew for each "condition".

I'm going to assume that your text file example is a simplification, maybe you have multiple parameters per line, and need to pass each of them as an argument to the conditions function. For example the file conditions.txt could contain:

'c01',5,false
'c02',100,true,0,'foo'
...

and you'd want to generate the calls

conditions('c01',5,false)
conditions('c02',100,true,0,'foo')
...

The following code accomplishes this:

f = fopen('conditions.txt','rt');
while true
   data = fgetl(f);
   if isequal(data,-1), break, end
   eval('conditions(',data,')')
end
fclose(f);
exit

You could save that as an M-file script (e.g. runconditions.m), and execute it from bash as follows:

matlab -nosplash -nodesktop -r runconditions

eval is evil, in general, but in this case it's the same as what you'd be doing from the Bash script in Christian's answer. The only difference with that answer is that you avoid starting up MATLAB repeatedly.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
0

At least on windows you can call matlab functions from batch like this: matlab -wait -r 'conditions(%var%)'

So your bash looping should be solvable with a code snipped like this:

while read p; do
 matlab -wait -r 'conditions($p)'
done <yourfile.txt

Or any other looping style of your choice: Looping through the content of a file in Bash

  • Doesn't seem to work. While the output indicates it is running through the text file line by line, it only performs the function for the very first input (i.e., line 1). – pomodoro Jul 23 '18 at 11:35
  • So if you add a `echo $p` into the while loop it shows each line? – Christian Heigele Jul 23 '18 at 11:43
  • echo indicates it is only using the first line of the list: 'c01'. The bash shell output of the MATLAB script suggests that for the remaining lines of the text file it is simply entering that line into MATLAB. I.e., >> ans = c02 >> ans == c03, and so on. – pomodoro Jul 23 '18 at 11:50
  • And you are sure, that you have no issues with multiply quotation marks? Not that you use the same type within your file and your matlab call. Beware: Since Matlab 2017 "asdasd" is a string, while 'asdt' is a char array. – Christian Heigele Jul 23 '18 at 11:52
  • I don't believe so. All lines in my text file are entered with single quotes. And the function picks up the first line, just not the rest. – pomodoro Jul 23 '18 at 12:23
  • You might want to remove `-wait` from the call to MATLAB. It proceses the first line then waits for MATLAB to terminate, so it doesn’t get to do the other lines. – Cris Luengo Jul 23 '18 at 13:47
  • I removed `-wait` as Matlab doesn't recognize it. – pomodoro Jul 24 '18 at 03:12
  • My workaround has been to simply edit the text file and include all condition names on the same line separated by commas. I.e.,'c01', 'c02', 'c03', etc.. My working script is: `while read p; do matlab -nosplash -r "conditions($p)" echo "Completed for following conditions: $p" done < conditions.txt` – pomodoro Jul 24 '18 at 03:16
  • 1
    @CrisLuengo I just assumed that if someone executes something from bash, they also want to have control over their return-codes and hence use explit exit(rc) calls. – Christian Heigele Jul 24 '18 at 07:32
  • Ah, my understanding of `-wait` was wrong. It's a Windows-only argument that makes it so `matlab` doesn't return immediately, but waits until MATLAB finishes. What is missing here is the `exit` at the end of the command, MATLAB starts up, and never finishes. The command needs to be `matlab -r "conditions($p); exit"` (note: double-quotes, as single quotes don't allow variable expansion). – Cris Luengo Jul 24 '18 at 17:09
  • @CrisLuengo your script certainly works - matlab now cycles through each line of the text file and executes the M-file correctly. Although, it does require that Matlab restart for each new line of the text file, which is time costly and slow. – pomodoro Jul 26 '18 at 06:14
  • @CrisLuengo Oh, it was in regards to `matlab -r "conditions($p); exit"` – pomodoro Jul 26 '18 at 06:38
  • @user240917: ah, yes, indeed, that will work, but start MATLAB anew for each line. There is no way AFAIK to pass commands to a running MATLAB session from a Bash script. MATLAB comes with a Python package that lets you do just that from Python, but I haven’t heard of a similar thing for Bash. A MATLAB script would be more efficient just for this. – Cris Luengo Jul 26 '18 at 12:52