I would like MATLAB to tell me if I have an input file (.m file) that contains some variables with their numbers (i.e., a = 5, b = 6, c = 7) so that I can then use that .m file in another program (main .m file) that uses these variables to calculate S = a + b + c. How can I then read the input file from the main file? Assume the input file is called INP and the main MAIN.
This is typically not good practice in MATLAB. The file containing the input variables would, in your example, be a script. As would your main file. MATLAB does not error when running one script from another, as suggested by ScottieT812, but under certain circumstances strange errors can arise. (Run time compiling has difficulty, variable name collisions across scripts)
A better option is to turn the inputs script into a function which returns the variables of interest
function [a,b c] = inputs
a = 5;
b = 6;
c = 7;
Then this function can be called in the main.m script.
% main.m
[a,b,c] = inputs;
s = a+b+c;
If your "input" file is an m-file, just use the name of the file in your "main" m-file. For example you might have a file called input.m that looks like this:
% File: inputs.m
a = 5;
b = 6;
c = 7;
Then, you can use it in the file main.m like this:
% File: main.m
inputs;
S = a + b + c;
For this sort of stuff (parameters that are easily adjusted later) I almost always use structures:
function S = zark
S.wheels = 24;
S.mpg = 13.2;
S.name = 'magic bus';
S.transfer_fcn = #(x) x+7;
S.K = [1 2; -2 1];
Then you can return lots of data without having to do stuff like [a,b,c,d,e,f]=some_function;
One nice thing about structures is you can address them dynamically:
>> f = 'wheels';
>> S.(f)
ans =
24
It sounds like you want to have some global configuration information that's used by scripts. Often, it's much better to create functions and pass values as arguments, but sometimes it makes sense to do things the way you suggest. One way to accomplish this is to save the information in a file. See "load" and "save" in the Matlab documentation.
I ran into the exact problem KennyMorton mentioned when trying to create runtime compiled versions of MATLAB software for my work. The software uses m-files extensively for passing arguments between functions. Additionally, we create these m-files dynamically which the deployed version of MATLAB does not play nice with. Our workaround was:
save the parameters to a file without the .m extension
read and eval the contents of the file
So, to follow the OPs example, in a function we would create a text file, INP, containing our parameters. We create this file in the directory returned by the ctfroot function. Then, in MAIN, we would use the following to retrieve these parameters:
eval(char(textread(fullfile(ctfroot, INP), '%s', 'whitespace', '');
If the data script is just a script, you can call it from a function or another script directly. Not extra commands required. For example:
%mydata.m
a = 1;
b = 2;
%mymain.m
mydata
whos
mymain
>>mymain
Name Size Bytes Class Attributes
a 1x1 8 double
b 1x1 8 double
This also works for functions in addition to scripts
%foo.m
function foo
mydata
whos
>>foo
Name Size Bytes Class Attributes
a 1x1 8 double
b 1x1 8 double
Generally, it is preferable to use a MAT or other data file for this sort of thing.
Related
I have some MATLAB code that I worked on with someone who is much more experienced in MATLAB than I am. The code was running perfectly fine the other day. When I tried running it today, I got the error "Dot indexing is not supported for variables of this type" and I have tried reading through many other stack overflow questions on the topic, but still struggling to resolve my issue. I will include the code up until the error below. Based on what I've read, it might be something to do with structure? I would appreciate any help or tips you could send my way. Thank you!
for j = 3:length(files)
files(j).name
folder_name = files(j).folder;
file2load = strcat(folder_name, '\', files(j).name);
data_input = load(file2load);
trace_names = fieldnames(data_input);
for i = 1:length(trace_names)
data_to_plot.x = data_input.(char(trace_names(i))).data.x;
data_to_plot.y = data_input.(char(trace_names(i))).data.y;
As the comments point out, it is not clear why you are getting this error, but I can tell you what is causing it. 'Dot indexing' is a way of accessing data fields in a type of Matlab variable called a struct. In your snippet files(j) is not a struct.
For example, you cannot do this:
>> s = {}; % s is a cell array (not a struct)
>> g = {};
>> g{1} = 'lala';
>> s{1} = g;
>> s.g % cannot access g using this syntax
Dot indexing is not supported for variables of this type.
But if you make s a struct, you can:
>> s = struct
s =
struct with no fields.
>> s.item1 = g; % create a field called item1 to hold the stuff in g
>> s.item1 % now you can use dot indexing to access the stuff you put in there
ans =
1×1 cell array
{'lala'}
I would guess that this snippet is part of a function where files is an argument or down the line of a script in which files is earlier defined. Probably the other day with your colleague, you had files set to a variable that is indeed an array of structures with the items name etc inside of them. Since then, something changed the value of files to an array of non-struct types.
So the output of my code produce many variables in every loop in Matlab workspace. I want to save two of the variables (namely MO and Vr) to a file having a fixed name with a number which change in every loop. The number which changes in each loop is "NT+1".
First I change the name of the two desired variables with following code:
eval(sprintf('MO%d=MO;',NT+1));
eval(sprintf('Vr%d=Vr;',NT+1));
Now I want to save the renamed MO and Vr variables in a .mat file having the NT+1 number at the end. For instance, if NT+1=60, I want the the two renamed variables (which are MO60 and Vr60) be saved in a file having the NT+1 number at the end: sim60.mat
save('sim%d.mat','MO%d','Vr%d',NT+1)
hypothetical, the output of the above code should be a file named 'sim60.mat' having the two variables MO60 and Vr60.
How can I automatically perform such saving when the NT+1 changes in every loop and the name of MO and Vr also must be changed for the save command at each loop?
You should not rename the workspace variables because you will need to use eval, which is almost always bad practice.
Go with
% create file name
flNm = num2str(i,'sim%d.mat');
% save file
save(flNm,'MO','Vr');
if you now load the file, load it to a struct
flNm = num2str(i,'sim%d.mat');
Dat = load(flNm,'MO','Vr');
% access the variables
Dat.Mo
Dat.Vr
usually one needs to load and save variables within a loop because the memory is too small to store them in a multidimensional array or a cell:
i_max = 10;
MO_all = NaN(3,3,i_max)
Vr_all = cell(i_max)
for i = 1:i_max
% what happens in every loop
MO = rand(3,3);
Vr = rand(randi(10),randi(10)); % changing size
% store for other loops
MO_all(:,:,i) = MO;
Vr_all{i} = Vr;
end
The solution to you particular question is
(I do not recommend using this as it is not flexible, not robust and requires eval to create the variables in the first place!)
flNm = num2str(NT+1,'sim%d.mat');
vars2save = {num2str(NT+1,'MO%d'),num2str(NT+1,'Vr%d')};
save('sim%d.mat',vars2save {:})
How to call an m file from another m file in MATLAB without add its folder path?
I don't want to add its folder via
addpath(genpath(''))
Similar to the functionality of MATLAB's built-in run for scripts, you can cd into the secondary path, execute your function, and then return to the previous directory.
A small example:
% testcode.m
function [output] = testcode(fullfunctionpath, A, B)
[pathname, functionName] = fileparts(fullfunctionpath);
olddir = cd(pathname);
output = feval(functionName, A, B);
cd(olddir);
end
% .\test\testing.m
function [output] = testing(A, B)
output = A + B;
end
With the call:
C = testcode('C:\testcode-matlab\test\testing.m', 1, 2);
Will return
C =
3
Note that this approach does not have error handling nor does it check for duplicates that already exist in your path definition. If the called function is not present in the target folder but does exist in the path, the function in MATLAB's path will still be executed. See: Function Precedence Order for more information.
All visibility rules for functions are based on Folders. If you want to have different visibilities you have to place your functions in different folders.
Typically, avoiding duplicate function names and just adding all source files to your search path is what works. To avoid duplicate function names you may want to take a look at packages.
I have problem with the following code:
.
.
.
a=zeros(1000,ctimes);
a1=zeros(1000,ctimes);
hold all
for i=num1:num2;
colors=Lines(i);
switch phantom
case 1
path=['E:\filename\'];
path1=['E:\filename2\'];
n=['S',num2str(emt),'_',num2str(i),'.m'];
d=load([path,name]);
a(:,i)=complex(d(:,2),d(:,3)));
n1=['S',num2str(emt),'_',num2str(i),'.m'];
d1=load([path1,name1]);
a1(:,i)=complex(d1(:,2),d1(:,3)));
the problem is that a(:,i) can not be defined. while there is no problem or with complex(d1(:,2),d1(:,3))) , can any expert body help me plz?!
thank you ...
Are you sure you are forming your file name correctly? You are doing something to create a variable n, but using a variable name when you form the path. Here are some recommended debugging steps:
1) make sure the file path is formed correctly:
filePath = fullfile(path, name);
disp(filePath);
The fullfile function concatenates elements of a file path & name, and takes care of using the right file path separator (good for portable code, stops you having to remember to add a / or \ to the end of a file path, etc).
2) check that d is loaded correctly:
clear d;
d = load(filePath);
disp(size(d));
3) check the size of the complex quantity you compute before assigning it to a(:,i):
temp = complex(d(:,2), d(:,3));
disp(size(temp));
By the time you have done these things, you should have found your problem (the dimensions of temp should be [1000 1] to match the size of a(:,i), of course).
As an aside, you should avoid using i as a variable name, especially when you are using complex numbers, since its built-in value is sqrt(-1). Thus, c = a + i * b; would create a complex number (a,b) and put it into c - until you change the meaning of i. A simple solution is to use ii. The same is true for j, by the way. It is one of the unfortunate design decisions in Matlab that you can overwrite built in values like that...
I want to change a variable name before I export it to the global enviroment, the data is very large, meaning I can not copy it to another variable and delete the first one.
the data is loaded to certain variables and that I cannot change as well, it is used multiple times in differnet background jobs, so what I want to do is rename it and send it renamed so the jobs won't mix and after for the next job load and rename again etc.
basically is to do in the command window what I can do with the mouse in the workspace....
does anyone knows how to do it?
When assigning variable names, matlab uses a "lazy copy", so there is no reason why:
new_name = old_name;
clear old_name;
shouldn't work.
The only way that I can think of to do this without a memory copy would be to wrap the original data in an object that is a subclass of the handle class.
http://www.mathworks.co.uk/help/techdoc/matlab_oop/brfylzt-1.html
You can then 'copy' the handle class using normal syntax
classB=classA
..but you are only making an alias for the same data (changes to classB are reflected in classA). This is the closest thing in matlab to pointer-like semantics.
For example, create a file called myHandle and paste the following text to define the class . .
classdef myHandle < handle
properties
data
moreData
end
methods
end
end
You can then use this just like a regular structure. From the command line do ..
>> x = myHandle
x =
myHandle handle
Properties:
data: []
moreData: []
Methods, Events, Superclasses
... we can then populate the data . . .
>> x.data = [1 2 3 4];
>> x.moreData = 'efg';
... once the original object has been populated with data, an alias of the original data can be made by typing . .
>> y = x
The interesting thing happens to x when y is modified, i.e.
>> y.data = [33 44 55 66];
>> disp(x)
x =
myHandle handle
Properties:
data: [33 44 55 66]
moreData: 'f'
Methods, Events, Superclasses
You can even clear one of the alias names . .
clear x
..and the data will still be available in the other handle for the data, y. The memory is only freed when there are no more handles referring to it (when the reference count has reached zero).