MATLAB: saving scatter plot takes too long - matlab

I'm using scatter function to plot data containing only 25000 rows, however when I use saveas function to save the image as png, it takes 2+ minutes to do so.
For example:
scatter(x,y,'filled');
pic_name = ['scatterplot.png'];
tic
saveas(gcf,pic_name,'png');
toc
Elapsed time is 152.681511 seconds.
Is there a quicker way to save a scatter plot?

scatter is known to be slow for high number of datapoints; that might include saving them (each point has a difference color, thus needs separate handling).
You might want to try plotting the data differently, like described here: matlab: scatter plots with high number of datapoints
This way, you get the same behaviour as with regular plots.

Instead of calling saveas(), you could try calling getframe() and then calling imwrite(), like this:
npoints = 25000;
x = linspace(0,3*pi, npoints);
y = cos(x) + rand(1, npoints);
scatter_series_handle = scatter(x,y,'filled');
pic_name = ['scatterplot.png'];
axes_handle = get(scatter_series_handle, 'Parent');
figure_handle = get(axes_handle, 'Parent');
img = getframe(figure_handle);
imwrite(img.cdata, pic_name, 'png');

Related

Matlab plotting a decaying exponential and curve fit to find peaks

I am trying to plot data from a csv file, I have successfully uploaded the csv as an array for each column. I'm then trying to find the peaks of each column, I need to then plot the peaks for each to a time constant (tau). I have been getting an error that I need to have the same size vectors to plot. I'm also trying to plot all sets of data on one plot and have a curve fit for each.
Please help me out!
code is below
Array=csvread("D:\Grad Lab\NMR\Data\T1 Data\compiledT1nolabel.csv");
tau = Array(:,1);
Water= Array(:,2);
Mineral_Oil = Array(:,3);
Glycerol = Array(:,4);
CuSO4_1=Array(:,5);
CuSO4_2=Array(:,6);
CuSO4_3=Array(:,7);
CuSO4_4=Array(:,8);
CuSO4_5=Array(:,9);
pks1 = findpeaks(Water);
pks2 = findpeaks(Mineral_Oil);
pks3 = findpeaks(Glycerol);
pks4 = findpeaks(CuSO4_1);
pks5 = findpeaks(CuSO4_2);
pks6 = findpeaks(CuSO4_3);
pks7 = findpeaks(CuSO4_4);
pks8 = findpeaks(CuSO4_5);
plot(pks1,tau)
The problem is that the pks vectors and the corresponding data arrays you are trying to plot don't have the same size: calling the plot function on vectors of different sizes produces the error.
In the sample script below, data contains a bunch of values. Invoking findpeaks with two outputs (i.e. locs and pks) allows both the locations and peak values to be stored. Now we can use locs and pks with plot to mark the peaks as follows:
data = [25 8 15 5 6 10 10 3 1 20 7];
[pks, locs] = findpeaks(data);
plot(data); hold
plot(locs, pks, 'd')
produces the following plot:
Alternatively, if you are just interested in plotting, you could use
findpeaks(data)
without any output: it will produce a plot like this:
For the OP's specific case, I modified his script as follows (just covered one set of peaks, the pattern should be clear):
Array=csvread("D:\Grad Lab\NMR\Data\T1 Data\compiledT1nolabel.csv");
tau = Array(:,1);
Water = Array(:,2);
[pks1, locs1] = findpeaks(Water);
figure
plot(tau, Water); hold on;
plot(tau(locs1), pks1, 'd');

Plotting many lines as a heatmap

