【问题标题】:Custom ColorFunction/ColorData in ArrayPlot (and similar functions)ArrayPlot 中的自定义 ColorFunction/ColorData(和类似函数)
【发布时间】:2011-04-22 08:08:14
【问题描述】:

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

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


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

现在在 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)}})

我得到以下情节:

我更喜欢 MATLAB 中丰富、明亮的颜色,而不是 mma 柔和/暗淡的颜色。如果我有来自 MATLAB 的颜色图的 RGB 值,如何让 mma 使用这些颜色?

您可以在 MATLAB 中下载默认颜色图的 RGB 值,并将其导入 mma 为

cMap = Transpose@Import["path-to-colorMapJet.mat", {"HDF5", 
      "Datasets", "cMap"}];

cMap 是一个64x3 数组,由01 之间的值组成。

只是为了给你一些背景知识,这里有一些来自 MathWorks documentation on colormap的相关文本

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

这里是map=cMapm=64

我尝试戳ColorDataFunction,发现ColorData 格式类似于colormap。但是,我不确定如何让ArrayPlot 使用它(并且大概它应该与其他绘图功能相同)。


另外,由于我在这里的练习纯粹是为了在 mma 中达到一定程度的舒适度,类似于我在 MATLAB 中的练习,我很感激 cmets 和关于改进我的代码的建议。具体来说,我对“修复”FrameTicks 的方法不太满意……肯定有更好/更简单的方法来做到这一点。

【问题讨论】:

  • 您是否尝试过使用 ColorData["LightTemperatureMap"] 或 ColorData["TemperatureMap"] 而不是“Rainbow”?这些会产生更明亮的情节。
  • 有比 yoda 年长的研究生导师吗?

标签: wolfram-mathematica


【解决方案1】:

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

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

你会得到这个:


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

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]

但你为什么不使用 DensityPlot?

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


编辑
请注意,在第二个图中,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}}]

【讨论】:

  • @Sjoerd:太棒了! DataRange 为我节省了很多不必要的替换。你是对的,我也可以使用DensityPlot 来完成它。我只是默认为ArrayPlot,因为我从 MATLAB(然后将其导入 mma)的所有输出都是数组。这只是一个具有简洁功能形式的示例。
  • @Sjoerd:为什么DataRange会翻转垂直轴?如果您查看答案中的最后两个图,ArrayPlot 图中的 y 轴刻度线会翻转。
  • @Sjoerd:谢谢。我也可以将Reverse@ 用于我不控制填充顺序的数组。
  • @Mr.Wizard 不,是一样的。对所有使用该版本的人的警告:确实,您必须注意括号的存在,因为 -> 的优先级高于 &
  • @yoda 你猜对了。试着问一个问题,比如“我知道如何在 Matlab 中做到这一点,但我如何在 Mathematica 中做到这一点?”。版主将在“我知道如何在另一个系统中执行此操作,但如何...”中更改此内容。我想这是为了防止战火纷飞,但我觉得比较各种 CA 系统中的作案手法并不一定要以这种方式结束。
【解决方案2】:

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

事实证明,为了与 Blend[] 一起使用,甚至不需要保留整个 64 个 RGBColor[] 指令集 @987654326 提供的线索肯定是这种情况cMap的列的@s:

{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"}}]}]

我们隐含地看到,表示这些组件的函数是分段线性的。由于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[]。这是比较ColorFunctions jetBlend[cols, #]&amp; 的梯度图:

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]}}]

这是一个机械验证,cols 中的 64 种颜色被很好地复制了:

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

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

【讨论】:

    猜你喜欢
    • 2014-06-14
    • 2021-02-15
    • 1970-01-01
    • 2018-08-06
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    相关资源
    最近更新 更多