Can i format output of matlab command such that i can use it to declare a new variable? - arrays

It's best explained with an easier example. Say some script in MATLAB gives me a cell array of strings:
temp = dir;
names = {temp.name}'
ans =
'folder1'
'folder2'
'file1'
I would like to use this output in another script, in another matlab session. Ideally, in the second script i would write
names = {'folder1', 'folder2', 'file1'}
but this means copypasting the output right under "ans = " and then manually adding the commas and curly brackets. In my case the cell array is quite large so this is undesirable. Even more it feels clumsy and there could be an easier way. Is there any way to make matlab print the output in such a way that i do not have to do this?
Exactly the same thing would be nice to know for matrices instead of cell arrays!!
I am aware of saving the variable in a .mat file and loading it, but i was wondering if the above is also possible (it would be cleaner in my case).

Personally I would advise the use of a cleaner way of handling this (such as mat files).
But then again sometimes the time spent setting these up is just not worth it for simple tasks which are unlikely to be repeated much...
For matrices there is a builtin function to do this, for cells however we would need produce a sting with the required format...
Matrix
For 1d or 2d matrices mat2str provides this functionality
mat2str(eye(2))
ans =
[1 0;0 1]
Cell
However to my knowledge there is no such builtin function for cells.
For a 1d cell array of strings the following will give the output in a copyable format:
['{',sprintf('''%s'' ',names{:}),'}']
ans =
{'folder1' 'folder2' 'file1' }
note: the stings in the cells cannot contain the ' character

If i understand you correctly, you are getting the names output from one script and want to use it within another script. Since you then cannot pass it as function argument, you are currently copying it over. One could do that with eval and copy&paste around:
names = {'folder1'
'folder2'
'file1'};
% create the command
n = length(names);
cmd = sprintf(['names = {',repmat('''%s'', ', 1, n-1) ,'''%s''}'], names{:}); % '%s, %s, ...., %s' format
% cmd contains the string: names_new = {'folder1', 'folder2', 'file1'}
% eval the cmd in script 2
eval(cmd) % evals the command names = {'folder1', 'folder2', 'file1'}
But this is generally very bad practice as it gets insanely hard to debug if something goes wrong somewhere. Also it makes you copy and paste things around, which i feel is uncomfortable. How about storing them in a txt file and loading them in the second script? It gets things done autmatically.
names = {'folder1'
'folder2'
'file1'};
% write output to file
fid = fopen('mynames.txt', 'w'); % open file to write something
fprintf(fid, [repmat('%s, ',1, n-1), '%s'], names{:});
fclose(fid);
% here comes script 2
fid = fopen('mynames.txt', 'r'); % open file to read something
names_loaded = textscan(fid, '%s');
names_loaded = names_loaded{:};
fclose(fid)

I think the key here is that you have a variable in 1 place, and want to use it in a different case.
In that situation you don't want to copy the output matlab generates, you just want to save the value itself.
After finding the result just do this:
save names
Later you can load this variable with
load names
Check doc save and doc names for more extensive examples. You may for example want to save all relevant variables in a file with a more generic name.

Related

Reading many (1000+) files with dlmread - Loop with varying filenames?

I'm very new to matlab, or coding for that matter.
I'm running a simulation which outputs thousands of files. These files are .vtk and are read correctly by dlmread.
I tried reading one of them, defining it as a matrix and extracting column vectors out of this matrix. This works fine. What i need now is to not only read one of them, but all. The filenames vary by a number, for example cover1000.vtk, cover2000.vtk, ...., cover1200000.vtk.
I want all of them to be read with dlmread and stored as a different matrix. How do i do that? Here is what i have right now, working with one file at a time:
A_1000 = dlmread ('cover1000.vtk') %matrix a containing values from vtk file_in_loadpath
fx_1000 = A(1:20,1) %extracting vector with specific values
fx_ave_1000 = sum(fx_1000)/length(fx_1000) % average of the values in extracted vector
I'm thinking of a loop, but how do i create a loop with varying file names?
Also I've read that a loop is not the best idea, cell arrays would be better. But i have absolutely no idea how to implement any of this.
Thanks for your help!
cheers
You can use the function dir to list all the vtk files in your directory then loop over those files.
filename = dir('*.vtk'); %list all the vtk files in your current directory.
for ii = 1:length(filename)
A = dlmread (filename(ii).name) %matrix a containing values from vtk file_in_loadpath
fx{ii} = A(1:20,1) %extracting vector with specific value
fx_ave{ii} = sum(fx{ii})/length(fx{ii}) % average of the values in extracted vector
end
The results are now stored in two cells: fx and fx_ave.

Passing an array as an argument from a Perl script to a R script

I am new to R and I have a Perl Script in which I want to call a R Script, which calculates something for me (not important what in this context). I want to give as arguments an input file, an array which contains some numbers and a number for a total number of clusters. medoid.r is the name of my R Script.
my $R_out;
$R_out = qx{./script/medoid.r $output #cluster $NUMBER_OF_CLUSTERS}
My current R code looks like this. Right now I just print cluster to see what is inside.
args <- commandArgs(TRUE)
filename = args[1]
cluster = as.vector(args[2])
number_of_cluster = args[3]
matrix = read.table(filename, sep='\t', header=TRUE, row.names=1, quote="")
print(cluster)
Is it possible to give an array as an argument? How can I save it in R? Right now only the first number of the array is stored and printed, but I would like to have every number in a vector or something similar.
If you do this in Perl
$R_out = qx{./script/medoid.r $output #cluster $NUMBER_OF_CLUSTERS};
your command line will look similar to this
./scriptmedoid.r output 111 222 333 3
assuming that $output is 'output' and #clusters = (111, 222, 333).
If you want to read that in R, you need to assign all elements after the first one in args to cluster but the last one, and the last one to number_of_cluster. In Perl you can use shift and pop for that.
my #args = #_;
my $output = shift #args;
my $number = pop #args;
# now #args only contains the clusters
I don't know if those operators exist in R.
You cannot pass a full data structure unless you serialize it in some way.
In perl, qx will expect a string as an argument. You may certainly use an array to generate that string, but ultimately it will still be a string. You cannot "pass an array" to a system call, you can only pass command-line text/arguments.
Keep in mind, you are executing a system call running Rscript as a child process. The way you're describing the issue, there is no inter-process communication beyond the command line. Think of it this way: how would you type an array on the command line? You may have some textual way of representing an array, but you can't type an array on the command line. Arrays are stored and accessed in memory differently by various different languages, and thus are not really portable between two languages like you're suggesting.
One solution: all that said, there may be a simple solution for you. You haven't provided any information on the type of data you want to pass in your array. If it is simple enough, you may try passing it on the command line as delimited text, and then break it up to use in your Rscript.
Here is an Rscript that shows you what I mean:
args = commandArgs(trailingOnly=TRUE)
filename = args[1]
cluster <- c(strsplit(args[2],"~"))
sprintf("Filename: %s",filename)
sprintf("Cluster list: %s",cluster)
print("Cluster:")
cluster
sprintf("First Item: %s",cluster[[1]][1])
Save it as "test.r" and try executing it with "Rscript test.r test.txt one~two" and you'll get the following output (tested on Rscript 46084, OpenBSD):
[1] "Filename: test.txt"
[1] "Cluster list: c(\"one\", \"two\")"
[1] "Cluster:"
[[1]]
[1] "one" "two"
[1] "First Item: one"
So, all you'd have to do on the perl side of things is join() your array using "~" or any other delimiter- it is highly dependent on your data, and you haven't provided it.
Summary: re-think how you want to communicate between perl and Rscript. Consider sending the data as a delimited string (if it's the right size) and breaking it up on the other side. Look into IPC if that won't work, consider environment variables or other options. There is no way to send an array reference on the command-line.
Note: you may want to read up on security risks of different system calls in perl.

How to run same code on multiple files, or all files in directory

so I am very new to coding and recently wrote a little program that involved R and sox. It looked like this
file <- "test.mp3"
testSox = paste("sox ",file," -n spectrogram -o ",file,".png stats",sep='')
sox = system(testSox, intern = TRUE)
print(sox)
Now, instead of assigning the one file manually within the code, I would just like to have this code read through all the mp3s in a folder automatically. Is this possible? Any help would be greatly appreciated. Thanks!
EDIT: Actually, I should add that I tried list.files, but when it comes to running the system() command, I get
"Error in system(command, as.integer(flag), f, stdout, stderr) :
character string expected as first argument"
Here's the list.files code I tried:
> temp = list.files(path = ".", pattern=".mp3")
>
> file <- temp
>
> firstSox = paste("sox ",file," -n spectrogram -o ",file,".png stats",sep='')
> sox = system(firstSox, intern = TRUE)
Error in system(command, as.integer(flag), f, stdout, stderr) :
character string expected as first argument
> print(sox)
I'm guessing this is not the correct route to go? Because I basically need to replace 'file' in the firstSox line with each mp3 that's in the temp array. So instead of running:
file <- "test.mp3"
...I would just like to have it re-assign each time for every file in the folder..., so it runs through as test.mp3, then 1.mp3, then 2.mp3, then 3.mp, etc.
I've scoured the net, and just feel like I've hit a brick wall. As stated in the comments, I've read up on loops, but for some reason I can't wrap my head around how to incorporate it into what I have written. I feel like I just need someone to show me at least the way, or maybe even write me an example so I can wrap my head around it. Would greatly appreciate help and any tips on what I'm doing wrong and could correct. Thanks.
Try the below code. I am using dir() instead of list.files, just because I find it easier. Remember there are many ways to do the same thing in R.
files <- dir(path = ".",pattern = ".mp3") #Get all the mp3 files
for(f in files) { #Loop over the mp3 files one at a time
firstSox = paste("sox ",f," -n spectrogram -o ",f,".png stats",sep='')
sox = system(firstSox, intern = TRUE)
print(sox)
}
Your firstSox variable will be a vector of commands to run (paste will generate a vector, one string for each element of file). So now you just need to run each command through system
One way to do this and capture the output is to use the lapply or sapply function:
sox <- lapply( firstSox, function(x) system(x, intern=TRUE) )
In this code lapply will run the function for each element of firstSox one at a time, the function just takes the current element (in x) and passes that to system. Then lapply gathers all the outputs together and combines them into a list that it puts into sox.
If the results of each run give the same shape of results (single number or vector of same length) then you can use sapply instead and it will simplify the return into a vector or matrix.

How to name a Matlab output file using input from a text file

I am trying to take an input from a text file in this format:
Processed_kplr010074716-2009131105131_llc.fits.txt
Processed_kplr010074716-2009166043257_llc.fits.txt
Processed_kplr010074716-2009259160929_llc.fits.txt
etc.... (there are several hundred lines)
and use that input to name my output files for a Matlab loop. Each time the loop ends, i would like it to process the results and save them to a file such as:
Matlab_Processed_kplr010074716-2009131105131_llc.fits.txt
This would make identifying the object which has been processed easier as I can then just look for the ID number and not of to sort through a list of random saved filenames. I also need it to save plots that are generated in each loop in a similar fashion.
This is what I have so far:
fileNames = fopen('file_list_1.txt', 'rt');
inText = textscan(fileNames, '%s');
outText = [inText]';
fclose(fileNames)
for j:numel(Data)
%Do Stuff
save(strcat('Matlab_',outText(j),'.txt'))
print(Plot, '-djpeg', strcat(outText(j),'.txt'))
end
Any help is appreciated, thanks.
If you want to use the save command to save to a text file, you need to use -ascii tab, see the documentation for more details. You might also want to use dlmwrite instead(or even fprintf, but I don't believe you can write the whole matrix at once with fprintf, you have to loop over the rows).

Create functions in matlab

How can I create a function with MATLAB so I can call it any where in my code?
I'm new to MATLAB so I will write a PHP example of the code I want to write in MATLAB!
Function newmatlab(n){
n=n+1;
return n;
}
array=array('1','2','3','4');
foreach($array as $x){
$result[]=newmatlab($x);
}
print_f($result);
So in nutshell, I need to loop an array and apply a function to each item in this array.
Can some one show me the above function written in MATLAB so I can understand better?
Note: I need this because I wrote a code that analyzes a video file and then plots data on a graph. I then and save this graph into Excel and jpg. My problem is that I have more than 200 video to analyze, so I need to automate this code to loop inside folders and analyze each *.avi file inside and etc.
As others have said, the documentation covers this pretty thoroughly, but perhaps we can help you understand.
There are a handful of ways that you can define functions in Matlab, but probably the most useful for you to get started is to define one in an m-file. I'll use your example code. You can do this by creating a file called newmatlab.m in your project's directory that looks something like this
% newmatlab.m
function result = newmatlab(array)
result = array + 1
Note that the function has the same name as the file and that there is no explicit return statement - it figures that out by what you've named the output parameter(s) (result in this case).
Then, in the same directory, you can create a script (or another function) that calls your newmatlab function by that name:
% main.m (or whatever)
a = [1 2 3 4];
b = newmatlab(a)
That's it! This is a simplified explanation, but hopefully enough to get you started and then the documentation can help more.
PS: There's no "include" in Matlab; any functions that are defined in m-files in the current path are visible. You can find out what's in the path by using the path command. Roughly, it's going to consist of
Matlab's own directory
The MATLAB subdirectory of your Documents directory
The current working directory

Resources