I have a large number (~1000) of files from a data logger that I am trying to process.
If I wanted to plot the trend from a single one of these log files I could do it using
plot(timevalues,datavalues)
I would like to be able to view all of these lines at same time in a similar way to how an oscilloscope has a "persistant" mode.
I can probably cobble together something that uses histograms but am hoping there is pre-existing or more elegant solution to this problem.
You can do exactly what you are suggesting yourself, i.e. plotting the heatmap of the signals.
Consider the following: I'll build a test signals (out of sine waves of different amplitude), then I'll plot the heatmap via hist3 and imagesc.
The idea is to build an auxiliary signal which is just the juxtaposition of all your time histories (both in x and y), then extract basic bivariate statistics out of that.
% # Test signals
xx = 0 : .01 : 2* pi;
center = 1;
eps_ = .2;
amps = linspace(center - eps_ , center + eps_ , 100 );
% # the auxiliary signal will be stored in the following variables
yy = [];
xx_f = [];
for A = amps
xx_f = [xx_f,xx];
yy = [yy A*sin(xx)];
end
% # final heat map
colormap(hot)
[N,C] = hist3([xx_f' yy'],[100 100]);
imagesc(C{1},C{2},N')
You can use also jet colormap instead of hot colormap for readability.
In the following the amplitude is gaussian instead of homogeneus.
here's a "primitive" solution that is just using hist:
%# generate some fake data
x=-8:0.01:8;
y=10*sinc(x);
yy=bsxfun(#plus,y,0.1*randn(numel(x),1000)' );
yy(randi(1000,1,200),:)= 5-randi(10)+ circshift(yy(randi(1000,1,200),:),[1 randi(numel(x),1,200)]);
%# get plot limit parameters
plot(x,yy)
yl=get(gca,'Ylim');
xl=get(gca,'Xlim');
close all;
%# set 2-d histogram ranges
ybins=100;
xbins=numel(x);
yrange=linspace(yl(1),yl(2),ybins);
xrange=linspace(xl(1),xl(2),xbins);
%# prealocate
m=zeros(numel(yrange),numel(xrange));
% build 2d hist
for n=1:numel(x)
ind=hist(yy(:,n),yrange);
m(:,n)=m(:,n)+ind(:);
end
imagesc(xrange,yrange,m)
set(gca,'Ydir','normal')
Why don't you normalize the data and then add all the lines together? You could then plot the heatmap from the single datafile.

Merging two plots in matlab

I am looking for a way to merge two Matlab plots. I have the figure files for each of them as fig1.fig and fig2.fig One figure contains a plot which runs for a certain range e.g 1 to 100 and the other figure contains the continuation of the first plot e.g 101 to 200. Each of these plots takes around 8 hours, so I do not want to replot them. Is there any simple way of merging these two plots?
It sounds like you want to join up your data, so you need to extract the x and y data from each of your plots. If you have a line plot, you can load the first .fig file
e.g.
and then type
a = gca
handles = findobj(a)
isLine = strcmp(get(handles, 'Type'), 'line')
XData1 = get(handles(isLine), 'XData')
YData1 = get(handles(isLine), 'YData')
That will extract the x and y data for your line, from your first plot.
Now close all your figures and load your second plot:
a = gca
handles = findobj(a)
isLine = strcmp(get(handles, 'Type'), 'line')
XData2 = get(handles(isLine), 'XData')
YData2 = get(handles(isLine), 'YData')
You can now plot your merged plot with:
figure
plot([XData1 XData2], [YData1 YData2])
title('mergedPlot')

Triangular wave graphed instead of Sin wave in matlab

I am designing composite sin wave such as
input=sin(2*pi*Fm_1*t) + sin(2*pi*Fm_2*t);
where Fm_1, and Fm_2 are given by the user and
t=0:Ts:2*Tm;
where
Ts=1/Fs;
Tm=1/(maxof(Fm_1,Fm_2) (NOT A FUNCTION, just to explain)
and Fm_1 = 5and Fm_2 = 10 and Fs = 30
and plot using plot(t,input);
Now for some reason, the output is correct but instead of being a sine wave, it's a triangular wave (straight lines). Other than that, the output is correct.
EDIT:
I just found out that because I plotted two graphs on the same scale, an error in the second graph screwed up the first.
Now the problem is filtering the input using this :
output = filtfilt(B,A,input);
Why does this give me nothing when I plot it (I also tried using filter)?
As mentioned in the comments above, the problem is that you're using a way too low sampling frequency to plot a detailed graph. You can see this using the function below:
function myplot(Fm_1, Fm_2, Fs)
Ts = 1/Fs;
Tm = 1/max(Fm_1,Fm_2);
t = 0:Ts:2*Tm;
input = sin(2*pi*Fm_1*t) + sin(2*pi*Fm_2*t);
plot(t, input);
end
As you noticed, for Fs = 30 you get a plot like this:
Increasing to Fs = 100, the situation improves:
And for Fs = 1000 the plot is what you'd probably expect in the first place:
Note that for all the above I've used the values Fm_1 = 5 and Fm_2 = 10 that you provided.

Help Required With Graph Plotting in MATLAB

I am about to present my work that I have created in MATLAB, but I am having trouble manipulating my data into a presentable form using the plot function.
My code looks like this:
[inputname, pathname] = uigetfile('*.wav', 'Select WAV-file');
thumb1 = inputname; %# Get filename information
fprintf('\n%s is being turned into a 30s thumbnail...\n', thumb1);
fprintf('Please wait..!\n\n');
%# load the signal
[y, fs, nb] = wavread(thumb1);
y = mean(y,2); %# stereo, take avrg of 2 channels
%# Calculate frame energy
fWidth = round(fs*10e-3); %# 10ms
numFrames = floor(length(y)/fWidth);
energy = zeros(1,numFrames);
for f=1:numFrames
energy(f) = sum( y((f-1)*fWidth+1:f*fWidth).^2 );
end
Basically I want to plot the energy of the track over time (in seconds).
plot(energy)
nearly does what I require, but I have an unusual amount of blank space at the end of the track which is not present in the .wav file. This blank space is the main issue that I'm having. Ideally I would like the x axis to be displayed in seconds! Any help would be much appreciated.
edit1:
Using the first suggested method:
There's also
axis tight
which sets "tight" limits for the axis. See doc: http://www.mathworks.com/help/techdoc/ref/axis.html
By default, Matlab uses some heuristic rules to choose the limits of graph scales. You can override them with the xlim and ylim functions (e.g. xlim([0 length(energy)])).
If you want to plot against actual time, you can do something like:
t = (0:length(energy)-1) / fs; % Timebase in seconds
plot(t, energy);