2

Using three colors, and values ranging from 0-100, Colorbar is per default splitting up the colors at, respectively, 1/3 and 2/3:

enter image description here

I would like to select this interval manually. E.g. at 1/4 and 1/2.

MWE:

clc; close all; clear all

data = (50+50)*rand(10,3)

% green if acc(:,1)<Crit1
% red if acc(:,1)>Crit2
% yellow if acc(:,1)>Crit1 && acc(:,1)<Crit2

Crit1 = 25; 
Crit2 = 50; 

imagesc(data)
mycolormap = [0 1 0; 1 1 0; 1 0 0];
colormap(mycolormap)
colorbar

I have previously posted this question (https://math.stackexchange.com/posts/3472347/), probably in the wrong forum, without any response.

Paolo
  • 21,270
  • 6
  • 38
  • 69
User4536124
  • 37
  • 1
  • 11
  • Compute the minimal common divisor between `1/4` and `1/2` which is `1/4`, so now you know that you need `1/0.25 = 4` color triplet into your colormap: `mycolormap = [0 1 0; 1 1 0; 1 0 0; 1 0 0];` should do the job – obchardon Dec 17 '19 at 12:31
  • Related (not dupes): [How do I change matlab colorbar scaling](https://stackoverflow.com/q/33650595/8239061), [MATLAB Colorbar - Same colors, scaled values](https://stackoverflow.com/q/45285114/8239061), [Control colorbar scale in MATLAB](https://stackoverflow.com/q/54675647/8239061) – SecretAgentMan Dec 17 '19 at 13:22
  • have a look at `caxis` – Tasos Papastylianou Dec 19 '19 at 14:43

1 Answers1

4

By default, imagesc scales the data and chooses the thresholds betwen uniformly. To change that, you have several options:

  1. Define a colormap with repeated colors that produces the correspondence that you want. To get 1/4 and 1/2 you would need

    mycolormap = [0 1 0; 1 1 0; 1 0 0; 1 0 0];
    

    This gives unequal lenghts in the colorbar, according to the separation between values:

enter image description here

  1. Apply the thresholds manually, and then change the colorbar labels:

    data = 100*rand(10,3);
    thresholds = [0 1/4 1/2 1]; % thresholds for normalized data
    mycolormap = [0 1 0; 1 1 0; 1 0 0]; % colormap with numel(threholds)-1 rows
    m = min(data(:)); % min of data
    data_normalized = data-min(data(:));
    r = max(data_normalized(:)); % range of data
    data_normalized = data_normalized./r;
    t = sum(bsxfun(@ge, data_normalized, reshape(thresholds, 1, 1, [])), 3);
    imagesc(t)
    colormap(mycolormap)
    h = colorbar;
    set(h, 'Ticks', 1:numel(thresholds))
    set(h, 'Ticklabels', m+r*thresholds)
    

    This gives equal lenghts in the colorbar, so the indicated values do not form a uniform scale. Thresholds are relative to the range of the data.

enter image description here

  1. Same as above but with absolute thresholds:

    data = 100*rand(10,3);
    thresholds = [0 25 50 100]; % absolute thresholds for data
    mycolormap = [0 1 0; 1 1 0; 1 0 0]; % colormap with numel(threholds)-1 rows
    t = sum(bsxfun(@ge, data, reshape(thresholds, 1, 1, [])), 3);
    imagesc(t)
    colormap(mycolormap)
    h = colorbar;
    set(h, 'Ticks', 1+linspace(0, 1, numel(thresholds))*(numel(thresholds)-2))
    set(h, 'Ticklabels', thresholds)
    
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • It seems that the strict intervals: `[0;25[` (green), `[25;50[` (yellow) and `[50;100]` (red) are not respected by the above algorithm, but that it instead changes dynamically for each computation of `rand(10,3)`? – User4536124 Dec 19 '19 at 07:33
  • @Ole Yes, that's what I understood from your example, in which you say "1/3 or 2/3" and "1/4 and 1/2" with data ranging from `0` to `100`, I understood thresholds as relative to the range of the data – Luis Mendo Dec 19 '19 at 09:18
  • Oh! My apologies then. The thresholds should be absolute (25 and 50 using the 0-100 range). As of now values can be e.g. 51 and then yield a yellow color, whereas it should be red since it is above 50 – User4536124 Dec 19 '19 at 10:35
  • It seems that this new version yields results similar to OP, or am I wrong? At least it doesn't reflect the full data set ranging from 0-100 – User4536124 Dec 19 '19 at 11:54
  • Method 1 should do what OP wants if you set `clim` to [0,100], no? – Cris Luengo Dec 19 '19 at 17:34
  • @CrisLuengo The problem with method 1 is that you need to manually decide how many times to repeat each color. Well, maybe not manually; it could be automated, but that would be a different answer... – Luis Mendo Dec 19 '19 at 17:39
  • @LuisMendo Definitely getting closer; now the colorbar is as wanted. However, when comparing the values in the 'data' matrix, then many values do not correspond to the colorbar. All values '\in[0;25[' should be green, all values '\in[25;50]' should be yellow, and all values '\in[50;100]' should be red (as of now they are not (?!)). It seems that I cannot upload an image here for further explanation. I hope the explanation is adequate – User4536124 Dec 19 '19 at 18:16
  • @Oles That's what the code does, isn't it? Try part 3 with `data = [1 24; 26 49; 51 99];` – Luis Mendo Dec 19 '19 at 21:23
  • 1
    @LuisMendo Yes, it works as wanted! Thank you. I really appreciate it. – User4536124 Dec 20 '19 at 10:17