pgfplots 中用于表面(2D)相图的循环色彩图

pgfplots 中用于表面(2D)相图的循环色彩图

shader我对 中的曲面图设置感到困惑pgfplots。具体来说,我想制作一个复数列表相位的二维曲面图。这意味着数据列表中存在不连续性,例如从 π 到 -π,这对于解释和可视化基本上毫无意义。

我已经找到了所谓的循环颜色图,它的两端颜色相同。到目前为止,我最喜欢的是来自 matplotlib 的暮光之城,我已将其转换为pgfplots 使用 Python 脚本在以下 MWE 中,它以非常简化的形式包含。

现在的问题是,用于表面图的美观着色器(即除 之外的任何着色器)shader = flat corner在非连续性值之间取一些值,以在中间插入值。如果从 π 跳到 -π,颜色会变为黑色,而不是保持白色。不幸的是,flat corner着色器需要大量的过采样才能接近interp着色器的外观,因此这不是一个真正可接受的解决方案。

一种解决方案是定期扩展颜色图并使用某种 2D 相位展开算法,但我不得不承认,我目前还不太清楚如何做,因为相位展开似乎并不完全简单。此外,这更像是一种绕过插值着色器限制的方法,而不是令人满意的解决方案。

更好的方法可能是改变着色器的工作方式,以便使用 pgfplots 中的循环颜色图。但我真的不知道该怎么做。也许可以检测极值(更接近元值的最大值/最小值而不是平均元值)并在这种情况下以循环方式更改用于插值的颜色图?

当然,我有一个简短的演示,演示了使用循环色图的不连续性效果。除了从正数到负数的过渡外,插值版本看起来很多更好。

\documentclass{standalone}
\usepackage{pgfplots}

\usepgfplotslibrary{colormaps}

\pgfplotsset{compat=newest}
\pgfplotsset{
  colormap/twilight/.style={colormap={twilight}{[1pt]
  rgb(0pt)=(0.8857501584075443, 0.8500092494306783, 0.8879736506427196);
  rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
  rgb(50pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
  rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
  rgb(100pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
}}}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
             view={90}{90},
             colormap/twilight,
             colorbar
             ]

  \addplot3[
           mesh/rows=8,
           surf,  
           shader = interp,             
           ] coordinates {
                          (0,0, 0) (0,1, 0)
                          (1,0, 1) (1,1, 1)
                          (2,0, 2) (2,1, 2)
                          (3,0, 3) (3,1, 3)
                          (4,0,-3) (4,1,-3) 
                          (5,0,-2) (5,1,-2)
                          (6,0,-1) (6,1,-1)
                          (7,0, 0) (7,1, 0)
                         };

\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
             view={90}{90},
             colormap/twilight,
             colorbar
             ]

  \addplot3[
           mesh/rows=8,
           surf,  
           shader = flat corner,             
           ] coordinates {
                          (0,0, 0) (0,1, 0)
                          (1,0, 1) (1,1, 1)
                          (2,0, 2) (2,1, 2)
                          (3,0, 3) (3,1, 3)
                          (4,0,-3) (4,1,-3) 
                          (5,0,-2) (5,1,-2)
                          (6,0,-1) (6,1,-1)
                          (7,0, 0) (7,1, 0)
                         };

\end{axis}
\end{tikzpicture}
\end{document}

插值与平角的比较

答案1

编辑:新的、更好的解决方案

我想到了一个无需绕道的实现colormap access=direct。这种方式只需要了解出现的point meta minpoint meta max值,这对于相位图来说通常很清晰,并且很容易从数据中提取。因此,它更加灵活,不需要额外的数据准备,因为一切都在代码内部完成。

restrict z to domain=-2:2相位(或循环数据)中的不连续性在两秒内被滤除\addplot,元值必须根据和设置point meta min=-3.14point meta max=3.14或π的某个更精确的值。第一个图是正常图(在左图下方的图片中),第二个图(下图:中间)使用移位版本的颜色图(适用于黄昏,否则可能必须构建)和根据对数据的简单操作z expr={\thisrow{z} > 0 ? -(\thisrow{z} - 3.14) : -(\thisrow{z} + 3.14) }。两个图的叠加给出了一个很好的连续和插值曲面图。边界restrict可能需要根据绘图数据进行调整。

\documentclass{standalone}
\usepackage{pgfplots}

\usepgfplotslibrary{colormaps}

