**Editor's Note:** This file was selected as MATLAB Central Pick of the Week

This simple tool intercepts data going into a plot and reduces it to the smallest possible set that looks identical given the number of pixels available on the screen. It then updates the data as a user zooms or pans. This is useful when a user must plot a very large amount of data and explore it visually.

This works with MATLAB's built-in line plot functions, allowing the functionality of those to be preserved.

Instead of:

plot(t, x);

One could use:

reduce_plot(t, x);

Most plot options, such as multiple series and line properties, can be passed in too, such that 'reduce_plot' is largely a drop-in replacement for 'plot'.

h = reduce_plot(t, x(1, :), 'b:', t, x(2, :), t, x(3, :), 'r--*');

This function works on plots where the "x" data is always increasing, which is the most common, such as for time series.

For more information, see:

>> help LinePlotReducer

or

>> help reduce_plot

Tucker McClure (2021). Plot (Big) (https://github.com/tuckermcclure/matlab-plot-big), GitHub. Retrieved .

Created with
R2012b

Compatible with any release

- MATLAB > Graphics > 2-D and 3-D Plots > Line Plots >

**Inspired:**
daniel-frisch-kit/plot-ecg, matfig2pgfdata(filename,m,n), JimHokanson/plotBig_Matlab, detectEcgWithAngle(ecg, fSInHz, varargin): Heartbeat detection using sample-to-sample angle, matlab2dplot2datafile

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!Create scripts with code, output, and formatted text in a single executable document.

laporte PierreI found the problem: just like figure listener must be destroyed, axe one's need to be destroyed too.

o.axe_listener1=addlistener(o.h_axes(k), 'Units', 'PreSet', ...

@(~,~) o.UnitsPreSet);

o.axe_listener2=addlistener(o.h_axes(k), 'XLim', 'PostSet', ...

@(~,~) o.RefreshData);

o.axe_listener3=addlistener(o.h_axes(k), size_cb{:}, ...

@(~,~) o.RefreshData);

... and further, in the DeleteFcn event

delete(o.axe_listener1);

delete(o.axe_listener2);

delete(o.axe_listener3);

laporte PierreHello, thank you for this amazing feature!

However, how can I delete properly a LinePlotReducer object? Because when I use delete methods, previous events on the axe are still working and error shows up.

Jim Hokanson@Myrtle42

I realize this is a bit late but I figure'd I'd comment in case others are curious. This library and others (e.g. mine, plotBig_Matlab) speed up plotting by reducing the time dimension to plot less. Since you only have 33 samples, this library won't help. In your case plotting will create a large number of line objects. If you are fine with a single color for plotting you'd be better off plotting one line with NaNs to create interruptions between columns. Something like this ... (It takes plotting time for me from 8 seconds to 0.02 seconds)

r = bsxfun(@plus,sin(linspace(0,3,33))',rand(33,28287));

r2 = r;

r2(34,:) = NaN;

x2 = ([1:33 33])'*ones(1,28287);

tic

plot(x2(:),r2(:));

toc

Myrtle42I was hoping this could help reduce the time it takes to plot many overlapping curves, but on a sample dataset (dimension 33 rows 28287 columns) it took 47 seconds to plot, compared to 9 seconds with builtin plot. Does anyone know of a function that might speed this up? Many of the curves are overlapping and thus don't need to be rendered individually.

Mehmet SaglamLuis MarvalSeyyed AliBrian CarsonBrian CarsonJessica BenjaminThis is such a helpful submission, but I'm still struggling to get it to hold and plot multiple lines from different cells? E.g.

for i = 1:5

hold on, LinePlotReducer(time{i},acceleration{i});

end

What am I doing wrong? The time is datenumber rather than a datetime, as I noticed several people earlier had had problems with datetime format. Thanks :)

David J. MackDear Tucker!

Thanks for this very helpful submission. This should actually be a built-in (especially with the focus on machine learning).

Greetings, David

DrewVam55Very useful tool that drastically increases performance on large datasets.

Has anyone modified this to make figures saveable/reloadable? Or possibly modified data cursors to interact appropriately with this?

These would be very good improvements.

YinghaoJoe SamelaTucker McClureThanks, all.

MM, thanks for pointing this out. That would make a good improvement.

Daniel, that's a good recommendation. Do you want to make the change and send a pull request on GitHub?

Prashant, this will work if you simply double the scalars you're starting with: [x x], [y y].

M MIt doesn't work (or I can't cook it), if first input (data for x axis) has datetime type. In that case it works as usual plot(very slow).

