3

Consider the following example:

[ X, Y, Z ] = peaks( 30 );
figure( 100 );
surfc( X, Y, Z );
zlabel( 'Absolute Values' );
colormap jet;
c = colorbar( 'Location', 'EastOutside' );
ylabel( c, 'Relative Values' );

The output looks as follows: MATLAB Colorbar - Absolute Scaling

How can I scale the ticks on the colorbar, i.e. scale the c-axis (e.g. divide the values by 100):

  • without changing the z values and colors on the plot
  • without changing the colors on the colorbar
  • without changing the relation between the colors on the plot, the colors on the colorbar and the z values of the plot
  • while still using the full range of the colorbar

In the picture above, I would like to scale the c-axis such that it shows this values for the related z:

z | c-axis
----------
8 | 8/100
6 | 6/100
4 | 4/100
. | ...

The function caxis, as I understand it, is not suited here, as it would just show the colors for a subsection of the z-axis and not for the whole z-axis.

Bonus question: How could one scale the color mapping and the colorbar as a function of X, Y and/or Z?

Discbrake
  • 315
  • 2
  • 14

2 Answers2

4
[ X, Y, Z ] = peaks( 30 );
figure( 101 );
surfc( X, Y, Z );
zlabel( 'Absolute Values' );
%
Z_Scl = 0.01;
Z_Bar = linspace( min(Z(:)), max(Z(:)), 10 );
%
colormap jet;
c = colorbar( 'Location', 'EastOutside', ...
    'Ticks', Z_Bar, 'TickLabels', cellstr( num2str( Z_Bar(:)*Z_Scl, '%.3e' ) ) );
ylabel( c, 'Relative Values' );

MATLAB Colorbar - Scaled Colorbar - Version 1

For an arbitrary mapping between the z-values and the colorbar, it is possible to combine surf, contourf and contour as follows (inspired by these two great answers):

[ X, Y, Z ] = peaks( 30 ); % Generate data
CB_Z = (sin( Z/max(Z(:)) ) - cos( Z/max(Z(:)) )).^2 + X/5 - Y/7; % Generate colormap
CF_Z = min( Z(:) ); % Calculate offset for filled contour plot
CR_Z = max( Z(:) ); % Calculate offset for contour plot
%
figure( 102 ); % Create figure
clf( 102 );
hold on; grid on; grid minor; % Retain current plot and create grid
xlabel( 'x' ); % Create label for x-axis
ylabel( 'y' ); % Create label for y-axis
zlabel( 'Scaling 1' ); % Create label for z-axis
surf( X, Y, Z, CB_Z ); % Create surface plot
%
CF_H = hgtransform( 'Parent', gca ); % https://stackoverflow.com/a/24624311/8288778
contourf( X, Y, CB_Z, 20, 'Parent', CF_H ); % Create filled contour plot
set( CF_H, 'Matrix', makehgtform( 'translate', [ 0, 0, CF_Z ] ) ); % https://stackoverflow.com/a/24624311/8288778
%
CR_H = hgtransform( 'Parent', gca ); % https://stackoverflow.com/a/24624311/8288778
contour( X, Y, CB_Z, 20, 'Parent', CR_H ); % Create contour plot
set( CR_H, 'Matrix', makehgtform( 'translate', [ 0, 0, CR_Z ] ) ); % https://stackoverflow.com/a/24624311/8288778
%
colormap jet; % Set current colormap
CB_H = colorbar( 'Location', 'EastOutside' ); % Create colorbar
caxis( [ min( CB_Z(:) ), max( CB_Z(:) ) ] ); % Set the color limits for the colorbar
ylabel( CB_H, 'Scaling 2' ); % Create label for colorbar

MATLAB Surf Contourf Contour Colorbar

Discbrake
  • 315
  • 2
  • 14
  • 1
    Do you want the values in the z-axis to be different from the c-axis? This is somewhat misleading... – EBH Jul 24 '17 at 17:51
  • @EBH The question is updated, is it clear now or still misleading? – Discbrake Jul 25 '17 at 06:38
  • 1
    Your intention was clear even before, it just seems to me either redundant or misleading to show the 2 axes for the same value. But I guess it may be useful for some visualizations (I think would rather put one of the values in parenthesis within the z-axis, like `5 (0.05)`). – EBH Jul 25 '17 at 06:46
  • 1
    @EBH Thank you. Yes, you are right, parenthesis are a great idea. One possibility could be to use SI Units on the z-axis and US or Imperial Units for the colorbar, as long as linear scaling is ensured. Now that I think about it, using a fourth parameter (C) with surfc in combination with the caxis command might be a better approach, see the updated answer. – Discbrake Jul 25 '17 at 07:03
3

As I wrote in your answer, I think a better choice for showing two related values is not to create a new axis for that, but to show them one near the other. Here is a suggestion:

[X,Y,Z] = peaks(30);
surfc(X,Y,Z);
zlabel('Absolute (Relative) Values');
colormap jet
Z_Scl = 0.01;
zticks = get(gca,'ZTick');
set(gca,'ZTickLabel',sprintf('%g (%g)\n',[zticks;zticks.*Z_Scl]))

enter image description here

EBH
  • 10,350
  • 3
  • 34
  • 59
  • Are MWEs discouraged here? I'm still convinced that adding the line 'ax = gca;' might help unexperienced users, as it does not run as it is. – Discbrake Jul 25 '17 at 07:37
  • @user5564832 You right! my apologies, I mixed between 2 versions of my code and forgot to fix that. Now fixed. – EBH Jul 25 '17 at 07:42
  • Perfect, your version looks cleaner anyways, and thanks for the answer, great idea. – Discbrake Jul 25 '17 at 08:04