Accessing variables from different files in matlab - matlab

I have a "data.m" file that contains a handful of large arrays that I do not want in my main file. For all intents and purposes, they are in the form
a1 = [1,2,3]
a2 = [3,4,5]
How can I access a1 and a2 from another script? Or should I be putting these in a .mat file? If so, how do I do that?

Heres an easy way:
Inside data.m, output your arrays:
function [a1, a2] = data( )
...
end
You can access these arrays from your "main" function (e.g thefunc.m) like this:
function [ ] = thefunc( )
//say you want to store array a1 into a variable X, and array a2 into variable Y
[X, ~] = data;
[~, Y] = data;
end
Of course, thefunc.m and data.m should be in the same working directory.

If the values of the variables are constant, it would be better to store these in MAT files. Also, try to use functions instead of scripts unless it is necessary to use scripts. Scripts define global variables which could lead to inadvertently overwriting variables among many other issues.

Say we have data.m of Yours and a function foo.m that is about to use variables from there.
Turn the data.m into this form:
function[]=data() % defines a function with no output nor input
a1=[1 2 3];
b2='string';
%Your definitions and other code
save('DataFile.mat'); % save EVERY varible used in the code with it's name
Then in foo.m
function[]=foo()
load('DataFile.mat'); % Load all variables saved in DataFile.mat
disp(b2);
You can also prevent temporary variables to be saved with the mandatory ones by deleting them just before save command by clear temp1 temp2
If you want to save some variables, say a1 in one file and other in different file You can use save('DataFile.mat','a1')
If you want to load specific variables You can use load('DataFile.mat','b1')

Related

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)

How to share variables between different m files in Matlab

I have three m files using the same variables and carrying out calculations on these variables. I have made an index m file in which i have declared all the variables and I can share the variables to the remaining m files using the variable names. My problem is that the variable names change too often and then I have to change the variable names in all these files manually. How can I make a Matlab script which can automatically get the variable names and value from the index m file and put these to the remaining m files.
I feel like you just need a little example from where you could go on so here we go:
First calling each value with a different variable name. if you have a lot of values of the same type a array is easier like:
A0=0; A1=6; A2=12 %each one with its own name
B=zeros(16,1); %create an array of 16 numbers
B(1)= 0; %1 is the first element of an array so care for A0
B(2)= 6;
B(8)= 12;
disp(B); % a lot of numbers and you can each address individually
disp(B(8)); %-> 12
you can put all that in your script and try it. Now to the function part. Your function can have input, output, neither or both. If you just want to create data you wont need an input but an output.
save this as myfile1.m:
function output = myfile1()
number=[3;5;6]; %same as number(1)=3;number(2)=5;number(3)=6
%all the names just stay in this function and the variable name is chosen in the script
output = number; %output is what the file will be
end
and this as myfile2.m
function output = myfile2(input)
input=input*2;%double all the numbers
%This will make an error if "input" is not an array with at least 3
%elements
input(3)=input(3)+2; %only input(3) + 2;
output = input;
end
and now try
B=myfile1() %B will become the output of myfile1
C=myfile2(B) %B is the input of myfile2 and C will become the output
save('exp.mat','C')
I hope this will get you started.

Does A Function's Workspace Duplicate A Variable Input?

I have defined in the base Workspace a variable
a = ones(10);
And I would like to create function that inputs a vector vec1 and gives back vec2:
function vec2 = myfun(vec1)
Operations with vec1
end
Lets make
b = myfun(a);
In the Workspace of myfun we will have a variable called vec1 which has the same values as a but it is not in the base Workspace.
When being in Debugging Mode and using
dbup;
I can see two different variables a and vec1 in base and myfun Workspaces respectively.
Is myfun duplicating the variable a in two different Workspaces (and therefore using more memory)?
If this is not the case, how does it work? Is it a pointer assigning two different names to the same information?
Thank you in advance.
MATLAB uses a system commonly called "copy-on-write" to avoid making a copy of the input argument inside the function workspace until or unless you modify the input argument. If you do not modify the input argument, MATLAB will avoid making a copy. For instance, in this code:
function y = functionOfLargeMatrix(x)
y = x(1);
MATLAB will not make a copy of the input in the workspace of functionOfLargeMatrix, as x is not being changed in that function. If on the other hand, you called this function:
function y = functionOfLargeMatrix2(x)
x(2) = 2;
y = x(1);
then x is being modified inside the workspace of functionOfLargeMatrix2, and so a copy must be made.

