{"id":1265,"date":"2015-01-20T18:35:44","date_gmt":"2015-01-20T23:35:44","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=1265"},"modified":"2019-11-01T11:27:37","modified_gmt":"2019-11-01T15:27:37","slug":"divergent-colormaps","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2015\/01\/20\/divergent-colormaps\/","title":{"rendered":"Divergent colormaps"},"content":{"rendered":"<div class=\"content\"><p>I promised earlier to post about divergent colormaps. A divergent colormap is usually constructed by concatenating two colormaps together that have different color schemes.<\/p><p>Here is an example of a divergent colormap from <a href=\"http:\/\/colorbrewer2.org\">www.ColorBrewer.org<\/a> by Cynthia A. Brewer, Geography, Pennsylvania State University.<\/p><pre class=\"codeinput\">rgb = [ <span class=\"keyword\">...<\/span>\r\n    94    79   162\r\n    50   136   189\r\n   102   194   165\r\n   171   221   164\r\n   230   245   152\r\n   255   255   191\r\n   254   224   139\r\n   253   174    97\r\n   244   109    67\r\n   213    62    79\r\n   158     1    66  ] \/ 255;\r\n\r\nb = repmat(linspace(0,1,200),20,1);\r\nimshow(b,[],<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\ncolormap(rgb)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_01.jpg\" alt=\"\"> <p>This colormap has the brightest color in this middle, which is typical for divergent colormaps.<\/p><p>A divergent colormap is used to compare data values to a reference value in a way that visually highlights whether values are above or below the reference.<\/p><p>Let me show you an example using sea surface temperatures. I learned today that 28 degrees Celsius has a specific meaning in hurricane modeling and prediction. It is considered to be the minimum temperature for hurricane formation.<\/p><p>Using the <a title=\"http:\/\/reverb.echo.nasa.gov\/reverb (link no longer works)\">NASA EOSDIS Reverb tool<\/a>, I found and downloaded sea surface temperature from the Aqua satellite for August 1, 2011. The data arrived as a netCDF file.<\/p><pre class=\"codeinput\">amsre = ncread(<span class=\"string\">'20110801-AMSRE-REMSS-L2P_GRIDDED_25-amsre_20110801rt-v01.nc'<\/span>,<span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">'sea_surface_temperature'<\/span>);\r\n\r\nsize(amsre)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n        1440         720           2\r\n\r\n<\/pre><p>The two planes contain data from two different orbits.<\/p><pre class=\"codeinput\">orbit1 = flipud(amsre(:,:,1)');\r\norbit2 = flipud(amsre(:,:,2)');\r\n\r\nimshow(orbit1,[],<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\ntitle(<span class=\"string\">'Orbit 1'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_02.jpg\" alt=\"\"> <pre class=\"codeinput\">imshow(orbit2,[],<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\ntitle(<span class=\"string\">'Orbit 2'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_03.jpg\" alt=\"\"> <p>The black regions are NaNs representing missing data. Combine the two orbits by taking the maximum.<\/p><pre class=\"codeinput\">sst = max(orbit1,orbit2);\r\nimshow(sst,[],<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_04.jpg\" alt=\"\"> <p>Now grab a subset of the data that includes a portion of the Atlantic Ocean.<\/p><pre class=\"codeinput\">ssta = sst(180:400,330:700);\r\nimshow(ssta,[],<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_05.jpg\" alt=\"\"> <p>Apply the divergent colormap.<\/p><pre class=\"codeinput\">colormap(rgb)\r\ncolorbar\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_06.jpg\" alt=\"\"> <p>OK, I see one problem right off the bat. It looks like our data is in Kelvin. Let's fix that.<\/p><pre class=\"codeinput\">ssta = ssta - 273.15;\r\nimshow(ssta,[],<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\ncolormap(rgb)\r\ncolorbar\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_07.jpg\" alt=\"\"> <p>Now I want to make use of our divergent colormap to highlight the temperature of interest, 28 degrees. To do that, I'll use the CLim property of the axes object. The CLim property is a two-element vector. The first element tells us the data value that maps to the lowest colormap color, and the second element tells us the data value that maps to the highest colormap color. MATLAB computes these values automatically based on the range of the data.<\/p><pre class=\"codeinput\">get(gca,<span class=\"string\">'CLim'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n   -1.9500   33.6000\r\n\r\n<\/pre><p>To get the middle colormap color to represent 28 degrees, we need to pick our two CLim values so that they are equally far away from 28 degrees. After some experimentation, I settled on a range from 22 degrees to 34 degrees.<\/p><pre class=\"codeinput\">set(gca,<span class=\"string\">'CLim'<\/span>,[22 34])\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_08.jpg\" alt=\"\"> <p>That's looking better, but it isn't helpful to have the missing data displayed using the bottom color of the colormap. I will fix that problem using this procedure.<\/p><div><ol><li>Construct a gray mask image (in truecolor format).<\/li><li>Display it on top of our sea surface temperature image.<\/li><li>Set the AlphaData of the gray mask image so that the sea surface temperatures show through.<\/li><\/ol><\/div><p>Here are just the first two steps.<\/p><pre class=\"codeinput\">mask = isnan(ssta);\r\ngraymask = 0.5 * mask;\r\ngraymask = repmat(graymask,1,1,3);\r\nhold <span class=\"string\">on<\/span>\r\nh = imshow(graymask);\r\nhold <span class=\"string\">off<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_09.jpg\" alt=\"\"> <p>The missing values are displayed as gray, but we can't see the sea surface temperatures. Fix that by using the NaN-mask as the overlay image's AlphaData.<\/p><pre class=\"codeinput\">h.AlphaData = mask;  <span class=\"comment\">% This syntax requires MATLAB R2014b.<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_10.jpg\" alt=\"\"> <p>Temperatures close to the threshold are displayed using yellow, the brightest color in the colormap and the one right in the middle. Temperatures above the threshold are displayed using oranges and reds, while temperatures below are displayed using greens and blues.<\/p><p>Before I go, I want to give a shout to the new <a href=\"https:\/\/blogs.mathworks.com\/developer\/\">Developer Zone<\/a> blog that just started today. If you are into advanced software developer topics, I encourage you to head over there and take a look.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_23e67dbfac504fc2bc3ecd8282538773() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='23e67dbfac504fc2bc3ecd8282538773 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 23e67dbfac504fc2bc3ecd8282538773';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2015 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_23e67dbfac504fc2bc3ecd8282538773()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2014b<br><\/p><\/div><!--\r\n23e67dbfac504fc2bc3ecd8282538773 ##### SOURCE BEGIN #####\r\n%%\r\n% I promised earlier to post about divergent colormaps. A divergent colormap is\r\n% usually constructed by concatenating two colormaps together that have\r\n% different color schemes.\r\n%\r\n% Here is an example of a divergent colormap from <http:\/\/www.ColorBrewer.org\r\n% www.ColorBrewer.org> by Cynthia A. Brewer, Geography, Pennsylvania State\r\n% University.\r\n\r\nrgb = [ ...   \r\n    94    79   162\r\n    50   136   189\r\n   102   194   165\r\n   171   221   164\r\n   230   245   152\r\n   255   255   191\r\n   254   224   139\r\n   253   174    97\r\n   244   109    67\r\n   213    62    79\r\n   158     1    66  ] \/ 255; \r\n\r\nb = repmat(linspace(0,1,200),20,1);\r\nimshow(b,[],'InitialMagnification','fit')\r\ncolormap(rgb)\r\n\r\n%%\r\n% This colormap has the brightest color in this middle, which is typical for\r\n% divergent colormaps.\r\n%\r\n% A divergent colormap is used to compare data values to a reference value in a\r\n% way that visually highlights whether values are above or below the reference.\r\n%\r\n% Let me show you an example using sea surface temperatures. I learned today\r\n% that 28 degrees Celsius has a specific meaning in hurricane modeling and\r\n% prediction. It is considered to be the minimum temperature for hurricane\r\n% formation.\r\n%\r\n% Using the <http:\/\/reverb.echo.nasa.gov\/reverb NASA EOSDIS Reverb tool>, I\r\n% found and downloaded sea surface temperature from the Aqua satellite for\r\n% August 1, 2011. The data arrived as a netCDF file.\r\n\r\namsre = ncread('20110801-AMSRE-REMSS-L2P_GRIDDED_25-amsre_20110801rt-v01.nc',...\r\n    'sea_surface_temperature');\r\n\r\nsize(amsre)\r\n\r\n%%\r\n% The two planes contain data from two different orbits.\r\n\r\norbit1 = flipud(amsre(:,:,1)');\r\norbit2 = flipud(amsre(:,:,2)');\r\n\r\nimshow(orbit1,[],'InitialMagnification','fit')\r\ntitle('Orbit 1')\r\n\r\n%%\r\nimshow(orbit2,[],'InitialMagnification','fit')\r\ntitle('Orbit 2')\r\n\r\n%%\r\n% The black regions are NaNs representing missing data. Combine the two orbits\r\n% by taking the maximum.\r\n\r\nsst = max(orbit1,orbit2);\r\nimshow(sst,[],'InitialMagnification','fit')\r\n\r\n%%\r\n% Now grab a subset of the data that includes a portion of the Atlantic Ocean.\r\n\r\nssta = sst(180:400,330:700);\r\nimshow(ssta,[],'InitialMagnification','fit')\r\n\r\n%%\r\n% Apply the divergent colormap.\r\n\r\ncolormap(rgb)\r\ncolorbar\r\n\r\n%%\r\n% OK, I see one problem right off the bat. It looks like our data is in\r\n% Kelvin. Let's fix that.\r\n\r\nssta = ssta - 273.15;\r\nimshow(ssta,[],'InitialMagnification','fit')\r\ncolormap(rgb)\r\ncolorbar\r\n\r\n%%\r\n% Now I want to make use of our divergent colormap to highlight\r\n% the temperature of interest, 28 degrees. To do that, I'll use the CLim\r\n% property of the axes object. The CLim property is a two-element vector. The\r\n% first element tells us the data value that maps to the lowest colormap color,\r\n% and the second element tells us the data value that maps to the highest\r\n% colormap color. MATLAB computes these values automatically based on the range\r\n% of the data.\r\n\r\nget(gca,'CLim')\r\n\r\n%%\r\n% To get the middle colormap color to represent 28 degrees, we need to pick our\r\n% two CLim values so that they are equally far away from 28 degrees. After some\r\n% experimentation, I settled on a range from 22 degrees to 34 degrees.\r\n\r\nset(gca,'CLim',[22 34])\r\n\r\n%%\r\n% That's looking better, but it isn't helpful to have the missing data displayed\r\n% using the bottom color of the colormap. I will fix that problem using this\r\n% procedure.\r\n%\r\n% # Construct a gray mask image (in truecolor format).\r\n% # Display it on top of our sea surface temperature image.\r\n% # Set the AlphaData of the gray mask image so that the sea surface\r\n% temperatures show through.\r\n%\r\n% Here are just the first two steps.\r\n\r\nmask = isnan(ssta);\r\ngraymask = 0.5 * mask;\r\ngraymask = repmat(graymask,1,1,3);\r\nhold on\r\nh = imshow(graymask);\r\nhold off\r\n\r\n%%\r\n% The missing values are displayed as gray, but we can't see the sea surface\r\n% temperatures. Fix that by using the NaN-mask as the overlay image's AlphaData.\r\n\r\nh.AlphaData = mask;  % This syntax requires MATLAB R2014b.\r\n\r\n%%\r\n% Temperatures close to the threshold are displayed using yellow, the brightest\r\n% color in the colormap and the one right in the middle. Temperatures above the\r\n% threshold are displayed using oranges and reds, while temperatures below are\r\n% displayed using greens and blues.\r\n%\r\n% Before I go, I want to give a shout to the new\r\n% <https:\/\/blogs.mathworks.com\/developer\/ Developer Zone> blog that just started\r\n% today. If you are into advanced software developer topics, I encourage you to\r\n% head over there and take a look.\r\n\r\n##### SOURCE END ##### 23e67dbfac504fc2bc3ecd8282538773\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2015\/divergent_colormap_10.jpg\" onError=\"this.style.display ='none';\" \/><\/div><p>I promised earlier to post about divergent colormaps. A divergent colormap is usually constructed by concatenating two colormaps together that have different color schemes.Here is an example of a... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2015\/01\/20\/divergent-colormaps\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[24],"tags":[1103,58,745,80,1105,90,36,376,32,122,1101,116,190,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1265"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=1265"}],"version-history":[{"count":3,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1265\/revisions"}],"predecessor-version":[{"id":2395,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1265\/revisions\/2395"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=1265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=1265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=1265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}