Beautiful Plots in MATLAB

Today, Jesse Marshall returns to discuss visualization in Matlab.

Did you ever think MATLAB could make this? Neither did I!

Did you ever think you could make plots like these in MATLAB? Neither did I!

Why Visualize?

Smartphones, tablets, wearables, smart-toasters and 8 billion other ‘devices’ have swamped us in data. This explosion of big, and sometimes bad data has led to seemingly endless charts that all compete for our rapidly shrinking attention. Scientists and statisticians are now tasked with explaining complex analyses and subtle concepts rapidly, in a compact, meaningful and compelling way. This means maximizing the perceptual differences of the points you want to make in the graphics so you can minimize the time a reader has to spend digesting your analysis.

Anyone that has tried to get a date, get a job, or get funding for a project will tell you that looks matter — gone are the days where you could get a way with a simple bar graph or scatter plot. The appearance of your data, and your attention to detail in designing the aesthetics, are a signaling mechanism that lets people know that you have put in your due diligence in collecting and analyzing the data as well. So now, after you dot your i’s and cross your t’s, you need to worry about adjusting your tick marks, tuning your colormaps and worrying about protanopia (color blindness).

This emphasis on visualization isn’t superficial. As the size of data grows, non-hypothesis based tests are becoming more and more important for exploring data and finding out new scientific data. This means at how we visualize data can have a big influence on our inspiration.

http://www.theonion.com/articles/americas-most-popular-charts,7492/

Edward Tufte wouldn’t approve. Source: The Onion.

Bauhaus, Art Deco, Brutalist, MATLAB, ggplot?

Matlab has made a mark on the scientific visualization world. To see this you need to look no further than the ubiquity of MATLAB’s former default colormap jet and the popularity of the MATLAB-inspired plotting package matplotlib in Python, the tool du jour for data scientists. However aesthetics are constantly changing. Muted, perceptually dramatic colormaps and visualizations that are easy to produce and manipulate are becoming the norm with the continued expansion of tools like Hadley Wickham’s ggplot2.

Can MATLAB  keep up? Of course! MATLAB continues to improve their graphics engine, and the MATLAB File Exchange is brimming with hacks that can take your visualization anywhere you want it to go. In this post, I’ll talk about ways you can take your plotting to the next level using built-in and user contributed functions.

Plotting basics

Let’s tackle the basics. Let’s visualize two different colormaps by generating a matrix of increasing values and then coloring this matrix with the two different colormaps using subplot. Then let’s print the matrix to a file using the print command.

colormap_bad

%generate increasing data for visualizing the colormap
color_matrix = (1:100)'*(1:100);

figure(5)

subplot(1,2,1)
imagesc(color_matrix)
colormap(jet)

subplot(1,2,2)
imagesc(color_matrix)
colormap(hot)
print('-dpng','example_colormaps_bad.png')

There’s a few noticeable problems. First, there are stray tick labels, which we don’t want distracting from the visualization of the colormap. Second, there is lots of extra whitespace in the figure between the subplots. Unfortunately, there’s no good way to adjust these margins in MATLAB. Third, the two subplots have the same colormap! In MATLAB, each figure can only use one colormap. Fourth, the background for the figure is gray, which I don’t find too appealing. Lastly, exporting the file as a .png bitmap means that you can’t open it with vector editors.
Let’s give it another try:

example_colormaps_good

%Visualization of two colormaps with improved aesthetics
color_matrix = (1:100)'*(1:100);
figure(6)
%set the default color as white
set(gcf,'Color','w')

%use this file exchange function to reduce the margin size
%in subplot
subplot_tight(1,2,1)
imagesc(color_matrix)
colormap(jet)

%these keep the axes tight and turn off the unneeded ticks
axis off

%this file-exchange function
freezeColors

subplot_tight(1,2,2)
imagesc(color_matrix)
colormap(hot)
axis off
print('-depsc','example_colormaps_good.eps')
print('-dpng','example_colormaps_good.png')

As you can see, the plots look much better! I’ve used a few built in functions and a few file exchange (FEX) functions to make this happen. I’ve set the figure background to white, and exported the file to .eps, so that we can open it in vector editors.

  • axis off: This turns off the axes to keep things clean.
  • freezeColors: This FEX functions freezes the colors in the subplot to allow more than one colormap per figure.
  • subplot_tight: This FEX function drastically reduces the whitespace between subplots.

Using the file exchange