How to clear variables of a mat file?

I have a mat file, named save.mat, which has two variables. I want to clear the variables and add some other variables. How could I clear/add variables inside a mat file?
Best
You can do this two ways, either through the Matlab GUI or through a script.
To do this within Matlab itself, simply navigate to the .mat file's directory, run 'clear' within your command window (make sure to save your current workspace if you need that data!), the double-click the .mat file to load it. From here you can use the workspace to delete and add variables to your heart's content.
If you want to do this in a script, set up something like this:
clear
load('save'); % load the .mat file
clear foo bar % removes the variables 'foo' and 'bar'
baz = 3; % adds the variable 'baz'
save('save'); % save over the old .mat file
To add one o more variables to an existing .mat file, you can use the save function by specifying the option -append.
To remove one or more variables from an existing .mat file you can:
load the .mat file into a struct using the load function: each read variable will be stored in a field of the struct
remove from that struct the the field corresponding to the varaible you want to delete from the original mat file by using the rmfield function
save the struct using the save function by specifying the option -struct: this will allow save the fields of a structure as individual variables
This is an example of the implementation:
% Define some varaible to be saved
a=1
b=2
c=3
% Save the varaibles
save('add_del.mat','a','b','c')
% Define an additional variable
d=4
% Add the new varaible to the ".mat" file
save('add_del.mat','d','-append')
% Load the ".mat" file into a struct
str=load('add_del.mat')
% Delete the field corresponding to the varaible to delete
str=rmfield(str,'b')
% Save the fields of a structure as individual variables
save('add_del.mat','-struct','str')
Hope this helps.
Qapla'
#excaza has made a good recommendation, I think. To verify that the matfile command works as suggested, try the following:
filename = ('file.mat');
m = matfile(filename,'Writable',true);
y = 23;
m.y = y;
clear y
load(filename);
display(y);
y = 24;
m.y = y;
clear y
load(filename);
display(y);

How to delete only variables created by a specific matlab script

Is there some way to delete only the variables generated in a matlab script at the end of the script and not any other variables of the workspace which are not generated in the script?
Note : The script is not a function.
Basically I want to do the following in one line
save abc.mat % saves the whole workspace
some_script % call the script
clear % deletes the variables created by the script along with the whole workspace
load abc.mat % again loads the whole earlier workspace
Use who before the script, then after the script; compare the results (setdiff) to detect variables created in the script, and then clear only those.
Variable names varsbefore, varsafter and varsnew in the following code should be guaranteed not to be used before the script or within the script.
varsbefore = who; %// get names of current variables (note 1)
some_script
varsafter = []; %// initiallize so that this variable is seen by next 'who'
varsnew = []; %// initiallize too.
varsafter = who; %// get names of all variables in 'varsbefore' plus variables
%// defined in the script, plus 'varsbefore', 'varsafter' and 'varsnew'
varsnew = setdiff(varsafter, varsbefore); %// variables defined in the script
%// plus 'varsbefore', 'varsafter' and 'varsnew'
clear(varsnew{:}) %// (note 2)
Notes about the code:
who used with an output argument returns a cell array of strings containing the names of all variables.
The functional form of clear is used, with input arguments in the form of a comma-separated list generated from a cell array.
You can create structures of variables in this way:
FOO_STRUCT.foo_var = var_from_abc.mat + rand(1);
FOO_STRUCT.foo_var2 = 10*log10(FOO_STRUCT.foo_var);
FOO_STRUCT.foo_var3 = FOO_STRUCT.foo_var2 + var_from_abc.mat;
The upper case part is the structure name. The lower case part is the variable.
You can use variables from the workspace in your script, make your work and at the end of the script you delete the entire structure
clear FOO_STRUCT