Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying trace of data vs time with "band of uncertainity"

Apologies in advance for bringing a non-programming question to SO, but the powers-that-be have determined that all MATLAB-related questions belong here.

I've been doing some Kalman Filters and plotting state variable estimates to see how they converge over time. Now, I'd like to visually represent the covariance matrix, which is an indication of the uncertainty in the estimate. So I wrote a little function that colors a band around the estimate.

(Edit note: A prior version made the mistake of using 2*cov for the width of each halfband, when it needs to be 2 standard deviations)

function [ls, regions] = plotuncertain( t, y, cov )
    t = t(:);
    y = y(:);
    stdev = cov(:).^(1/2);
    a = ones(size(t));
    regions(1) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y + 2*stdev; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    regions(2) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y - 2*stdev; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    ls = line('XData', t, 'YData', y);

And it looks reasonable:

One cone of uncertainty

But I have two state variables with similar meaning that I'd like to plot concurrently on a single axis.

Two cones of uncertainty

Uh-oh, the initial data for k_1 is obscured by the (top half of the) k_2 band. MATLAB didn't draw the lines and patches in the order I submitted them. And even if I manage to control the order they draw, alpha-blending is still less optimal than mixing the colors based on the probabilities.

Any ideas how to render both at the same time? Can I somehow take advantage of the fact that I'm using two distinct color planes for the two variables?

like image 307
Ben Voigt Avatar asked Jul 22 '13 14:07

Ben Voigt


2 Answers

When plots are too complex, matlab starts to behave erratically just like here. I often try to apply a solution described here.

For your particular (and very nice) plot, I would modify the function by declaring an axes:

function [ax, ls, regions] = plotuncertain( t, y, cov )

    ax = axes;

    t = t(:);
    y = y(:);
    cov = cov(:);
    a = ones(size(t));
    regions(1) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y + 2*cov; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    regions(2) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y - 2*cov; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    ls = line('XData', t, 'YData', y);

and then call the function with:

[ax1, ls, regions] = plotuncertain( t, y, cov );
[ax2, ls, regions] = plotuncertain( t, y, cov );
set(ax2,'Visible','off');
linkaxes([ax1 ax2],'xy'); %or any (XLim,YLim) settings

This way, transparency in one axes is independent of the other.

EDIT

A way to better control the color blending is to convert each of the axes created in a dedicated figure into an image and then fuse them. One can use for example imfuse(im1,im2,'blend') (image processing toolbox) or whatever function that mixes 2 images.

The way to extract an image from a figure is

F = getframe(gcf);
imwrite(F.cdata, 'image.png');

enter image description here

For sure, this solution is only suitable at the final step of a reporting process (I would definitively not use it for a scientific article - see the comments - but for spectacular presentations). It may also be more efficient to use an alternative software that better deals with transparency/OpenGL than Matlab does.

like image 100
marsei Avatar answered Sep 20 '22 23:09

marsei


Although you suggest having attempted this, I found swapping the order of the patches made a large difference.

My version of your example, first without swapping:

t=[1:100];
y=t.^2;
cov=t.^2;

t2=[1:100];
y2=t2.^2.05;
cov2=t2.^2;

figure

t = t(:);
y = y(:);
cov = cov(:);
a = ones(size(t));

t2 = t2(:);
y2 = y2(:);
cov2 = cov2(:);

a = ones(size(t2));

regions(1) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y + 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');

regions(2) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y - 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');
ls = line('XData', t, 'YData', y,'Linewidth',1.5);

regions(3) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 - 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');
ls = line('XData', t2, 'YData', y2,'Linewidth',1.5);

regions(4) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 + 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');

not swapped

then with swapping:

regions(1) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y + 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');

regions(3) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 - 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');
ls = line('XData', t2, 'YData', y2,'Linewidth',1.5);


regions(2) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y - 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');
ls = line('XData', t, 'YData', y,'Linewidth',1.5);


regions(4) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 + 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');

swapped

Great effect, I hadn't seen this before in Matlab.

like image 28
Buck Thorn Avatar answered Sep 20 '22 23:09

Buck Thorn