As you can see above, the File Exchange (FEX) is an amazing resource for any MATLAB user. Anytime you run into problems with MATLAB with seemingly no workaround (like the inability to adjust $subplot$ margins, it’s likely many other users have as well! It’s also likely that a clever programmer such as yourself has either found a workaround and posted it on Stack Exchange, or written a function to solve the problem and put it up on the File Exchange.

To use File Exchange packages, download them to a directory of your choice, i.e. ‘FEX_code/’, and add that directory to your path using the ‘addpath’ command. You can also do this manually through the ‘addpath’ menu option. You can also add this path to your startup.m file so you don’t need to manually add it each time you fire up MATLAB.

I’ve also included links to all the FEX functions I use in the post at the end so that you don’t have to search too far for them.

Colormaps

jet and hot are a little intense as far as colormaps go. They are big and bold, and while they get the point across, sometimes you want something a little more subtle. Luckily, there are tons of other colormaps inside and outside of MATLAB to choose from.

Cartographer Cynthia Brewer designed a set of colormaps that give a range of beautiful diversity, known as brewer colormaps. They aren’t builtin, but you can easily get them from the FEX package cbrewer (see below). Another notable package is the perceptually distinct light-bartlein maps available in lbmap. Take a look below. Also, if you are just trying to pick a few colors for a plot, you can use a color palette designer like here.

Aesthetics are changing. Can Matlab keep up?

Aesthetics are changing. Can Matlab keep up?

%% First generate a matrix of data
color_matrix = (1:100)'*(1:100);
num_plots = 5;

%I use FEX function subplot_tight to minimize whitespace
figure(2)
subplot_tight(1,num_plots,1)
%change figure background to white
set(gcf,'Color','w')
imagesc(color_matrix)

axis off %turn off the axes
axis tight %make the axes square
colormap(jet)

%Typically figures are limited to one colormap, this FEX function lets you
%use multiple colormaps in different subplots
freezeColors

%% repeat for other examples
subplot_tight(1,num_plots,2)
imagesc(color_matrix)
axis off
cmap = cbrewer('seq','YlGn',100);
colormap(cmap)
freezeColors

subplot_tight(1,num_plots,3)
imagesc(color_matrix)
axis off
colormap(parula) %MATLAB's new default!
freezeColors

subplot_tight(1,num_plots,4)
imagesc(color_matrix)
axis off

%the colorbrewer FEX
cmap = cbrewer('div','PuOr',100);
colormap(flipud(cmap))
freezeColors

subplot_tight(1,num_plots,5)
imagesc(color_matrix)
axis off

%the lbmap FEX
cmap = lbmap(100,'RedBlue');
colormap(flipud(cmap))
freezeColors

%% print to both vector (.eps) and bitmap (.png) formats
print('-depsc','example_colormaps.eps')
print('-dpng','example_colormaps.png')

Polar plots and opacity

Next I’ll show you how to make the spiral plots seen at the beginning of the post. The spirals are rose plots, which are also known as Coxcomb plots (invented by Florence Nightingale!). Rose plots are circular histograms, where the height of each wedge reflects the number of counts within the section. Here is what the default MATLAB rose plot looks like

Rose_Example_bad
%% Example of a default rose plot
hf = figure(5)
%change default figure background from the defaul gray
set(0,'defaultfigurecolor','w')

%Generate data for plotting
num_wedges = 30;
wedge_centers = 0:(2*pi)/num_wedges:(2*pi);
wedge_heights = [];
for ll=1:num_wedges
 wedge_heights=cat(1,wedge_heights,repmat(wedge_centers(ll),ll,1));
end
%demonstrate normal plotting
rose(wedge_heights,wedge_centers)
print('-dpng','Rose_Example_bad.png' )

As you can see, there are lots of grid lines, and there’s no obvious way to change the fill color or line color of the different wedges independently in the rose function. To get it done, I’ll have to pull out a few tricks.

Did you ever think MATLAB could make this? Neither did I!

%%Generate data for plotting
 num_wedges = 30;
 wedge_centers = 0:(2*pi)/num_wedges:(2*pi);

% generate colormaps for spirals
 num_cmaps = 3;
cmap = cell(1,3);
cmap{2} = parula(num_wedges);
cmap{1} = flipud(lbmap(num_wedges,'RedBlue'));
cmap{3} = cbrewer('div','RdYlGn',num_wedges);

% generate different view angles for spirals
view_list{1} = [90 -90];
view_list{2} = [180 -90];
view_list{3} = [270 -90];

This code starts as before. I generate three different colormaps (from the FEX packages mentioned above), and three different view angles to view the same data from different perspectives. Not too tough. Below it gets really interesting.

for kk =1:num_cmaps
for ll=num_wedges:(-1):1

%generate a separate figure for each colormap and view angle
hf = figure(1);

%use subplot tight to keep tight spacing between objects
subplot_tight(1,num_cmaps,kk)

set(hf,'Color','w') %change figure background 

%draw the rose plot
hfig= rose(repmat(wedge_centers(ll),ll,1),wedge_centers);
if(ll ==num_wedges)
hold on
end

%turn off the edges of the spiral lines
set(hfig,'Linestyle','none')

%make the patches using the patch function (tricky -- I had to google how to do this!)
hpatch = patch( get(hfig,'XData'), get(hfig,'YData'), cmap{kk}(ll,:),'EdgeColor','none');

%change the opacity to add a nice mellowness
alpha(hpatch, 0.5)

%turn off the extraneous lines in the plot (tricky again)
delete(findall(ancestor(hfig,'figure'),'HandleVisibility','off','type','line','-or','type','text'));
end
hold off

%change the perspective
view(view_list{kk})
end

%Changing the alpha changed the renderer to OpenGL, so we have to use .svg to export. This is an FEX function.
plot2svg('Rose_Example.svg',hf,'png' )

Wow! This is tricky. I’ve used lots of new functions here. I plot each wedge separately, and then modify each wedge by removing its edges, and filling it in with a different color using the $patch$ command. I also delete all the grid lines and tick marks by finding all the text and lines in the figure and deleting them.

  • alpha: Changing the alpha of a filled element changes its opacity. This gives a visually pleasing shading to the plots.
  • plot2svg: Using different opacities requires the MATLAB graphics engine to use the OpenGL renderer. This renderer doesn’t play nicely with many common vector formats (.pdf and .eps for instance), but it does work with .svg.
  • patch: This function draws a patch within the defined verticies.

New Plots
Data visualization isn’t limited to color. It’s also about how you represent the data. You’re probably familiar with overwhelming number of plots available to you as a MATLAB user, and if that wasn’t enough, there are plenty more on the FEX. To get ideas, there are good online resources, like plotly to help inspire you to take visualizations to further heights, but here are some useful examples that will convince you that MATLAB can still keep up with Python and R.

example_violin_bubble

%% Demonstrate some other example plots
%generate generic datasets
numpts = 50;
rand_x = 2+randn(numpts ,1);
rand_y = -0.4+2*randn(numpts ,1);

%make a violin plot using the violin FEX function
figure(10)
subplot(1,2,1)
violin([rand_x rand_y],'facecolor',[[1 0 0];[0 0 1]],'medc','','mc','k')
legend off
box off
axis off

%generate a bubble plot using the scatter function
marker_sizes = abs(300+100*randn(numpts,1));
colors = lbmap(50,'RedBlue');
subplot(1,2,2)
scatter(rand_x,rand_y,marker_sizes,colors,'filled')
alpha(0.8)
axis off
box off
print('-dpng','example_violin_bubble.png')

These two examples are the violin and bubble plots, which add information to simple box-and-whisker and scatter plots, respectively. The violin plots give a display of the full distribution of data, and the bubble plot allows visualization of a third dimension of data in addition to its position.

Another interesting plot, popular in genomics research and database work is the ‘schemaball’ plot (also see: Circos plots). This allows you to take a set of interconnected nodes, and visualize their connectivity to one another in a circular arrangement. MATLAB doesn’t have great tools to do this yet, but I’m sure it is on the horizon.
example_circos

 

rand_connections = abs(rand(numpts,numpts));
figure(9)
schemaball(rand_connections)
print('-depsc','example_circos.eps')
print('-dpng','example_circos.png')

Downloads
FEX functions:

Code:

This entry was posted in Intermediate, Learning Matlab, Optimizing your code. Bookmark the permalink.

4 Responses to Beautiful Plots in MATLAB

  1. Kevin says:

    Excellent use of the rose function. I have been working this morning on applying some of your techniques to my data.
    I may have noticed a problem though. If you were to set all of your wedges to a constant height, you would notice that one wedge is not plotted. This goes unnoticed when making the nautilus shapes but applied to real data it becomes noticeable.
    To try for yourself simply change
    hfig= rose(repmat(wedge_centers(ll),ll,1),wedge_centers);
    to
    hfig= rose(repmat(wedge_centers(ll),2,1),wedge_centers);

    I have been working on a workaround and will update you if I solve it.

    • Kevin says:

      The simplest solution I’ve found is just to remove one value from wedge_centers:
      dtheta = (2*pi)/num_wedges
      wedge_centers = 0:dtheta:(2*pi)-dtheta;

      But I’ve actually made some further changes to make this much simpler to use with real data. I take advantage of the theta and rho output of rose() and input it into polar(). I can share my methods if there is interest.

  2. hossein says:

    Hi
    How can I change marker in plot command in a way that instead of usual markers available in matlab (i.e. o x * … ) a special small figure be used?? and is it possible to add a number beside this figure (now used as marker)???

Leave a Reply

Your email address will not be published. Required fields are marked *