{"id":3634,"date":"2017-07-25T10:52:29","date_gmt":"2017-07-25T09:52:29","guid":{"rendered":"http:\/\/www.blopig.com\/blog\/?p=3634"},"modified":"2017-07-25T16:33:22","modified_gmt":"2017-07-25T15:33:22","slug":"in-matlab-its-colormaps-all-the-way-down","status":"publish","type":"post","link":"https:\/\/www.blopig.com\/blog\/2017\/07\/in-matlab-its-colormaps-all-the-way-down\/","title":{"rendered":"In MATLAB, it&#8217;s colormaps all the way down"},"content":{"rendered":"<p>My overriding emotion, working in R, has been incomprehension: incomprehension at the gallery of ugly gnomes that populate the namespace and worried puzzlement over the strange incantations required to get them to dance in a statistically harmonious way. But all that aside, I resolved, joining the group, to put aside my misgivings and give the gnomes another try.<\/p>\n<p>Soon, I found myself engaged in a reassessment of my life choices. I realized that life&#8217;s too short to spend it tickling gnomes &#8211; especially when only one of them knows how to do linear regression, but he won&#8217;t tell you your <em>p<\/em> value unless you give him the right kinds of treats.&nbsp;I fired up MATLAB and I haven\u2019t looked back.<\/p>\n<p>However, there was issue of continued perplexity, and I\u2019m not referring to why MATLAB insists on shouting itself at you. I need to make a lot of 2-D plots of protein distance matrices. The trouble is that I like to highlight parts of them, and that&#8217;s not straightforward in MATLAB. Let\u2019s have a look at an example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&gt;&gt; dists=dlmread('1hel.distances');\r\n&gt;&gt; colormap gray;\r\n&gt;&gt; imagesc(dists&gt;8);\r\n&gt;&gt; axis square;<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1_1hel_map.png?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-3635\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1_1hel_map.png?resize=300%2C225&#038;ssl=1\" alt=\"Contact map\" width=\"300\" height=\"225\" srcset=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1_1hel_map.png?resize=300%2C225&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1_1hel_map.png?w=560&amp;ssl=1 560w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Now, let\u2019s load up a set of residues and try to overlay them on top of the first image:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&gt;&gt; resn=dlmread('1hel.resn');\r\n&gt;&gt; mask = zeros(size(dists));\r\n&gt;&gt; mask(resn,resn)=1;\r\n&gt;&gt; hold on\r\n&gt;&gt; imagesc(1-mask, 'AlphaData',mask*.5);\r\n<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1.5_1hel_mask.png?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-3638\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1.5_1hel_mask.png?resize=300%2C225&#038;ssl=1\" alt=\"\" width=\"300\" height=\"225\" srcset=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1.5_1hel_mask.png?resize=300%2C225&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/1.5_1hel_mask.png?w=560&amp;ssl=1 560w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>So far, so easy. To review the main points:<\/p>\n<p><code>mask<\/code> is a matrix which has a one at all the pixels that we want to highlight. But we use <code>imagesc(1-mask)<\/code> because the gray colormap displays black at 0 and white at 1. If we did&nbsp;<code>imagesc(mask)<\/code>, we would end up with grey everywhere and white only where we hoped to highlight &#8211; the opposite effect from the one that we sought.<\/p>\n<p><code>AlphaData<\/code> is a property which sets the transparency of the image. We want the image to be fully transparent where <code>mask<\/code> is 0 &#8211; so as not to fog out the underlying image &#8211; and partially transparent where <code>mask<\/code> is 1. <code>0.5*mask<\/code> is a matrix which is 0.5 everywhere that <code>mask<\/code> is 1 and 0 everywhere else. &nbsp;If we&nbsp;set <code>0.5*mask<\/code> as the <code>AlphaData<\/code> property, then the colour we add will be at half transparency and the white areas will be fully transparent.<\/p>\n<p>But this isn\u2019t a very pleasant image. We want to be able to highlight the regions in some colour other than grey. Let\u2019s try.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&gt;&gt; close all\r\n&gt;&gt; imagesc(dists&gt;8)\r\n&gt;&gt; colormap gray\r\n&gt;&gt; axis square\r\n&gt;&gt; imagesc(1-mask, 'AlphaData',mask*.3,'ColorMap','jet');\r\nError using image\r\nThere is no ColorMap property on the Image class.\r\n\r\nError in imagesc (line 39)\r\nhh = image(varargin{:},'CDataMapping','scaled');\r\n<\/pre>\n<p>No luck! What&#8217;s more, setting the colormap between calls to <code>image()<\/code> and <code>imagesc()<\/code> also doesn\u2019t work. Here\u2019s the problem: the <code>colormap<\/code> is a property of the <em>figure<\/em>, not the data. (More precisely, it is not a property of the MATLAB axes.) When you change the <code>colormap<\/code>, you change the colors of <em>every<\/em> datapoint in the image.<\/p>\n<h1><strong>The fix<\/strong><\/h1>\n<p>MATLAB\u2019s <code>colormap<\/code> mechanism is just simple enough to be confusing. MATLAB stores colours as 1&#215;3 vectors, where each element in the vector is the proportion of red, green, or blue, respectively. [1 1 1] is white, [0 0 0] is black, and [1 0 0] is a frightfully iridescent red. A colormap is just a list of colors \u2013 64 will normally do \u2013 which change smoothly from from one colour to another. To have a look at the built-in MATLAB colormaps, see <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/colormap.html#buc3wsn-6\">here<\/a>.<\/p>\n<p><code>image<\/code> rounds every value in the matrix to the nearest whole number (call that number <code>i<\/code>)&nbsp;&nbsp;and plots that pixel with the color given by <code>colormap(i,:)<\/code>. Zero or below gets the first entry in the <code>colormap<\/code> and any index higher than the maximum is displayed with the last color in the <code>colormap<\/code>. So: if we construct a new <code>colormap<\/code>&nbsp;by concatenating two colormaps \u2013 the first running from rows 1 to 64 and the second running from 65 to 128 &#8211; if we scale our data so that the minimum is 65 and the maximum is 128, the data will never use the first set of colors. And, likewise, if we scale so that the lowest value is 1 and the highest is 64, we will use the first colormap. This seems like the sort of thing that we could manage automatically &#8211; and should, in fact. So I set myself to replace <code>image<\/code> and <code>imagesc<\/code>&nbsp;so that they would accept a <code>ColorMap<\/code>&nbsp;parameter.<\/p>\n<p>How would it work?<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&gt;&gt; colormap bone\r\n&gt;&gt; imagesc(dists&gt;8)\r\n&gt;&gt; hold on\r\n&gt;&gt; imagesc(mask,'ColorMap',[0.5 0 0.5],'AlphaData',0.5*(mask&gt;0))\r\n&gt;&gt; axis square<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/3_1hel_success.png?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-3637\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/3_1hel_success.png?resize=300%2C225&#038;ssl=1\" alt=\"\" width=\"300\" height=\"225\" srcset=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/3_1hel_success.png?resize=300%2C225&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2017\/07\/3_1hel_success.png?w=560&amp;ssl=1 560w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Beautiful!<\/p>\n<h1>Implementation notes<\/h1>\n<ul>\n<li><code>image<\/code> is implemented in the MATLAB Java source code, but <code>imagesc<\/code> is a wrapper to <code>image<\/code>, written directly in MATLAB code. Therefore, overloading <code>image<\/code> requires the new function to be placed in a special directory called <code>@double<\/code>, while <code>imagesc<\/code> can be placed anywhere (except it cannot be placed in&nbsp;<code>@double<\/code>). If you then want to call the original version of <code>image()<\/code>, you can use <code>builtin(\u2018image\u2019,arg1,arg2,\u2026)<\/code>, whereas if you want to call the original <code>imagesc<\/code>, it is a right pain. Instead, I used <code>type imagesc<\/code> to extract the source of <code>imagesc<\/code> and I modified that source directly &#8211; obviating any need to call the original <code>imagesc<\/code>. For reference, though, the most efficient way works out to be to find the function with <code>which('imagesc')<\/code>, <code>cd<\/code> into the containing directory, create a function handle to <code>imagesc<\/code>, and then <code>cd<\/code> out. As I said, it&#8217;s a mess.<\/li>\n<li>These edits break colorbars. I added a spacer entry in each colormap which stores the maximum and minimum \u2018real\u2019 values of the data \u2013 in case that is useful for when I get around to extending <code>colorbar<\/code>. colormap entries must be inside [0,1] so these data are stored in the first twelve decimal places of the colormap entries: a strange burlesque on floating points. It\u2019s a hack, but for my purposes it works.<\/li>\n<li>In addition to the standard colormaps, I often require a mask in a particular color. For this purpose it helps to have a <code>colormap<\/code> that smoothly varies from white to the color in question. It actually doesn&#8217;t matter if it varies from white or any other color &#8211; ultimately, I only use the full colour value, since I set the transparency of all other pixels to maximum &#8211; but either way, passing the colour on [0,1] scale or [0,255] scale sets a <code>colormap<\/code> which varies from white to that color.<\/li>\n<\/ul>\n<p><span style=\"font-size: 1rem\">The code is available on MATLAB File Exchange <\/span><a style=\"font-size: 1rem\" href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/63183-image-overlays\">at this link<\/a><span style=\"font-size: 1rem\">&nbsp;and is installable by copying <code>imagesc.m<\/code>,&nbsp;<code>bootleg_fp.m<\/code>, and the directory <code>@double<\/code> into your working directory.&nbsp;<em>The idea to concatenate colormaps is widely available online &#8211; for example,&nbsp;<a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/101346-how-do-i-use-multiple-colormaps-in-a-single-figure\">here<\/a>.<\/em><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>My overriding emotion, working in R, has been incomprehension: incomprehension at the gallery of ugly gnomes that populate the namespace and worried puzzlement over the strange incantations required to get them to dance in a statistically harmonious way. But all that aside, I resolved, joining the group, to put aside my misgivings and give the [&hellip;]<\/p>\n","protected":false},"author":46,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","wikipediapreview_detectlinks":true,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"ngg_post_thumbnail":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[29],"tags":[],"ppma_author":[496],"class_list":["post-3634","post","type-post","status-publish","format-standard","hentry","category-code"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"authors":[{"term_id":496,"user_id":46,"is_guest":0,"slug":"mark","display_name":"Mark","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/4993b5241cf007fa9b439f82360e05c268e9d358a0153d0a78f40df9ace86f42?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/3634","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/users\/46"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/comments?post=3634"}],"version-history":[{"count":14,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/3634\/revisions"}],"predecessor-version":[{"id":3651,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/3634\/revisions\/3651"}],"wp:attachment":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/media?parent=3634"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/categories?post=3634"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/tags?post=3634"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=3634"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}