표면 (2D) 위상 플롯에 대한 pgfplot의 순환 컬러 맵
shader
에서 표면도에 대한 설정으로 어려움을 겪 습니다 pgfplots
. 특히 복소수 목록의 위상에 대한 2D 표면 플롯을 만들고 싶습니다. 즉, 데이터 목록에 불연속성 (예 : π에서 –π까지)이 있으며 이는 해석 및 시각화에 기본적으로 의미가 없습니다.
나는 이미 양쪽 끝이 같은 색을 가진 소위 순환 컬러 맵을 발견했습니다. 지금까지 내가 가장 좋아하는 것은 matplotlib의 twilight 인데 pgfplots
, 파이썬 스크립트와 함께 사용하기 위해 변환했습니다 . 다음 MWE에서는 매우 축소 된 형태로 포함됩니다.
문제는 이제 표면 플롯에 대한 멋진 셰이더, 즉를 제외한 모든 셰이더 shader = flat corner
가 그 사이의 값을 보간하기 위해 불연속성 값 사이의 값을 취 한다는 것 입니다. π에서 –π 로의 점프가 발생하면 색상이 흰색으로 유지되는 대신 검정색으로 바뀝니다. 안타깝게도 flat corner
셰이더 는 셰이더의 모양에 가까워 지려면 많은 오버 샘플링이 필요 interp
하므로 실제로 허용되는 솔루션이 아닙니다.
한 가지 해결책은 주기적으로 컬러 맵을 확장하고 2D 위상 언 래핑 알고리즘을 사용하는 것이지만, 위상 언 래핑이 완전히 사소 해 보이지 않기 때문에 지금은 그렇게 할 마음이 없습니다. 또한 이것은 만족스러운 솔루션 이라기보다는 보간 셰이더의 한계를 극복하는 방법과 비슷합니다.
훨씬 더 나은 접근 방식은 pgfplot에서 순환 컬러 맵으로 작업하기 위해 셰이더의 작동 방식을 변경하는 것입니다. 그러나 나는 이것을하는 방법을 정말로 모른다. 그런 경우에 극단적 인 값 (평균 메타 값보다 메타 값의 최대 / 최소값에 더 가깝 음)을 감지하고 이러한 경우 주기적으로 보간에 사용되는 컬러 맵을 변경할 수 있습니까?
물론 순환 컬러 맵을 사용한 불연속 효과에 대한 간단한 데모가 있습니다. 양수에서 음수로의 전환을 제외하고 보간 버전이 훨씬 더 멋지게 보입니다 .
\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}

답변
편집 : 새롭고 훨씬 더 나은 솔루션
를 통해 우회하지 않고 작업을 구현했습니다 colormap access=direct
. 이 방법은 표시 point meta min
및 point meta max
값 에 대한 지식 만 필요하며 , 이는 일반적으로 위상 플롯을위한 것이며 데이터에서 쉽게 추출 할 수 있습니다. 따라서 모든 것이 코드 내에서 이루어지기 때문에 훨씬 더 유연하고 추가 데이터 준비가 필요하지 않습니다.
위상 (또는 주기적 데이터)의 불연속성은 restrict z to domain=-2:2
2 (!) \addplot
초 안에 필터링 되고 메타 값은 point meta min=-3.14
및 에 따라 설정되어야 point 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 access
로를 direct
. 그러나 이렇게하려면 컬러 맵 정의 범위에서 값을 가져 오려면 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}
