How to print the current filename in a plot in matlab? - matlab

I have one .m file per plot and want to see in my draft printouts, which file was used to create it.
This should be done with a function which can be placed in my .m file and
commented out, for the final version.
% addWatermarkFilename() %
So far I found mfilename(), but it could not get the name of the calling function. I am looking also for a good way to put the text in the picture without changing the size.
Solution:
I combined the suggestions by Luis Mendo and NKN to:
function [ output_args ] = watermarkfilename( )
% WATERMARKFILENAME prints the filename of the calling script in the
% current plot
s = dbstack;
fnames = s(2).name;
TH = text(0,0,fnames,'Interpreter','none');
TH.Color = [0.7 0.7 0.7];
TH.FontSize = 14;
TH.Rotation = 45;
uistack(TH,'bottom');
end

I suggest instead of commenting out a function from the code, use a proper flag. For instance the code can be something like this:
clc,clear,close all
addWaterMark = true; % if true you will get the filename in the title
fname = mfilename; % get file name mfilename('fullpath') for the full-path
t=-2*pi:0.1:2*pi;
y = sin(t);
plot(t,y); grid on;
xlabel('t');ylabel('y');
if addWaterMark
title(['filename: ' fname '.m']);
else
title('plot no.1');
end
A little bit playing with the text function, you can make a proper watermark. something like this:
clc,clear,close all
addWaterMark = true;
fname = mfilename;
fnames = [fname '.m'];
t=-2*pi:0.1:2*pi;
y = sin(t);
plot(t,y); grid on;
xlabel('t');ylabel('y');
if addWaterMark
title(['filename: ' fnames]);
t = text(-3,-0.4,fnames);
t.Color = [0.7 0.7 0.7];
t.FontSize = 40;
t.Rotation = 45;
else
title('plot no.1');
end
Note: Obviously the code between the if and else can be stored as a function that receives the string (char) from the fnames variable and a handle for the figure.

If you want to get the name of the function or script that called the current function or script, use dbstack as follows:
s = dbstack; % get struct with function call stack information
callerName = s(2).name; % get name of second function in the stack
The first entry in s refers to the current function; the second refers to the one that called it.

Related

How can I loop through and process files from a directory individually?

