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

10 wolfram-mathematica

这与Simon 关于在Mathematica中更改默认ColorData问题有关.虽然这些解决方案都解决了改变ColorData线条图的问题,但我并没有发现讨论有助于改变ColorFunction/ ColorDatain ContourPlot/ ArrayPlot/ Plot3D等.

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


考虑sin(x^2+y^3)我在MATLAB中创建的函数的以下示例图:

在此输入图像描述

现在在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)}})
Run Code Online (Sandbox Code Playgroud)

我得到以下情节:

在此输入图像描述

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

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

cMap = Transpose@Import["path-to-colorMapJet.mat", {"HDF5", 
      "Datasets", "cMap"}];
Run Code Online (Sandbox Code Playgroud)

cMap是和64x3之间的值数组.或者,您也可以从此处复制值.01

为了给您一些背景知识,这里是关于colormap的MathWorks 文档中的一些相关文本

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

在这里map=cMap,和m=64.

我试过戳ColorDataFunction,我看到ColorData格式类似于colormap.但是,我不确定如何ArrayPlot使用它(并且可能它应该与其他绘图功能相同).


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

Sjo*_*ies 18

替换你ColorData["Rainbow"]的这个:

Function[Blend[RGBColor @@@ cMap, Slot[1]]]
Run Code Online (Sandbox Code Playgroud)

你得到这个:

在此输入图像描述


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

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]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

但为什么不使用DensityPlot?

DensityPlot[Sin[y^3 + x^2], {x, -xMax, xMax}, {y, -yMax, yMax}, 
 ColorFunction -> Function[Blend[RGBColor @@@ cMap, Slot[1]]], 
 PlotPoints -> 300]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


编辑
请注意,在第二个图中,y范围标记是相反的.那是因为它考虑了DataReversed设置.ArrayPlot以与屏幕上打印数组内容时出现的顺序相同的顺序绘制数组的行.因此,第一行绘制在顶部,最后一行绘制在底部.高行值对应于低y值,反之亦然.DataReversed-> 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}}]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • @ Mr.Wizard不,它是一样的.对每个将要使用该版本的人发出警告:事实上,你必须注意括号是否存在,因为 - >具有比&更高的优先级 (2认同)
  • @yoda你猜对了.尝试提出一个问题,例如"我知道如何在Matlab中执行此操作,但我如何在Mathematica中执行此操作?".主持人将在"我知道如何在另一个系统中执行此操作,但如何..."中更改此设置.我想这是为了防止火焰战争,但我觉得在各种CA系统中比较运作方式不一定以此为结尾. (2认同)

小智 18

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

事实证明,RGBColor[]为了使用Blend[]A线索,人们甚至不需要保留整套64个指令,这肯定是由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"}}]}]
Run Code Online (Sandbox Code Playgroud)

LisPlot []的MATLAB的jet colormap的RGB组件

我们隐含地看到,表示这些组件的函数是分段线性的.由于Blend[]必须在颜色之间进行线性插值,如果我们可以找到与分段线性图中的"角"对应的那些颜色,我们可以消除这些角之间的所有其他颜色(因为我们Blend[]会对它进行插值),因此可能不得不随身携带,比方说,七,而不是六十四种颜色.

通过阅读上面给出的代码,您会注意到我已经为您找到了这些转换点(提示:检查设置GridLines).有关这些颜色可能是什么的进一步提示由以下文档提供colormap():

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

可能吗?让我们检查:

cols = RGBColor @@@ Rationalize[cMap];
Position[cols, #][[1, 1]] & /@ {Blue, Cyan, Yellow, 
  Orange // Rationalize, Red}
{8, 24, 40, 48, 56}
Run Code Online (Sandbox Code Playgroud)

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

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

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

cols[[{1, Length[cols]}]]
{RGBColor[0, 0, 9/16], RGBColor[1/2, 0, 0]}
Run Code Online (Sandbox Code Playgroud)

将原始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
Run Code Online (Sandbox Code Playgroud)

我们进行两次比较以验证jet[].这是一个比较ColorFunctions jet和的梯度图Blend[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]}}]
Run Code Online (Sandbox Code Playgroud)

喷射和显式64色混合的颜色梯度比较

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

Rationalize[Table[jet[k/63], {k, 0, 63}]] === cols
True
Run Code Online (Sandbox Code Playgroud)

您现在可以jet[]用作ColorFunction任何支持它的绘图功能.请享用!