5
$\begingroup$

I want to use Rescale on a ColorData, like this:

ColorData[{"TemperatureMap", {-100, 10}}]

However, I still want the value 0 to get plotted with the white color of the scheme. Any idea how to force Mma to do so? I tried "specific discrete values" {{x1, x2, ...}} but it's not working.

$\endgroup$
5
  • $\begingroup$ You want the blue to correspond to -100, the White to 0, and the Red to still correspond to 10? $\endgroup$
    – Jason B.
    Apr 13, 2016 at 12:35
  • $\begingroup$ This is correct! $\endgroup$
    – Kay
    Apr 13, 2016 at 12:35
  • $\begingroup$ @JasonB - I managed to get the desired ColorFunction with Blend. I was just hoping for a more easier way with Rescale and a ColorScheme or so... $\endgroup$
    – Kay
    Apr 13, 2016 at 12:37
  • $\begingroup$ Consider using an interpolating polynomial as the mapping function, mapping $-100,0,10$ to $0,1/2,1$. Adjust derivative values (Hermite interpolation) if need be. $\endgroup$ Apr 13, 2016 at 12:38
  • $\begingroup$ @J.M. - Could you give an example? I mean, how to incorporate that into the properties of ColorData? $\endgroup$
    – Kay
    Apr 13, 2016 at 12:40

2 Answers 2

8
$\begingroup$

What you need is a nonlinear function to map to, one that is close to zero for values near x=-100, reaches 1/2 at x=0, and 1 at x=10. This works,

Plot[Exp[x Log[2]/10]/2, {x, -100, 10}, PlotRange -> All]

enter image description here

So applying this to a ColorFunction

cf = ColorData["TemperatureMap"][Exp[# Log[2]/10]/2] &

BarLegend[{cf, {-100, 10}}]

enter image description here

Using a 3-point Interpolating function

J.M. suggested using a 3-point interpolation function, which at first I was unable to get to work. Here is a naive attempt, and remember that the function must stay between 0 and 1.

Plot[Interpolation[{{-100, 0}, {0, .5}, {10, 1}}][x], {x, -100, 10}]

enter image description here

Then I read the rest of his comment, about supplying derivatives. Still thinking about the exponential function above, I assumed the derivative should start at some small value and be monotonically increasing.

Plot[Interpolation[{{{-100}, 0, .001}, {{0}, 1/2, 1}, {{10}, 1, 2}}][
  x], {x, -100, 10}]

enter image description here

which would clearly make an awful color map since more than one value would correspond to a single color.

Here are derivative values that seem to work

fun = Interpolation[{{{-100}, 0, 0}, {{0}, 1/2, .015}, {{10}, 
     1, .015}}];
{Plot[fun[x], {x, -100, 10}],
 BarLegend[{ColorData["TemperatureMap"][fun[#]] &, {-100, 10}}]}

You could use Manipulate to get just the right color function as well,

Manipulate[
 fun = Interpolation[{{{-100}, 0, d1}, {{0}, 1/2, d2}, {{10}, 1, d3}}];
 {Plot[fun[x], {x, -100, 10}, ImageSize -> 300],
  BarLegend[{ColorData["TemperatureMap"][fun[#]] &, {-100, 10}}]},
 {d1, 0, .02}, {d2, 0, .02}, {d3, 0, .02}]

enter image description here

Gonna take this time to mention this post which allows you to create a completely custom color function interactively.

$\endgroup$
6
  • $\begingroup$ Nice one, thanks a lot! Lesson learned: my skills on handling # and & are to be improved!! $\endgroup$
    – Kay
    Apr 13, 2016 at 12:54
  • $\begingroup$ You could just as easily write that as cf[x_]: = ColorData["TemperatureMap"][Exp[x Log[2]/10]/2] , but hang around here long enough and you use pure functions and Map for everything $\endgroup$
    – Jason B.
    Apr 13, 2016 at 12:55
  • $\begingroup$ Also, see this post for some more nonlinear color functions $\endgroup$
    – Jason B.
    Apr 13, 2016 at 12:56
  • $\begingroup$ Yeah, I already realized, that these commands might save tons of coding text. But I'm still not very familiar with them. Anyway, my time is limited so I'll learn it peux á peux :D $\endgroup$
    – Kay
    Apr 13, 2016 at 12:58
  • $\begingroup$ Thanks for following through. :) $\endgroup$ Apr 13, 2016 at 14:08
5
$\begingroup$

It can be done by applying ColorData["TemperatureMap"] to a piecewise function that rescales the intervals -100 to 0 and 0 to 10 separately.

cf[u_] =
  ColorData["TemperatureMap"] @ 
    Piecewise[
      {{Rescale[u, {-100, 0}, {0., .5}], -100 < u < 0}, 
       {Rescale[u, {0, 10}, {.5, 1.}], 0 <= u <= 10}}];

DensityPlot[x, {x, -100, 10}, {y, 0, 1},
  ColorFunction -> cf,
  ColorFunctionScaling -> False]

plot

Update

Since

ColorData["TemperatureMap"] @ 
  Piecewise[
    {{Rescale[u, {-100, 0}, {0., .5}], -100 < u < 0}, 
     {Rescale[u, {0, 10}, {.5, 1.}], 0 <= u <= 10}}]

returns a color blend, cf can be written more directly as

cf[u_] =
  Blend[
    "TemperatureMap", 
    Piecewise[{{0.5 + 0.005 u, -100 < u < 0}, {0.5 + 0.05 u, 0 <= u <= 10}}]];

Further, as J.M. suggests in his comment, an interpolating function can be used.

cf[u_] = 
  (ColorData["TemperatureMap"] @*
     Interpolation[{{-100, 0.}, {0, .5}, {10, 1.}}, InterpolationOrder -> 1])[u];

or

cf[u_] =
  Blend[
   "TemperatureMap",
   Interpolation[{{-100, 0.}, {0, .5}, {10, 1.}}, InterpolationOrder -> 1][u]];
$\endgroup$
1
  • $\begingroup$ Equivalently, one could have used Interpolation[] with the setting InterpolationOrder -> 1. $\endgroup$ Apr 13, 2016 at 14:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.