If I convert it to number(using datenum), it works as expected.

K EThanks for providing such a useful function. Makes large datasets more tractable.

Daniel FrischVery good submission, really well written & documented...

But if you close the figure while LinePlotReducer.m isn't any more on MATLAB's search path, error messages are shown. I would recommend to define the 'DeletePlot' function as Nested Function instead of an object method. That way, the handle will always be valid to MATLAB.

Justin Rehakalbert huarhua tupayachithat good function

samPrashantFor additional information, I use "hold on" and refresh the plot every time new data is acquired for x & y. Thanks for your help.

PrashantHello. I am trying to use this function to plot two scalars x & y that get refreshed overtime for a long time.

Eg: reduce_plot(x,y);

I see the error: "There must be at least one valid axes." Can you please suggest how to address this error? Thank you, Prashant

Tucker McClureHi Yngve,

While there's no built-in support for timeseries, you can easily extract the Data and Time fields and pass those to the reduce_plot command as normal:

reduce_plot(ts.Time, ts.Data);

Did you have something else in mind? Hope this helps.

Yngve(sorry for spamming, I am not able to edit my last post. I forgot to mention that i need the output as a table of values, not a figure)

YngveHello. Is it possible to port this into reducing data from a simulink dataset instead of a function? (1x1 double timeseries)

Sean ThomsonTucker McClureJust updated this to better handle memory when reusing figures and axes again and again. Thanks to Jack for pointing this out.

George ZipfelI have large time series data sets and need to look for and examine occasional events. This code works like a champ.

onewhaleidSimply superb. What a great idea.

RaptrickThis piece of code helps me a lot with exploring big sets of timedomain data. Great!! It is understandable that it does not work for big sets of scattered data e.g.

r = unifrnd(-1,1,1e4,2);

LinePlotReducer(r(:,1),r(:,2),'.');

h1 = gca;

figure

plot(r(:,1),r(:,2),'.')

h2 = gca;

linkaxes([h1 h2]) %compare figs play with zoom

Maybe an idea for the future ScatterPlotReducer :)

Regards Patrick

Agamemnon KrasoulisThis is an amazing tool.

However, I 've just noticed there is a compatibility issue with the new graphics system in MATLAB R2014b.

Thanks,

Agamemnon

RobbertHi Tucker,

Great piece of code that saved me a lot of time.

However, it looks like there is a bug, which causes the maximum and minimum for data within a pixel from the edges not always being displayed.

Example code:

y=[0 1 zeros(1,1e6) 1 zeros(1,1e6) 1 0];

x=1:length(y);

reduce_plot(x,y,'*-')

The last peak does not show in the plot until sufficiently zoomed in.

Do you think this can be fixed? Thanks a lot!

James MorrisThis is exactly what I need except I would like to plot in 3D. Any help on how I could do this would be great.

James MorrisThis is exactly what I need except I would like to plot in 3D. Any help on how I could do this would be great.

Agamemnon KrasoulisVery smart and useful, thanks!

xsystem1I have put data cursors using your submission plot code. After zooming-in the data and putting a data cursor, once I zoom out, the value of the data cursor changes a lot! Can you correct this?? I have to export 20 odd data cursors to workspace and your work around is quite fast.

JamesTucker McClureUpdated to gracefully allow multiple LinePlotReducers in a single axes object for convenience (thanks for all the feedback, Plastic). However, note that it's still fastest to use a single LinePlotReducer to manage multiple lines. Thanks all.

JohanPlastic SoulPlastic SoulHi, thanks for your quick answer.

Well, it works, but gives me only first graph and a little bit of the other one (not the rest), and if I try to move them with Pan, it gives an error (huge one, with first line saying - Subscripted assignment dimension mismatch.).

Note that I am using "hold on" to keep them all together.

Thanks.

Tucker McClureHi Soul,

Looks like that should work. Basically, if it works with a 'plot' command, it should work with 'LinePlotReducer' (or equivalently, 'reduce_plot'). The examples_of_line_plot_reducer.m file holds many such things, including this example, where three things are plotted, all managed by a LinePlotReducer:

lpr = LinePlotReducer( ...

t, x(1, :), 'b:', ...

t, x(2, :), 'g', ...

t, x(3, :), 'r--*');

Plastic SoulHi Tucker,

Is it possible to apply plot reducer and explorer in a FOR loop? Also, plotting from structures and cell arrays?

i.e.

for i=1:3

