Matlab, print() function generates a png file without Y asymptote data - matlab

I have been currently using a Matlab script that plots a function and prints its data into a png file, but I have a problem with this last phase.
The fact is that, moving from plotted image to png files, some data points disappear.
Here are my images.
What Matlab (correctly) plots (note that the maximum is (0; 7.7)):
And here's what Matlab prints into the file:
Note that all the points in the Y asymptote are missing!
Why does this happen?
Here's my code:
grafico2D('filename.dat', -1);
...
function [result] = grafico2D(filename, max_X)
% function that loads data from a two-column file and plot them in 2D image
close all;
dati = load(filename); % load data from file
X = dati(:,1); % X axis
Y = dati(:,2); % Y axis
temp = size(X);
lungX = temp(1);
hFig = figure();
set(hFig, 'Visible', 'on');
plot(X, Y, 'red');
hold on;
ylim([0 1]);
if(max_X==-1)
xlim([1 X(lungX)]);
else
xlim([1 max_X]);
end
xlim
title(strrep(filename,'_','\_')); % substitute _ with \_
xlabel('annotation prediction position'), ylabel('likelihood');
grid
print(hFig, '-dpng', filename); % stampa su file
% }
result = 1;
end
Is there someone who can help me?
Thanks!

You can increase the resolution of your image with the -r option which specifies the resolution in dot per inch (with 90 as default). It should solve your problem (at least it did for me). See the Matlab print function documentation.
PS: you could also use thicker lines with the line property LineWidth.

You could just extend the x-limit a little bit:
xlim(xlim() - [0.05 0])

Related

How do i produce an animated GIF in MATLAB?

I want to produce a animated gif of a solution to a partial differential equation. That is the gif should show the solution at specific time.
Currently I can only make pictures in which all times are plotted.
Below is my entire program, with figure(3) being my attempt of making a gif.
clear all;
close all;
%%%%%%%%%%%%
% For slide 27 of Diffusion 1D
% The equation to be graphed in latex form is
% u(x,t)=\frac{1}{L}+\frac{2}{L}\sum^{\infty}_{n=1}cos(\frac{n\pi x_0}{L})cos(\frac{n\pi x}{L})e^{-k(\frac{n\pi}{L})^2t}
%%%%%%%%%%%%
%define constants
%note that the constants listed in the file are arbitrary
L = 2; %length of the rod
k= 0.01; % Diffusivity, which is assume to be constant but can be a function of x
x0 = 1; %location of the inital condition i.e. f(x)=delta(x-x0)
tmax= 50; %maximum amount of time the simulation runs
nmax = 200; % maximum value for n, increase to accuracy
tgrid = 21; %The number of points to be evaluated in the time domain
xgrid = 51; %The number of points to be evaluated in the space domain
%initialize variables
u=zeros(tgrid,xgrid); %preallocate array used for storing values of the solution
t=linspace(0,tmax,tgrid);%We assume that time is evenly distributed
x=linspace(0,L,xgrid); %We assume that space is evenly distributed
%Plotting variables
figure(1);
hold on;
axis([0 L -inf inf]);
xlabel('x');
ylabel('u(x,t)');
%Calculation,
for i=1:tgrid
for j=1:xgrid
seriesSum=0;
%Calculate the fourier series up to nmax for each point u(x,t)
for n= 1:nmax
seriesSum= seriesSum + cos(n*pi*x0/L)*cos(n*pi*x(j)/L)*exp(-k*t(i)*(n*pi/L)^2);
end
%Finish calcuation for solution at a specific point
u(i,j)= 1/L+(2/L)*seriesSum;
end
%After we have calculated all points at time t, we graph it for time t
plot(x,u(i,:),'linewidth',4);
end
saveas(gcf,'PDE_sol.png')%Save figure as png in current directory
%run a second loop that does not include the initial condition to get a
%better view of the long term behaviour.
%Plotting variables
figure(2);
hold on;
axis([0 L -inf inf]);
xlabel('x');
ylabel('u(x,t)');
for i=2:tgrid
plot(x,u(i,:),'linewidth',4);
end
saveas(gcf,'PDE_sol_without_inital.png')%Save figure as png in current directory
%Create a gif verison of figure 2
figure(3);
axis([0 L -inf inf]);
xlabel('x');
ylabel('u(x,t)');
filename = 'PDE_sol.gif';
for i=2:tgrid
plot(x,u(i,:),'linewidth',4);
drawnow
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if i == 2;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end
The output gif that I get is
which is clearly not animated.
Note: If you think there is a better place to post this question please direct me to it. As my issue is with the MATLAB programming language and not the math involved I thought this would be the best place to post my question.
The first input to getframe is the handle of the figure that you'd like to take a screenshot of. As you have it written, you are grabbing figure 1 which is actually referring to the first figure that you create that you aren't updating within your loop.
You have assigned a numeric handle of 3 to the figure that you create right before your last loop so you'll want to tell getframe to use that figure instead.
Additionally, I would create one plot object and update the XData and YData rather than continuously creating new plot objects. The issue with calling plot continuously is that it's slow AND it completely resets all of your axes settings such as x and y labels as well as x and y limits.
% Store the handle to the figure in hfig
hfig = figure(3);
% Create the initial plot object
hplot = plot(NaN, NaN, 'LineWidth', 4);
axis([0 L 0 2]);
xlabel('x');
ylabel('u(x,t)');
filename = 'PDE_sol.gif';
for i=2:tgrid
% Update the plot appearance
set(hplot, 'XData', x, 'YData', u(i,:));
drawnow
% Get a screenshot of THIS figure
frame = getframe(hfig);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if i == 2;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
end

