Gnuplot 在平行图中插入点
Gnuplot insert points in a parallel plot
我需要使用 gnuplot 创建一个包含线和点的平行图。
不幸的是,要么使用
set style line 1 lc rgb 'blue' lt 1 lw 2 pt 7 ps 0.75 pi 5
或者在 plot 命令中设置 pt ps 和 pi
Gnuplot 不插入任何点。
我需要插入点来区分两条颜色相同的线。
它们必须是相同的颜色,因为它们具有相同的 "family"。因此,我不能简单地更改颜色:(
我该怎么做?
谢谢
不幸的是,Gnuplot 确实不支持此功能 "out of the box",但是如果您只是为了一些快速的一次性生产情节而需要它,那么有一种稍微脏的方法可以做到这一点。更具体地说,可以获得当前的Gnuplot源代码,以一种或多或少令人满意的方式引入此功能并使用Gnuplot的修改版本生成所需的图形。
为了说明这个想法,假设我们想要平行绘制以下仅包含三个 "sets":
的数据文件 data.dat
1 2 3
2 1 1
3 3 3
受默认 Gnuplot 演示 parallel.dem
的启发,人们可能会尝试使用这样的脚本 test.gpl
来实现这一点:
set title "Parallel Axis Plot" font ",15"
set terminal pdf
set output 'test.pdf'
set border 0
unset key
set xrange [] noextend
unset ytics
# use x-axis tic positions to label the axes
set xtics 1 format "axis %g" scale 0,0
# turn on axis tics for the parallel axes
set for [i=1:3] paxis i tics
plot 'data.dat' using 1:2:3 with parallel
然而,这产生的情节可能类似于:
在这里,所有的线条都是相同的类型和颜色,这让人很困惑。作为一个小的升级,让我们修改我们的输入数据文件如下:
1 2 3 5
2 1 1 6
3 3 3 7
并使用略有不同的绘图命令
plot 'data.dat' using 1:2:3:4 with parallel lc var
这会产生
结果图看起来好一点,但假设我们确实坚持要有一个带点的图。简单地添加类似 pt 1
的内容是行不通的。此外,它会产生一条警告消息:"test.gpl", line 17: warning: No pointtype specifier allowed, here
表明 parallel
样式根本不喜欢任何点规范。
脏修复
为了对此进行部分改进,让我们按以下步骤进行:
cd ${HOME}
#prepare a sand box directory
mkdir gpl
cd gpl
#download the latest version
wget -O gnuplot_latest.tgz http://sourceforge.net/projects/gnuplot/files/latest/download?source=files
tar -xzvf gnuplot_latest.tgz
cd gnuplot-5.0.0
./configure --prefix=${HOME}/gpl/local
make && make install
在这里,我们假设我们的系统已经具备成功构建的所有必要先决条件。例如在 Ubuntu 上,这种最小情况可能只需要 libpango 和 libreadline 的开发包。
现在,我们需要播放一些存储在 ${HOME}/gpl/gnuplot-5.0.0/src
中的源文件。也就是说,我们必须
说服 Gnuplot 绘图风格 parallel
喜欢点。为此,修改 gp_types.h
中的行 114
并替换
就足够了
PARALLELPLOT = 32*PLOT_STYLE_BITS + PLOT_STYLE_HAS_LINE
与
PARALLELPLOT = 32*PLOT_STYLE_BITS + PLOT_STYLE_HAS_LINE + PLOT_STYLE_HAS_POINT
引入了在 parallel
样式中绘制点的功能。为此,必须在文件 graphics.c
中找到函数 plot_parallel
。默认情况下它看起来像这样:
static void
plot_parallel(struct curve_points *plot)
{
int i, j;
int x0, y0, x1, y1;
for (i = 0; i < plot->p_count; i++) {
/* rgb variable - color read from data column */
check_for_variable_color(plot, &plot->varcolor[i]);
x0 = map_x(1.0);
y0 = AXIS_MAP(PARALLEL_AXES+0, plot->z_n[0][i]);
for (j = 1; j < plot->n_par_axes; j++) {
x1 = map_x((double)(j+1));
y1 = AXIS_MAP(PARALLEL_AXES+j, plot->z_n[j][i]);
draw_clip_line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;
}
}
}
让我们稍微打扮一下:
static void
plot_parallel(struct curve_points *plot)
{
int i, j;
int x0, y0, x1, y1;
int point_type;
struct termentry *t = term;
for (i = 0; i < plot->p_count; i++) {
/* rgb variable - color read from data column */
check_for_variable_color(plot, &plot->varcolor[i]);
point_type = plot->varcolor?((int)plot->varcolor[i]-1):plot->lp_properties.p_type;
x0 = map_x(1.0);
y0 = AXIS_MAP(PARALLEL_AXES+0, plot->z_n[0][i]);
(*t->pointsize)(plot->lp_properties.p_size);
(*t->point)(x0, y0, point_type);
for (j = 1; j < plot->n_par_axes; j++) {
x1 = map_x((double)(j+1));
y1 = AXIS_MAP(PARALLEL_AXES+j, plot->z_n[j][i]);
draw_clip_line(x0, y0, x1, y1);
(*t->point)(x1, y1, point_type);
x0 = x1;
y0 = y1;
}
}
}
就是这样!现在用 make && make install
再次编译 Gnuplot(从目录 ${HOME}/gpl/gnuplot-5.0.0
调用)。使用 ${HOME}/gpl/local/bin/gnuplot ${HOME}/gpl/test.gpl
(使用绘图命令 plot 'data.dat' using 1:2:3:4 with parallel lc var ps 1.5
)生成的输出应类似于:
说明
gp_types.h
中的修改确保最终绘图中使用的点大小规范 ps 3
不会被忽略(并且可以在 plot_parallel
函数中访问)
- 在
plot_parallel
函数中,我们需要引入一个指向全局终端变量的指针,即struct termentry *t = term;
。然后将其用于实际绘制点。
在for
循环中迭代输入数据文件中的各个行,我们用
确定对应的点类型
`point_type = plot->varcolor?((int)plot->varcolor[i]-1):plot->lp_properties.p_type;`
这确保如果我们不使用 lc var
,则点类型由 pt
(或默认值)确定。如果lc var
处于活动状态,则点类型取自输入数据文件中相应的数据列。
- 调用
(*t->pointsize)(plot->lp_properties.p_size);
设置用 ps
(或默认值)指定的所需点大小。
- 最后,
(*t->point)(x0, y0, point_type);
类型的调用用点来增加单独的线段。
我需要使用 gnuplot 创建一个包含线和点的平行图。 不幸的是,要么使用
set style line 1 lc rgb 'blue' lt 1 lw 2 pt 7 ps 0.75 pi 5
或者在 plot 命令中设置 pt ps 和 pi
Gnuplot 不插入任何点。
我需要插入点来区分两条颜色相同的线。 它们必须是相同的颜色,因为它们具有相同的 "family"。因此,我不能简单地更改颜色:(
我该怎么做?
谢谢
不幸的是,Gnuplot 确实不支持此功能 "out of the box",但是如果您只是为了一些快速的一次性生产情节而需要它,那么有一种稍微脏的方法可以做到这一点。更具体地说,可以获得当前的Gnuplot源代码,以一种或多或少令人满意的方式引入此功能并使用Gnuplot的修改版本生成所需的图形。
为了说明这个想法,假设我们想要平行绘制以下仅包含三个 "sets":
的数据文件data.dat
1 2 3
2 1 1
3 3 3
受默认 Gnuplot 演示 parallel.dem
的启发,人们可能会尝试使用这样的脚本 test.gpl
来实现这一点:
set title "Parallel Axis Plot" font ",15"
set terminal pdf
set output 'test.pdf'
set border 0
unset key
set xrange [] noextend
unset ytics
# use x-axis tic positions to label the axes
set xtics 1 format "axis %g" scale 0,0
# turn on axis tics for the parallel axes
set for [i=1:3] paxis i tics
plot 'data.dat' using 1:2:3 with parallel
然而,这产生的情节可能类似于:
在这里,所有的线条都是相同的类型和颜色,这让人很困惑。作为一个小的升级,让我们修改我们的输入数据文件如下:
1 2 3 5
2 1 1 6
3 3 3 7
并使用略有不同的绘图命令
plot 'data.dat' using 1:2:3:4 with parallel lc var
这会产生
结果图看起来好一点,但假设我们确实坚持要有一个带点的图。简单地添加类似 pt 1
的内容是行不通的。此外,它会产生一条警告消息:"test.gpl", line 17: warning: No pointtype specifier allowed, here
表明 parallel
样式根本不喜欢任何点规范。
脏修复
为了对此进行部分改进,让我们按以下步骤进行:
cd ${HOME}
#prepare a sand box directory
mkdir gpl
cd gpl
#download the latest version
wget -O gnuplot_latest.tgz http://sourceforge.net/projects/gnuplot/files/latest/download?source=files
tar -xzvf gnuplot_latest.tgz
cd gnuplot-5.0.0
./configure --prefix=${HOME}/gpl/local
make && make install
在这里,我们假设我们的系统已经具备成功构建的所有必要先决条件。例如在 Ubuntu 上,这种最小情况可能只需要 libpango 和 libreadline 的开发包。
现在,我们需要播放一些存储在 ${HOME}/gpl/gnuplot-5.0.0/src
中的源文件。也就是说,我们必须
说服 Gnuplot 绘图风格
就足够了parallel
喜欢点。为此,修改gp_types.h
中的行114
并替换PARALLELPLOT = 32*PLOT_STYLE_BITS + PLOT_STYLE_HAS_LINE
与
PARALLELPLOT = 32*PLOT_STYLE_BITS + PLOT_STYLE_HAS_LINE + PLOT_STYLE_HAS_POINT
引入了在
parallel
样式中绘制点的功能。为此,必须在文件graphics.c
中找到函数plot_parallel
。默认情况下它看起来像这样:static void plot_parallel(struct curve_points *plot) { int i, j; int x0, y0, x1, y1; for (i = 0; i < plot->p_count; i++) { /* rgb variable - color read from data column */ check_for_variable_color(plot, &plot->varcolor[i]); x0 = map_x(1.0); y0 = AXIS_MAP(PARALLEL_AXES+0, plot->z_n[0][i]); for (j = 1; j < plot->n_par_axes; j++) { x1 = map_x((double)(j+1)); y1 = AXIS_MAP(PARALLEL_AXES+j, plot->z_n[j][i]); draw_clip_line(x0, y0, x1, y1); x0 = x1; y0 = y1; } } }
让我们稍微打扮一下:
static void plot_parallel(struct curve_points *plot) { int i, j; int x0, y0, x1, y1; int point_type; struct termentry *t = term; for (i = 0; i < plot->p_count; i++) { /* rgb variable - color read from data column */ check_for_variable_color(plot, &plot->varcolor[i]); point_type = plot->varcolor?((int)plot->varcolor[i]-1):plot->lp_properties.p_type; x0 = map_x(1.0); y0 = AXIS_MAP(PARALLEL_AXES+0, plot->z_n[0][i]); (*t->pointsize)(plot->lp_properties.p_size); (*t->point)(x0, y0, point_type); for (j = 1; j < plot->n_par_axes; j++) { x1 = map_x((double)(j+1)); y1 = AXIS_MAP(PARALLEL_AXES+j, plot->z_n[j][i]); draw_clip_line(x0, y0, x1, y1); (*t->point)(x1, y1, point_type); x0 = x1; y0 = y1; } } }
就是这样!现在用
make && make install
再次编译 Gnuplot(从目录${HOME}/gpl/gnuplot-5.0.0
调用)。使用${HOME}/gpl/local/bin/gnuplot ${HOME}/gpl/test.gpl
(使用绘图命令plot 'data.dat' using 1:2:3:4 with parallel lc var ps 1.5
)生成的输出应类似于:
说明
gp_types.h
中的修改确保最终绘图中使用的点大小规范ps 3
不会被忽略(并且可以在plot_parallel
函数中访问)- 在
plot_parallel
函数中,我们需要引入一个指向全局终端变量的指针,即struct termentry *t = term;
。然后将其用于实际绘制点。 在
确定对应的点类型for
循环中迭代输入数据文件中的各个行,我们用`point_type = plot->varcolor?((int)plot->varcolor[i]-1):plot->lp_properties.p_type;`
这确保如果我们不使用
lc var
,则点类型由pt
(或默认值)确定。如果lc var
处于活动状态,则点类型取自输入数据文件中相应的数据列。- 调用
(*t->pointsize)(plot->lp_properties.p_size);
设置用ps
(或默认值)指定的所需点大小。 - 最后,
(*t->point)(x0, y0, point_type);
类型的调用用点来增加单独的线段。