LinePlotReducer(x.something{i},y.something{i}, Color{i});

end

LinePlotExplorer(gcf());

Thanks alot!

veleno85Hi Tucker McClure

yes, now it's working :)

sorry for the silly question and thanks for the clear answer!

Tucker McClureHi veleno85,

Ah, yes, you can't pass cell arrays directly to 'plot'. Notice that your commented-out line 'plot(Load{...})' uses curly brackets and so is actually returning a matrix and not a cell array. However, you're passing the cell arrays to reduce_plot. There are many ways to fix this.

% Easiest way

Load = cell2mat(Data(:, 9));

Time = cell2mat(Data(:, 1));

% Use curly braces to access the cells and add square brackets to form a new matrix with the guts of all those cells (a little harder to understand).

Load = [Data{:, 9}];

Time = [Data{:, 1}];

Alternately, if your 'importfile' function is auto-generated using the Import Tool, then you could re-run the Import Tool and select "column vectors" as the output type so that you don't have to select columns from a big cell array. Then you could generate a new 'importfile' function with this option.

Does that help?

And welcome to MATLAB. :)

veleno85Hi, i'm pretty new in MATLAB and i'm trying to print my huge amount of data. using reduce_plot in this code i get this error, i'm sure i'm making some basic mistake.. do u have any idea?

Data are in a cell array

close all; clear all; clc;

Data = importfile('25112013.xls','Ark1','A6:P35785');

Load = Data (:,9);

Time = Data(:,1);

T= Time';

L= Load';

% plot(Load{1:10:end})

reduce_plot(L,T)

LinePlotReducer had trouble managing the plot function. Perhaps the arguments are incorrect. The error is below.

Error using plot

Not enough input arguments.

Error in LinePlotReducer (line 402)

o.h_plot = plot_fcn(plot_args{:});

Error in reduce_plot (line 12)

lpr = LinePlotReducer(varargin{:});

Error in Loading11 (line 13)

reduce_plot(L,T)

Tucker McClureUpdated to work with input data in different combinations of rows and columns, more like MATLAB's built-in functions (see "Updates" below).

Thanks, Edwin and Greg. These should both be fixed.

EdwinVery nice and very usefull! Maybe a small issue: the data should be in a colomn vector; you get no warning when the data is in a row vector and Matlab stops functioning.

MatthewNice work as always.

Greg LaskyGreat program!

But here's the issue: It seems to work for a stand alone axis.

But it does not work if I'm trying to hand over an axis in a GUI to it (I don't know if I'm doing it right though).

For example, I have a GUI with 5 separate axes and I need to specify which one I want to plot my data to.

So I have:

h=plot(handles.RawData,data); %handles.RawData is the reference to the axis

LinePlotReducer(h);

But I get the error:

Cell contents reference from a non-cell array object.

Error in LinePlotReducer (line 157)

o.x{k} = o.x{k}(:);

Seems though that what's causing the problem here is the section in LinePlotReducer that deals with this which seems to think that the 'XData' field in the handle for plot is a cell array when in fact it is just a regular array.

Or maybe I'm not doing something right

J.R.! MenzingerExcellent!

Tucker McClureExcellent point, dberm22.

Kelly, good suggestions. Plotting detailed coastlines would be a great use case for improvement! In the meantime, if you're displaying landmasses with patches, do you know about reducepatch? This could be used (pre-rendering) for multiple levels of fidelity.

Thanks to all for the ratings!

dberm22I did my own testing on this for speed, and at first I was tempted to give this 1 star because the tic-toc results show that reduce_plot() takes twice as long to create the plot than the regular plot() does. Don't be fooled by this! tic-toc does not take into account how long it takes to show the plot on the screen, for which reduce_plot() is extremely efficient. Also, with the such large amount of numbers I was using, zooming was rendered impossible with the normal plot() function. reduce_plot() was a life-saver in those scenarios.

plot() = 1.66s (create plot) + 7.54s (show on screen) = 9s total (& cannot zoom)

reduce_plot = 3.65s (create plot) + .8s (show on screen) = 4.45s total + .7s (zooming) = priceless

Kelly KearneyVery useful function. However, it currently only works if your data describes a function (in the mathematical sense of one y per x). It would be great if it could be extended to work when the y axis is the independent variable, or for lines defining polygons (for example, I originally stumbled on this looking for a more efficient way to plot high-resolution coastlines while allowing lots of efficient zooming and panning).

JorgeBrett ShoelsonAwesome!

Adam FilionDoug HullMichael