Specifying limits of axes

I'm trying to limit x axis, i.e., frequency axis to 4 Hz in MatLab. This is the code I used:
subplot(3,1,2);
%Fse = 220;
time = 0:1/fse:secBuffer-1/fse;
%a = eegCounter;
c = eegBuffer;
wo = 50 / (1000/2);
bw = wo / 60;
[b,a] = iirnotch(wo,bw);
y = filter(b,a,c);
ydft = fft(c);
xdft = fft(y);
xlabel('Frequency');
ylabel('Signal');
xlim([1,4]);
ylim([1,4]);
plot(xdft,ydft);
However mine is live signal plotting and both x axis and y axis keep changing according to incoming packets. How to limit x axis to 4 Hz?
When plotting MATLAB automatically tries to fit the axis with the dynamic range of the data. Therefore if you want to make sure only a given range is plotted, you need to specify it AFTER the call to plot to force MATLAB to do it, otherwise it won't and you will be stuck with the whole data.
Here is a very simple code in which I call xlim either before or after the call to plot. See the difference?
clear
clc
close all
x = 1:50;
y = x.^2;
figure
subplot(1,2,1)
xlim([1 20])
plot(x,y)
title('xlim before call to plot')
subplot(1,2,2)
plot(x,y)
xlim([1 20])
title('xlim after call to plot')
Produces this:
You have to set the XLimMode (and YLimMode) properties of the axes to manual. But even if you do so every call to plot(...) will reset that to auto and mess up your axes limits.
The cleanest way is to first define your axes and your plots outside of any loop (not forgetting to get their handle), then when you update the data just update the XData and YData of the line objects, using the set method. The set method will only update the property you pass in parameters, so it will not modify the XLimMode property.
%// This part of the code should run only once
h.ax = subplot(3,1,2) ; %// get the handle of the axes
h.line = plot(0) ; %// create an empty line plot
set(h.ax , 'XLimMode','manual' , 'XLim',[1 4]) ; %// define the properties of the axes (X)
set(h.ax , 'YLimMode','manual' , 'YLim',[1 4]) ; %// define the properties of the axes (Y)
xlabel('Frequency');
ylabel('Signal');
%//
%// This part of the code is the loop where you calculate and update your plot
%// ...
%// now do your calculations
%// ...
%// when it is time to update, just call:
set( h.line, 'XData',xdft 'YData',ydft ) ;
You can use the function axis as defined there axis function matlab

Draw vertical lines on matlab spectrogram plot

