I am trying to basically copy this graph for practice for my final coming up but I don't understand how to change the font,size or labeling the axis. Simply put, I need to replicate this graph exactly from my code. I need the font to be times new roman and size 18 with a marker size of 8. How would I format my code into this?
This is my code:
clear
clc
x = linspace(0,2);
y1 = sin(2*pi*x);
y2 = exp(-0.5*2*pi*x).*sin(2*pi*x);
figure
subplot(2,1,1);
hPlot1 = plot(x,y1,'rs');
ylabel('f(t)')
set(gca,'YLim',[-1 2],'YTick',-1:1:2,'XTick',0:.5:2)
subplot(2,1,2);
hPlot2 = plot(x,y2,'k*');
xlabel('Time(s)')
ylabel('g(t)')
set(gca,'YLim',[-0.2,0.6],'YTick',[-0.2,0,0.2,0.4,0.6],'XTick',0:.5:2)
The code below:
%// x = linspace(0,2); %// changed that to respect where the markers are on your example figure
x = 0:0.1:2 ;
y1 = sin(2*pi*x);
y2 = exp(-0.5*2*pi*x).*sin(2*pi*x);
figure
h.axtop = subplot(2,1,1) ;
h.plottop = plot(x,y1,'LineStyle','-','Color','r', ...
'Marker','s', ...
'MarkerEdgeColor','k', ...
'MarkerFaceColor','none', ...
'MarkerSize',8) ;
set(gca,'YLim',[-1 2],'YTick',-1:1:2,'XTick',0:.5:2)
h.ylbl(1) = ylabel('\itf(t)') ; %// label is set in "italic" mode with the '\it' tag at the beginning
h.axbot = subplot(2,1,2);
h.plotbot = plot(x,y2,'-ks', ...
'Marker','*', ...
'MarkerEdgeColor','r', ...
'MarkerSize',8) ;
set(gca,'YLim',[-0.2,0.6],'YTick',[-0.2,0,0.2,0.4,0.6],'XTick',0:.5:2)
h.xlbl(1) = xlabel('Time(s)') ;
h.ylbl(2) = ylabel('\itg(t)') ; %// label is set in "italic" mode with the '\it' tag at the beginning
%// create the "text" annotations
h.txttop = text(0.5,1.5, 'Harmonic force \itf(t)=sin(\omegat)' , 'Parent',h.axtop ) ; %// note the 'parent' property set to the TOP axes
h.txtbot = text(0.5,0.3, 'Forced response \itg(t)=e^{\zeta\omegat} sin(\omegat)' , 'Parent',h.axbot ) ; %// note the 'parent' property set to the BOTTOM axes
%// set the common properties for all text objects in one go
set( [h.xlbl h.ylbl h.txttop h.txtbot] , 'FontName','Times New Roman' , 'FontSize',18)
will produce the following figure:
note how the handle of the graphic object were saved and re-used to set properties later on. If multiple graphic object (even different) have the same property, it is possible to assign this property to all the graphic object in one go.
Look at the Matlab text function documentation for more detail on how to place annotations on your figure.
Replace xlabel('Time(s)') by:
xlabel('Time(s)','FontName','TimesNewRoman','FontSize',18)
and do the same for ylabel.
For the marker size, replace hPlot1 = plot(x,y1,'rs'); by
hPlot1 = plot(x,y1,'r-',x(1:5:end),y1(1:5:end),'ks','MarkerSize',8);
and the same for the other plot.
Finally, you can add text to the figure using the text function, e.g.:
text(0.5,1.5,'Harmonic force f(t) = sin(\omega t)')
Again, you can change the font size and font name, as with xlabel and ylabel.
Related
I want to add a marker/special tick mark in my MATLAB colorbar. For example, lets say I have a colorbar scale from -2 to 3 and my critical value is -1.8, how can I add a marker of the value by symbol/marker?
One way to do this is to fetch the colorbar position, compute the location where you want your marker, and place an annotation object (like an arrow) there:
% Plot sample data, displaying color bar and getting its limits:
data = peaks();
imagesc(data);
hBar = colorbar();
cLimits = caxis();
hold on;
% Select and plot a point of interest:
point = [31 15];
value = data(point(1), point(2));
plot(point(2), point(1), 'r+');
% Compute location of color bar pointer and make annotation:
barPos = get(hBar, 'Position');
xArrow = barPos(1)+barPos(3)/2+[0.05 0];
yArrow = barPos(2)+barPos(4)*(value-cLimits(1))/diff(cLimits)+[0 0];
hArrow = annotation('textarrow', xArrow, yArrow, ...
'String', num2str(value, '%.2f'), 'Color', 'r');
If the figure is resized, the position of the annotation object may shift with respect to the color bar. One way to avoid this is to tweak the axes and color bar resize behavior with the following code:
axesPos = get(gca, 'Position');
set(hBar, 'Location', 'manual');
set(gca, 'Position', axesPos);
This should allow the annotation object to stay fixed to the proper spot over the color bar.
Here is yet another option - just add/change the tick label at the specific value:
MarkTxt = '<-Mark';
imagesc(rand(10)-2) % something to plot
colormap('jet')
CB = colorbar;
% in case you DON'T want the value to appear:
value = -1.8;
t = find(CB.Ticks==value);
if ~isempty(t)
CB.TickLabels{t} = MarkTxt;
else
[CB.Ticks,ord] = sort([CB.Ticks value],'ascend');
t = CB.Ticks==value;
CB.TickLabels{t} = MarkTxt;
end
%% OR - in case you want the value to appear:
value = -1.24;
t = find(CB.Ticks==value);
if ~isempty(t)
CB.TickLabels{t} = [CB.TickLabels{t} MarkTxt];
else
[CB.Ticks,ord] = sort([CB.Ticks value],'ascend');
t = CB.Ticks==value;
CB.TickLabels{t} = [CB.TickLabels{t} MarkTxt];
end
Without the value:
With the value:
You can simply add text outside the plotting area and use that for your marker:
A = rand(15);
f=figure;
imagesc(A);
text(7,7,'X','Color','red') % Put a red X in the middle
text(17.5,size(A,1)*(1-A(7,7)),'<marker'); % Set a marker on the colour bar for the middle point
colorbar
Which results in:
I haven't found a way yet to plot a marker over the colour bar, as the colour bar is not one of the plot children which I can use in uistack for some reason.
I am trying to make an animation where several datasets are being cycled through in a histogram plot, and a datatip follows the highest bar in every frame, as demonstrated below:
Here's a code which achieves the desired result using a bar graph:
%% // Initialization
close all force; clear variables; clc;
%% // Generate some data:
indMax = 20; data = randi(indMax,[5,45]);
%% // Generate the 1st values to plot:
edges = 0.5:1:indMax+0.5;
counts = histcounts(data(1,:),edges);
[~,maxInd] = max(counts);
%% // Create the plot and the datatip:
figure(100); hBar = bar(1:indMax,counts);
hDT = makedatatip(hBar,maxInd); hDT = handle(hDT);
grid on; hold on; grid minor; xlim([0,indMax+1]); ylim([0,10]);
%% // Update the figure and the datatip:
for indFrame = 2:size(data,1)
counts = histcounts(data(indFrame,:),edges);
[~,maxInd] = max(counts);
hBar.YData = counts; %// Update bar heights
hDT.Cursor.DataIndex = maxInd; %// Update datatip location
%// Alternatively to the above line: hDT.Position = [newX newY newZ];
java.lang.Thread.sleep(1000);
drawnow;
end
Note that the datatip is created using a modified version of the makedatatip submission from FEX, as per the comment on the submission page (this is true for the 27/06/2012 version of makedatatip):
a couple of changes need to be made to the code:
***********CHANGE 1*********
line 122 needs to be: pos = [X(index(n)) Y(index(n)) 0];
***********CHANGE 2*********
lines 135-141 should be commented OUT
And also Change 3: line 84 to Z = [];
Since makedatatip attempts to acces the 'XData' and 'YData' properties of the input handle, which are absent in histogram plots, it refuses to work. So my question is:
How can datatips be created and updated programmatically in histogram plots (using matlab-hg2), along with the histogram itself?
Turns out the solution is quite straight-forward, at least when only a single datatip is needed. Here are the required steps:
Replace the bar plot with a histogram:
hHist = histogram(data(1,:),edges);
Create the datatip "manually" instead of using makedatatip:
hDataCursorMgr = datacursormode(ancestor(hHist,'figure'));
hDT = createDatatip(hDataCursorMgr,hHist);
Update the position as needed:
hDT.Cursor.DataIndex = maxInd;
To update the histogram's bar heights, it is not possible to update the 'Values' property directly (since it's read-only), so one must update the 'Data' property (and let MATLAB recompute the bar heights on its own):
hHist.Data = data(indFrame,:);
And everything put together:
%% // Initialization
close all force; clear variables; clc;
%% // Generate some data:
indMax = 20; data = randi(indMax,[5,45]);
%% // Generate the 1st values to plot:
edges = 0.5:1:indMax+0.5;
counts = histcounts(data(1,:),edges);
[~,maxInd] = max(counts);
%% // Create the plot and the datatip:
figure(100); hHist = histogram(data(1,:),edges);
hDataCursorMgr = datacursormode(ancestor(hHist,'figure'));
hDT = createDatatip(hDataCursorMgr,hHist); hDT.Cursor.DataIndex = maxInd;
grid on; hold on; grid minor; xlim([0,indMax+1]); ylim([0,10]);
%% // Update the plot and the datatip:
for indFrame = 2:size(data,1)
[~,maxInd] = max(histcounts(data(indFrame,:),edges));
hHist.Data = data(indFrame,:);
hDT.Cursor.DataIndex = maxInd;
java.lang.Thread.sleep(1000);
drawnow;
end
Which results in:
Some notes \ observations:
Datatips can only be added to supported data types, which currently only consist of double values (i.e. plotting something other than double doesn't let you add datatips to it, apparently). This is true for MATLAB 2015a. See another discussion about it here.
If datatips should contain some LaTeX-formatted strings, this Q&A describes what needs to be done.
The gif animations I used were created using this.
To center the animations in the posts, I used a combination of "alt+0160" and "alt+255".
Is there a way to add some space between the plots for the plotmatrix function? (I would like to label every x and y axis)
You can do it by using a specific output argument in the call to plotmatrix. You can then retrieve the position of each individual axes and modify it (making it smaller).
Example:
clc
clear
rng default
X = randn(50,3);
Y = reshape(1:150,50,3);
%// Use this output argument
[~,AX,~,~,~] = plotmatrix(X,Y);
%// Fetch all the positions and alter them (make axes smaller)
AllPos = get(AX(:),'Position');
AllPos = vertcat(AllPos{:});
NewPos = [AllPos(:,1)+.05 AllPos(:,2)+.05 AllPos(:,3)-.1 AllPos(:,4)-.1]
%// Update the plot
for k = 1:numel(AX)
axes(AX(k))
set(AX(k),'Position',NewPos(k,:))
xlabel(sprintf('Axes %i',k))
end
Outputs the following:
In contrast to the original plot:
I'm trying to find a way to nicely plot my measurement data of digital signals.
So I have my data available as csv and mat file, exported from an Agilent Oscilloscope. The reason I'm not just taking a screen shot of the Oscilloscope screen is that I need to be more flexible (make several plots with one set of data, only showing some of the lines). Also I need to be able to change the plot in a month or two so my only option is creating a plot from the data with a computer.
What I'm trying to achieve is something similar to this picture:
The only thing missing on that pic is a yaxis with 0 and 1 lines.
My first try was to make a similar plot with Matlab. Here's what I got:
What's definitely missing is that the signal names are right next to the actual line and also 0 and 1 ticks on the y-axis.
I'm not even sure if Matlab is the right tool for this and I hope you guys can give me some hints/a solution on how to make my plots :-)
Here's my Matlab code:
clear;
close all;
clc;
MD.RAW = load('Daten/UVLOT1 debounced 0.mat'); % get MeasurementData
MD.N(1) = {'INIT\_DONE'};
MD.N(2) = {'CONF\_DONE'};
MD.N(3) = {'NSDN'};
MD.N(4) = {'NRST'};
MD.N(5) = {'1V2GD'};
MD.N(6) = {'2V5GD'};
MD.N(7) = {'3V3GD'};
MD.N(8) = {'5VGD'};
MD.N(9) = {'NERR'};
MD.N(10) = {'PGD'};
MD.N(11) = {'FGD'};
MD.N(12) = {'IGAGD'};
MD.N(13) = {'GT1'};
MD.N(14) = {'NERRA'};
MD.N(15) = {'GT1D'};
MD.N(16) = {'GB1D'};
% concat vectors into one matrix
MD.D = [MD.RAW.Trace_D0, MD.RAW.Trace_D1(:,2), MD.RAW.Trace_D2(:,2), MD.RAW.Trace_D3(:,2), ...
MD.RAW.Trace_D4(:,2), MD.RAW.Trace_D5(:,2), MD.RAW.Trace_D6(:,2), MD.RAW.Trace_D7(:,2), ...
MD.RAW.Trace_D8(:,2), MD.RAW.Trace_D9(:,2), MD.RAW.Trace_D10(:,2), MD.RAW.Trace_D11(:,2), ...
MD.RAW.Trace_D12(:,2), MD.RAW.Trace_D13(:,2), MD.RAW.Trace_D14(:,2), MD.RAW.Trace_D15(:,2)];
cm = hsv(size(MD.D,2)); % make colormap for plot
figure;
hold on;
% change timebase to ns
MD.D(:,1) = MD.D(:,1) * 1e9;
% plot lines
for i=2:1:size(MD.D,2)
plot(MD.D(:,1), MD.D(:,i)+(i-2)*1.5, 'color', cm(i-1,:));
end
hold off;
legend(MD.N, 'Location', 'EastOutside');
xlabel('Zeit [ns]'); % x axis label
title('Messwerte'); % title
set(gca, 'ytick', []); % hide y axis
Thank you guys for your help!
Dan
EDIT:
Here's a pic what I basically want. I added the signal names via text now the only thing that's missing are the 0, 1 ticks. They are correct for the init done signal. Now I just need them repeated instead of the other numbers on the y axis (sorry, kinda hard to explain :-)
So as written in my comment to the question. For appending Names to each signal I would recommend searching the documentation of how to append text to graph. There you get many different ways how to do it. You can change the position (above, below) and the exact point of data. As an example you could use:
text(x_data, y_data, Var_Name,'VerticalAlignment','top');
Here (x_data, y_data) is the data point where you want to append the text and Var_Name is the name you want to append.
For the second question of how to get a y-data which contains 0 and 1 values for each signal. I would do it by creating your signal the way, that your first signal has values of 0 and 1. The next signal is drawn about 2 higher. Thus it changes from 2 to 3 and so on. That way when you turn on y-axis (grid on) you get values at each integer (obviously you can change that to other values if you prefer less distance between 2 signals). Then you can relabel the y-axis using the documentation of axes (check the last part, because the documentation is quite long) and the set() function:
set(gca, 'YTick',0:1:last_entry, 'YTickLabel',new_y_label(0:1:last_entry))
Here last_entry is 2*No_Signals-1 and new_y_label is an array which is constructed of 0,1,0,1,0,....
For viewing y axis, you can turn the grid('on') option. However, you cannot chage the way the legends appear unless you resize it in the matlab figure. If you really want you can insert separate textboxes below each of the signal plots by using the insert ->Textbox option and then change the property (linestyle) of the textbox to none to get the exact same plot as above.
This is the end result and all my code, in case anybody else wants to use the good old ctrl-v ;-)
Code:
clear;
close all;
clc;
MD.RAW = load('Daten/UVLOT1 debounced 0.mat'); % get MeasurementData
MD.N(1) = {'INIT\_DONE'};
MD.N(2) = {'CONF\_DONE'};
MD.N(3) = {'NSDN'};
MD.N(4) = {'NRST'};
MD.N(5) = {'1V2GD'};
MD.N(6) = {'2V5GD'};
MD.N(7) = {'3V3GD'};
MD.N(8) = {'5VGD'};
MD.N(9) = {'NERR'};
MD.N(10) = {'PGD'};
MD.N(11) = {'FGD'};
MD.N(12) = {'IGAGD'};
MD.N(13) = {'GT1'};
MD.N(14) = {'NERRA'};
MD.N(15) = {'GT1D'};
MD.N(16) = {'GB1D'};
% concat vectors into one matrix
MD.D = [MD.RAW.Trace_D0, MD.RAW.Trace_D1(:,2), MD.RAW.Trace_D2(:,2), MD.RAW.Trace_D3(:,2), ...
MD.RAW.Trace_D4(:,2), MD.RAW.Trace_D5(:,2), MD.RAW.Trace_D6(:,2), MD.RAW.Trace_D7(:,2), ...
MD.RAW.Trace_D8(:,2), MD.RAW.Trace_D9(:,2), MD.RAW.Trace_D10(:,2), MD.RAW.Trace_D11(:,2), ...
MD.RAW.Trace_D12(:,2), MD.RAW.Trace_D13(:,2), MD.RAW.Trace_D14(:,2), MD.RAW.Trace_D15(:,2)];
cm = hsv(size(MD.D,2)); % make colormap for plot
figure;
hold on;
% change timebase to ns
MD.D(:,1) = MD.D(:,1) * 1e9;
% plot lines
for i=2:1:size(MD.D,2)
plot(MD.D(:,1), MD.D(:,i)+(i-2)*2, 'color', cm(i-1,:));
text(MD.D(2,1), (i-2)*2+.5, MD.N(i-1));
end
hold off;
%legend(MD.N, 'Location', 'EastOutside');
xlabel('Zeit [ns]'); % x axis label
title('Messwerte'); % title
% make y axis and grid the way I want it
set(gca, 'ytick', 0:size(MD.D,2)*2-3);
grid off;
set(gca,'ygrid','on');
set(gca, 'YTickLabel', {'0'; '1'});
ylim([-1,(size(MD.D,2)-1)*2]);
I have 13 lines on a plot, each line corresponding to a set of data from a text file. I'd like to label each line starting with the first set of data as 1.2, then subsequently 1.25, 1.30, to 1.80, etc., with each increment be 0.05. If I were to type it out manually, it would be
legend('1.20','1.25','1.30', ...., '1.80')
However, in the future, I might have more than 20 lines on the graph. So typing out each one is unrealistic. I tried creating a loop in the legend and it doesn't work.
How can I do this in a practical way?
N_FILES=13 ;
N_FRAMES=2999 ;
a=1.20 ;b=0.05 ;
phi_matrix = zeros(N_FILES,N_FRAMES) ;
for i=1:N_FILES
eta=a + (i-1)*b ;
fname=sprintf('phi_per_timestep_eta=%3.2f.txt', eta) ;
phi_matrix(i,:)=load(fname);
end
figure(1);
x=linspace(1,N_FRAMES,N_FRAMES) ;
plot(x,phi_matrix) ;
Need help here:
legend(a+0*b,a+1*b,a+2*b, ...., a+N_FILES*b)
As an alternative to constructing the legend, you can also set the DisplayName property of a line so that the legend is automatically correct.
Thus, you could do the following:
N_FILES = 13;
N_FRAMES = 2999;
a = 1.20; b = 0.05;
% # create colormap (look for distinguishable_colors on the File Exchange)
% # as an alternative to jet
cmap = jet(N_FILES);
x = linspace(1,N_FRAMES,N_FRAMES);
figure(1)
hold on % # make sure new plots aren't overwriting old ones
for i = 1:N_FILES
eta = a + (i-1)*b ;
fname = sprintf('phi_per_timestep_eta=%3.2f.txt', eta);
y = load(fname);
%# plot the line, choosing the right color and setting the displayName
plot(x,y,'Color',cmap(i,:),'DisplayName',sprintf('%3.2f',eta));
end
% # turn on the legend. It automatically has the right names for the curves
legend
Use 'DisplayName' as a plot() property, and call your legend as
legend('-DynamicLegend');
My code looks like this:
x = 0:h:xmax; % get an array of x-values
y = someFunction; % function
plot(x,y, 'DisplayName', 'Function plot 1'); % plot with 'DisplayName' property
legend('-DynamicLegend',2); % '-DynamicLegend' legend
source: http://undocumentedmatlab.com/blog/legend-semi-documented-feature/
legend can also take a cell list of strings as an argument. Try this:
legend_fcn = #(n)sprintf('%0.2f',a+b*n);
legend(cellfun(legend_fcn, num2cell(0:N_FILES) , 'UniformOutput', false));
The simplest approach would probably be to create a column vector of the numbers to use as your labels, convert them to a formatted character array with N_FILES rows using the function NUM2STR, then pass this as a single argument to LEGEND:
legend(num2str(a+b.*(0:N_FILES-1).','%.2f'));
I found this I found through Google:
legend(string_matrix) adds a legend containing the rows of the matrix string_matrix as labels. This is the same as legend(string_matrix(1,:),string_matrix(2,:),...).
So basically, it looks like you can construct a matrix somehow to do this.
An example:
strmatrix = ['a';'b';'c';'d'];
x = linspace(0,10,11);
ya = x;
yb = x+1;
yc = x+2;
yd = x+3;
figure()
plot(x,ya,x,yb,x,yc,x,yd)
legend(strmatrix)