Skip to content

Commit

Permalink
Improved legend layout. Various optimizations
Browse files Browse the repository at this point in the history
- Optimized resizing callback
- Optimized line drawing
- Corrected bug with continuous colors in geom_point()
  • Loading branch information
piermorel committed Apr 13, 2016
1 parent b326278 commit 6e260a1
Show file tree
Hide file tree
Showing 12 changed files with 342 additions and 143 deletions.
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ The typical workflow to generate a figure with gramm is the following:
- In the next steps, add graphical layers to your figure: raw data layers (directly plot data as points, lines...) or statistical layers (plot fits, histograms, densities, summaries with confidence intervals...). One instruction is enough to add each layer, and all layers offer many customization options.
- In the last step, gramm draws the figure, and takes care of all the annoying parts: no need to loop over colors or subplots, colors and legends are generated automatically, axes limits are taken care of, etc.

For example, with gramm, 6 lines of code are enough to create the figure below from the <code>carbig</code> dataset. Here the figure represents the evolution of fuel economy of new cars in time, with number of cylinders indicated by color, and regions of origin separated across subplot columns:
<img src="/img/carbig_example.png" alt="gramm example" width="830">
For example, with gramm, 7 lines of code are enough to create the figure below from the <code>carbig</code> dataset. Here the figure represents the evolution of fuel economy of new cars in time, with number of cylinders indicated by color, and regions of origin separated across subplot columns:
<img src="/img/carbig_example.png" alt="gramm example" width="880">

```matlab
load carbig.mat %Load example dataset about cars
origin_region=num2cell(org,2); %Convert origin data to a cellstr
Expand All @@ -29,6 +30,8 @@ g.geom_point()
g.stat_glm()
% Set appropriate names for legends
g.set_names('column','Origin','x','Year of production','y','Fuel economy (MPG)','color','# Cylinders')
%Set figure title
g.set_title('Fuel economy of new cars between 1970 and 1982')
% Do the actual drawing
g.draw()
```
Expand All @@ -44,7 +47,7 @@ Type <code>doc gramm</code> to find links to the documentation of each method.


## Features
- Accepts x and y data as arrays, matrices or cells of arrays
- Accepts X Y and Z data as arrays, matrices or cells of arrays
- Accepts grouping data as arrays or cellstr.


Expand All @@ -70,14 +73,15 @@ Type <code>doc gramm</code> to find links to the documentation of each method.
- Custom fits with user-provided anonymous function (<code>stat_fit()</code>)
- Ellipses of confidence (<code>stat_ellipse()</code>)

