# scatter3, stop the color changing after a second scatter3 command

2 views (last 30 days)
Lorenzo Chiaverini on 10 Apr 2021
Edited: Lorenzo Chiaverini on 10 Apr 2021
I am having some problems with scatter3, this is an example code:
figure
colormap jet
a = scatter3([1 2 3], [1 2 3],[1 2 3], 50, [1; 2; 2], 'filled')
hold on
scatter3([0 1 2], [1 2 3],[1 2 3], 50, [1; 2; 3], 'filled')
hold off
After the second scatter3 command the colors of the first scatter change accordingly. I want to remove this effect. How can I do so?
Thank you!
Lorenzo Chiaverini on 10 Apr 2021
A final comment for anybody who needs it: the linear mapping that matlab does is useful but it applies to all the colors of the image. I wrote a short code which returns the same rgb matrix that matlab effectively uses automatically, in this way different colormap limits can be used for different scatter commands.
norms = vecnorm(uvw(:, 1:3), 2, 2);
resolution = 256;
colors = jet(resolution); % the chosen colormap with chosen resolution
Mid = norms; % the middle values you want to assign a color to
Min = 0; % your defined minimum
Max = max(Mid); % your defined maximum
indexes = round(((Mid - Min) ./ (Max)) * (resolution - 1)) + 1; % the indexes which refer to the colors matrix
scatter3(uvw(:, 1), uvw(:, 2), uvw(:, 3), 10, colors(indexes, :), 'filled');

Walter Roberson on 10 Apr 2021
When you use scatter3() and pass in a vector of color information, the information you pass in is not color indices into the current colormap. Instead, the data is interpreted according to the current color axis; see https://www.mathworks.com/help/matlab/ref/caxis.html and https://www.mathworks.com/help/matlab/creating_plots/change-mapping-of-data-values-into-the-colormap.html . For scatter3() there is no CDataMapping property: you should intepret CDataMapping in the case of vector of color values as if CDataMapping were 'scaled' .
When you add the original data in range 1 to 2, the min and max are used to set the caxis. The minimum value (1) is mapped to the first entry in the color map, and the maximum value (2) is mapped to the last entry in the colormap.
When you add the additional data with color info, the min and max of all the data in the axis is used, so the caxis expands to [1 3] . The min value (1) maps to the first entry, the max value (3) maps to the last entry, and the 2 values interpolate over [1 3] and so map to the middle of the color map.
When you say that you do not want the colors of the first scatter to change, that could be interpreted as saying that you want the 1's to map to the first color, and you want the 2's to continue to map to the last color, and you want the 3's to map to.... it isn't clear what you would want them to map to?
If you are doing some kind of presentation over time where you want to show the first version and let the user see it, and then show the second version, and what you are concerned about is consistency over time rather than about the exact colors, then there are multiple approaches:
• Before doing the first scatter3(), do a caxis() call that gives the minimum and maximum of all of the data you are going to plot. That will set axes CLimMode to 'manual' and so the 1 and 2 of the original scatter3 will already be color interpolated over the entire range, so the mapping will be consistent over time; Or
• switch to supplying RGB colors for each color instead of a vector of color values. rescale() and ind2rgb() can help with that.

Cris LaPierre on 10 Apr 2021
This might be a bit tricky to explain what is happening. By specifying C as a vector, the following method is used to determine the color.
• If C is a vector with length equal to the length of X, Y, and Z, then the values in C are linearly mapped to the colors in the current colormap.
What the actual color is depends on what the current colormapping is. Dy default, the colormap is applied to the range of your color data. When you plot the first scatter3 plot, your color values range from 1 to 2. You can see this if you turn on the colorbar.
scatter3([1 2 3], [1 2 3],[1 2 3], 50, [1; 2; 2], 'filled')
colormap jet
colorbar
What happens is that, when you add your second plot, the range of your color data changes to 1-3. The colormap is rescaled to include the new data, now making 3 dark red, and moving 2 into the center of the range, changing all points with C==2 to green.
figure
scatter3([1 2 3], [1 2 3],[1 2 3], 50, [1; 2; 2], 'filled')
hold on
scatter3([0 1 2], [1 2 3],[1 2 3], 50, [1; 2; 3], 'filled')
hold off
colormap jet
colorbar
There are two ways I can think of to fix this.
1. Use caxis to set the color range up front
2. Specify rgb values for your colors rather than the vector approach you are using.
% Method 1 - caxis
figure
scatter3([1 2 3], [1 2 3],[1 2 3], 50, [1; 2; 2], 'filled')
colormap jet
colorbar
caxis([1 3])
% Method 2 - RGB
figure
cmap=[0 0 1;0 1 0;1 0 0];
scatter3([1 2 3], [1 2 3],[1 2 3], 50, cmap([1;2;2],:), 'filled')
hold on
scatter3([0 1 2], [1 2 3],[1 2 3], 50, cmap([1;2;3],:), 'filled')
hold off
colormap jet

R2021a

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by