Does the matlab spectrogram function lock the created figure in anyway? I want to draw vertical lines on the figure but the line function does not seem to do anything. How can I draw a line on a matlab spectrogram?
clc; clear all; close all;
[data, fs, nbits] = wavread(<INSERT WAVE FILE HERE>);
% [data, fs, nbits] = wavread('white_0.05_6sec_aud.wav');
N_data=length(data); N_frame=128; N_half=N_frame/2; N_loop=N_data/(N_half);
output=zeros(N_data,1);
hz=0:(fs/2)/N_half:(fs/2)-(fs/2)/N_half;
spectrogram(data, hanning(N_frame), N_half, N_frame, fs);
x = [6500 6500];
y = [0 5.5];
H = gca;
% set(gca, 'NextPlot', 'add');
% line(x, y);
h = line([6500, 6500], [0, 5.5]);
set(h, 'parent', handles.predicted_ax);
% view(-90,90)
% set(gca,'ydir','reverse')
%
% [y, x] = ginput(1)
% view(-90, 180);
The spectogram generates a surf and sets the view to (0,90). The surf sets the zlim to some values (dependent on the spectrogram data), and apparently, adding a line to the current plot does not change the zlim (probably because spectrogram locked the axes somehow; should be findable in edit spectrogram). Therefore, in view(0,90), the line completely disappears (rotate the plot; you'll see the line appear somewhere above the surface).
To resolve: the way you add a line defaults to the line having z-coordinates of [0 0],
which, for many spectrograms, will be above the range of the axes set by spectrogram.
Issuing
zl = zlim;
axis([xlim ylim zl(1) max(0, zl(2))])
view(0,90)
after the line should then make the line appear.
Also: in my case, the surface over which the line was hovering was mostly blue, as was the line. This doesn't help making it apparent there is a line :) I made it white, which contrasted better with the blue/yellow/red surf below.

Producing subplots and then combine them into a figure later in MATLAB

My program produces small figures during the command cycle. Is there a way to just save these figures and then combine them in one figure later?
Consider the code:
hFig = figure;
%# create temporary subplots as template
for i=1:2, h(i) = subplot(2,1,i); end %# create subplots
pos = get(h, 'Position'); %# record their positions
delete(h) %# delete them
%# load the .fig files inside the new figure
fileNames = {'a.fig' 'b.fig'}; %# saved *.fig file names
for i=1:2
%# load fig
hFigFile = hgload( fileNames{i} );
%# move/copy axis from old fig to new fig
hAx = get(hFigFile, 'Child'); %# hAx = gca;
set(hAx, 'Parent',hFig)
%#hAx = copyobj(hAx,hFig);
%# resize it to match subplot position
set(hAx, 'Position',pos{i});
%# delete old fig
delete(hFigFile)
end
This was adapted from this newsgroup discussion
Use saveas. Save your subplot as a FIG file so you have complete control over it later (as opposed to a JPG).
Choose a tiling pattern and then use subplot to display multiple figures in one.
I have an answer here as an example:
h1 = figure(1)
plot(1:10,'o-r');
title('title');
xlabel('xlabel');
ylabel('ylabel');
% Copy contents
ch(1) = copyobj(gca,gcf);
% Figure 2
h2 = figure(2)
plot(1:30,'o-r');
title('title fig2');
xlabel('xlabel');
ylabel('ylabel');
% copy contents
ch(2) = copyobj(gca,gcf);
figure(3)
sh = subplot(1,2,1);
clear axes
p = get(sh,'position');
ah = copyobj(ch(1),gcf);
set(ah,'position',p);
% Create axis template
sh = subplot(1,2,2);
clear axes
p = get(sh,'position');
ah = copyobj(ch(2),gcf);
set(ah,'position',p);
% Delete template
% delete(sh);
Amro's solution works greatly, but with boxplots you have to reset the Xtick and Xtick labels, otherwise, for some reason, they will not be resized according to the the subplot. When you create the boxplot or after opening the figure add:
set(gca,'XTick',<1d vector>,'XTickLabel',<1d cell vector>)
or put automatic ticks and labels
set(gca,'XTickMode','auto','XTickLabelMode','auto')

How can I put a background image in a movie in matlab

I need to put a background image in a movie created using MATLAB?
I have posted below an example code of how I am generating a movie in Matlab. I need to add a background image to this movie. Thanks for your help.
for i=1:128
for j=1:128
p(i,j,:)=randn(1,200);
end
end
[u,v,w]=size(p);
frm_r=1:128;
frm_c=1:128;
figure; j=1;
for t=1:w
surface(frm_c,frm_r,p(:,:,t),'EdgeColor','none');
pause(0.1)
colorbar;
F(j) = getframe;
j=j+1;
end
movie(F,1,50)
If you have access to MATLAB code that creates movie, you can place an axes with IMAGE or IMSHOW as a background and make axes on the top of it transparent.
Here is a simple example:
im = image; % create image object (default pic)
imax = get(im,'parent'); % get image axes handle
axis ij
set(imax,'position',[0 0 1 1]) % make it to fill the whole figure
ax = axes; % new axes
h = plot(ax,rand(100),'ro'); % initial plot
for i=1:20
set(h,'ydata',rand(100,1)); % change the data in a loop
pause(0.1)
end
You can get get better answer if you show your code how you create a movie.
EDIT:
I simplified the code in your answer a little. For example you don't need loops to fill up 3D array. And you don't need to repeat surface function in the loop. Just change zdata property.
Try this code (substitute yourimage.jpg to real file name):
p = randn(128,128,200);
[u,v,w]=size(p);
frm_r=1:128;
frm_c=1:128;
figure;
im = imshow('yourimage.jpg'); % create and display image object from a file
imax = get(im,'parent'); % get image axes handle
set(imax,'position',[0 0 1 1]) % make it to fill the whole figure
ax = axes('color','none'); % new axes
hsurf = surface(frm_c,frm_r,p(:,:,1),'EdgeColor','none','Parent',ax);
colorbar;
xlim([1 u])
ylim([1 v])
j=1;
for t=1:w
set(hsurf,'zdata',p(:,:,t))
F(j) = getframe;
j=j+1;
end
movie(F,1,50)