0

我正在尝试使用 splot(xyz 值)绘制 4d 图。我想将第 4 列显示为热色。到目前为止,我很好。在网上搜索答案后,我无法弄清楚的是,点的颜色是透明的,但根据它们的值具有不同的透明度。

例如,假设我有以下数据集:

0 0 0 0.1
0 0 1 0.2

0 1 0 0.2
0 1 1 2

1 0 0 1
1 0 1 3

1 1 0 0.5
1 1 1 4

现在,我想让颜色条(第 4 列)是这样的:第 4 列值越接近 1,图中的点/点就越透明。我看过的所有地方只能给我整个颜色条的统一透明度。

我想知道是否有人以前处理过这个问题,或者知道如何做到这一点。非常感谢!

4

1 回答 1

0

我不完全理解您希望透明度如何取决于值,因此我将给出一个一般性的答案,您可以在其中将透明度函数替换为您自己的函数。

虽然您可以为线条颜色指定透明度,但这在使用调色板时似乎是不可能的,这将是实现您想要的最直接的方法。仅使用 gnuplot 可以实现的最远距离是使颜色显示为透明,如以下脚本所示,其中 in.data 是包含示例数据的文件。

#!/usr/bin/env gnuplot

set term pngcairo
in_data = "in.data"
set out "out.png"

# function to combine color and alpha channels with white background
# 0: no transparency, 1: fully transparent
make_transparent(x1, t) = (1-t)*x1 + t

# a function to decide transparency
# the input and output must be in range of [0,1]
#get_transparency(x1) = 0      # no transparency
#get_transparency(x1) = 1      # fully transparent
get_transparency(x1) = 1 - x1  # smaller values are more transparent

# convenience function to truncate values
minval(x1, x2) = x1<x2?x1:x2
maxval(x1, x2) = x1>x2?x1:x2
truncval(x1, xmin, xmax) = maxval(minval(x1, xmax), xmin)
trunc(x1) = truncval(x1, 0, 1)

# the default palette consists of rgbfunctions 7,5,15
# we redefine their transparency enabled versions here
# the input and output must be in range of [0,1]
# see other formulae with "show palette rgbformulae" command in gnuplot
f7(x1)  = make_transparent(sqrt(x1)           , get_transparency(x1))
f5(x1)  = make_transparent(x1**3              , get_transparency(x1))
f15(x1) = make_transparent(trunc(sin(2*pi*x1)), get_transparency(x1))

set palette model RGB functions f7(gray),f5(gray),f15(gray)

splot in_data palette  

此脚本假定背景为白色,但可以适应任何其他纯色背景。但是,一旦点开始重叠,它就会分崩离析。

要获得真正的透明度,您需要将每个数据点绘制为单独的线并为其赋予不同的线颜色。这可以通过预处理数据来实现,如下面的 bash 脚本所示。

#!/usr/bin/env bash

set -eu

in_data="in.data"
out_png="out.png"

pi=3.141592653589793

# function to convert data value into rgba value
function value2rgba()
{
  # arguments to function
  local val="${1}"
  local min="${2}"
  local max="${3}"

  # normalized value
  local nval=$( bc -l <<< "(${val}-${min})/(${max}-${min})" )

  #### alpha channel value ####
  local alpha="$( bc -l <<< "255 * (1-${nval})" )"
  # round to decimal
  alpha=$( printf "%0.f" "${alpha}" )

  #### red channel value ####
  # rgbformulae 7 in gnuplot
  local red="$( bc -l <<< "255 * sqrt(${nval})" )"
  # round to decimal
  red=$( printf "%0.f" "${red}" )

  #### green channel value ####
  # rgbformulae 5 in gnuplot
  local red="$( bc -l <<< "255 * sqrt(${nval})" )"
  local green="$( bc -l <<< "255 * ${nval}^3" )"
  # round to decimal
  green=$( printf "%0.f" "${green}" )

  #### blue channel value ####
  # rgbformulae 15 in gnuplot
  local blue="$( bc -l <<< "255 * s(2*${pi}*${nval})" )"
  # round to decimal
  blue=$( printf "%0.f" "${blue}" )
  # make sure blue is positive
  if (( blue < 0 ))
  then
    blue=0
  fi

  ### whole rgba value
  local rgba="#"
  rgba+="$( printf "%02x" "${alpha}" )"
  rgba+="$( printf "%02x" "${red}" )"
  rgba+="$( printf "%02x" "${green}" )"
  rgba+="$( printf "%02x" "${blue}" )"

  echo "${rgba}"

}

# data without blank lines
data="$( sed -E  "/^[[:space:]]*$/d" "${in_data}" )"

# number of lines
nline=$( wc -l <<< "${data}" )

# get the minimum and maximum value of the 4-th column
min_max=( $( awk '{ print $4 }' <<< "${data}" | sort -g | sed -n '1p;$p' ) )

# array of colors for each point
colors=()
while read -r line
do
  colors+=( $( value2rgba "${line}" "${min_max[@]}" ) )
done < <( awk '{ print $4 }' <<< "${data}" )

# gather coordinates into one row
coords=( $( awk '{ print $1,$2,$3 }' <<< "${data}" ) )

gnuplot << EOF

set term pngcairo

set out "${out_png}"

\$DATA << EOD
${coords[@]}
EOD

nline=${nline}
colors="${colors[@]}"

unset key

splot for [i=0:nline-1] \$DATA \
  u (column(3*i+1)):(column(3*i+2)):(column(3*i+3)) \
  pt 1 lc rgb word(colors, i+1)

EOF 

这些脚本使用 gnuplot 5 进行了测试。

于 2017-11-14T04:55:35.010 回答