Matlab creating mat files which names are written in the variable - matlab

I have a variable 'b'. Inside of b, I have 27X1 cell. In every cell there is some characters for example in 1x1 there is asdf, in 2x1 there is dfgh it's going on like this. I want that matlab creates mat files which names are asdf, dfgh and assign scalar valurs to these files. Could you help me please?

You might have a loop going through the "b"cellarray containing the "filenames" and:
1)get the filename by converting the content of the i-th to a string by using "char" function
2)call "save" specifying the filename (see previous point) and the list of scalar you want to save in it (in the question you did not specified which scalar to be saved)
% Generation of cellarray
b{1,1}='asdf'
b{2,1}='dfgh'
b{3,1}='third_mat_file'
% Loop through cellarray
for i=1:length(b)
% Get the filename
a=char(b(i))
% Generate a dummy scalar to be saved
m=rand;
% Save the scalar in the ".mat" file
save(a,'m')
end
Hope this helps.

Related

Initialize variables with names from a file

I have a txt file with a bunch of parameters created by the external program.
Let us consider a simple example:
input.txt
a= 1
b= 2
c= 3
I can read both names and values in matlab 2018a:
[names, values]=textread('input.txt','%s%f');
As a result, names will be a 3x1 cell array with entries a=, b= and so on, whereas values will be a conventional 3x1 array of doubles.
In my current workspace, I want to initialize the obtained variables (with the corresponding names) and set them equal to the corresponding values.
In the example above, variables a=1, b=2 and c=3 should be created in the current workspace.
I have no idea how to do it...
Thanks!
Edit: in my actual example variable names can contain many characters/numbers (by the standard convention, variable names always start with the letter, not a digit), e.g.
Rcirc1= 30.0
SaveStride= 1000
You can use a combination of regexp and assignin to achieve the desired output:
%Read data.
data = fileread('input.txt')
%Extract variable name and value in named groups.
s = regexp(data,'(?<var>[A-Z]\w+)\D+(?<val>\d+(?:\.\d+)?)','names');
%Loop over struct s contents to create variables in workspace.
cellfun(#(x,y) assignin('base',x,str2double(y)),{s.var},{s.val})
The assignments in the text file can be directly evaluated by MATLAB. You don't need to extract them. In order to silence the text printed for each line you can use evalc
evalc(fileread('input.txt'));

Performing operations on a variable number of workspace elements in MATLAB

new MATLAB user here so apologies if this seems like a silly question. I have the following list of variables (doubles) in my workspace:
E1_01Strain E1_06Strain E1_07Strain E1_08Strain E1_09Strain E1_10Strain
E1_01Stress E1_06Stress E1_07Stress E1_08Stress E1_09Stress E1_10Stress
These are lists of numbers. I would like to remove the last n elements from each variable. I can do it with the command
E1_01Strain = E1_01Strain(1:end-100)
but it's impractical because later I'm going to have to do it on many, many more similar variables. Therefore I wanted to write a function that accepts as inputs a list of the workspace variables (as in, I highlight the variables I want and drag and drop into the function input) and removes from each one n elements.
I understand that I can write a function like this:
function [X1, X2, X3, X4] = Remove_n_elements[n, X1, X2, X3, X4]
X1 = X1(1:end-100);
X2 = X2(1:end-100);
X3 = X3(1:end-100);
X4= X4(1:end-100);
end
but that would mean that I would have to change the number of inputs, outputs, and the lines of code in the function every time. I'm sure there's a better way to do it but I can't figure it out.
I keep thinking that there might be a way to do it by looping over all the inputs but I can't get it to work since (as far as I know) I need to create a list of the inputs and then the operation is performed only on the elements of that list, not the inputs themselves.
I was looking at Passing A Variable Number of Arguments into a Function and from that using inputParser from https://www.mathworks.com/help/matlab/matlab_prog/parse-function-inputs.html but since I'm new to MATLAB I'm not sure how to use it for my case.
I used the code provided by il_raffa for a bit but followed his advice and went back and reconsidered how the script functions. After some more digging I wrote the following script that does exactly what I need. This script extracts the columns des_cols from all .csv files in a folder and plots them together. It then makes another plot of the averages.
files = dir('*.csv'); % navigate to the folder that you want to run the script on in MATLAB
avgStress = [];
avgStrain = [];
set(groot, 'DefaultLegendInterpreter', 'none') % the names of my .csv files have underscores that I want to see in the legend, if you don't want this then comment this line
hold on; %comment this and hold off further down if you want separate plots for every .csv
for file = files'
csv = xlsread(file.name);
[n,s,r] = xlsread(file.name);
des_cols = {'Stress','Ext.1(Strain)'}; % type here the names of the columns you want to extract
colhdrs = s(2,:);
[~,ia] = intersect(colhdrs, des_cols);
colnrs = flipud(ia);
file.name = n(:, colnrs);
file.name = file.name(1:end-600,:); % I wanted to remove the last 600 rows but if you want them all, remove the -600
plot(file.name(:,2),file.name(:,1),'DisplayName',s{1,1});
avgStress = [avgStress file.name(1:1500,1)]; % calculates the average stress for the first 1500 points, you can change it to whatever you want
avgStrain = [avgStrain file.name(1:1500,2)];
end
ylabel({'Stress (MPa)'}); % y-axis label
xlabel({'Strain (%)'}); %x-axis label
title({'E_2'}); % title of the plot
legend('show');
hold off; % commment this if you want different plots for all .csv files
avgStress = mean(avgStress,2);
avgStrain = mean(avgStrain,2);
plot(avgStrain,avgStress);
This creates two plots, one with all the raw data and another with just the averages. I hope this helps anyone that might have a similar issue.
The best thing you can do is to review the architecture of your SW in order to avoid the needs to perform such operations on the Workspace variables.
That is: how those variables are created? Are these variables loaded from a ".mat" file? etc.
Anyway, in order to avoid using the eval function and given your situation, a possible approach could be:
identify the names of the varailbes by using the function who. You can specify in the call to who the root name of the varaibles and use the * as, for example, who('E1*'). Make sure it fit wiht the desired variables. You can also use regexp to better refine the selection of the variables
save these varaibles in a temporary .mat file: the name (including the path of the temporary file can be created with the function tempname
load the temporary .mat file: this will create a struct in the Workspace whose fields are the variables you want to midify
call the function to remove the undesired elements form the fields of the struct. The function have to return the updated struct
save the updated struct in the temporary file
load again the temporary file by specifying the option -struct which allows loading the content of the file as single varaibles
The function to remove the undesired elements can be made as follows:
get the nams of the struct's fields by using the function fieldnames
loop over the filed of the struct by using the dynamic field names property
remove the undesired elements form the fields
return the updated struct
A possible implementatin could be:
Code "before" the call to the function
% Get the names of the variables
list_var=who('E1*')
% Define the name of a temporary ".mat" file
tmp_file=tempname
% Save the variables in the temporary ".mat" file
save(tmp_file,list_var{:});
% Load the variables in a struct
sel_vars=load(tmp_file);
% Call the function to remove the elements
out_str=Remove_n_elements(8,sel_vars)
Function to remove the undesired elements
function sel_vars=Remove_n_elements(n,sel_vars)
% Get the names of the fields of the struct
var_names=fieldnames(sel_vars)
% Loop over the fields and remove the undesired elements
for i=1:length(var_names)
sel_vars.(var_names{i})=sel_vars.(var_names{i})(1:end-n)
end
Code "after" the call to the function
% Save the updated struct in the temporary ".mat" file
save(tmp_file,'-struct','out_str')
% Load the updated struct as separate variables
load(tmp_file)

Sequence of data in MATLAB

I have sequence of data in MATLAB: data1, data2, data3,.... I want to print them one after one. I am stuck on that.
clear; clc;
data1=[1,2];
data2=[3,4];
n=[1,2];
for i=1:length(n)
fname(i,:)=sprintf('data%d',n(i));
end
Does this work for you?
clear; clc;
data1=[1,2];
data2=[3,4];
n=[1,2];
for i=1:length(n)
eval(['data' num2str(n(i))])
end
A possible solution not involving the use of eval could be the following.
Basically it consists of the following steps:
Get the list of data in the Workspace (with who function)
Identify the data to be printed (using regexp to identfy the variables names of the form dataxwhere x is a number)
save these variables in a temporary .mat file
load the .mat file in a struct which allows to have only the variables to be printed
exploit the dynamic field names to get access to the variables
This the code:
% Define some data
data1=[1,2];
data2=[3,4];
data3=rand(5)
data4a=rand(5)
dataaaa3=rand(5)
var_1=1
b=2
% Get the list of data in the Workspace
str=who
% Identify the data to be printed
var_to_print=regexp(str,'data\d$')
idx=~cellfun(#isempty,var_to_print)
% Down select the variables to be printed
str{idx}
% Generate a temporary ".mat" filename
tmp_name=[tempname '.mat']
% Save the data to be printed in the temporary ".mat" file
save(tmp_name,str{idx})
% Load the data to be printed into a struct
v=load(tmp_name)
% Get the names of the varaibles to be printed
f_name=fieldnames(v)
% print the value of the variables
for i=1:length(f_name)
[char(f_name(i)) ' = ']
v.(f_name{i})
end
% Move the temporary ".mat" file in the recycle folder
recycle('on')
delete(tmp_name)
Hope this helps.
Qapla'

Saving multiple .mat files from workspace to .txt files

I have created a script to create ~300 variable names in my workspace. I need to save these .mat files to .txt files - is there any way to call these variables in some sort of loop or just save them all at once to .txt files?
They are all cells of varying size, about 1000x5 on average.
The first row of the data contains strings, the other elements are all non integer numbers.
Here is an example of one of the .mat files-
http://www.yourfilelink.com/get.php?fid=1065782
I don't know a whole lot about Matlab so any help would be really appreciated! Thank you.
A possible solution could be:
to load the .matfiles through a loop (the name of the file can be either dynamically generated or read from a list)
to extract the first row of the cellarray (the string) and write it in a .txt file by using the dlmwrite function
to remove the first row and write (again with dlmwrite) the numerical values in the .txt having converted them using the cell2mat function.In the writing of the numerical values, the precision has to carefully set.
file_name_root='x2413';
% dummy loop (one iteration) just to test dynamic filename generation
for i=3:3
% generate the name of the input file
input_file_name=[file_name_root int2str(i)];
% generate the name of the output file
output_file_name=[file_name_root int2str(i) '.txt'];
% extract the name of the cellarray and assign it to "the_cell" variable
tmp=load(input_file_name);
var_name=char(fieldnames(tmp));
eval(['the_cell=tmp.' var_name ';'])
[r,c]=size(the_cell);
str='';
% get the first row string (probably a cleaver way to do it exists)
for i=1:c
str=[str ' ' char(the_cell(1,i))];
end
% print the first row in a ".txt" file
dlmwrite(output_file_name,sprintf('%s',str),'delimiter','')
% remove the first row
the_cell(1,:)=[];
% write the numerical values in the ".txt" file
% the "precision" shall be carefully set
dlmwrite(output_file_name,cell2mat(the_cell),'precision','%13.9f','delimiter',' ','-append')
end

csvwrite in loop with numbered filenames in matlab

kinda new to matlab here, searching the csvwrite tutorial and some of the existing webportals regarding my question couldn't find a way to pass my variables by value to the output file names while exporting in csv; providing my bellow scripts, i would like to have the output files something like output_$aa_$dd.csv which aa and dd are respectively the first and second for counters of the scripts.
for aa=1:27
for dd=1:5
M_Normal=bench(aa,dd).Y;
for j=1:300
randRand=M_Normal(randperm(12000,12000));
for jj = 1:numel(randMin(:,1)); % loops over the rand numbers
vv= randMin(jj,1); % gets the value
randMin(jj,j+1)=min(randRand(1:vv)); % get and store the min of the selction in the matix
end
end
csvwrite('/home/amir/amir_matlab/sprintf(''%d%d',aa, bb).csv',randMin);
end
end
String concatenation in MATLAB is done like a matrix concatenation. For example
a='app';
b='le';
c=[a,b] % returns 'apple'
Hence, in your problem, the full path can be formed this way.
['/home/amir/amir_matlab/',sprintf('%d_%d',aa,bb),'.csv']
Furthermore, it is usually best not to specify the file separator explicitly, so that your code can be implemented in other operating systems. I suggest you write the full path as
fullfile('home','amir','amir_matlab',sprintf('%d_%d.csv',aa,bb))
Cheers.