1 /* cmap.i
2  * Large enhancement to palette function, including dozens of additional
3  * pre-defined palette choices: ColorBrewer, Matplotlib (python), Gnuplot,
4  * and GMT palettes included.
5  */
6 /* Copyright (c) 2013, David H. Munro.
7  * All rights reserved.
8  * This file is part of yorick (http://yorick.sourceforge.net).
9  * Read the accompanying LICENSE file for details.
10  */
11 
12 func cmap(p, n, hist=, hsv=, hsl=, rev=, gamma=, lgamma=, usehue=, nmax=)
13 /* DOCUMENT cmap, p, n
14  *       or rgb = cmap(p, n)
15  *   returns a list of colors 0xrrggbb corresponding to the colormap
16  *   defined by parameters P.  The N argument is optional; it is the
17  *   the number of colors you want in the palette.  N defaults to the
18  *   number of colors in the palette for the current window (usually 200).
19  *   If you specify N<0, that many colors will be appended to the
20  *   existing palette, enabling you to stack multiple shortened palettes.
21  *   Called as a subroutine, actually sets the palette; called as a
22  *   function, returns [r,g,b] as Nx3 char array.
23  *
24  *   Recommendations: Read http://www.sandia.gov/~kmorel/documents/ColorMaps/
25  *   Most color maps here are rather poor choices.  Some reasonably good ones
26  *   are: "gray", "coolwarm", "bone", "copper", and most of the ColorBrewer
27  *   maps, such as "Blues" or "PuOr".  The function cmap_test makes a
28  *   picture you can use to test palettes.  The "dblue", "dred", and "dgreen"
29  *   maps are a matched set designed to be distinguishable by colorblind
30  *   people.  Use them if you need multiple maps in one picture.
31  *
32  *   Keywords:
33  *     hist=1  if P is a simple list of colors, creates a stepped
34  *             palette instead of interpolating between colors
35  *     hist=2  like hist=1, but the first and last colors get only a
36  *             single map index instead of a full width step
37  *     rev=1   reverses order of the colors (also "_r" when P is name)
38  *     hsv=1   interpret P values as hue, saturation, value, not rgb
39  *     hsl=1   interpret P values as hue, saturation, lightness, not rgb
40  *     gamma=  adjust the value (after transforming to HSV) by V^gamma
41  *             gamma=1 does nothing, gamma>1 darkens the colors, and
42  *             gamma<1 brightens the colors
43  *     lgamma= adjust the lightness (after transforming to HSL) by L^gamma
44  *             gamma=1 does nothing, gamma>1 darkens the colors, and
45  *             gamma<1 lightens the colors
46  *     usehue=1  if P is a simple list of colors, interpolates in hsv
47  *             instead of rgb, sometimes a nicer option (try with "accent")
48  *
49  *   Specifiy the rev=, gamma=, or lgamma= keywords with no other parameters
50  *   to adjust the existing palette.  In the case of gamma corrections,
51  *   cmap remembers the initial rgb values, so that you can accurately
52  *   apply multiple gamma corrections interactively.  The total gamma is
53  *   kept in the external variable _cm_gamma (the product of all the
54  *   applied gammas).  Hence, a sequence of cmap,gamma=.8 commands (say)
55  *   can be used to brighten the colors preogressively, and a sequence of
56  *   cmap,gamma=1.25 commands will darken it.
57  *
58  *   P can be:
59  *   name
60  *     a scalar string naming a named palette
61  *     append "_r" to name to reverse it, "_N" to name, where N is a
62  *     number, to select a map of that name with the specified number
63  *     of colors and select hist=N
64  *   [rgb1, rgb2, ...]
65  *     a list of equally spaced colors as 0xrrggbb; all three components
66  *     will be linearly interpolated between these given colors
67  *   [[x1,rgb1], [x2,rgb2], ..., [xN,rgbN]]
68  *     a list of unequally spaced colors as 0xrrggbb; all three components
69  *     will be linearly interpolated between these given colors,  The
70  *     x values are linearly scaled so that x1 is mapped to the first
71  *     returned color and xN is mapped to the last returned color.
72  *   [[r1,g1,b1], [r2,g2,b2], ...]
73  *     equally spaced colors as rgb triples, range 0.0 to 1.0 if real,
74  *     0 to 255 if integers
75  *   [[x1,r1,g1,b1], [x2,r2,g2,b2], ...]
76  *     unequally spaced colors as rgb triples, range 0.0 to 1.0 if real,
77  *     0 to 255 if integers
78  *   [&[[xr1,r1], [xr2,r2], ...], &[[xg1,g1], [xg2,g2], ...],
79  *    &[[xb1,b1], [xb2,b2], ...]]
80  *     a list of unequally spaced color components rN, gN, bN, which are
81  *     in the range from 0.0 to 1.0 inclusive (mapped to 0 and 255 as char
82  *     color component values for the returned palette).  Again, the
83  *     xrN, xgN, and xbN values are linearly scaled so that the first color
84  *     in the returned list gets the first value in the list and the last
85  *     color gets the last value.  Matplotlib calls this a "linearly
86  *     segmented color map".
87  *   [[rindex, gindex, bindex]]
88  *     gnuplot function indices for each component, 0 to 36 inclusive
89  *     trailing 1-length dimension distinguishes from [rgb1, rgb2, ...].
90  *   [[[p1, p2, p3, p4]]]
91  *     cmap_nonlin function parameterizing a few power laws and trig
92  *     functions:
93  *       p1*sin((p2*x+p3)*pi) + p4       but
94  *       abs(p1*sin((p2*x+p3)*pi) + p4)  if p1<0 and p2<0
95  *       p1*x^p3 + p4                    if p2==0
96  *   [r, g, b]
97  *     sets palette directly, ignoring n parameter unless hist=1, but
98  *     accepting hsv=, hsl=, and rev= keywords.  (r, g, b must have more
99  *     than 4 colors, but no more than 240.)
100  *   save(p=params,hist=hist,...)
101  *     an object containing cmap parameters and keywords permits any
102  *     input to cmap (except n) to be return value of another function
103  *
104  *  Available named color maps are the yorick palette names (less ".gp"),
105  *  the ColorBrewer color maps (help, cb_choices), Matplotlib (python)
106  *  color maps, and GMT (Generic Mapping Tools) color maps.  Some of the
107  *  names conflict; you can use the functions gistct, mplct, and gmtct
108  *  to break any conflicts (the ColorBrewer names are all unique).  Also
109  *  featured are several of the diverging color maps devised by Kenneth
110  *  Moreland.  See help,mshct for more on those.  Finally, a sequential
111  *  map design tool I invented, seqct, is available.
112  *
113  *  The Gnuplot and IDL programs use a scheme of indexed palettes; the
114  *  functions gplct and idlct allow you to set those palettes.  Some of
115  *  the Gnuplot palettes are named Matplotlib palettes, including all
116  *  the ones mentioned in the Gnuplot user manual.  The cubehelix function
117  *  lets you set palettes by parameters; you can get the default parameters
118  *  with cmap, "cubehelix".
119  *
120  * SEE ALSO: mshct, seqct, gplct, mplct, gmtct, gistct, idlct, cubehelix,
121  *           cb_choices, cmap_rd, cmap_test
122  */
123 {
124   if (!is_void(lgamma)) { gamma = lgamma; lgamma = 1; }
125   if (is_void(p)) {
126     local r, g, b;
127     palette, query=1, r, g, b;
128     if (!numberof(r)) return [];
129     p = transpose([r, g, b]);
130     if (!rev && !gamma && !n) return p;
131     if (is_void(n)) n = numberof(r);
132   }
133   if (is_obj(p)) {
134     if (is_void(hist)) hist = p.hist;
135     if (is_void(usehue)) usehue = p.usehue;
136     if (is_void(rev)) rev = 0;
137     rev = (rev!=0) ^ (p.rev!=0);
138     hsv = p.hsv;
139     hsl = p.hsl;
140     p = p.p;
141   }
142   if (!is_void(n) && (n<2 || n>240))
143     error, "illegal number of colors for palette, must be between 2 and 240";
144   n0 = n;
145   if (structof(p) == string) {  /* name */
146     name = p = cmap_name(p, n, rev);
147     if (is_func(cmap_user_map)) p = cmap_user_map(name, n);
148     else p = [];
149     if (!is_void(cmap_alias)) {
150       list = where(name == cmap_alias(1,));
151       if (numberof(list)) name = cmap_alias(2,list(1));
152     }
153     if (is_void(p) && name=="cubehelix") {
154       rgb = cubehelix(n);
155       if (rev) rgb = rgb(::-1,);
156       if (am_subroutine()) palette, rgb(,1), rgb(,2), rgb(,3);
157       return rgb;
158     }
159     if (is_void(p)) {
160       local type;
161       p = cb_map(name, ((n && n<13)?n:[]), type);
162       if (!is_void(p)) {
163         if ((n != n0) && is_void(hist)) hist = 1;
164         n = n0;
165         if (is_void(hist) && type==3) hist = 1;
166       }
167     }
168     if (is_void(p)) {
169       i = mshct(name, , n0);
170       if (numberof(i)) p = transpose(i);
171     }
172     if (is_void(p)) {
173       i = seqct(name, n0);
174       if (numberof(i)) p = transpose(i);
175     }
176     if (is_void(p)) {
177       i = where(mpl_names == name);
178       if (numberof(i)) p = *mpl_maps(i(1));
179     }
180     if (is_void(p)) {
181       i = where(gmt_names == name);
182       if (numberof(i)) {
183         p = *gmt_maps(i(1));
184         flags = gmt_flags(i(1));
185         if (flags == 1) hist = 1;
186         else if (flags == 2) hsv = 1;
187       }
188     }
189     if (is_void(p)) {
190       i = where(gist_names == name);
191       if (numberof(i)) {
192         p = *gist_maps(i(1));
193         if (name == "earth") hsv = 1;
194       }
195     }
196     if (is_void(p)) error, "unrecognized palette name "+name;
197   }
198   if (is_void(n)) {
199     n = cmap_ncolors();  /* avoids calling it twice */
200   } else if (n < 0) {
201     palette, query=1, r, g, b;
202     rgb0 = [r, g, b];   /* for append mode */
203     n = -n;
204   }
205   d = dimsof(p);
206   if (structof(p) == pointer) {     /* [&[[xr1,r1], [xr2,r2], ...], ...] */
207     r = *p(1);
208     g = *p(2);
209     b = *p(3);
210     scale = cmap_get_scale(r, g, b);
211   } else if (d(1) == 2) {
212     if (d(3) == 1) {         /* [[rindex, gindex, bindex]] */
213       rgb = gnu_map(p(1), p(2), p(3), n);
214       r = g = b = span(0.,1.,numberof(rgb)/3)(-:1:2,);
215       r(2,) = rgb(,1);
216       g(2,) = rgb(,2);
217       b(2,) = rgb(,3);
218       if (hsv || hsl) r *= 360.;
219       scale = 255.;
220     } else if (d(2) == 2) {  /* [[x1,rgb1], [x2,rgb2], ... */
221       r = g = b = p;
222       p = p(2,);
223       r(2,) = char(p >> 16);
224       g(2,) = char(p >> 8);
225       b(2,) = char(p);
226       scale = 1.;
227     } else if (d(2) == 3) {  /* [[r1,g1,b1], [r2,g2,b2], ... */
228       r = g = b = structof(p+0)(indgen(numberof(p)/3))(-:1:2,);
229       r(2,) = p(1,);
230       g(2,) = p(2,);
231       b(2,) = p(3,);
232       scale = cmap_get_scale(r, g, b);
233       histok = 1;
234     } else if (d(2) == 4) {  /* [[x1,r1,g1,b1], [x2,r2,g2,b2], ... */
235       r = g = b = p(1,-:1:2,);
236       r(2,) = p(2,);
237       g(2,) = p(3,);
238       b(2,) = p(4,);
239       scale = cmap_get_scale(r, g, b);
240     } else if (d(3) == 3) {  /* [r, g, b] */
241       if (rev) p = p(::-1,);
242       if (hsv) p = hsv2rgb(p);
243       else if (hsl) p = hsl2rgb(p);
244       if (structof(p+0) != long) p = long(255*p+0.5);
245       if (hist) {
246         x = span(0., 1., n);
247         x = digitize(x, span(0., 1., numberof(p)/3+1)(2:-1));
248         p = p(x,);
249       }
250       if (am_subroutine()) palette, char(p(,1)), char(p(,2)), char(p(,3));
251       return p;
252     } else {
253       error, "unrecognized color map parameterization";
254     }
255   } else if (d(1)==3 && d(2)==4 && d(3)==3 && d(4)==1) {
256     x = span(0., 1., n);
257     r = g = b = x(-:1:2,);
258     r(2,) = cmap_nonlin(p(,1,1), x);
259     g(2,) = cmap_nonlin(p(,2,1), x);
260     b(2,) = cmap_nonlin(p(,3,1), x);
261     scale = 255.;
262   } else if (structof(p+0) == long) {  /* [rgb1, rgb2, ... */
263     r = g = b = indgen(numberof(p))(-:1:2,);
264     r(2,) = (p >> 16) & 0xff;
265     g(2,) = (p >> 8) & 0xff;
266     b(2,) = p & 0xff;
267     scale = 1.;
268     histok = 1;
269   } else {
270     error, "unrecognized color map parameterization";
271   }
272   if (nmax) {
273     if (am_subroutine()) error, "too many colors to set";
274     n = 256;
275   }
276   x = span(0., 1., n);
277   if (rev) x = 1. - x;
278   if (hist) {
279     if (!histok) error, "need simple list of colors for hist=1";
280     if (hist != 2) x0 = span(0., 1., numberof(r)/2+1)(2:-1);
281     else x0 = span(1.e-6, 1.-1.e-6, numberof(r)/2-1);
282     x = digitize(x, x0);
283     r = r(2,x);
284     g = g(2,x);
285     b = b(2,x);
286   } else {
287     cminterp = cmap_interp;
288     if (usehue) {
289       if (!histok) error, "need simple list of colors for usehue=1";
290       if ((!hsv) & (!hsl)) hsv = 1;
291       rgb = (hsv? rgb2hsv : rgb2hsl)(r(2,), g(2,), b(2,));
292       r = double(r);  g = double(g);  b = double(b);
293       r(2,) = rgb(,1);  g(2,) = rgb(,2);  b(2,) = rgb(,3);
294       scale = 255.;
295       cminterp = hue_interp;
296     }
297     r = cminterp(r, x);
298     g = cmap_interp(g, x);
299     b = cmap_interp(b, x);
300   }
301   if (hsv || hsl) {
302     if (scale != 255.) error, "expecting real values for hsv or hsl";
303     rgb = (hsv? hsv2rgb : hsl2rgb)(r, g, b);
304   } else {
305     rgb = char(scale*[r, g, b] + 0.5);
306   }
307   if (numberof(rgb0)) rgb = grow(rgb0, rgb);
308   /* remember initial rgb to permit accurate multiple gamma corrections */
309   if (numberof(rgb)!=numberof(_cm_rgb) || nallof(rgb==_cm_rgb)) {
310     extern _cm_gamma, _cm_rgb0;
311     _cm_gamma = _cm_lgamma = _cm_rgb0 = _cm_rgb = [];
312   }
313   if (gamma && gamma!=1.) {
314     cmg = (lgamma? _cm_lgamma : _cm_gamma);
315     if (cmg) {
316       rgb = _cm_rgb0;
317       gamma *= cmg;
318     }
319     _cm_rgb0 = rgb;
320     if (lgamma) {
321       _cm_lgamma = gamma;
322       _cm_gamma = [];
323     } else {
324       _cm_gamma = gamma;
325       _cm_lgamma = [];
326     }
327     rgb = (lgamma? rgb2hsl : rgb2hsv)(rgb);
328     rgb(,3) = rgb(,3)^gamma;
329     rgb = _cm_rgb = (lgamma? hsl2rgb : hsv2rgb)(rgb);
330   }
331   if (!am_subroutine()) return rgb;
332   palette, rgb(,1), rgb(,2), rgb(,3);
333 }
334 
335 cmap_alias = [["france", "polar"]];
336 
337 func cmap_name(name, &n, &rev)
338 {
339   if (strpart(name,-1:0) == "_r") {
340     rev = !rev;
341     name = strpart(name, 1:-2);
342   }
343   i = strgrep("(.+)_([0-9]+)", name, sub=[1,2]);
344   if (i(4) > i(3)) {
345     n = long(tonum(strpart(name, i(3:4))));
346     if (n<2 || n>240)
347       error, "illegal number of colors for palette, must be between 2 and 240";
348     name = strpart(name, i(1:2));
349   }
350   return name;
351 }
352 
cmap_get_scale(r,g,b)353 func cmap_get_scale(r, g, b)
354 {
355   if (structof(r(1)+g(1)+b(1)+0)==long && max(r(2,max),g(2,max),b(2,max))>1)
356     return 1.;
357   else
358     return 255.;
359 }
360 
cmap_ncolors(void)361 func cmap_ncolors(void)
362 {
363   local r, g, b;
364   palette, query=1, r, g, b;
365   return (numberof(r) < 2)? 200 : numberof(r);
366 }
367 
cmap_clip(x)368 func cmap_clip(x)
369 {
370   return min(max(x, 0.), 1.);
371 }
372 
cmap_nonlin(p,x)373 func cmap_nonlin(p, x)
374 {
375   if (!p(1)) return (2.*x-1.)^2;   /* gnuplot function 12 */
376   if (!p(2)) x = p(1)*x^p(3) + p(4);
377   else x = p(1)*sin((p(2)*x + p(3)) * pi) + p(4);
378   if (p(1)<0. && p(2)<0.) x = abs(x);
379   return cmap_clip(x);
380 }
381 
cmap_interp(p,x)382 func cmap_interp(p, x)
383 {
384   xp = p(1,);
385   xp = (xp - xp(1)) / double(xp(0) - xp(1));
386   list = where(!xp(dif));
387   if (numberof(list)) { /* arrange for discontinuous jump */
388     xp(list+1) += 1.e-6;
389     if (xp(0) > 1.) {
390       xp(-1) -= 1.e-6;
391       xp(0) = 1.;
392     }
393   }
394   return interp(p(2,), xp, x);
395 }
396 
hue_interp(p,x)397 func hue_interp(p, x)
398 {
399   p = p;
400   h = p(2,) / 360.;
401   h -= floor(h);
402   dh = h(dif);
403   list = where(abs(dh) > 0.5);
404   if (numberof(list)) dh(list) -= sign(dh(list));
405   h = h(1) + dh(cum);
406   p(2,) = 360. * h;
407   return cmap_interp(p, x);
408 }
409 
410 func cmap_test
411 /* DOCUMENT cmap_test
412  *   Create a picture to help test color maps for artifacts and common
413  *   misfeatures.  After calling this, call cmap or one of the *ct
414  *   functions to change the color map.
415  * SEE ALSO: cmap, mshct, seqct, mplct, gplct, gmtct, idlct, cb_choices
416  */
417 {
418   x=span(0,1,400)(,-:1:400);  y=transpose(x);
419   fma;  limits;
420   pli, (1.02-y)*sin(8*pi*x);
421 }
422 
gistct(name)423 func gistct(name)
424 /* DOCUMENT cm = gistct(name)
425  *       or gistct, name
426  *   return color map (ct = "color table") specification for yorick
427  *   map NAME (where NAME.gp is the name of the palette file).
428  *   You may append "_r" to the name to reverse the colors.
429  *   Called as a subroutine, sets the current palette.
430  * SEE ALSO: cmap, mplct, gplct, gmtct, idlct
431  */
432 {
433   local n, rev;
434   name = cmap_name(name, n, rev);
435   i = where(name == gist_names);
436   if (!numberof(i)) error, name+" is not a gist color map";
437   p = *gist_maps(i(1));
438   if (name == "earth") hsv = 1;
439   if (!am_subroutine())
440     return (hsv || rev)? save(p=p, hsv=hsv, rev=rev) : p;
441   cmap, p, rev=rev, hsv=hsv;
442 }
443 
444 /* these are good approximations to the gist palettes of the same names */
445 gist_names = ["earth", "heat", "rainbow", "gray", "yarg", "stern", "ncar"];
446 
447 /* heat, rainbow, stern, and ncar parameterizations by
448  *   Reinier Heeres for matplotlib
449  * earth is hsv
450  */
451 gist_maps = [&[[1,0,0,0],[1,240,1,.135],[7,240,1,.455],[57,180,.629,.5],
452                [109,93.9,.512,.65],[157,40.67,.472,.753],[200,0,0,1]],
453              &[&[[0,0], [7,1], [10,1]], &[[0,0], [19,0], [40,1]],
454                &[[0,0], [3,0], [4,1]]],
455              &[[1,0xff0029],[8,0xff0000],[52,0xffff00],[97,0x00ff00],
456                [141,0x00ffff],[185,0x0000ff],[229,0xff00ff],[240,0xff00bf]],
457              &[0x000000,0xffffff], &[0xffffff,0x000000],
458              &[&[[0,0], [0.0547,1], [0.25,.027], [0.25,.25], [1,1]],
459                &[[0,0], [1,1]], &[[0,0], [.5,1], [0.735,0], [1,1]]],
460              &[&[[0,0],[0.3098,0],[0.3725,0.3993],[0.4235,0.5003],[0.5333,1],
461                  [0.7922,1],[0.8471,0.6218],[0.8980,0.9235],[1,0.9961]],
462                &[[0,0],[0.0510,0.3722],[0.1059,0],[0.1569,0.7202],
463                  [0.1608,0.7537],[0.1647,0.7752],[0.2157,1],[0.2588,0.9804],
464                  [0.2706,0.9804],[0.3176,1],[0.3686,0.8081],[0.4275,1],
465                  [0.5216,1],[0.6314,0.7292],[0.6863,0.2796],[0.7451,0],
466                  [0.7922,0],[0.8431,0.1753],[0.8980,0.5],[1,0.9725]],
467                &[[0.0,0.5020],[0.0510,0.0222],[0.1098,1],[0.2039,1],
468                  [0.2627,0.6145],[0.3216,0],[0.4157,0],[0.4745,0.2342],
469                  [0.5333,0],[0.5804,0],[0.6314,0.0549],[0.6902,0],[0.7373,0],
470                  [0.7922,0.9738],[0.8000,1],[0.8431,1],[0.8980,0.9341],
471                  [1,0.9961]]]];
472 
473 func cmap_rd(f, &hsv)
474 /* DOCUMENT rgb = cmap_rd(filename, hsv)
475  *       or cmap_rd, filename
476  *  Read a color map from file FILENAME.  Called as a subroutine, passes
477  *  the map to cmap to install it as the current palette.  Accepts yorick
478  *  (gist) .gp format or GMT .cpt format.  The HSV argument is an output,
479  *  non-nil if and only if this is to be interpreted in HSV color space.
480  * SEE ALSO: cmap
481  */
482 {
483   hsv = [];
484   lines = text_lines(f);
485   n = strgrep("^[ \t]*ncolors[ \t]*=[ \t]*([0-9]+)", lines, sub=1);
486   list = where(n(1,) < n(2,));
487   if (numberof(list)) {  /* this is .gp format */
488     nc = 0;
489     sread, strpart(lines(list(1)), n(,list(1))), nc;
490     lines = strpart(lines, strgrep("^[ \t]*([0-9]+[ \t]*[0-9]+[ \t]*[0-9]+)",
491                                    lines, sub=1));
492     lines = lines(where(lines));
493     if (numberof(lines) != nc)
494       error, "ncolors does not match rgb list in "+f;
495     rgb = array(char, 3, nc);
496     if (sread(lines, rgb) != 3*nc)
497       error, "problem reading .gp file "+f;
498   } else {
499     lines = strtrim(lines);
500     n = strgrep("^#[ \t]*COLOR_MODEL[ \t]*=.*(RGBA?|HSV|CMYK)[ \t]*",
501                 lines, sub=1);
502     m = strpart(lines, n);
503     m = m(where(m))(1);
504     if (m == "HSV") hsv = 1;
505     else if (m == "CMYK") cmyk = 1;
506     else if (m == "RGBA") rgba = 1;
507     else if (m == "RGB") rgb = 1;
508     else if (m) error, "unrecognized COLOR_MODEL in "+f;
509     lines = strpart(lines, strgrep("^[-+. \t0-9]+", lines));
510     lines = lines(where(lines));
511     rgb = array(0., 4+(cmyk||rgba), 2, numberof(lines));
512     if (sread(lines, rgb) != numberof(rgb))
513       error, "problem reading color table in "+f;
514     if (cmyk) error, "no support for CMYK color table in "+f;
515     rgb = rgb(1:4,*);
516     if (!hsv) {
517       if (allof(rgb == long(rgb))) rgb = long(rgb);
518       else if (max(rgb(2:4,)) > 1.) rgb(2:4,) /= 255.;
519     }
520   }
521   if (!am_subroutine()) return rgb;
522   cmap, rgb, hsv=hsv;
523 }
524 
525 /* ------------------------------------------------------------------------ */
526 /* msh colormaps, http://www.sandia.gov/~kmorel/documents/ColorMaps/
527  * devised by Kenneth Moreland
528  * The coolwarm Matplotlib map below is apparently a botched version of these.
529  * Coolwarm, blutan, and redgrn appear in Moreland's paper.  The others are
530  * random fiddling with the mshct rgb1 and rgb2.
531  */
532 
533 msh_names = ["coolwarm", "blutan", "ornpur", "grnred",
534              "purple", "blue", "green", "red", "brown"];
535 msh_maps = [[[ 59, 76,192], [180,  4, 38]], [[ 55,133,232], [172,125, 24]],
536             [[179, 88,  6], [ 84, 39,136]], [[ 22,135, 51], [193, 54, 59]],
537             [[ 63,  0,125], [221,221,221]], [[  8, 48,107], [221,221,221]],
538             [[ 30, 90,  0], [221,221,221]], [[180,  0, 30], [221,221,221]],
539             [[103,  0, 13], [221,221,221]]];
540 
541 func mshct(rgb1, rgb2, n, wht=, msh=, cmax=)
542 /* DOCUMENT cm = mshct(name)
543  *       or cm = mshct(rgb1, rgb2)
544  *       or mshct, name
545  *       or mshct, rgb1, rgb2
546  *   return diverging color map going from RGB1 to RGB2 through white.  If
547  *   either color is too close to white, produces a sequential map between
548  *   the two.  If one of RGB1 or RGB2 is nil, it is taken to be white.
549  *   If the two colors are too close in hue, also just produces a
550  *   sequential map.  The algorithm is from Kenneth Moreland,
551  *   http://www.sandia.gov/~kmorel/documents/ColorMaps/ and references
552  *   therein.  A few reasonable RGB1 and RGB2 values have been given names.
553  *   The name "coolwarm" produces Moreland's recommended color table.
554  *   Called as a subroutine, sets the current palette.
555  * SEE ALSO: cmap, seqct, gmtct, gplct, gistct, idlct
556  */
557 {
558   if (structof(rgb1) == string) {
559     /* some predefined diverging and sequential maps */
560     list = where(rgb1 == msh_names);
561     if (!numberof(list)) {
562       if (!am_subroutine()) return [];
563       error, "unknown mshct name "+rgb1;
564     }
565     rgb1 = msh_maps(,1,list(1));
566     rgb2 = msh_maps(,2,list(1));
567     msh = [];
568   }
569 
570   /* pushing wht higher than about 93 gives white band */
571   if (is_void(wht)) wht = 88.;
572   if (msh) {
573     msh1 = rgb1;  msh2 = rgb2;
574   } else {
575     msh1 = rgb2msh(rgb1);
576     if (!is_void(rgb2)) msh2 = rgb2msh(rgb2);
577   }
578   if (is_void(msh2)) msh2 = [max(msh1(1), wht), 0., 0.];
579   else if (is_void(msh1)) msh1 = [max(msh2(1), wht), 0., 0.];
580   wht = max(msh1(1), msh2(1), wht);
581   if (is_void(n)) n = cmap_ncolors();
582   x = span(0., 1., abs(n));
583   if (n < 0) {
584     if (msh == 1) x = 2.*x(where(x < 0.5));
585     else x = 2.*x(where(x >= 0.5)) - 1.;
586   }
587   s1 = msh1(2);
588   s2 = msh2(2);
589   dh = abs(msh1(3) - msh2(3)) % (2.*pi);
590   dh = min(dh, 2.*pi-dh);
591   if (s1>0.5 && s2>0.05 && dh>pi/3.) {
592     /* if rgb1, rgb2 are saturated and distinct, put white at x=0.5
593      * (otherwise, this is just a fragment going from rgb1 to rgb2)
594      * neither recursion can take this branch
595      */
596     rgb1 = transpose(mshct(msh1, , -n, cmax=cmax, wht=wht, msh=1));
597     rgb2 = transpose(mshct(, msh2, -n, cmax=cmax, wht=wht, msh=2));
598     rgb = transpose(grow(rgb1, rgb2));
599   } else {
600     /* avoid perceptual kink near white */
601     if (s1<0.5 && s2>0.05) msh1(3) = _adjust_hue(msh2, msh1(1));
602     else if (s2<0.5 && s1>0.05) msh2(3) = _adjust_hue(msh1, msh2(1));
603     /* then just interpolate polar coordinates
604      * why isn't this broken for h1, h2 separated across 0,2*pi?
605      */
606     msh = x(..,-:1:3);
607     x = x(*);
608     msh(*,) = (1.-x)*msh1(-,) + x*msh2(-,);
609     rgb = msh2rgb(msh, cmax=cmax);
610   }
611   if (!am_subroutine()) return rgb;
612   cmap, rgb;
613 }
614 
rgb2msh(rgb,g,b)615 func rgb2msh(rgb, g, b)
616 {
617   msh = rgb2lab(rgb, g, b);
618   l = msh(..,1);  a = msh(..,2);  b = msh(..,3);  c = abs(b, a);
619   msh(..,3) = atan(b, a+!c);
620   msh(..,1) = a = abs(c, l);
621   msh(..,2) = atan(c, l+!a);
622   return msh;
623 }
624 
625 func msh2rgb(msh, cmax=)
626 {
627   s = msh(..,2);  h = msh(..,3);
628   lab = double(msh);
629   lab(..,1) = cos(s);
630   lab(..,2:3) = sin(s) * [cos(h), sin(h)];
631   return lab2rgb(msh(..,1)*lab, cmax=cmax);
632 }
633 
_adjust_hue(msh,mu)634 func _adjust_hue(msh, mu)
635 { /* only needs to work for scalar m,s,h and mu */
636   m = msh(1);  s = msh(2);  h = msh(3);
637   if (m >= mu) return h;
638   hspin = s * sqrt(mu*mu - m*m) / (m * sin(s));
639   return (h > -pi/3.)? h + hspin : h - hspin;  /* -pi/3 seems odd?? */
640 }
641 
642 /* ------------------------------------------------------------------------ */
643 /* Sequential colormaps built on similar principles to Moreland */
644 
645 /* named cm_seq map parameters are h (degrees), l1 (bright L), l2 (dark L)
646  * where the L values can be a negative integer to use -L as the index
647  * into seq_params of another named map for the L and saturation
648  *
649  * dblue, dred, dgreen are three matched maps carefully designed to
650  *   be distinguishable to dichromats (colorblind people)
651  */
652 seq_names = ["dblue", "dred", "dgreen"];
653 seq_params = [[228, -2, -3], [345, 90, -3], [65, -2, 20]];
654 
655 /* lRGB hues in degrees, r=0, g=120, b=240
656  * LMS color directions:
657  *   Vischeck L=351.23, M=156.73, S=253.69   (180+156.73 = 336.73)
658  *   Meyer    L=355.21, M=344.47, S=255.34   (344.47-180 = 164.47)
659  * Dichromat simulator primaries:
660  *                Vischeck         Meyer
661  *   protan    227.99  49.13   228.92  47.02
662  *   deuteran  227.99  49.13   221.03  34.76
663  *   tritan    202.14 352.67   184.16   0.36
664  */
665 
666 func seqct(h, n, l1, l2, cmax=)
667 /* DOCUMENT cm = seqct(name)
668  *       or cm = seqct(h, n, l1, l2)
669  *       or seqct, h
670  *   Return a sequential colormap based on hue H, running from lighter
671  *   shades to darker shades in equal steps of luminance.  A few good
672  *   choices of hue have names; you can also pass such a NAME.  The
673  *   remaining arguments are optional: N is the number of colors to
674  *   return, which defaults to the number in the currently installed
675  *   colormap (usually 200).  L1 is the luminance for the lightest (first)
676  *   shade, which defaults to 90, and L2 is the luminance of the darkest
677  *   (last) shade, which defaults to 20.  L1 or L2 may also be RGB triples,
678  *   which causes both the endpoint luminance and chroma to match that
679  *   given color.  The hue H may be specified as an RGB triple, or as an
680  *   angle in degrees in lRGB color space, with r=0, g=120, and b=240.
681  *   The returned map is based on Luv luminance and hue; all points will
682  *   have the same (u,v) hue, and therefore the same lRGB hue.  By default,
683  *   the color will be maximally saturated at the endpoints, but you can
684  *   desaturate it by specifying unsaturated RGB triples for L1 or L2.
685  *   Typically, you pick L1 or L2 to be the endpoint of another seqct
686  *   map you wish to match, or rgb_saturate on another hue.
687  *   The colormap follows a second degree Bezier curve in lRGB space,
688  *   with the control point between the endpoints located on the fully
689  *   saturated edge of the RGB color cube, at the point with the given hue,
690  *   guaranteeing the whole curve lies inside the cube.  The points are
691  *   evenly spaced in luminance along this curve.
692  *
693  *   The named seqct maps are "dblue", "dred", and "dgreen".  These maps
694  *   are matched to have equal luminance and comparable saturation, so that
695  *   you can use them for situations in which you use all three maps
696  *   in the same figure.  Furthermore, the three hues are carefully chosen
697  *   to be distinguishable by dichromats (colorblind people).
698  * SEE ALSO: cmap, mshct, gmtct, gplct, gistct, idlct
699  */
700 {
701   if (is_void(n)) n = cmap_ncolors();
702   if (structof(h) == string) {
703     list = where(h == seq_names);
704     if (!numberof(list)) {
705       if (!am_subroutine()) return [];
706       error, "unknown seqct name "+h;
707     }
708     h = seq_params(,list(1));
709     if (h(2) >= 0.) l1 = h(2);
710     else l1 = rgb_saturate(seq_params(1,-h(2)), seq_params(2,-h(2)), cmax=1);
711     if (h(3) >= 0.) l2 = h(3);
712     else l2 = rgb_saturate(seq_params(1,-h(3)), seq_params(3,-h(3)), cmax=1);
713     h = h(1);
714   }
715   rgb = _lrgbsat(cm_hue2lrgb(h))
716   lmid = _lrgb2luv(rgb)(1);
717   gmid = _luv2lrgb([lmid,0.,0.])(1);  /* lrgb gray of same luminance as rgb */
718 
719   s1 = _cm_get_sat(l1, 90.);
720   s2 = _cm_get_sat(l2, 20.);
721   if (l1<0 || l2>100 || abs(l1-l2)<20) error, "bad endpoint luminances";
722   /* select gray levels with equal luminance steps */
723   g = _luv2lrgb([span(l1, l2, n),0.,0.])(,1);
724   g1 = g(1);  g2 = g(0);
725   /* move endpoints to fully saturated colors of given hue */
726   rgb1 = (g1<=gmid)? rgb*g1/gmid : 1.-(1.-rgb)*(1.-g1)/(1.-gmid);
727   rgb2 = (g2<=gmid)? rgb*g2/gmid : 1.-(1.-rgb)*(1.-g2)/(1.-gmid);
728   /* desaturate endpoints if requested */
729   if (numberof(s2)) rgb2 = _cm_desat(rgb2, s2);
730   if (numberof(s1)) rgb1 = _cm_desat(rgb1, s1);
731   /* move midpoint to mean of endpoint luminances or lrgb grays
732    * get brighter colors with mean gray if gmid not between g1 and g2,
733    * otherwise with mean luminance
734    * -- this switch leads to slight discontinuity as function of hue
735    */
736   if ((g1-gmid)*(gmid-g2)<0.) gm = 0.5*(g1 + g2);
737   else gm = _luv2lrgb([0.5*(l1+l2),0.,0.])(1);
738   mask = double(gmid >= gm);
739   rgb = mask*gm/gmid*rgb + (1.-mask)*(1. - (1.-rgb)*(1.-gm)/(1.-gmid));
740   gmid = gm;
741 
742   /* [g,g,g] is gray value for points in colormap
743    * colormap is order 2 Bezier curve [rgb1,rgb,rgb2]
744    * first find s Bezier parameter which gives yl
745    */
746   s = (g - g1) / (g2 - g1);
747   sm = (gmid - g1) / (g2 - g1);
748   s /= sm + sqrt(sm*sm + (1.-sm-sm)*s);
749   s = s(-:1:3,);  t = 1. - s;
750   rgb = rgb1*t*t + rgb*2.*t*s + rgb2*s*s;
751   rgb = transpose(rgb_l2s(rgb, cmax=cmax));
752   if (!am_subroutine()) return rgb;
753   cmap, rgb;
754 }
755 
_lrgb2luv(rgb)756 func _lrgb2luv(rgb) { lrgb_skip=3; return rgb2luv(rgb); }
_luv2lrgb(luv)757 func _luv2lrgb(luv) { lrgb_skip=3; return luv2rgb(luv); }
_lrgbsat(rgb)758 func _lrgbsat(rgb) {
759   rgb -= rgb(min);
760   g = rgb(max);
761   return rgb / (g + !g); /* on maximal saturation edge of cube */
762 }
763 func _cm_get_sat(&l, l0) {
764   if (is_void(l)) l = l0;
765   if (numberof(l) == 3) { s = rgb_s2l(l); l = rgb2luv(l)(1); }
766   return s;
767 }
_cm_desat(rgb,s)768 func _cm_desat(rgb, s) {
769   luv = _lrgb2luv(rgb);  c0 = abs(luv(2), luv(3));
770   s = _lrgb2luv(s);      s = abs(s(2), s(3));
771   if (s > 1.01*c0) error, "L1 or L2 more saturated than max for this hue";
772   else if (s >= c0) return rgb;
773   return _luv2lrgb(luv * [c0,s,s]/c0);
774 }
775 
cm_hue2lrgb(h)776 func cm_hue2lrgb(h)
777 {
778   if (numberof(h) == 3) {
779     return rgb_s2l(h);
780   } else {
781     h *= pi/180.;  /* h is lRGB hue */
782     return [2.,-1.,-1.]/sqrt(6.)*cos(h) + [0.,1.,-1.]/sqrt(2.)*sin(h);
783   }
784 }
785 
786 func rgb_saturate(rgb, l, &uvc, cmax=)
787 /* DOCUMENT rgbsat = rgb_saturate(rgb, l, uv)
788  *          rgbsat = rgb_saturate(hue, l, uv)
789  *   Return [r,g,b] with same Luv hue as RGB, saturated at luminosity L.
790  *   Optionally return the uv chroma, sqrt(u^2+v^2) for this color.
791  *   In the second form, HUE is the lRGB hue in degrees, lRGB=rgb_s2l(rgb),
792  *   the angle in the lRGB color cube of the plane determined by lRGB
793  *   and the gray diagonal of the cube.
794  *   With the cmax= keyword, rgbsat is normalized to cmax.
795  * SEE ALSO: seqct
796  */
797 {
798   gl = _luv2lrgb([l,0.,0.])(1);      /* lrgb gray of luminance l */
799   rgb = _lrgbsat(cm_hue2lrgb(rgb));  /* hue of input rgb on edge of cube */
800   g = _luv2lrgb([_lrgb2luv(rgb)(1),0.,0.])(1);
801   mask = double(gl <= g);  /* luminance l below rgb */
802   rgb = mask*gl/g*rgb + (1.-mask)*(1. - (1.-rgb)*(1.-gl)/(1.-g));
803   luv = _lrgb2luv(rgb);
804   uvc = abs(luv(2), luv(3));
805   return rgb_l2s(rgb, cmax=cmax);
806 }
807 
808 /* ------------------------------------------------------------------------ */
809 /* matplotlib colormaps, plus four additional names for gnuplot maps */
810 
mplct(name)811 func mplct(name)
812 /* DOCUMENT cm = mplct(name)
813  *       or mplct, name
814  *   return color map (ct = "color table") specification for Matplotlib
815  *   map NAME.  You may append "_r" to the name to reverse the colors.
816  *   Called as a subroutine, sets the current palette.
817  * SEE ALSO: cmap, mshct, seqct, gmtct, gplct, gistct, idlct
818  */
819 {
820   local n, rev;
821   name = cmap_name(name, n, rev);
822   i = where(name == mpl_names);
823   if (!numberof(i)) error, name+" is not a known Matplotlib color map";
824   p = *mpl_maps(i(1));
825   if (!am_subroutine())
826     return p;
827   cmap, p;
828 }
829 
830 mpl_names = ["binary", "gray", "cool", "bwr", "brg",
831              "autumn", "spring", "summer", "winter",
832              "seismic", "spectral", "coolwarm", "pink", "terrain",
833              "hsv", "bone", "copper", "hot", "jet", "flag", "prism",
834              "gnuplot", "gnuplot2", "ocean", "rainbow", "afmhot",
835              "gnuplot3", "gnu_hot", "gnuplot4", "gnuplot5"];
836 /* gnuplot is traditional pm3d map, BkBlRdYl
837  * gnuplot2 is gray-printable, BkBuViYlWt
838  * following are all mentioned in gnuplot user manual,
839  * gnuplot3 and later not in matplotlib
840  */
841 
842 /* matplotlib color maps begin with equally spaced color lists */
843 mpl_maps = [&[0xffffff,0x000000], &[0x000000,0xffffff], &[0x00ffff,0xff00ff],
844             &[0x0000ff,0xffffff,0xff0000], &[0x0000ff, 0xff0000, 0x00ff00],
845             &[0xff0000, 0xffff00], &[0xff00ff, 0xffff00],
846             &[0x008066, 0xffff66], &[0x0000ff, 0x00ff80],
847             &[0x00004d, 0x0000ff, 0xffffff, 0xff0000, 0x800000],
848             &[0x000000,0x770088,0x880099,0x0000aa,0x0000dd,0x0077dd,0x0099dd,
849               0x00aaaa,0x00aa88,0x009900,0x00bb00,0x00dd00,0x00ff00,0xbbff00,
850               0xeeee00,0xffcc00,0xff9900,0xff0000,0xdd0000,0xcc0000,0xcccccc],
851             &[0x1d2660,0x212d66,0x26336b,0x2b3a70,0x304074,0x364778,0x3b4d7b,
852               0x40527d,0x46577e,0x4c5c7f,0x51607f,0x56647e,0x5c677c,0x616a7a,
853               0x656c76,0x6a6d72,0x6e6e6e,0x726c68,0x756962,0x78665c,0x7a6256,
854               0x7b5d50,0x7b5849,0x7b5243,0x7a4c3d,0x784637,0x753f31,0x72382b,
855               0x6e3026,0x6a2721,0x651e1c,0x5f1417,0x590113],
856             &[0x1e0000,0x321a1a,0x402525,0x4b2d2d,0x553434,0x5e3b3b,0x664040,
857               0x6e4545,0x754a4a,0x7b4f4f,0x825353,0x885757,0x8d5b5b,0x935f5f,
858               0x986262,0x9d6666,0xa26969,0xa76c6c,0xac6f6f,0xb07272,0xb57575,
859               0xb97878,0xbd7b7b,0xc27e7e,0xc38481,0xc58a83,0xc79086,0xc99588,
860               0xca9a8b,0xcc9f8d,0xcea490,0xcfa992,0xd1ae94,0xd3b297,0xd4b799,
861               0xd6bb9b,0xd8bf9d,0xd9c3a0,0xdbc7a2,0xdccba4,0xdecfa6,0xdfd3a8,
862               0xe1d7aa,0xe2daac,0xe4deae,0xe5e1b0,0xe7e5b2,0xe8e8b4,0xeaeab9,
863               0xebebbf,0xededc4,0xeeeec9,0xf0f0ce,0xf1f1d3,0xf3f3d8,0xf4f4dd,
864               0xf5f5e1,0xf7f7e6,0xf8f8ea,0xfafaee,0xfbfbf3,0xfcfcf7,0xfefefb,
865               0xffffff],
866             /* followed by piecewise linear unequally spaced color lists */
867             &[[0,0x333399], [3,0x0099ff], [5,0x00cc66], [10,0xffff99],
868               [15,0x805c54], [20,0xffffff]],
869             &[[0, 0xff0000], [10,0xffef00], [11,0xf7ff00], [21,0x08ff00],
870               [22,0x00ff10], [32,0x00ffff], [42,0x0010ff], [43,0x0800ff],
871               [53,0xf700ff], [54,0xff00ef], [63,0xff0018]],
872             /* followed by piecewise linear individual color components */
873             &[&[[0,0], [47,47./72], [63,1]],
874               &[[0,0], [23,23./72], [47,56./72], [63,1]],
875               &[[0,0], [23,32./72], [63,1]]],
876             &[&[[0,0], [17,1], [21,1]],
877               &[[0,0], [21,482./617]],
878               &[[0,0], [21,199./400]]],
879             &[&[[0,26./625], [23,1], [63,1]],
880               &[[0,0], [23,0], [47,1], [63,1]],
881               &[[0,0], [47,0], [63,1]]],
882             &[&[[0,0], [.35,0], [.66,1], [.89,1], [1,.5]],
883               &[[0,0], [.125,0], [.375,1], [.64,1], [.91,0], [1,0]],
884               &[[0,.5], [.11,1], [.34,1], [.65,0], [1,0]]],
885             /* followed by cmap_nonlin individual color components */
886             &[[[0.75, 31.5, 0.25, 0.5], [1, 31.5, 0, 0],
887               [0.75, 31.5, -0.25, 0.5]]],
888             &[[[0.75, 20.9, 0.25, 0.67], [0.75, 20.9, -0.25, 0.33],
889               [-1.1, 20.9, 0, 0]]],
890             /* followed by gnuplot color component enumerated functions */
891             &[[7, 5, 15]], &[[30, 31, 32]], &[[23, 28, 3]], &[[33, 13, 10]],
892             &[[34, 35, 36]], &[[3, 11, 6]], &[[21, 22, 23]], &[[21, 23, 3]],
893             &[[3, 23, 21]]];
894 
895 func cubehelix(n, gamma=, s=, r=, h=)
896 /* DOCUMENT cubehelix, n
897  *       or cubehelix(n)
898  *   Set cubehelix palette, designed by D.A. Green, adapted from matplotlib.
899  *   Optional argument N is number of colors in palette, defaults to 200.
900  *   If called as function, returns [r,g,b] without setting palette.
901  *   Optional keyword arguments:
902  *   Keyword     Description
903  *   gamma       gamma factor to emphasise either low intensity values
904  *               (gamma < 1), or high intensity values (gamma > 1);
905  *               defaults to 1.0.
906  *   s           the start color; defaults to 0.5 (i.e. purple).
907  *   r           the number of r,g,b rotations in color that are made
908  *               from the start to the end of the color scheme; defaults
909  *               to -1.5 (i.e. -> B -> G -> R -> B).
910  *   h           the hue parameter which controls how saturated the
911  *               colors are. If this parameter is zero then the color
912  *               scheme is purely a greyscale; defaults to 1.0.
913  */
914 {
915   if (is_void(n)) n = cmap_ncolors();
916   if (is_void(gamma)) gamma = 1.0;
917   if (is_void(s)) s = 0.5;
918   if (is_void(r)) r = -1.5;
919   if (is_void(h)) h = 1.0;
920   x = span(0., 1., (n?n:200));
921   rgb = [cubehelix_gcf(x, -0.14861, 1.78277),
922          cubehelix_gcf(x, -0.29227, -0.90649),
923          cubehelix_gcf(x, 1.97294, 0.0)];
924   rgb = char(255*rgb);
925   if (!am_subroutine()) return rgb;
926   cmap, rgb;
927 }
928 
cubehelix_gcf(x,p0,p1)929 func cubehelix_gcf(x, p0, p1)
930 {
931   xg = x^gamma;
932   a = h * xg * (1.-xg) / 2.;
933   phi = 2.*pi * (s/3. + r*x);
934   return xg + a * (p0*cos(phi) + p1*sin(phi));
935 }
936 
937 /* ------------------------------------------------------------------------ */
938 /* gnuplot colormaps specified by rgbformulae */
939 
gplct(r,g,b)940 func gplct(r, g, b)
941 /* DOCUMENT cm = gplct(r, g, b)
942  *       or gplct, r, g, b
943  *   return color map (ct = "color table") specification for gnuplot
944  *   function indices (R,G,B), suitable to pass to cmap.  This is
945  *   equivalent to:
946  *     cm = [[r, g, b]]
947  *   Each of R, G, B must be between 0 and 36 inclusive.  A negative
948  *   number reverses the sense of the function.
949  *   Called as a subroutine, sets the current palette.
950  * SEE ALSO: cmap, gmtct, mplct, gistct, idlct
951  */
952 {
953   rgb = [[r, g, b]];
954   if (max(abs(rgb)) > 36)
955     error, "known gnuplot colormap functions are 0 through 36";
956   if (!am_subroutine()) return rgb;
957   cmap, rgb;
958 }
959 
gnu_map(r,g,b,n)960 func gnu_map(r, g, b, n)
961 {
962   if (is_void(n)) n = cmap_ncolors();
963   x = span(0., 1., n);
964   return [gnu_func(r,x), gnu_func(g,x), gnu_func(b,x)];
965 }
966 
gnu_func(n,x)967 func gnu_func(n, x)
968 {
969   rev = (n < 0);
970   if (rev) n = -n;
971   if (n > 36) return [];
972   p = *_gnu_funcs(n+1);
973   if (rev) x = 1. - x;
974   return ((dimsof(p)(1) == 2)? cmap_interp : cmap_nonlin)(p, x);
975 }
976 
977 _gnu_funcs = [&[[0,0], [1,0]], &[[0,0.5], [1,0.5]], &[[0,1], [1,1]],
978               &[[0,0], [1,1]], &[1, 0, 2, 0], &[1, 0, 3, 0], &[1, 0, 4, 0],
979               &[1, 0, 0.5, 0], &[1, 0, 0.25, 0],
980               &[1, 0.5, 0, 0], &[1, 0.5, 0.5, 0],
981               &[[0,0.5], [1,0], [2,0.5]], &[0.],
982               &[1., 1, 0, 0], &[-1, -1, -0.5, 0],
983               &[1., 2, 0, 0], &[1, 2, 0.5, 0],
984               &[-1., -2, 0, 0], &[-1, -2, -0.5, 0],
985               &[-1., -4, 0, 0], &[-1, -4, -0.5, 0],
986               &[[0,0], [1,1], [3,1]], &[[0,0], [1,0], [2,1], [3,1]],
987               &[[0,0], [2,0], [3,1]], &[[0,1], [1,0], [2,1], [3,1]],
988               &[[0,1], [1,1], [2,0], [3,1]],
989               &[[0,0], [1,0], [3,1]], &[[0,0], [2,0], [3,0.5]],
990               &[[0,0.5], [1,0], [3,1]], &[[0,1], [2,0], [3,0.5]],
991               &[[0,0], [25,0], [57,1], [100,1]],
992               &[[0,0], [42,0], [92,1], [100,1]],
993               &[[0,0], [25,1], [42,1], [92,0], [100,1]],
994               &[[0,0.5], [1,0], [3,1], [4,1]], &[[0,0], [1,1], [2,1]],
995               &[[0,0], [1,0], [3,1], [4,1]], &[[0,0], [1,0], [2,1]]];
996 
997 /* ------------------------------------------------------------------------ */
998 /* The following colors and names are repackaged from GMT,
999  * Generic Mapping Tools, distributed under the following license:
1000  *
1001  * Copyright (c) 1991-2013, P. Wessel & W. H. F. Smith
1002  *
1003  * This program is free software; you can redistribute it and/or modify
1004  * it under the terms of the GNU General Public License as published by
1005  * the Free Software Foundation; version 2 or any later version.
1006  *
1007  * This program is distributed in the hope that it will be useful,
1008  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1010  * GNU General Public License for more details.
1011  *
1012  * Contact info: http://gmt.soest.hawaii.edu
1013  *
1014  * The palette files are in the share/cpt/ subdirectory of the
1015  * GMT source distribution.
1016  */
1017 
gmtct(name)1018 func gmtct(name)
1019 /* DOCUMENT cm = gmtct(name)
1020  *       or gmtct, name
1021  *   return color map (ct = "color table") specification for GMT
1022  *   map NAME.  You may append "_r" to the name to reverse the colors.
1023  *   Called as a subroutine, sets the current palette.
1024  *   Note that the cmap_rd function can read GMT color map files.
1025  * SEE ALSO: cmap, mplct, gplct, gistct, cmap_rd
1026  */
1027 {
1028   local n, rev;
1029   name = cmap_name(name, n, rev);
1030   i = where(name == gmt_names);
1031   if (!numberof(i)) error, name+" is not a known GMT color map";
1032   p = *gmt_maps(i(1));
1033   flags = gmt_flags(i(1));
1034   if (flags == 1) hist = 1;
1035   else if (flags == 2) hsv = 1;
1036   if (!am_subroutine())
1037     return (hist || hsv)? save(p=p, hsv=hsv, hist=hist) : p;
1038   cmap, p, hist=hist, hsv=hsv;
1039 }
1040 
1041 gmt_names = ["cool","copper","cyclic","drywet","gebco","globe","gray",
1042              "haxby","hot","jet","nighttime","no_green","ocean","paired",
1043              "panoply","polar","rainbow","red2green","relief","sealand",
1044              "seis","split","topo","wysiwyg"];
1045 
1046 /* flags is 1 for hist=1, 2 for hsv=1 */
1047 gmt_flags = [0,0,2,0,0,0,0,1,0,0,2,1,0,1,1,0,2,0,0,2,0,0,2,1];
1048 
1049 gmt_maps = [&[0x00ffff,0xff00ff], &[[0,0x000000],[51,0xff9f66],[64,0xffc880]],
1050             &[[0.,1,1],[360,1,1]],
1051             &[0x86612a,0xeec764,0xb4ee87,0x32eeeb,0x0c78ee,0x2601b7,0x083371],
1052             &[[0,0x00f0ff],[10,0x00f0ff],[10,0x23ffff],[20,0x23ffff],
1053               [20,0x5affff],[30,0x5affff],[30,0x8cffe6],[40,0x8cffe6],
1054               [40,0xa5ffd7],[50,0xa5ffd7],[50,0xc3ffd7],[60,0xc3ffd7],
1055               [60,0xd2ffd7],[65,0xd2ffd7],[65,0xe6fff0],[68,0xe6fff0],
1056               [68,0xebffff],[70,0xebffff]],
1057             &[[-100,0x9900ff],[-95,0x9900ff],[-90,0x9900ff],[-85,0x9900ff],
1058               [-85,0x8811ff],[-80,0x8811ff],[-80,0x7722ff],[-75,0x7722ff],
1059               [-75,0x6633ff],[-70,0x6633ff],[-70,0x5544ff],[-65,0x5544ff],
1060               [-65,0x4455ff],[-60,0x4455ff],[-60,0x3366ff],[-55,0x3366ff],
1061               [-55,0x2277ff],[-50,0x2277ff],[-50,0x1188ff],[-45,0x1188ff],
1062               [-45,0x0099ff],[-40,0x0099ff],[-40,0x1ba4ff],[-35,0x1ba4ff],
1063               [-35,0x36afff],[-30,0x36afff],[-30,0x51baff],[-25,0x51baff],
1064               [-25,0x6cc5ff],[-20,0x6cc5ff],[-20,0x86d0ff],[-15,0x86d0ff],
1065               [-15,0xa1dbff],[-10,0xa1dbff],[-10,0xbce6ff],[-5,0xbce6ff],
1066               [-5,0xd7f1ff],[-2,0xd7f1ff],[-2,0xf1fcff],[0,0xf1fcff],
1067               [0,0x336600],[1,0x33cc66],[1,0x33cc66],[2,0xbbe492],
1068               [2,0xbbe492],[5,0xffdcb9],[5,0xffdcb9],[10,0xf3ca89],
1069               [10,0xf3ca89],[15,0xe6b858],[15,0xe6b858],[20,0xd9a627],
1070               [20,0xd9a627],[25,0xa89a1f],[25,0xa89a1f],[30,0xa49019],
1071               [30,0xa49019],[35,0xa28613],[35,0xa28613],[40,0x9f7b0d],
1072               [40,0x9f7b0d],[45,0x9c7107],[45,0x9c7107],[50,0x996600],
1073               [50,0x996600],[55,0xa25959],[55,0xa25959],[60,0xb27676],
1074               [60,0xb27676],[65,0xb79393],[65,0xb79393],[70,0xc2b0b0],
1075               [70,0xc2b0b0],[75,0xcccccc],[75,0xcccccc],[80,0xe5e5e5],
1076               [80,0xe5e5e5],[85,0xf2f2f2],[85,0xf2f2f2],[90,0xffffff],
1077               [90,0xffffff],[95,0xffffff],[95,0xffffff],[100,0xffffff]],
1078             &[0x000000,0xffffff],
1079             &[0x0a0079,0x280096,0x1405af,0x000ac8,0x0019d4,0x0028e0,
1080               0x1a66f0,0x0d81f8,0x19afff,0x32beff,0x44caff,0x61e1f0,0x6aebe1,
1081               0x7cebc8,0x8aecae,0xacf5a8,0xcdffa2,0xdff58d,0xf0ec79,0xf7d768,
1082               0xffbd57,0xffa045,0xf4754b,0xee504e,0xff5a5a,0xff7c7c,0xff9e9e,
1083               0xf5b3ae,0xffc4c4,0xffd7d7,0xffebeb,0xffffff],
1084             &[[0,0x000000],[3,0xff0000],[6,0xffff00],[8,0xffffff]],
1085             &[[0,0x00007f],[1,0x0000ff],[3,0x00ffff],[5,0xffff7f],
1086               [7,0xff0000],[8,0x7f0000]],
1087             &[[0,260,1,0.1],[1,195,0.55,0.55],[1,65,0.55,0.55],[2,0,0.1,1]],
1088             &[0x2060ff,0x209fff,0x20bfff,0x00cfff,0x2affff,0x55ffff,0x7fffff,
1089               0xaaffff,0xffff54,0xfff000,0xffbf00,0xffa800,0xff8a00,0xff7000,
1090               0xff4d00,0xff0000],
1091             &[0x000000,0x000519,0x000a32,0x00507d,0x0096c8,0x56c5b8,0xacf5a8,
1092               0xd3fad3,0xfaffff],
1093             &[0xa6cee3,0x1f78b4,0xb2df8a,0x33a02c,0xfb9a99,0xe31a1c,0xfdbf6f,
1094               0xff7f00,0xcab2d6,0x6a3d9a,0xffff99,0xb15928],
1095             &[0x040ed8,0x2050ff,0x4196ff,0x6dc1ff,0x86d9ff,0x9ceeff,0xaff5ff,
1096               0xceffff,0xfffe47,0xffeb00,0xffc400,0xff9000,0xff4800,0xff0000,
1097               0xd50000,0x9e0000],
1098             &[0x0000ff,0xffffff,0xff0000], &[[300.,1,1],[0,1,1]],
1099             &[0xff0000,0xffffff,0x00ff00],
1100             &[[-80,0x000000],[-70,0x000519],[-60,0x000a32],[-50,0x00507d],
1101               [-40,0x0096c8],[-30,0x56c5b8],[-20,0xacf5a8],[-10,0xd3fad3],
1102               [0,0xfaffff],[0,0x467832],[5,0x786432],[10,0x927e3c],
1103               [20,0xc6b250],[30,0xfae664],[30,0xfae664],[40,0xfaea7e],
1104               [40,0xfaea7e],[50,0xfcee98],[50,0xfcee98],[60,0xfcf3b1],
1105               [60,0xfcf3b1],[70,0xfdf9d8],[70,0xfdf9d8],[80,0xffffff]],
1106             &[[0,255,0.6,1],[1,240,0.6,1],[2,225,0.6,1],[3,210,0.6,1],
1107               [4,195,0.6,1],[5,180,0.6,1],[6,165,0.6,1],[7,150,0.6,1],
1108               [8,135,0.6,1],[9,120,0.6,1],[10,105,0.6,1],[11,90,0.6,1],
1109               [12,75,0.6,1],[12,60,0.35,1],[13,40,0.35,1],[13,40,0.35,1],
1110               [14,20,0.35,1],[14,20,0.35,1],[15,0,0.35,1],[15,360,0.35,1],
1111               [16,345,0.3,1],[16,345,0.3,1],[17,330,0.25,1],[17,330,0.25,1],
1112               [18,315,0.2,1]],
1113             &[0xaa0000,0xff0000,0xff5500,0xffaa00,0xffff00,0xffff00,0x5aff1e,
1114               0x00f06e,0x0050ff,0x0000cd],
1115             &[0x8080ff,0x000080,0x000000,0x800000,0xff8080],
1116             &[[-70,290,0.45,0.85],[-65,265,0.45,0.85],[-65,265,0.4,0.9],
1117               [-60,240,0.4,0.9],[-55,220,0.4,0.9],[-50,199,0.4,0.9],
1118               [-45,175,0.4,0.95],[-40,150,0.45,0.95],[-35,125,0.45,0.95],
1119               [-30,99,0.45,0.95],[-25,75,0.45,0.95],[-20,50,0.45,0.95],
1120               [-15,25,0.45,0.95],[-5,10,0.35,0.85],[-5,0,0.25,0.85],
1121               [0,0,0.25,0.8],[0,195,0.35,0.7],[2,160,0.4,0.7],
1122               [2,160,0.4,0.7],[4,125,0.45,0.7],[4,125,0.45,0.7],
1123               [6,99,0.45,0.8],[6,99,0.45,0.8],[10,75,0.45,0.8],
1124               [10,75,0.45,0.8],[15,50,0.35,0.9],[15,50,0.35,0.9],
1125               [35,25,0.1,1],[35,25,0.05,1],[70,0,0,1]],
1126             &[0x400040,0x4000c0,0x0040ff,0x0080ff,0x00a0ff,0x40c0ff,0x40e0ff,
1127               0x40ffff,0x40ffc0,0x40ff40,0x80ff40,0xc0ff40,0xffff40,0xffe040,
1128               0xffa040,0xff6040,0xff2040,0xff60c0,0xffa0ff,0xffe0ff]];
1129 
1130 /* ------------------------------------------------------------------------ */
1131 /* The following colors and names are repackaged from a spreadsheet
1132  * obtained from http://colorbrewer.org bearing the following
1133  * open source license:
1134  *
1135  * Copyright (c) 2002 Cynthia Brewer, Mark Harrower,
1136  *                    and The Pennsylvania State University.
1137  *
1138  * Licensed under the Apache License, Version 2.0 (the "License"); you
1139  * may not use this file except in compliance with the License.  You may
1140  * obtain a copy of the License at
1141  *
1142  *        http://www.apache.org/licenses/LICENSE-2.0
1143  *
1144  * Unless required by applicable law or agreed to in writing, software
1145  * distributed under the License is distributed on an "AS IS" BASIS,
1146  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1147  * implied.  See the License for the specific language governing
1148  * permissions and limitations under the License.
1149  */
1150 
1151 /* Unlike the other color maps defined in this file, these sets of
1152  * colors are carefully selected individually.  They are intended to
1153  * be used to color maps with a small number of colors (12 or less).
1154  * Each name corresponds to a family of these sets with increasing
1155  * numbers of colors.
1156  *
1157  * By default, yorick palettes all have 200 colors, usually varying
1158  * smoothly, intended to represent continuous variables.  By default,
1159  * therefore, we interpret the ColorBrewer palette names as the
1160  * largest set of colors availble with that name, and regard these
1161  * as equally spaced, linearly interpolating the r, g, b components
1162  * to fill in the 200 (or other large number) of smoothly varying
1163  * colors.  This interpolation works very well for the sequential
1164  * and diverging ColorBrewer sets, but is a bit odd for the qualitative
1165  * sets, which are specifically chosen not to appear in any natural
1166  * sequence.
1167  *
1168  * You can specify a "histogram" colormap with cmap, which will
1169  * produce a palette having only the specific colors in the ColorBrewer
1170  * color sets.  To do that, append "_N" to the name, where N is the
1171  * number of distinct colors you want.  Thus, "Blues" will give the
1172  * smoothly interpolated table, while "Blues_7" gives a palette with
1173  * seven steps corresponding exactly to the 7 level ColorBrewer Blues.
1174  */
1175 
1176 cb_names = ["Accent","Blues","BrBG","BuGn","BuPu","Dark2","GnBu","Greens",
1177             "Greys","Oranges","OrRd","Paired","Pastel1","Pastel2","PiYG",
1178             "PRGn","PuBu","PuBuGn","PuOr","PuRd","Purples","RdBu","RdGy",
1179             "RdPu","Reds","RdYlBu","RdYlGn","Set1","Set2","Set3","Spectral",
1180             "YlGn","YlGnBu","YlOrBr","YlOrRd"];
1181 
1182 /* 1=sequential, 2=divergent, 3=qualitative */
1183 cb_types = [3,1,2,1,1,3,1,1,1,1,1,3,3,3,2,2,1,1,2,1,1,2,2,1,1,2,2,3,3,3,2,
1184             1,1,1,1];
1185 
1186 /* here are the 379 unique ColorBrewer colors as 0xrrggbb */
1187 cb_colors =
1188   [0x000000,0x003c30,0x00441b,0x004529,0x005824,0x005a32,0x006837,0x006d2c,
1189    0x008837,0x014636,0x016450,0x01665e,0x016c59,0x018571,0x023858,0x02818a,
1190    0x034e7b,0x045a8d,0x053061,0x0570b0,0x0571b0,0x081d58,0x08306b,0x084081,
1191    0x084594,0x08519c,0x08589e,0x0868ac,0x0c2c84,0x1a1a1a,0x1a9641,0x1a9850,
1192    0x1b7837,0x1b9e77,0x1c9099,0x1d91c0,0x1f78b4,0x2166ac,0x2171b5,0x225ea8,
1193    0x238443,0x238b45,0x252525,0x253494,0x276419,0x2b83ba,0x2b8cbe,0x2c7bb6,
1194    0x2c7fb8,0x2ca25f,0x2d004b,0x313695,0x3182bd,0x31a354,0x3288bd,0x33a02c,
1195    0x35978f,0x3690c0,0x377eb8,0x386cb0,0x3f007d,0x40004b,0x404040,0x41ab5d,
1196    0x41ae76,0x41b6c4,0x4292c6,0x4393c3,0x43a2ca,0x4575b4,0x49006a,0x4a1486,
1197    0x4d004b,0x4d4d4d,0x4d9221,0x4dac26,0x4daf4a,0x4eb3d3,0x525252,0x542788,
1198    0x54278f,0x543005,0x5aae61,0x5ab4ac,0x5e3c99,0x5e4fa2,0x636363,0x662506,
1199    0x666666,0x66a61e,0x66bd63,0x66c2a4,0x66c2a5,0x67000d,0x67001f,0x67a9cf,
1200    0x6a3d9a,0x6a51a3,0x6baed6,0x6e016b,0x737373,0x74a9cf,0x74add1,0x74c476,
1201    0x756bb1,0x7570b3,0x762a83,0x78c679,0x7a0177,0x7b3294,0x7bccc4,0x7f0000,
1202    0x7f2704,0x7f3b08,0x7fbc41,0x7fbf7b,0x7fc97f,0x7fcdbb,0x800026,0x8073ac,
1203    0x807dba,0x80b1d3,0x80cdc1,0x810f7c,0x878787,0x88419d,0x8856a7,0x8c2d04,
1204    0x8c510a,0x8c6bb1,0x8c96c6,0x8da0cb,0x8dd3c7,0x8e0152,0x91003f,0x91bfdb,
1205    0x91cf60,0x92c5de,0x969696,0x980043,0x984ea3,0x990000,0x99000d,0x993404,
1206    0x9970ab,0x998ec3,0x999999,0x99d594,0x99d8c9,0x9e0142,0x9e9ac8,0x9ebcda,
1207    0x9ecae1,0xa1d76a,0xa1d99b,0xa1dab4,0xa50026,0xa50f15,0xa63603,0xa65628,
1208    0xa6611a,0xa6761d,0xa6bddb,0xa6cee3,0xa6d854,0xa6d96a,0xa6dba0,0xa8ddb5,
1209    0xabd9e9,0xabdda4,0xaddd8e,0xae017e,0xaf8dc3,0xb10026,0xb15928,0xb2182b,
1210    0xb2abd2,0xb2df8a,0xb2e2e2,0xb30000,0xb35806,0xb3b3b3,0xb3cde3,0xb3de69,
1211    0xb3e2cd,0xb8e186,0xbababa,0xbae4b3,0xbae4bc,0xbc80bd,0xbcbddc,0xbd0026,
1212    0xbdbdbd,0xbdc9e1,0xbdd7e7,0xbeaed4,0xbebada,0xbf5b17,0xbf812d,0xbfd3e6,
1213    0xc2a5cf,0xc2e699,0xc51b7d,0xc51b8a,0xc6dbef,0xc7e9b4,0xc7e9c0,0xc7eae5,
1214    0xc994c7,0xca0020,0xcab2d6,0xcb181d,0xcbc9e2,0xcbd5e8,0xcc4c02,0xcccccc,
1215    0xccebc5,0xccece6,0xce1256,0xd01c8b,0xd0d1e6,0xd1e5f0,0xd4b9da,0xd53e4f,
1216    0xd6604d,0xd7191c,0xd7301f,0xd73027,0xd7b5d8,0xd8b365,0xd8daeb,0xd94701,
1217    0xd94801,0xd95f02,0xd95f0e,0xd9d9d9,0xd9ef8b,0xd9f0a3,0xd9f0d3,0xdadaeb,
1218    0xdd1c77,0xdd3497,0xde2d26,0xde77ae,0xdecbe4,0xdeebf7,0xdf65b0,0xdfc27d,
1219    0xe08214,0xe0e0e0,0xe0ecf4,0xe0f3db,0xe0f3f8,0xe31a1c,0xe34a33,0xe41a1c,
1220    0xe5c494,0xe5d8bd,0xe5f5e0,0xe5f5f9,0xe6550d,0xe66101,0xe6ab02,0xe6f598,
1221    0xe6f5c9,0xe6f5d0,0xe7298a,0xe78ac3,0xe7d4e8,0xe7e1ef,0xe9a3c9,0xec7014,
1222    0xece2f0,0xece7f2,0xedf8b1,0xedf8e9,0xedf8fb,0xef3b2c,0xef6548,0xef8a62,
1223    0xefedf5,0xeff3ff,0xf0027f,0xf03b20,0xf0f0f0,0xf0f9e8,0xf16913,0xf1a340,
1224    0xf1b6da,0xf1e2cc,0xf1eef6,0xf2f0f7,0xf2f2f2,0xf46d43,0xf4a582,0xf4cae4,
1225    0xf5f5f5,0xf6e8c3,0xf6eff7,0xf768a1,0xf781bf,0xf7f4f9,0xf7f7f7,0xf7fbff,
1226    0xf7fcb9,0xf7fcf0,0xf7fcf5,0xf7fcfd,0xfa9fb5,0xfb6a4a,0xfb8072,0xfb9a99,
1227    0xfbb4ae,0xfbb4b9,0xfc4e2a,0xfc8d59,0xfc8d62,0xfc9272,0xfcae91,0xfcbba1,
1228    0xfcc5c0,0xfccde5,0xfcfbfd,0xfd8d3c,0xfdae61,0xfdae6b,0xfdb462,0xfdb863,
1229    0xfdbb84,0xfdbe85,0xfdbf6f,0xfdc086,0xfdcc8a,0xfdcdac,0xfdd0a2,0xfdd49e,
1230    0xfddaec,0xfddbc7,0xfde0dd,0xfde0ef,0xfe9929,0xfeb24c,0xfec44f,0xfecc5c,
1231    0xfed976,0xfed98e,0xfed9a6,0xfee08b,0xfee090,0xfee0b6,0xfee0d2,0xfee391,
1232    0xfee5d9,0xfee6ce,0xfee8c8,0xfeebe2,0xfeedde,0xfef0d9,0xff7f00,0xffd92f,
1233    0xffed6f,0xffeda0,0xfff2ae,0xfff5eb,0xfff5f0,0xfff7bc,0xfff7ec,0xfff7f3,
1234    0xfff7fb,0xffff33,0xffff99,0xffffb2,0xffffb3,0xffffbf,0xffffcc,0xffffd4,
1235    0xffffd9,0xffffe5,0xffffff];
1236 
1237 /* indices into cb_colors for each color map */
1238 cb_maps =
1239   [&[&[117,196,332],&[117,196,332,371],&[117,196,332,371,60],
1240      &[117,196,332,371,60,283],&[117,196,332,371,60,283,198],
1241      &[117,196,332,371,60,283,198,89]],
1242    &[&[246,153,53],&[282,195,99,39],&[282,195,99,53,26],
1243      &[282,205,153,99,53,26],&[282,205,153,99,67,39,25],
1244      &[304,246,205,153,99,67,39,25],&[304,246,205,153,99,67,39,26,23]],
1245    &[&[230,297,84],&[161,248,123,14],&[161,248,297,123,14],
1246      &[129,230,298,208,84,12],&[129,230,298,297,208,84,12],
1247      &[129,199,248,298,208,123,57,12],&[129,199,248,298,297,208,123,57,12],
1248      &[82,129,199,248,298,208,123,57,12,2],
1249      &[82,129,199,248,298,297,208,123,57,12,2]],
1250    &[&[260,149,50],&[277,179,92,42],&[277,179,92,50,8],&[277,218,149,92,50,8],
1251     &[277,218,149,92,65,42,5],&[308,260,218,149,92,65,42,5],
1252     &[308,260,218,149,92,65,42,8,3]],
1253    &[&[251,152,127],&[277,183,131,126],&[277,183,131,127,124],
1254     &[277,200,152,131,127,124],&[277,200,152,131,130,126,100],
1255     &[308,251,200,152,131,130,126,100],&[308,251,200,152,131,130,126,124,73]],
1256    &[&[34,234,106],&[34,234,106,267],&[34,234,106,267,90],
1257     &[34,234,106,267,90,263],&[34,234,106,267,90,263,162],
1258     &[34,234,106,267,90,263,162,89]],
1259    &[&[252,168,69],&[286,189,111,47],&[286,189,111,69,28],
1260     &[286,217,168,111,69,28],&[286,217,168,111,78,47,27],
1261     &[306,252,217,168,111,78,47,27],&[306,252,217,168,111,78,47,28,24]],
1262    &[&[259,155,54],&[276,188,104,42],&[276,188,104,54,8],
1263     &[276,207,155,104,54,8],&[276,207,155,104,64,42,6],
1264     &[307,259,207,155,104,64,42,6],&[307,259,207,155,104,64,42,8,3]],
1265    &[&[285,193,87],&[303,216,139,79],&[303,216,139,87,43],
1266     &[303,236,193,139,87,43],&[303,236,193,139,101,79,43],
1267     &[379,285,236,193,139,101,79,43],&[379,285,236,193,139,101,79,43,1]],
1268    &[&[354,326,261],&[357,330,324,232],&[357,330,324,261,159],
1269     &[357,335,326,324,261,159],&[357,335,326,324,287,233,128],
1270     &[364,354,335,326,324,287,233,128],&[364,354,335,326,324,287,233,159,113]],
1271    &[&[355,329,255],&[358,333,316,227],&[358,333,316,255,180],
1272     &[358,336,329,316,255,180],&[358,336,329,316,279,227,142],
1273     &[367,355,336,329,316,279,227,142],&[367,355,336,329,316,279,227,180,112]],
1274    &[&[164,37,178],&[164,37,178,56],&[164,37,178,56,312],
1275     &[164,37,178,56,312,254],&[164,37,178,56,312,254,331],
1276     &[164,37,178,56,312,254,331,359],&[164,37,178,56,312,254,331,359,211],
1277     &[164,37,178,56,312,254,331,359,211,97],
1278     &[164,37,178,56,312,254,331,359,211,97,371],
1279     &[164,37,178,56,312,254,331,359,211,97,371,175]],
1280    &[&[313,183,217],&[313,183,217,245],&[313,183,217,245,347],
1281     &[313,183,217,245,347,375],&[313,183,217,245,347,375,258],
1282     &[313,183,217,245,347,375,258,337],&[313,183,217,245,347,375,258,337,293]],
1283    &[&[185,334,214],&[185,334,214,296],&[185,334,214,296,265],
1284     &[185,334,214,296,265,363],&[185,334,214,296,265,363,290],
1285     &[185,334,214,296,265,363,290,216]],
1286    &[&[271,303,154],&[220,289,186,76],&[220,289,303,186,76],
1287     &[203,271,340,266,154,75],&[203,271,340,303,266,154,75],
1288     &[203,244,289,340,266,186,115,75],&[203,244,289,340,303,266,186,115,75],
1289     &[134,203,244,289,340,266,186,115,75,45],
1290     &[134,203,244,289,340,303,266,186,115,75,45]],
1291    &[&[173,303,116],&[110,201,167,9],&[110,201,303,167,9],
1292     &[107,173,269,239,116,33],&[107,173,269,303,239,116,33],
1293     &[107,145,201,269,239,167,83,33],&[107,145,201,269,303,239,167,83,33],
1294     &[62,107,145,201,269,239,167,83,33,3],
1295     &[62,107,145,201,269,303,239,167,83,33,3]],
1296    &[&[274,163,47],&[291,194,102,20],&[291,194,102,47,18],
1297     &[291,221,163,102,47,18],&[291,221,163,102,58,20,17],
1298     &[369,274,221,163,102,58,20,17],&[369,274,221,163,102,58,20,18,15]],
1299    &[&[273,163,35],&[299,194,96,16],&[299,194,96,35,13],
1300     &[299,221,163,96,35,13],&[299,221,163,96,58,16,11],
1301     &[369,273,221,163,96,58,16,11],&[369,273,221,163,96,58,16,13,10]],
1302    &[&[288,303,146],&[262,328,177,85],&[262,328,303,177,85],
1303     &[181,288,350,231,146,80],&[181,288,350,303,231,146,80],
1304     &[181,249,328,350,231,177,120,80],&[181,249,328,350,303,231,177,120,80],
1305     &[114,181,249,328,350,231,177,120,80,51],
1306     &[114,181,249,328,350,303,231,177,120,80,51]],
1307    &[&[270,209,241],&[291,229,247,219],&[291,229,247,241,140],
1308     &[291,223,209,247,241,140],&[291,223,209,247,267,219,135],
1309     &[302,270,223,209,247,267,219,135],&[302,270,223,209,247,267,219,140,95]],
1310    &[&[281,191,105],&[292,213,151,98],&[292,213,151,105,81],
1311     &[292,240,191,151,105,81],&[292,240,191,151,121,98,72],
1312     &[323,281,240,191,151,121,98,72],&[323,281,240,191,151,121,98,81,61]],
1313    &[&[280,303,96],&[210,295,138,21],&[210,295,303,138,21],
1314     &[176,280,338,222,96,38],&[176,280,338,303,222,96,38],
1315     &[176,225,295,338,222,138,68,38],&[176,225,295,338,303,222,138,68,38],
1316     &[95,176,225,295,338,222,138,68,38,19],
1317     &[95,176,225,295,338,303,222,138,68,38,19]],
1318    &[&[280,379,147],&[210,295,187,63],&[210,295,379,187,63],
1319     &[176,280,338,250,147,74],&[176,280,338,379,250,147,74],
1320     &[176,225,295,338,250,187,125,74],&[176,225,295,338,379,250,187,125,74],
1321     &[95,176,225,295,338,250,187,125,74,30],
1322     &[95,176,225,295,338,379,250,187,125,74,30]],
1323    &[&[339,309,204],&[356,314,300,172],&[356,314,300,204,109],
1324     &[356,321,309,300,204,109],&[356,321,309,300,242,172,109],
1325     &[368,339,321,309,300,242,172,109],&[368,339,321,309,300,242,172,109,71]],
1326    &[&[351,318,243],&[353,319,310,212],&[353,319,310,243,158],
1327     &[353,320,318,310,243,158],&[353,320,318,310,278,212,143],
1328     &[365,351,320,318,310,278,212,143],&[365,351,320,318,310,278,212,158,94]],
1329    &[&[316,374,136],&[226,325,169,48],&[226,325,374,169,48],
1330     &[228,316,349,253,136,70],&[228,316,349,374,253,136,70],
1331     &[228,294,325,349,253,169,103,70],&[228,294,325,349,374,253,169,103,70],
1332     &[157,228,294,325,349,253,169,103,70,52],
1333     &[157,228,294,325,349,374,253,169,103,70,52]],
1334    &[&[316,374,137],&[226,325,166,31],&[226,325,374,166,31],
1335     &[228,316,348,237,137,32],&[228,316,348,374,237,137,32],
1336     &[228,294,325,348,237,166,91,32],&[228,294,325,348,374,237,166,91,32],
1337     &[157,228,294,325,348,237,166,91,32,7],
1338     &[157,228,294,325,348,374,237,166,91,32,7]],
1339    &[&[256,59,77],&[256,59,77,141],&[256,59,77,141,359],
1340     &[256,59,77,141,359,370],&[256,59,77,141,359,370,160],
1341     &[256,59,77,141,359,370,160,301],&[256,59,77,141,359,370,160,301,147]],
1342    &[&[93,317,132],&[93,317,132,268],&[93,317,132,268,165],
1343     &[93,317,132,268,165,360],&[93,317,132,268,165,360,257],
1344     &[93,317,132,268,165,360,257,182]],
1345    &[&[133,373,197],&[133,373,197,311],&[133,373,197,311,122],
1346     &[133,373,197,311,122,327],&[133,373,197,311,122,327,184],
1347     &[133,373,197,311,122,327,184,322],&[133,373,197,311,122,327,184,322,236],
1348     &[133,373,197,311,122,327,184,322,236,190],
1349     &[133,373,197,311,122,327,184,322,236,190,217],
1350     &[133,373,197,311,122,327,184,322,236,190,217,361]],
1351    &[&[316,374,148],&[226,325,170,46],&[226,325,374,170,46],
1352     &[224,316,348,264,148,55],&[224,316,348,374,264,148,55],
1353     &[224,294,325,348,264,170,93,55],&[224,294,325,348,374,264,170,93,55],
1354     &[150,224,294,325,348,264,170,93,55,86],
1355     &[150,224,294,325,348,374,264,170,93,55,86]],
1356    &[&[305,171,54],&[375,202,108,41],&[375,202,108,54,7],
1357     &[375,238,171,108,54,7],&[375,238,171,108,64,41,6],
1358     &[378,305,238,171,108,64,41,6],&[378,305,238,171,108,64,41,7,4]],
1359    &[&[275,118,49],&[375,156,66,40],&[375,156,66,49,44],
1360     &[375,206,118,66,49,44],&[375,206,118,66,36,40,29],
1361     &[377,275,206,118,66,36,40,29],&[377,275,206,118,66,36,40,44,22]],
1362    &[&[366,343,235],&[376,346,341,215],&[376,346,341,235,144],
1363     &[376,352,343,341,235,144],&[376,352,343,341,272,215,128],
1364     &[378,366,352,343,341,272,215,128],&[378,366,352,343,341,272,215,144,88]],
1365    &[&[362,342,284],&[372,344,324,254],&[372,344,324,284,192],
1366     &[372,345,342,324,284,192],&[372,345,342,324,315,254,174],
1367     &[375,362,345,342,324,315,254,174],&[375,362,345,342,324,315,254,192,119]]];
1368 
1369 func cb_map(name, nlevs, &type)
1370 {
1371   if (structof(name) == string) {
1372     maps = where(strcase(0,name) == strcase(0,cb_names));
1373     if (numberof(maps) != 1) return [];
1374     m = maps(1);
1375   } else {
1376     m = name;
1377     if (m<1 || m>numberof(cb_maps)) return [];
1378   }
1379   eq_nocopy, maps, *cb_maps(m);
1380   type = cb_types(m);
1381   if (!nlevs) return cb_colors(*maps(0));
1382   for (i=1 ; i<=numberof(maps) ; ++i) if (nlevs == numberof(*maps(i))) break;
1383   if (i > numberof(maps))
1384     error, cb_names(m)+" has no maps with "+totxt(nlevs)+" levels";
1385   return cb_colors(*maps(i));
1386 }
1387 
cb_choices(n,what)1388 func cb_choices(n, what)
1389 /* DOCUMENT cb_choices, n, what
1390  *       or cb_choices, name
1391  *   list available ColorBrewer color map choices with N colors.  The
1392  *   WHAT argument is "sequential", "diverging", or "qualitative", which
1393  *   can be abbreviated to any smaller number of characters.  The N and
1394  *   WHAT arguments are both optional, and may occur in either order.
1395  *   Called as a function, cb_choices returns a list of palette names;
1396  *   if the N argument is specified, "_N" will be appended to the
1397  *   returned names.
1398  *   In the second form, prints (or displays) a list of the different
1399  *   numbers of colors available for color map NAME.
1400  */
1401 {
1402   if (structof(n) == string) {
1403     tmp = n;
1404     n = what;
1405     what = tmp;
1406   }
1407   list = msort(cb_types, cb_names);
1408   names = cb_names(list);
1409   types = cb_types(list);
1410   type = ["sequential", "diverging", "qualitative"];
1411   if (!is_void(what)) {
1412     i = where(strcase(0, what) == strcase(0, names));
1413     if (!numberof(i)) {
1414       i = where(strglob(what+"*", type));
1415       if (numberof(i) != 1) error, "unrecognized color map type "+what;
1416       flag = i(1);
1417       i = where(types == i);
1418       list = list(i);
1419       names = names(i);
1420       types = types(i);
1421     } else {
1422       list = list(i(1));
1423       names = names(i(1));
1424       types = types(i(1));
1425       flag = -1;
1426     }
1427   }
1428   lens = array(int, 20, numberof(list));
1429   maps = cb_maps(list);
1430   for (i=1 ; i<=numberof(maps) ; ++i) {
1431     m = *maps(i);
1432     for (j=1 ; j<=numberof(m) ; ++j) lens(numberof(*m(j)), i) = 1;
1433   }
1434   if (flag == -1) {
1435     lens = where(lens);
1436     if (am_subroutine()) {
1437       write, names(1)+" maps available with";
1438       print, lens;
1439       write, "colors";
1440     }
1441     return lens;
1442   }
1443   if (n) {
1444     if (n<1 || n>20) error, "bad color map size "+totxt(n);
1445     i = where(lens(n,));
1446     if (!numberof(i)) {
1447       if (am_subroutine())
1448         write, "No "+(flag?type(flag)+" ":"")+"maps with "+totxt(n)+" colors";
1449       return [];
1450     }
1451     list = list(i);
1452     names = names(i);
1453     types = types(i);
1454     sfx = "_"+totxt(n);
1455     if (am_subroutine())
1456       write, "Available maps with "+totxt(n)+" colors:";
1457   } else {
1458     sfx = string(0);
1459   }
1460   if (!am_subroutine()) return names+sfx;
1461   i = where(types == 1);
1462   if (numberof(i)) write, grow("Sequential maps:",names(i));
1463   i = where(types == 2);
1464   if (numberof(i)) write, grow("Diverging maps:",names(i));
1465   i = where(types == 3);
1466   if (numberof(i)) write, grow("Qualitative maps:",names(i));
1467 }
1468 
1469 /* ------------------------------------------------------------------------ */
1470 /* Many published figures use color tables from the IDL (or PVWAVE)
1471  * programming language.  See
1472  *   http://www.exelisvis.com/language/en-us/productsservices/idl.aspx
1473  *   http://en.wikipedia.org/wiki/IDL_%28programming_language%29
1474  */
1475 
1476 func idlct_rd(filename, &names)
1477 /* DOCUMENT tables = idlct_rd(filename, names)
1478  *   read an IDL color table file, returning TABLES and NAMES.
1479  *   TABLES is a 256-by-3-by-N array of N [r,g,b] color mappings, and
1480  *   NAMES is a corresponding list of N descriptions.
1481  *   The first index of tables corresponds to color index values 0:255.
1482  *
1483  *   The default IDL color tables file is colors1.tbl in the
1484  *   resource/colors subdirectory of the IDL distribution.  Copies
1485  *   and modified copies can be found on the Web, for example:
1486  *     http://www.bnl.gov/x26a/download/colors1.zip
1487  *   The IDLVM virtual machine is available without charge and
1488  *   includes this file.
1489  *
1490  *   This function will also read the png files posted at
1491  *     http://docs.idldev.com/vis/color/default-colors.png
1492  *     (see http://docs.idldev.com/vis/color/vis_loadct.html)
1493  *   (Assumes you have the yorick-z package installed.)
1494  * SEE ALSO: idlct
1495  */
1496 {
1497   if (strpart(filename, -3:0) != ".png") {
1498     f = open(filename, "rb");
1499     ntab = char(0);
1500     _read, f, 0, ntab;
1501     if (!ntab) error, filename+" has no color tables";
1502     if (sizeof(f) < 1+800*ntab) error, filename+" too short";
1503     if (sizeof(f) > 1+800*ntab) write, "idlct: "+filename+" not truncated?";
1504     names = array(char, 32, ntab);
1505     _read, f, 1+768*ntab, names;
1506     names = strtrim(strchar(names));
1507     tables = array(char, 256, 3, ntab);
1508     _read, f, 1, tables;
1509     tables = transpose(tables, [1,2]);
1510   } else {
1511     tables = png_read(filename)(1:3, 1:256, 7::13);
1512     names = [];
1513   }
1514   return tables;
1515 }
1516 
idlct(n,ncols)1517 func idlct(n, ncols)
1518 /* DOCUMENT idlct, n
1519  *       or idlct, tables
1520  *   set palette to IDL color table N.  You must first call the function
1521  *   with the TABLES returned by idlct_rd.  A second parameter is interpreted
1522  *   as the number of colors to use; the default is the size of the current
1523  *   palette or 200 if there is none.
1524  *   Hint: You can set _idlctables to a string containing the name of
1525  *     a file readable by idlct_rd to automatically load the tables the
1526  *     first time idlct is called.
1527  * SEE ALSO: idlct_rd, cmap
1528  */
1529 {
1530   d = dimsof(n);
1531   if (d(1)) {
1532     if (d(1)!=3 || d(2)!=3 || structof(n)!=char)
1533       error, "IDL tables array not in format returned by idlct_rd";
1534     extern _idlctables;
1535     _idlctables = n;
1536   } else {
1537     if (structof(_idlctables) == string)
1538       _idlctables = idlct_rd(_idlctables);
1539     if (is_void(_idlctables))
1540       error, "IDL color tables not installed, use idlct,idlct_rd(file)";
1541     if (n<0 || n>=dimsof(_idlctables)(4))
1542       error, "invalid color table index, "+totxt(d(4))+" tables installed";
1543     ct = _idlctables(,,1+n);
1544     if (!am_subroutine()) return ct;
1545     cmap, ct, ncols;
1546   }
1547 }
1548