- When Z data is provided in the call to <code>gramm()</code>, <code>geom_point()</code> and <code>geom_line()</code> generate 3D plots
- Subplots are created without too much empty space in between (and resize properly !)
- Polar coordinates (<code>set_polar()</code>)
- Color data can also be displayed as a continous variable, not as a grouping factor (<code>set_continuous_color()</code>)
- Possibility to customize color generations in the LCH color space, chose alternative colormaps (Matlab's default, [colorbrewer2](http://colorbrewer2.org)), or provide a custom colormap (<code>set_color_options()</code>)
- Possibility to change ordering of grouping variables between native, sorted, or custom (<code>set_order_options</code>)
- Confidence intervals as shaded areas, error bars or thin lines
- Results of computations from <code>stat_</code> plots are returned in the member structure <code>results</code>
- Global title (<code>set_title()</code>)
- Figure title (<code>set_title()</code>)
- Multiple gramm plots can be combined in the same figure by creating a matrix of gramm objects and calling the <code>draw()</code> method on the whole matrix. An overarching title can be added by calling <code>set_title()</code> on the whole matrix.
- Matlabs axes properties are acessible through the method <code>axe_property()</code>
- Custom legend labels with <code>set_names()</code>
Expand All @@ -87,41 +91,43 @@ Type <code>doc gramm</code> to find links to the documentation of each method.

## Examples

The code for the following figures and numerous others is in <code>examples.m</code>.

### Custom fits ###
<code>stat_fit()</code>

<img src="/img/fit_example.png" alt="Custom fits" width="558">
<img src="/img/fit_example.png" alt="Custom fits" width="561">

### GLM fits (carbig data) ###
<code>stat_glm()</code>
Note that the fit is made across color groups. this is done by superimposing gramm plots.

<img src="/img/carbig_glm_example.png" alt="GLM fits" width="559">
<img src="/img/carbig_glm_example.png" alt="GLM fits" width="560">

### Multiple gramm objects in a single figure
Also shows histograms, categorical x values

<img src="/img/multiple_gramm_example.png" alt="Multiple gramm" width="800">
<img src="/img/multiple_gramm_example.png" alt="Multiple gramm" width="692">

### Histograms ###
<code>stat_bin()</code> with different <code>'geom'</code> options: <code>'bar'</code>, <code>'stacked_bar'</code>,<code>'point'</code>,<code>'line'</code>, <code>'overlaid_bar'</code>,<code>'stairs'</code>

<img src="/img/histograms_example.png" alt="Histograms example" width="733">
<img src="/img/histograms_example.png" alt="Histograms example" width="933">

### Colormap customization ###
<code>set_color_options()</code> with <code>'map'</code> set as <code>'lch'</code> with various customization on the first row. <code>'map'</code> set to <code>matlab</code>,
<code>brewer1</code>, and <code>brewer2</code> on the second line

<img src="/img/colormaps_example.png" alt="Colormaps example" width="788">
<img src="/img/colormaps_example.png" alt="Colormaps example" width="944">

### 2D density visualizations ###
<code>stat_ellipse()</code> and <code>stat_bin2d()</code> with <code>'geom'</code> set to <code>'contour'</code>,<code>'point'</code>,<code>'image'</code>

<img src="/img/2D_densities_example.png" alt="2D density" width="653">
<img src="/img/2D_densities_example.png" alt="2D density" width="649">

### Continuous colors

<img src="/img/continuous_color_example.png" alt="Continuous colors" width="556">
<img src="/img/continuous_color_example.png" alt="Continuous colors" width="558">

## Acknowledgements
gramm was inspired and/or used code from:
Expand Down
77 changes: 39 additions & 38 deletions examples.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
%% Example use

figure
g1=gramm('x',x,'y',y,'color',fouraltc,'linestyle',twoaltcb)
g1.facet_grid(twoaltc,twoaltcb,'scale','fixed')
g1.geom_point()
g1.stat_smooth('lambda',1000,'geom','area')
g1=gramm('x',x,'y',y,'color',fouraltc,'linestyle',twoaltcb);
g1.facet_grid(twoaltc,twoaltcb,'scale','fixed');
g1.geom_point();
g1.stat_smooth('lambda',1000,'geom','area');
%It's possible to set native axis properties
g1.axe_property('XGrid','on','YGrid','on')
g1.draw()
g1.axe_property('XGrid','on','YGrid','on');
g1.draw();



Expand All @@ -43,28 +43,28 @@

clear g2

g2(1,1)=gramm('x',x,'y',y,'color',fouraltc)
g2(1,1).facet_grid(twoaltc,twoaltcb) %,'scales','independent'
g2(1,1).stat_smooth('lambda',1000,'geom','area')
g2(1,1).geom_point()
g2(1,1)=gramm('x',x,'y',y,'color',fouraltc);
g2(1,1).facet_grid(twoaltc,twoaltcb); %,'scales','independent'
g2(1,1).stat_smooth('lambda',1000,'geom','area');
g2(1,1).geom_point();

%Also works with categorical data
g2(1,2)=gramm('x',y,'y',x,'color',categorical(twoaltc))
g2(1,2).geom_point()
g2(1,2)=gramm('x',y,'y',x,'color',categorical(twoaltc));
g2(1,2).geom_point();

% X data can be a cellstr, data will be treated as being categorical
g2(2,1)=gramm('x',fouraltc,'y',y,'color',twoaltcb,'size',4)
g2(2,1).facet_grid(twoaltc,[],'scale','fixed')
g2(2,1).geom_jitter('width',0.2,'height',0) %We can jitter the points in the scatter plot to make the density more apparent
g2(2,1)=gramm('x',fouraltc,'y',y,'color',twoaltcb,'size',4);
g2(2,1).facet_grid(twoaltc,[],'scale','fixed');
g2(2,1).geom_jitter('width',0.2,'height',0); %We can jitter the points in the scatter plot to make the density more apparent

g2(2,2)=gramm('x',y,'color',twoaltc)
g2(2,2).no_legend() %It's possible to drop the side legends (useful when the grouping is the same across multiple objects)
g2(2,2).stat_bin('geom','bar') %Using stat_bin we can create histograms
g2(2,2).set_limit_extra(0.1,0)
g2(2,2)=gramm('x',y,'color',twoaltc);
g2(2,2).no_legend(); %It's possible to drop the side legends (useful when the grouping is the same across multiple objects)
g2(2,2).stat_bin('geom','bar'); %Using stat_bin we can create histograms
g2(2,2).set_limit_extra(0.1,0);

%And call the draw function on the whole array !
figure
g2.draw()
g2.draw();



Expand Down Expand Up @@ -293,9 +293,11 @@
load carbig.mat %Load example dataset about cars
origin_region=num2cell(org,2); %Convert origin data to a cellstr


%figure('Position',[100 100 600 400])
% Create a gramm object, provide x (year of production) and y (fuel economy) data,
% color grouping data (number of cylinders) and select a subset of the data
g=gramm('x',Model_Year,'y',MPG,'color',Cylinders,'subset',Cylinders~=3 & Cylinders~=5)
g=gramm('x',Model_Year,'y',MPG,'color',Cylinders,'subset',Cylinders~=3 & Cylinders~=5) %& ~strcmp(origin_region,'Europe ')
% Subdivide the data in subplots horizontally by region of origin
g.facet_grid([],origin_region)
% Plot raw data as points
Expand All @@ -304,8 +306,8 @@
g.stat_glm()
% Set appropriate names for legends
g.set_names('column','Origin','x','Year of production','y','Fuel economy (MPG)','color','# Cylinders')
%Set title
g.set_title('Evolution of fuel economy between 1970 and 1982')
%Set figure title
g.set_title('Fuel economy of new cars between 1970 and 1982')
% Do the actual drawing
g.draw()

Expand Down Expand Up @@ -434,19 +436,19 @@
figure


g10=gramm('x',Horsepower,'y',Acceleration,'color',Cylinders,'subset',Cylinders~=3 & Cylinders~=5)
g10.set_names('color','# Cylinders','x','Horsepower','y','Acceleration')
g10.stat_glm('geom','area','disp_fit',true) %Linear fit (default for stat_glm
g10.geom_point()
g10.draw(false) %To superimpose over a gramm plot, call draw with false as an argument

%We add another gramm plot (without color) to have a fit across all
%cylinders. Superimposition only works with gramm plots that have similar
%faceting
g10b=gramm('x',Horsepower,'y',Acceleration,'subset',Cylinders~=3 & Cylinders~=5)
g10b.stat_glm('geom','line','disp_fit',false)
g10b.stat_glm('geom','area','disp_fit',false)
g10b.set_color_options('chroma',0,'lightness',30)
g10b.draw()
g10b.draw(false)
g10=gramm('x',Horsepower,'y',Acceleration,'color',Cylinders,'subset',Cylinders~=3 & Cylinders~=5)
g10.set_names('color','# Cylinders','x','Horsepower','y','Acceleration')
%g10.stat_glm('geom','area','disp_fit',true) %Linear fit (default for stat_glm
g10.geom_point()
g10.draw()



%% Colormap customization
Expand All @@ -460,21 +462,21 @@
%Default: LCH-based colormap with hue variation
g(1,1)=gramm('x',Origin,'y',Horsepower,'color',Origin)
g(1,1).stat_summary('geom',{'bar'},'dodge',-1)
g(1,1).set_title('Default LCH colormap (''color'' grouping)')
g(1,1).set_title('Default LCH colormap (''color'' groups)')

%Possibility to change the hue range as well as lightness and chroma of
%the LCH-based colormap
g(1,2)=gramm('x',Origin,'y',Horsepower,'color',Origin)
g(1,2).stat_summary('geom',{'bar'},'dodge',-1)
g(1,2).set_color_options('hue_range',[-60 60],'chroma',40,'lightness',90)
g(1,2).set_title('Modified LCH colormap (''color'' grouping)')
g(1,2).set_title('Modified LCH colormap (''color'' groups)')

%Possibility to change the lightness and chroma range of the LCH-based
%colormap when a 'lightness' variable is given
g(1,3)=gramm('x',Origin,'y',Horsepower,'lightness',Origin)
g(1,3).stat_summary('geom',{'bar'},'dodge',-1)
g(1,3).set_color_options('lightness_range',[0 95],'chroma_range',[0 0])
g(1,3).set_title('Modified LCH colormap (''lightness'' grouping)')
g(1,3).set_title('Modified LCH colormap (''lightness'' groups)')

%Go back to Matlab's defauls colormap
g(2,1)=gramm('x',Origin,'y',Horsepower,'color',Origin)
Expand All @@ -496,7 +498,7 @@

%Some methods can be called on all objects at the same time !
g.axe_property('YLim',[0 140])
%g.axe_property('XTickLabelRotation',60) %Should work for recent Matlab
g.axe_property('XTickLabelRotation',60) %Should work for recent Matlab
%versions
g.set_names('x','Origin','y','Horsepower','color','Origin','lightness','Origin')
g.set_title('Colormap customizations examples')
Expand Down Expand Up @@ -575,7 +577,7 @@
%Here we create x as a 1xN array (see example above), and use a MxN matrix
%for y. Color applies to the M rows of y.
g18=gramm('x',900:2:1700,'y',NIR,'color',octane);
g18.set_names('x','Wavelength (nm)','y','NIR','color','octane')
g18.set_names('x','Wavelength (nm)','y','NIR','color','Octane')
g18.set_continuous_color('colormap','hot')
g18.geom_line;
g18.draw;
Expand Down Expand Up @@ -651,7 +653,6 @@
%The measurements are now binomial (follows a logit curve centered on 5)
y=random('binomial',1,1./(1+exp(5-x)))

figure
g(1,2)=gramm('x',x,'y',y)
%We plot jittered points to get a better idea of the distribution
%g.geom_jitter('width',0.2,'height',0.1)
Expand Down Expand Up @@ -685,7 +686,7 @@
g=gramm('x',x,'y',y,'color',cat)
g.geom_point()
g.stat_fit('fun',fun,'disp_fit',true) %We provide the function for the fit
g.set_title('stat_fit() with user-provided function')
g.set_title({'stat_fit() with user-provided function:' '@(alpha,beta,gamma,x)alpha*exp(cos(x-beta)*gamma)'})
g.draw()

%% Changing the order of elements with set_order_options()
Expand Down
Loading

0 comments on commit 6e260a1

Please sign in to comment.