I'm trying to write a function that iteratively loops through a bunch of .txt files in a directory and processes them individually. After a file has been processed I would like to plot output variables, then on the next iteration plot the new variables on the same graph. My code is shown below however does not seem to be working, it returns a 'output argument 'output1' (and maybe others) not assigned during call to function2.
Currently my code looks something like this:
function [output1, output2, fig] = Processing(Folder_1,Folder_2,Folder_3)
%% Read in all the Data
% Initialise Loop to process each file independently
for i = 1 : length(Text_Files1)
Sorted_Index1 = Indices1(i);
Path1 = fullfile(Folder_1,Text_Files1(Sorted_Index1).name);
Table1 = readtable(Path1);
Sorted_Index2 = Indices2(i);
Path2 = fullfile(Folder_2,Text_Files2(Sorted_Index2).name);
Table2 = readtable(Path2);
Sorted_Index3 = Indices3(i);
Path3 = fullfile(Folder_3,Text_Files3(Sorted_Index3).name);
Table3 = readtable(Path3,'Delimiter',';');
%% Process Data through the Loop
[HR] = function1(processed_data)
[output1 output2] = function2(HR, Time);
hold on
fig = figure('Visible', false);
subplot(10,10,1:90)
plot(output2, output1, 'Color', [0.92 0.47 0.44], 'LineWidth', 1.5);
end
end
%% Function 2:
function [output1, output2] = function2(t, y, z)
segment = 1:z:max(y);
% Iterate through each time segment and calculate average t value
for x = 1:length(segment)-1
SegmentScores = find(y > segment(x) & ...
y < segment(x+1));
output1(x) = mean(y(SegmentScores));
output2(x) = Segment(x+1);
end
end
The problem is that you're calling function2(HR, Time) with two inputs, while it needs three function2(t, y, z).
For that reason, I'm assuming that inside function2 segment is an empty array, and thus the loop for x = 1:length(segment) - 1 is not entered at all.
Since the definition of output1 and output2 is only inside the loop, they will never be created and thus the error.
If you provide three inputs to your function2, the problem will be solved. Just pay attention to the order in which you provide them (for example, I'm assuming your Time input should be the same as t in the function, so it should be the first input to be passed).

Loop for frame extraction matlab

Im currently trying to make a loop to do the same action to multiply videofiles. Currently my code looks like this:
close all
clear all
clc
movFiles = dir('*.mov');
numFiles = length(movFiles);
mydata = cell(1,numFiles);
% mydata = zeros(numFiles);
for k = 1:numFiles
mydata{1,k} = VideoReader(movFiles(k).name);
end
for k=1:numFiles
figure;
video = read(mydata{k},[1 Inf]);
for img = 60:60:360;
filename=strcat('File',num2str(img),'.jpg');
b = read(mydata{k}, img);
imwrite(b,filename);
end
end
The problem is that the frames get overwritten so what i need is a way to not make that happened. The moviefiles are named 1-200 so the filename i would like is something like 1framenr, 2framenr. Hope that somebody can help me with that
The problem is in the way you are defining the filename for each frame inside the loop. If you look at the line:
filename=strcat('File',num2str(img),'.jpg');
It is only composed of the frame number (img), which will repeat for every video file. Try replacing that line with following:
filename = ['Video_' num2str(k) '_frame_' num2str(img) '.jpg'];
This will give you files called Video_1_frame_1.jpg, Video_1_frame_2.jpg, etc.

MATLAB Data Cursor Mode

I have a simple class that plots basic x and y data. Within the class I have a method that enables the data cursor mode, customizes the text, and collects and saves the points. I'd like to change the behavior of the method so that I can collect only two points at a time. Right now it stores every point even when I turn off the data cursor mode and turn it back on to use it. Here is my code for my class:
classdef CursorPoint
properties
Xdata
Ydata
end
methods
function me = CursorPoint(varargin)
x_data = 0:.01:2*pi;
y_data = cos(x_data);
f= figure;
plot(x_data,y_data);
me.DCM(f);
end
function DCM(me,fig)
dcm_obj = datacursormode(fig);
set(dcm_obj,'UpdateFcn',#myupdatefcn)
set(dcm_obj,'enable','on')
myPoints=[];
function txt = myupdatefcn(empt,event_obj)
% Customizes text of data tips
pos = get(event_obj,'Position');
myPoints(end + 1,:) = pos;
txt = {['Time: ',num2str(pos(1))],...
['Amplitude: ',num2str(pos(2))]};
end
end
end
end
Could you change the myPoints variable to two variables called myPointCurrent and myPointPrevious. When ever the myupdatefcn method is called you would move the contents of myPointCurrent into myPointPrevious and then store the current position in myPointCurrent.
The new function (with some error checking) would look something like:
function txt = myupdatefcn(empt,event_obj)
% Customizes text of data tips
myPointPrevious=myPointCurrent;
pos = get(event_obj,'Position');
myPointCurrent=pos;
txt = {['Time: ',num2str(pos(1))],...
['Amplitude: ',num2str(pos(2))]};
end

Use MATLAB's 'keyPressFcn' in a simple program

I am trying to use the 'KeyPressFcn' in a normal MATLAB script, but I am having problems. I can use it nicely WITHIN a function, (like here), but I would like to use it in a normal script like so.
My simple script is:
%Entry Point
clear all
N = 100;
x = randn(1,N);
figHandle = figure(1);
clf(figHandle);
set(figHandle, 'KeyPressFcn', myFunction(~, eventDat,x,N))
Here is the function 'myFunction' that sits in the same directory:
function myFunction(~, eventDat,x,N)
mean = sum(x)/N;
disp(mean);
key = eventDat.Key;
disp(key);
end
Now, if I run this, it does not work, because, (I suspect), something is wrong with the way I am calling myFunction, but I cannot figure out what the problem is exactly, since I am a noob at using KeyPressFcn. Help would be appreciated for this problem. Thanks!
You need to do it through anonymous functions:
In script file, for example called test.m:
%Entry Point
clear all
N = 100;
x = randn(1,N);
figHandle = figure(1);
clf(figHandle);
set(figHandle, 'KeyPressFcn', ...
#(fig_obj , eventDat) myFunction(fig_obj, eventDat, x, N));
In a file called myFunction.m in the same folder as test.m
function myFunction(~, eventDat, x, N)
mean = sum(x)/N;
disp(mean);
key = eventDat.Key;
disp(key);
How to return value from myFunction?
There are few ways of doing this. It depends on what u want to do. But quickly you could use mutable variables for this, such as, containers.Map. This is one example of ding this. The returned variable is newN.
In script file, for example called test.m:
%Entry Point
clear all
N = 100;
x = randn(1,N);
% this map will store everything u want to return from myFunction.
returnMap = containers.Map;
figHandle = figure(1);
clf(figHandle);
set(figHandle, 'KeyPressFcn', ...
#(fig_obj , eventDat) myFunction(fig_obj, eventDat, x, N, returnMap));
% wait till gui finishes in this example.
waitfor(figHandle);
newN = returnMap('newN');
% display newN
newN
In a file called myFunction.m:
function myFunction(handle, eventDat, x, N, returnMap)
mean = sum(x)/N;
disp(mean);
key = eventDat.Key;
disp(key);
newN = 435;
returnMap('newN') = newN;

Matlab Legend after FOR loop

I am creating a file to read in a certain number of .wav files, each of these corresponding to a musical note. I am performing an FFT on each of them and plotting them all on the same figure. However I am having a problem with getting the legend to print correctly, it is separating the names I want to use into individual letters instead of using them as a string. My code is as follows:
clear all
mydir = 'Note Values/';
wavFiles = dir([mydir '*.wav']);
length(wavFiles)
legendText = [];
figure(1);
hold on;
for i = 1:length(wavFiles)
wavFiles(i).name
[y, fs] = wavread([mydir wavFiles(i).name]);
sound(y, fs)
currentSample = y(round(length(y)/2)-2048:round(length(y)/2)+2047);
FFT = abs(fft(currentSample));
Power = FFT.*conj(FFT)/length(FFT);
if (mod(i, 2) == 1)
h = plot(Power, 'Color', 'red');
else
h = plot(Power, 'Color', 'blue');
end
sri = wavFiles(i).name;
sri
legendText = [legendText, sri];
end
length(legendText)
legendText(1)
legend(legendText(:));
hold off;
The sri variable is always a full string, but legendText(1) only prints out A instead of A3.wav. I know it's probably something really obvious but I just can't find it. Thanks
The output on my graph appears as this:
You should use
legendText{i} = sri
to fill the cell with strings and
legend(legendText{:});
at end.
I don't have MATLAB by me, so I'm not able to test it, but as I recall, you should use { instead of [ :
legendText = {legendText, sri};