I would like to store some values that are printed during the iterative procedure of a function, but I have no idea how.
here is the code I am using:
a = 0
b = 2
tol = 1.e-6
trace = 1
F = #(x)1./(x.^3-2*x-5);
Q = quad(F,a,b,tol,trace);
the quad funciton gives the integral of F from a to b using the adaptive quadrature method. trace = 1 prints the values to the console [fcnt a b-a Q] during the recursion, but does not store them to the variable.
I would like to store the values a and b-a that are printed during the procedure, for later use.
for instance, this code gives
>> quad(F,0,2,1.e-6,1);
9 0.0000000000 5.43160000e-01 -0.0989460227
11 0.5431600000 9.13680000e-01 -0.1584111746
13 0.5431600000 4.56840000e-01 -0.0755952309
15 1.0000000000 4.56840000e-01 -0.0828028464
17 1.0000000000 2.28420000e-01 -0.0391911692
19 1.2284200000 2.28420000e-01 -0.0436112507
21 1.4568400000 5.43160000e-01 -0.2054245169
23 1.4568400000 2.71580000e-01 -0.0667670196
25 1.4568400000 1.35790000e-01 -0.0302481864
27 1.5926300000 1.35790000e-01 -0.0365183194
29 1.7284200000 2.71580000e-01 -0.1366285551
31 1.7284200000 1.35790000e-01 -0.0492888403
33 1.8642100000 1.35790000e-01 -0.0871164919
35 1.8642100000 6.78950000e-02 -0.0350033472
37 1.9321050000 6.78950000e-02 -0.0520998049
39 1.9321050000 3.39475000e-02 -0.0228214919
41 1.9660525000 3.39475000e-02 -0.0292778809
I need the values printed in the second and third columns above.
Thank you.
I'm not sure I've understood your question; if you want to store the trace values
9 0.0000000000 5.43160000e-01 -0.0989460227 11
0.5431600000 9.13680000e-01 -0.1584111746
etc ...
into an array, consider that the trace values are printed by the quad funcition by using the fprintf.
You can edit the quand function - edit quad - and see:
if trace
fprintf('%8.0f %16.10f %18.8e %16.10f\n',fcnt,a,h,Q);
end
I see at least two possibilities:
1) Use the diary function
You can modify your code by calling diary right before calling quad; this function create a log of the ouput displayed in the CommandWindow into a text file.
Then, you can load the content of that file to impport its content (the trace data) in the Workspace.
Do not forget to add ";" at the end of the call to quad otherwise also the output of the function will be stored into the diary file and this will prevent the possibility of loading it
a = 0
b = 2
tol = 1.e-6
trace = 1
F = #(x)1./(x.^3-2*x-5);
% Define the name of the diary file
diary_filename='trace_data.txt';
% Enable saving the data into the "trace_data.txt" output file
diary(diary_filename)
Q1 = my_quad(F,a,b,tol,trace);
% Turn off the diary log
diary
% Load the trace data into the "trace_data" array in the workspace
trace_data=load(diary_filename)
You might have a more "general" approach and dynamically generate the trace data output file, by using tempname.
(tempname generate the filename in the temporary folder, so,if you want to store it into you current directory you have to split it, extract the actual filename by using fileparts)
a = 0
b = 2
tol = 1.e-6
trace = 1
F = #(x)1./(x.^3-2*x-5);
% Dynamically generation of the output file name
tmpName = tempname
% Extract the actual filename
[pathstr,name,ext]=fileparts(tmpName)
% Build the filename and add the extension
diary_file=[name '.txt']
% Enable saving the data into the "trace_data.txt" output file
diary(diary_file)
Q1 = my_quad(F,a,b,tol,trace);
% Turn off the diary log
diary
% Load the trace data into the "trace_data" array in the workspace
trace_data=load(diary_file)
2) Modify the quad function
Since the source code of the quad function is available, you can either directly modify the function (not recommended) or copy it in a folder on your path and modify it.
There are many way to modify the function.
One of them could be to:
add an input parameter in which you can specify the name of the output file
add in the function the code to open the file (fopen)
add the file handle in the fprintf call
close the output file at the end (fclose)
another possibility could be to add an output parameter in the definitin of the function in which to store the trace data; in thsi case you also have to add the code to store the trace data into an array at each iteration of the function.
Hope this helps.
Qapla'
Related
I'm new to MATLAB, and I can't manage to make my function work in order to save my data into a .mat file.
The input:
A structure, with 5 fields:
data: 3D matrix of 19x1000x143
labels: 1x143 matrix with 1 or -1 in it
subject_number: an integer
sampling_rate: an integer, 500 Hz
channel_names: 1x19 matrix with text in it
name: a string for the name of the file
clean: a matrix 1x143 with 1 or 0 in it.
The idea is to save only the clean data, marked as 1 in the clean matrix.
If clean(i) is equal to 1:
save data(:,:,i) and labels(:,i)
This is the code I've tried to implement in the saving.m file:
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
for j=1:nb_epoch
if clean(j) == 1
% Keep the epoch and label
data = cat(3, data, EEG_struct.data(:,:,j));
labels = cat(2, labels, EEG_struct.labels(:,j));
end
end
save(name, data, labels, subject_number, fs, chan_names)
As you can see, I would like to save the data as a structure with the same shape as the EEG_struct input.
Moreover, I would like to use a parfor instead of a for, but it raised me an error I didn't quite get:
An UndefinedFunction error was thrown on the workers for 'data'. This might be because the file containing 'data' is not accessible on the workers. Use addAttachedFiles(pool, files) to specify the required files to be attached. See the documentation for 'parallel.Pool/addAttachedFiles' for more details. Caused by: Undefined function or variable 'data'.
Thanks for the help !
You can use your clean variable as a logical index and parse out your data and labels at once. So there is no need for a loop.
Also the save command needs the "names" of the vars to save not the variables themselves. So I just put ' ' around each one.
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
%No need for a loop at all
data = EEG_struct.data(:,:,logical(clean));
labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
save(name, 'data', 'labels', 'subject_number', 'fs', 'chan_names');
EDIT:
Per you comment if you want to just leave everything in the structure. I gave you 2 options for how to save it.
function saving(EEG_struct, clean, name)
%Crop out ~clead data
EEG_struct.data = EEG_struct.data(:,:,logical(clean));
EEG_struct.labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
% Option 1
save(name, 'EEG_struct');
% Option2
save(name, '-struct', 'EEG_struct');
Option 1 will directly save the struct to the MAT file. So if you were to load the data back like this:
test = load(name);
test =
EEG_struct: [1x1 struct]
You would get your structure placed inside another structure ... which might not be ideal or require an extra line to de-nest it. On the other hand just loading the MAT file with no outputs load(name) would put EEG_struct into your current workspace. But if in a function then it sort of springs into existence without every being declared which makes code a bit harder to follow.
Option 2 uses the '-struct' option which breaks out each field automatically into separate vars in the MAT file. So loading like this:
EEG_struct = load(name);
Will put all the fields back together again. To me at least this looks cleaner when done within a function but is probably just my preference
So comment out which ever you prefer. Also, not I did not include clean in the save. You could either append it to the MAT or add it to your structure.
To get a structure the same as EEG_struct but with only the data/labels corresponding with the clean variable, you can simply make a copy of the existing structure and remove the rows where clean=0
function saving(EEG_struct, clean, name)
newstruct = EEG_struct;
newstruct.data(:,:,logical(~clean)) = '';
newstruct.labels(logical(~clean)) = '';
save(name,'newstruct');
result 'output1' 'output2'
result1 [1.0000] [0.0182]
counter [ 2] [ 0]
percentage [ 4] [ 7]
I have an output stored in a table (T), I want to print all my 200 loop results in just one text file. I already tried with writetable function and always have a problem, the output overwrite the previous output.
fid = fopen(filename,'w');
for i = 1:200
writetable(T,'finalresult.txt','Delimiter','\t','WriteRowNames',true);
end
fclose(fid);
the output should be like this:
result 'output1' 'output2'
result1 [1.0000] [0.0182]
counter [ 2] [ 0]
percentage [ 4] [ 7]
result 'output1' 'output2'
result1 [0.0182] [1.0000]
counter [ 3] [ 0]
percentage [ 4] [ 7]
and so on for all the outputs i = 200
Per MATLAB's documentation for writetable, this is the default behavior.
If filename is the name of an existing text file, then writetable overwrites the file.
This gives you two options: create your own export routine or overload MATLAB's with the desired behavior. Let's look at the latter.
Warning: Modifying default MATLAB behavior can lead to unexpected results and errors. Take care to modify only copies of MATLAB's default files so you can revert MATLAB's state when you are finished.
Fortunately for us, the source code for table and its related methods are currently open so you can use open to read them and understand their behavior. We see that writetable is a thin wrapper for the undocumented table.write, which parses the input arguments and makes the determination whether or not to write to a text file or to a spreadsheet. For the text case MATLAB calls the writeTextFile function (again, undocumented) which handles writing table data to a text file.
If you look at line 25, you will see that MATLAB opens the file for writing as follows:
% Open the file for writing
[fid,errmsg] = fopen(file,'Wt'); % text mode: CRLF -> LF
Per the documentation for fopen this opens the file for writing ('W'), which will discard any existing contents. Saving a copy of writeTextFile and changing the fopen call to append data rather than overwrite it should give the desired behavior.
% Open the file for writing
fprintf('!!! Using overloaded writeTextFile D:\n%s\n', mfilename('fullpath'));
[fid,errmsg] = fopen(file,'At'); % text mode: CRLF -> LF
Per MATLAB's Function Precedence Order, Private or Object functions take precedence over functions in MATLAB's path, so we need to place this modified file in the same location as the original. You can find this location this using which -all:
>> which writeTextFile -all
C:\excaza\writeTextFile.m
C:\Program Files\MATLAB\R2016b\toolbox\matlab\datatypes\#tabular\writeTextFile.m % tabular method
You should see your saved copy and MATLAB's built-in version. You should now rename the built-in function (e.g. writeTextFile_builtin.m) and copy your modified version of the file into the folder. Run a clear all once to clear any memory cached version of the function.
We can now test to see if we've achieved the desired result:
filename = 'test.txt';
var1 = 1;
var2 = 2;
T1 = table(var1, 'RowNames', {'hi'});
T2 = table(var2, 'RowNames', {'hi'});
writetable(T1, filename)
writetable(T2, filename)
Which returns the following test.txt:
Row var1
hi 1
Row var2
hi 2
When you are done, be sure to revert the changes you made to the built-in.
a1=0.1;
a2=0.2;
opt =fopen('test.txt','a');
for i=1: size(t,1)
j=1;
if(i==1)
s=strcat('\n','result','\t',t(i,j),'\t',t(i,j+1),'\n');
s=s{1};
end
if (i==2)
a1=t{i,j};
a2=t{i,j+1};
s=strcat('\n','result1','\t',num2str(a1),'\t',num2str(a2),'\n');
end
if (i==3)
a1=t{i,j};
a2=t{i,j+1};
s=strcat('\n','counter','\t',num2str(a1),'\t',num2str(a2),'\n');
end
if (i==4)
a1=t{i,j};
a2=t{i,j+1};
s=strcat('\n','counter1','\t',num2str(a1),'\t',num2str(a2),'\n');
end
if (i==5)
a1=t{i,j};
a2=t{i,j+1};
s=strcat('\n','percentage','\t',num2str(s1),'\t',num2str(s1),'\n');
end
fprintf(opt,s);
end
the output will be like this
result output1 output2
result1 1.0000 0.0182
counter 1 1
counter1 0 0
percentage 0 0
I solved it without doing any function modification. #Brian thank you for the answer, and clear explanation.
For debugging purpose, I want to print out the name of the m-file and the line number so that, when something goes off, it says something like
Error at 197th line of run.m
Given that Matlab displays an error message of this type, there must be a solution.
How can I do this?
===========Follow-up question==============
Thank you! But I got a follow-up question.
I have main.m which is the main m-file and main.m calls lower.m
I wrote
info = dbstack()
and
try
error('Toto')
catch ME
ME.stack
end
to the main.m. Then Matlab displays
info =
file: 'main.m'
name: 'main'
line: 15
ans =
file: 'C:\Users\account1\Google Drive\1AAA-RA\11HHJK(O…'
name: 'main'
line: 18
However, when I write dbstack and try-catch thing to lower.m, then Matlab does not display any exact information.
I ran the main.m and main.m called the lower level m-file but it doesn't display any information.
info =
2x1 struct array with fields:
file
name
line
ans =
2x1 struct array with fields:
file
name
line
What should I do to make it display every file, name, line information?
Ideally, Matlab will display the information of both main.m and lower.m like the following:
file1: 'main.m'
name1: 'main'
line1: 15
file2: 'lower.m'
name2: 'lower'
line2: 6
Is this possible?
You can use the Matlab Exception object. The line information is contained in the 'stack' property.
Example create a 'test.m' script:
try
error('Toto')
catch ME
ME.stack
end
Output of command window is:
>> test
ans =
file: 'D:\MATLAB\Sandboxes\AVLab\test.m'
name: 'test'
line: 2
Or without a try/catch you can use MException.last.
See documentation link http://www.mathworks.com/help/matlab/matlab_prog/capture-information-about-errors.html
info = dbstack();
% info is now a struct that has 3 fields
% info.file
% is a string containing the file name in which the function appears.
% info.name
% is a string containing the name of the function within the file.
% info.line
% is the line number on which dbstack was called
MATLAB's error function will automatically display the filename and line number.
function [ ] = wsgefiow9ey( )
n = 7;
if n > 1
msg = 'Error: n is too big.';
error(msg)
end % if
end % function definition
click here to see console output resulting from call to MATLAB error function
I'm developing a piece of k-means fuzzy code. Now I want to save the data of each iteration that is displayed by statset('Display','iter');. Help me please.
X = [randn(20,2)+ones(20,2); randn(20,2)-ones(20,2)];
opts = statset('Display','iter');
[cidx, ctrs] = kmeans(X, 2, 'Distance','city', ...
'Replicates',5, 'Options',opts);
plot(X(cidx==1,1),X(cidx==1,2),'r.', ...
X(cidx==2,1),X(cidx==2,2),'b.', ctrs(:,1),ctrs(:,2),'kx');
A dummy solution is given by the function diary which enables the storing of the matlab console output on a file.
X = [randn(20,2)+ones(20,2); randn(20,2)-ones(20,2)];
opts = statset('Display','iter');
diary('output.txt') % # Whatever is displayed from now on is saved on 'output.txt'
[cidx, ctrs] = kmeans(X, 2, 'Distance','city', ...
'Replicates',5, 'Options',opts);
diary('off') % # logging is disabled
After the execution, output.txt will contain
iter phase num sum
1 1 40 96.442
2 1 8 79.7403
3 1 6 70.2776
...
You may want to clean the content of output.txt at every run, otherwise it will just append the new log after the previous one.
One way to achieve would be to redirect the output displayed in the MATLAB terminal to a file, say 'my_file.txt'. To do so:
Use the command edit statset.m; to open the file in the MATLAB
editor.
Open the output file you require with fid =
fopen('my_file.txt','w');.
Replace fprintf( with fprintf(fid,.
You might want to keep a backup copy of statset.m too, just to be on the safe side.
EDIT
#Acorbe's solution gives the same result without all the above hassle.
I have a code for "for loop"
for i=1:4
statement...
y=sim(net, I);
end
now i need to export the value of y to excel sheet. for that i used..
xlswrite('output_data.xls', y, 'output_data', 'A1')
but my problem is that the ID of excel i.e. "A1" should change according to each iteration... in my case for iteration 1-> A1, iteration-> A2 and so on..
anybody please help me out ..
thanks in advance. for any assistance.. or suggestion..
You can store sim outputs in a vector (y(ii)) and save in the sheet with a single write. This is also more efficient since you perform a single bulk-write instead of many small writes.
Specify the first cell and y will be written starting from there.
last = someNumber;
for i=1:last statement... y(i)=sim(net, I); end
xlswrite('output_data.xls', y', 'output_data', 'A1');
If you prefer specify the range write ['A1:A',num2str(last)] instead of A1.
If you really want to write within the loop try:
for ii=1:last
...
y=sim(net, I);
xlswrite('output_data.xls', y, 'output_data', sprintf('A%d',ii));
end
You can also do for yourself what xlswrite does internally, which is interact using COM. I prefer to do this when I have a frequently used excel template or data file, because it allows for more control (albeit with more lines of code).
Excel = actxserver('Excel.Application');
Workbook = Excel.Workbooks.Open('myExcelFile.xlsx');
MySheet = Excel.ActiveWorkBook.Sheets.Item(1);
set( get(MySheet,'Range','A1:A10'), 'Value', yourValues);
...
invoke(Workbook, 'Save');
invoke(Excel, 'Quit');
delete(Excel);
This would allow you to save new data to new ranges without re-opening excel each time.
Even better would be to define an oncleanup function (as does xlswrite) to prevent lost file locks (especially when you're doing things like exiting out of debug mode):
...
myWorkbook = Excel.Workbooks.Open(filename,0,true);
cleanUp = onCleanup(#()xlsCleanup(Excel, filename));
function xlsCleanup(Excel,filepath)
try
Excel.DisplayAlerts = 0; %// Turn off dialog boxes
[~,n,e] = fileparts(filepath); %// Excel API expects just the filename
fileName = [n,e];
Excel.Workbooks.Item(fileName).Close(false);
end
Excel.Quit;
end
You can put xlswrite after for loop.You just want to do is save you result in a matrix.This function can write a matrix.
also,you can use [] to combine string to change the range.
>> for i=1:4
Range=['A' num2str(i)]
end
Range =
A1
Range =
A2
Range =
A3
Range =
A4
But,this is a bad way.You should open and write Excel file every time.