ArrayPlot中的自定义ColorFunction / ColorData(和类似的函数)

时间:2011-04-22 08:08:14

标签: wolfram-mathematica

这与Mathematica中的Simon question on changing default ColorData有关。虽然这些解决方案都解决了在行图中更改ColorData的问题,但我并未发现该讨论对于更改ColorFunction / {{ColorData / ContourPlot有帮助1}} / ArrayPlot等等。

  

TLDR:有没有办法让mma在ArrayPlot / ContourPlot / etc中使用自定义颜色。

<小时/>  考虑我在MATLAB中创建的函数Plot3D的以下示例图:

enter image description here

现在在mma中做同样的事情:

sin(x^2+y^3)

我得到以下情节:

enter image description here

我更喜欢MATLAB中丰富,明亮的色彩,以及mma的柔和/暗淡色彩。如果我从MATLAB获得色彩映射的RGB值,我如何让mma使用这些颜色?

您可以从here下载MATLAB中默认色图的RGB值(我为megaupload链接道歉......我没有其他托管方式)。您可以将其导入到mma中

xMax = 3; yMax = 3;
img = Transpose@
   Table[Sin[y ^3 + x^2], {x, -xMax, xMax, 0.01}, {y, -yMax, yMax, 
     0.01}];
plot = ArrayPlot[img, ColorFunction -> ColorData["Rainbow"], 
   AspectRatio -> 1, 
   FrameTicks -> {FindDivisions[{0, (img // Dimensions // First) - 1},
       4], FindDivisions[{0, (img // Dimensions // Last) - 1}, 4], 
     None, None}, 
   DataReversed -> 
    True] /. (FrameTicks -> {x_, 
      y_}) :> (FrameTicks -> {x /. {a_?NumericQ, b_Integer} :> {a, 
         2 xMax (b/((img // Dimensions // First) - 1) - 1/2)}, 
      y /. {a_?NumericQ, b_Integer} :> {a, 
         2 yMax (b/((img // Dimensions // Last) - 1) - 1/2)}})

cMap = Transpose@Import["path-to-colorMapJet.mat", {"HDF5", "Datasets", "cMap"}]; cMap64x3之间的0数组。或者,您也可以复制here.

中的值

为了给您一些背景知识,这里是MathWorks documentation on colormap

中的一些相关文字
  

色彩图是真实的m×3矩阵   数字介于0.0和1.0之间。每一行   是一个定义一个的RGB矢量   颜色。色图的第k行   定义第k个颜色,其中map(k,:)   = [r(k)g(k)b(k)])指定红色,绿色和蓝色的强度。

此处1map=cMap

我尝试了m=64,我发现ColorDataFunction格式类似于ColorData。但是,我不确定如何让colormap使用它(并且可能它应该与其他绘图函数相同)。


此外,由于我在这里的练习纯粹是为了达到mma的舒适度,类似于我在MATLAB中所做的,我会感谢有关改进我的代码的意见和建议。具体来说,我对“修复”ArrayPlot的方式并不太满意......当然必须有更好/更简单的方法来实现它。

2 个答案:

答案 0 :(得分:18)

将此ColorData["Rainbow"]替换为:

Function[Blend[RGBColor @@@ cMap, Slot[1]]]

你得到了这个:

enter image description here


至于你的第二个问题,你可以这样做:

xMax = 3; yMax = 3;
img = Transpose@
   Table[Sin[y^3 + x^2], {x, -xMax, xMax, 0.01}, {y, -yMax, yMax, 
     0.01}];
plot = ArrayPlot[img, 
  ColorFunction -> Function[Blend[RGBColor @@@ cMap, Slot[1]]], 
  AspectRatio -> 1, FrameTicks -> Automatic, 
  DataRange -> {{-xMax, xMax}, {-yMax, yMax}}, DataReversed -> True]

enter image description here

但为什么不使用DensityPlot?

DensityPlot[Sin[y^3 + x^2], {x, -xMax, xMax}, {y, -yMax, yMax}, 
 ColorFunction -> Function[Blend[RGBColor @@@ cMap, Slot[1]]], 
 PlotPoints -> 300]

enter image description here


修改
请注意,在第二个图中,y范围标记是相反的。那是因为它考虑了DataReversed设置。 ArrayPlot以与屏幕上打印数组内容时出现的顺序相同的顺序绘制数组的行。因此,第一行绘制在顶部,最后一行绘制在底部。高行值对应于低y值,反之亦然。 DataReversed-&gt; True校正此现象,但在这种情况下,它也“校正”y值。解决方法是从高y值开始向下填充数组。在这种情况下,您不需要DataReversed:

xMax = 3; yMax = 3;
img = Transpose@
   Table[Sin[y^3 + x^2], {x, -xMax, xMax, 0.01}, {y, 
     yMax, -yMax, -0.01}];
plot = ArrayPlot[img, 
  ColorFunction -> Function[Blend[RGBColor @@@ cMap, Slot[1]]], 
  AspectRatio -> 1, FrameTicks -> Automatic, 
  DataRange -> {{-xMax, xMax}, {-yMax, yMax}}]

enter image description here

答案 1 :(得分:18)

(我希望这还不算太晚。)

事实证明,为了与RGBColor[]一起使用,人们甚至不需要保留整套64个Blend[]指令。一个线索肯定是这样的由ListPlot[]列的cMap提供:

{rr, gg, bb} = Transpose[Rationalize[cMap]];
GraphicsGrid[{MapThread[
   ListPlot[#1, DataRange -> {0, 1}, Frame -> True, 
     GridLines -> {{1/9, 23/63, 13/21, 55/63}, None}, 
     PlotLabel -> #2] &, {{rr, gg, bb}, {"Red", "Green", "Blue"}}]}]

LisPlot[]s of RGB components of MATLAB's jet colormap

我们隐含地看到,表示这些组件的函数是分段线性。由于Blend[]必然会在颜色之间进行线性插值,如果我们可以在分段线性图中找到与“角”对应的颜色,我们可以消除这些角之间的所有其他颜色(因为Blend[]将会为我们做插值),因此可能只需携带,比如七,而不是六十四种颜色。

通过阅读上面给出的代码,您会注意到我已经为您找到了这些转换点(提示:检查GridLines的设置)。 documentation for colormap()

提供了有关这些颜色的更多提示
  

jet的范围从蓝色到红色,并通过青色,黄色和橙色。

可能吗?我们来看看:

cols = RGBColor @@@ Rationalize[cMap];
Position[cols, #][[1, 1]] & /@ {Blue, Cyan, Yellow, 
  Orange // Rationalize, Red}
{8, 24, 40, 48, 56}

这只是给出了数组cols中颜色的位置,但我们可以重新缩放事物以对应于色彩映射的预期参数范围:

(# - 1)/(Length[cols] - 1) & /@ %
{1/9, 23/63, 13/21, 47/63, 55/63}

,这些正是与色彩图的RGB分量对应的分段线性函数的断点所在的位置。那是五种颜色;为了确保平滑插值,我们还将第一个和最后一个颜色添加到此列表中,

cols[[{1, Length[cols]}]]
{RGBColor[0, 0, 9/16], RGBColor[1/2, 0, 0]}

将原始cols列表总计为七个。由于7/64大约是11%,这是相当大的节省。

因此我们寻求的颜色功能是

jet[u_?NumericQ] := Blend[
        {{0, RGBColor[0, 0, 9/16]}, {1/9, Blue}, {23/63, Cyan}, {13/21, Yellow},
         {47/63, Orange}, {55/63, Red}, {1, RGBColor[1/2, 0, 0]}}, 
                          u] /; 0 <= u <= 1

我们进行两次比较以验证jet[]。这是一个比较ColorFunction s jetBlend[cols, #]&的渐变图:

GraphicsGrid[{{
   Graphics[Raster[{Range[100]/100}, ColorFunction -> (Blend[cols, #] &)], 
    AspectRatio -> .2, ImagePadding -> None, PlotLabel -> "Full", 
    PlotRangePadding -> None], 
   Graphics[Raster[{Range[100]/100}, ColorFunction -> jet], 
    AspectRatio -> .2, ImagePadding -> None, 
    PlotLabel -> "Compressed", PlotRangePadding -> None]}}]

color gradient comparison of jet and explicit 64-color Blend

这是一个机械验证,可以很好地再现cols中的64种颜色:

Rationalize[Table[jet[k/63], {k, 0, 63}]] === cols
True

现在,您可以将jet[]用作ColorFunction用于支持它的任何绘图功能。享受!