Back to the main page.

Bug 3000 - saturation masking in ft_plot_matrix/topo leads to grey colors for many colormaps

Reported 2015-11-05 20:30:00 +0100
Modified 2019-08-10 12:30:42 +0200
Product: FieldTrip
Component: plotting
Version: unspecified
Hardware: PC
Operating System: Mac OS
Importance: P5 normal
Assigned to:
Depends on:
Blocks: 2574
See also:

Roemer van der Meij - 2015-11-05 20:30:18 +0100

In jet, this does not occur. It's a property of parula, but the resulting effect is undesired. It also doesn't occur when using opacity masking. Replicate: cdat = ones(30,50); mask = rand(30,50); % parula saturation figure('colormap',parula) ft_plot_matrix(cdat,'clim',[0 2],'highlightstyle','saturation','highlight',mask) % jet saturation figure('colormap',jet) ft_plot_matrix(cdat,'clim',[0 2],'highlightstyle','saturation','highlight',mask) % parula opacity figure('colormap',parula) ft_plot_matrix(cdat,'clim',[0 2],'opacity','saturation','highlight',mask) % jet opacity figure('colormap',jet) ft_plot_matrix(cdat,'clim',[0 2],'opacity','saturation','highlight',mask)

Roemer van der Meij - 2015-11-05 22:48:34 +0100

I spent quite some time on this, and I have the feeling there's no way around this, it's just a property of how the PARULA colors are defined. The thing that tipped the balance for me is: Using these converters to transform a PARULA color (the center one for example: 29 179 175 in RGB) you can notice that the 'value' of its HSV representation is not 100%$ (or 1 in matlab). When the saturation is 0 (using the other converter), the value determines whether the color is white<->black. Given the above, my conclusion is the following: Some PARULA colors are defined by an HSV 'value' of less than 1 (matlab terms), and therefore become a tint of grey as opposed to white when their saturation is lowered. Actually, this is also the case for JET actually. % Shown by rgb2hsv(ind2rgb(uint8(floor(rand(20,20)*2^8)), jet)) % for jet rgb2hsv(ind2rgb(uint8(floor(rand(20,20)*2^8)), parula)) % for parula Which explains why sometimes saturated colors turned grey in the past, which I assumed was a bug which I was chasing down. It only happens occasionally, which is likely due to the fact that the colors we usually 'saturate down', are those close to primary colors, like red, or blue (the ends of the JET), which do have an HSV value of 1.

Roemer van der Meij - 2015-11-05 22:50:23 +0100

(there's a silly mistake actually in the first code I pasted, but it still had the desired effect due to appropriate defaults)

Roemer van der Meij - 2015-11-05 22:56:12 +0100

So, this actually is a bit of an issue then. Should we still use saturation masking? Knowing that it fails in (quite a bit) of colors? I changed to title to reflect the generalness of the problem. Something to be discussed in the meeting I think.

Roemer van der Meij - 2015-11-05 23:01:49 +0100

One thing the HSV transform can still be useful for is to knock out NANs or data points completely by turning them white. This involves (1) setting the saturation to 0 and (2) the value to 0. It will be white regardless of the value of hue. It's easy to implement, a good name would be huesaturationvalue or saturationvalue (hsv is confusing because of the name of the particular colormap). The benefit is still that avoids the opengl issue when saving files.

Robert Oostenveld - 2015-11-05 23:34:42 +0100

(In reply to Roemer van der Meij from comment #3) > Should we still use saturation masking? Saturation might not work in all cases, but it does work in some and does solve certain problems. Therefore I think we should support it in general. Recently Stephen (CC) encountered issues (cortical source-level representation with opacity) that could only be resolved by rendering it on a local PC (no software but hardware OpenGL). See

Robert Oostenveld - 2015-11-05 23:36:13 +0100

(In reply to Roemer van der Meij from comment #4) > a good name would be huesaturationvalue or saturationvalue I would opt for "saturation".

Roemer van der Meij - 2015-11-05 23:51:00 +0100

I wasn't very clear in my comments, it's been a long day (but, colorful, ha!) The option 'saturation' in its current implementation causes grey values for certain colors in all colormaps. We use it for: 1) masking: setting pixels to white (100% transparent using opacity in opengl) 2) highlighting: shading pixels to white (transparent using opacity in opengl) The approach itself (using an HSV transform) can in principle do (1), but it can never really do (2). I meant to propose to make saturation only work for masking (1): - binarizing any mask that is used - also adjust Value of HSV We can keep on calling it saturation, although that is not entirely correct. I'd be happy to change the implementation in ft_plot_matrix/topo.

Roemer van der Meij - 2015-11-06 00:48:33 +0100

Actually went ahead and did it already (the implementation, not a name change), I was on a role. Also described the approach a little better: % This approach changes the color of pixels to white, regardless of colormap, without using opengl % It does by converting by: % 1) convert the to-be-plotted data to their respective rgb color values (determined by colormap) % 2) convert these rgb color values to hsv values, hue-saturation-value % 3) for to-be-masked-pixels, set saturation to 0 and value to 1 (hue is irrelevant when they are) % 4) convert the hsv values back to rgb values % 5) plot these values Also expanded test_ft_plot_matrix for comparing opacity vs saturation masking. See test_ft_plot_matrix and test_ft_plot_topo for seeing the effect of the above.

Robert Oostenveld - 2019-08-10 12:30:42 +0200

This closes a whole series of bugs that have been resolved (either FIXED/WONTFIX/INVALID) for quite some time. If you disagree, please file a new issue on