\pgfplotsset{compat=newest}
\pgfplotsset{
  colormap/twilight/.style={colormap={twilight}{[1pt]
  rgb(0pt)=(0.8857501584075443, 0.8500092494306783, 0.8879736506427196);
  rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
  rgb(50pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
  rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
  rgb(100pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
}},
  colormap/twilight_shifted/.style={colormap={twilight_shifted}{[1pt]
rgb(0pt)=(0.18739228342697645, 0.07710209689958833, 0.21618875376309582);
rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
rgb(50pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
rgb(100pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
}}}


\begin{filecontents}{data.txt}
x y z
0 0 0
0 1 0
1 0 1
1 1 1
2 0 2
2 1 2
3 0 3 
3 1 3
4 0 -3
4 1 -3 
5 0 -2
5 1 -2
6 0 -1
6 1 -1
7 0  0
7 1  0
\end{filecontents}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
             view={90}{90},
             colormap/twilight,
             colorbar,
             title=normal colormap,
             ]

  \addplot3[
           mesh/rows=8,
           surf,  
           colormap/twilight,
           shader = interp,   
           point meta min= -3.14,   
           point meta max=  3.14,
           ] table[restrict z to domain=-2:2] from {data.txt};


\end{axis}
\end{tikzpicture}
\begin{tikzpicture}

\begin{axis}[
             view={90}{90},
             colormap/twilight_shifted,
             colorbar,
             xmin=0,xmax=7,
             title=plus shifted colormap,
             ]

  \addplot3[
           mesh/rows=8,
           surf,  
           colormap/twilight_shifted,
           shader = interp,   
           point meta min= -3.14,   
           point meta max=  3.14,
           ] table[z expr={\thisrow{z} > 0 ? -(\thisrow{z} - 3.14) :  -(\thisrow{z} + 3.14) }, % minus signs are necessary due to 'inverted' definition of twilight_shifted
           restrict z to domain=-2:2
           ] from {data.txt};

\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
             view={90}{90},
             colormap/twilight,
             colorbar,
             title=results in a complete plot,
             ]

  \addplot3[
           mesh/rows=8,
           surf,  
           colormap/twilight,
           shader = interp,   
           point meta min= -3.14,   
           point meta max=  3.14,
           ] table[restrict z to domain=-2:2] from {data.txt};
  \addplot3[
           mesh/rows=8,
           surf,  
           colormap/twilight_shifted,
           shader = interp,   
           point meta min= -3.14,   
           point meta max=  3.14,
           ] table[z expr={\thisrow{z} > 0 ? -(\thisrow{z} - 3.14) :  -(\thisrow{z} + 3.14) }, % minus signs are necessary due to 'inverted' definition of twilight_shifted
           restrict z to domain=-2:2
           ] from {data.txt};


\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

以前的解决方案输出比较丑陋,为了完整性,留在这里

一种方法,可能只适用于相当精细的采样(即,只有当颜色从一个点到另一个点平滑过渡时)是改变 到 的方式colormap accessdirect然而,这要求meta(或此处z)值从颜色图定义的范围中取值。不是很好,但不错的输出证明了手段的合理性 :)

颜色图缩放来自这篇文章被用来为颜色条提供至少正确的刻度(但输入数据必须以缩放形式提供)。

\documentclass{standalone}
\usepackage{pgfplots}

\usepgfplotslibrary{colormaps}

\pgfplotsset{compat=newest}
\pgfplotsset{
  colormap/twilight/.style={colormap={twilight}{[1pt]
  rgb(0pt)=(0.8857501584075443, 0.8500092494306783, 0.8879736506427196);
  rgb(25pt)=(0.38407269378943537, 0.46139018782416635, 0.7309466543290268);
  rgb(50pt)=(0.18488035509396164, 0.07942573027972388, 0.21307651648984993);
  rgb(75pt)=(0.6980608153581771, 0.3382897632604862, 0.3220747885521809);
  rgb(100pt)=(0.8857115512284565, 0.8500218611585632, 0.8857253899008712);
}}}

\pgfplotsset{
    linear colormap trafo/.code n args={4}{
        \def\scalefactor{((#2-#1) / (#4-#3))}%
        \def\offsetin{(#3)}%
        \def\offsetout{(#1)}%
        \pgfkeysalso{%
            y coord trafo/.code={%
                \pgfmathparse{(##1)}%-\offsetin )*\scalefactor + \offsetout}%
                % this part of the transformation does not work
                % it seems not to be 'compatible' with colormap access=direct
            },
            y coord inv trafo/.code={%
                \pgfmathparse{(##1-\offsetout)/\scalefactor + \offsetin}%
            },
        }%
    },
    colorbar map from to/.code n args={4}{
        \def\scalefactor{((#2-#1) * (#4-#3))}%
        \def\offsetin{(#1)}%
        \def\offsetout{(#3)}%
        \pgfkeysalso{
            colorbar style={
                linear colormap trafo={#1}{#2}{#3}{#4},
                point meta min={#1},
                point meta max={#2},
            },
           % point meta={(y)},%-\offsetin )/\scalefactor + \offsetout},
        }%
    },
}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
             view={90}{90},
             colormap/twilight,
             colorbar,
             colorbar map from to={0}{100}{-3.14159265359}{3.14159265359},
             ]

  \addplot3[
           mesh/rows=8,
           surf,  
           shader = interp,  colormap access=direct,           
           ] coordinates {
                          (0,0, 50) (0,1, 50)
                          (1,0, 63) (1,1, 63)
                          (2,0, 76) (2,1, 76)
                          (3,0,100) (3,1,100)
                          (4,0,  5) (4,1,  5) 
                          (5,0, 24) (5,1, 24)
                          (6,0, 37) (6,1, 37)
                          (7,0, 50) (7,1, 50)
                         };

\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容