Построение графиков в gnuplot: двухмерные графики

Построение графиков в gnuplot достаточно просто и очень эффективно, особенно когда их нужно строить много. Ниже на примерах будет показано, как строить двухмерные графики.

Как построить несколько функций на одном графике?
Есть два варианта: использовать функцию multiplot или внешними редакторами шаманить с EPS-файлами. Ниже будет описан первый вариант как более простой.

При построении нескольких графиков нужно включить режим multi-plot, после чего будет возможно размещать несколько функций или графиков данных в одном окне. Например, построим три функции: y=x, y=x*x и y=x*x*x. Что для этого дополнительно нужно задать в интерактивном режиме:

gnuplot> set multiplot
multiplot> plot x
multiplot> plot x*x
multiplot> plot x*x*x
multiplot> set nomultiplot
Вот что при этом может произойти:



Такое случается потому, что гнуплот определяет границы для каждого графика автоматически, что может привести к нежелательному результату. Следует задавать границы принудительно:
gnuplot> set xrange [-10:10]
gnuplot> set yrange [-10:10]





Как построить график внутри графика?
Рассмотрим это на рабочем примере. Есть файл с данными, точек много, и интерес представляет участок на кривой. Данных много, и естественно это скормить перловому скрипту, который нашинкует графики с подстановкой имён. Вот код графика:
#! /usr/bin/gnuplot -persist
set terminal postscript eps enhanced color solid
set output "~/matlab/programs/kmvdecoder/plots/2conventionalRAWMAXtoSaturatecomparing.ps"
set encoding koi8r
set xlabel "Exposure time, sec." font "Helvetica,18"
set xrange [1:60]
set key top right
set ylabel "Pixels maximum value" font "Helvetica,18"
Это не должно вызывать вопросов - подобное разбиралось тут. Дальше:
set multiplot
set origin 0.0,0.0
set size 1.0,1.0
Устанавливаем стиль линий, которыми будем строить графики
set style line 1 lt 1 pt 9
set style line 2 lt 3 pt 7
set style line 3 lt 2 pt 5
Теперь, собственно, строим основной график.
plot "~/matlab/programs/kmvdecoder/plots/RAWMAXmeasurementresult"
using
3 notitle with linespoints linestyle 2,
"~/matlab/programs/kmvdecoder/plots/RAWMAXmeasurementresult" using 3 n
Пути и имена файлов, естественно, нужно поменять, так как я даю всё на примере собственных файлов. Напоминаю, что для ленивых людей, помимо гнуплота, есть ещё и Perl, скрипты которого резво подставят всё нужное в имя файла: и вы поймёте, и цикл перебора организовать проще. Основной график построен - загружаем его в программу просмотра PostScript-файлов и смотрим, где значения, которые нужно строить внутри маленького графика.
set origin 0.55,0.1
set size 0.4,0.4
Первый параметр задаёт положение левой верхней границы маленького графика в относительных единицах длины. Второй - размер графика. Так как подписи к осям на вложенном графике будут только мешать - отключаем их:
set noxlabel 
set noylabel
С видом графика определились, теперь определяемся с осями:
set xrange [ 30 : 38]
set yrange [ 3300 : 3800 ]
Всё, теперь осталось приказать гнуплоту перестроить график (чтобы появился вложенный):
replot
set nomultiplot
Готово - качественный график быстро и легко построен. Вот как он выглядит:



Как построить простую гистограмму?
Если вы создаёте графики в формате PostScript, самый простой способ заключается в том, чтобы нарисовать это при помощи with impluses с очень тонкими линиями. Например, так:
gnuplot> set term postscript eps enhanced color
gnuplot> set style line 1 lt 1 lw 50
gnuplot> plot "test.dat" using 1:2 with imp ls 1
Вот что при этом получится:


Так же можно заполнять столбики гистограмм цветом или вариантами текстурной заливки при помощи команд
with boxes fs [pattern | solid] номерстилязаливки. Так же можно задавать независимо стиль при помощи команды set style fill.

В случае с with boxes fs pattern, параметр pattern используется для определения заполняющей текстуры. Параметр solid определяет плотность заполнения столбца гистограммы, значени от 0 до 1.

Вот пример гистрограммы, построенной с различной заливкой:
gnuplot> plot "test.dat" usi 1:2:(3) w boxes fs pattern 1,\
gnuplot> "test.dat" usi ($1+5):2:(3) w boxes fs solid 0.7






Как на одном графике построить данные в логарифмическом и обычном масштабе?
Например, есть такой график:


По оси Х в диапазоне [0:30], но вблизи нуля по оси Х данные очень важны и нужно показать их детально. Можно сделать два разных графика, но можно провернуть тоже и на одном.
Сначала построим график до единицы в логарифмическом масштабе:
gnuplot> set log xy
gnuplot> set xrange [ 0.001 : 1 ]
gnuplot> set yrange [ 0.1 : 5000 ]
gnuplot> set xlabel "Energy [eV]"
Для данных в диапазоне [1:30] используем линейные оси, и поместим второй график за первым, используя возможности multiplot. Таким образом, логарифмическая часть графика будет слева, а линейная - справа. Каждый подграфик займёт половину размера картинки. Вот как это выглядит в коде:
gnuplot> set multiplot
multiplot> set size 0.5,1
multiplot> set origin 0.0,0.0
multiplot> set lmargin 10
multiplot> set rmargin 0
multiplot> plot "calc.dat" u 1:2 w l
multiplot> set origin 0.5,0.0
multiplot> set format y ""
multiplot> set lmargin 0
multiplot> set rmargin 2
multiplot> set nolog x
multiplot> set xrange [1:30]
multiplot> set xtic 0,10
multiplot> set mxtic 5
multiplot> plot "calc.dat" u 1:2 w l
multiplot> set nomultiplot
gnuplot>
Результат смотрится очень эффектно:





Как сравнить похожие данные на одном графике?
Если нужно сравнить два набора сходных данных на одном и том же графике, полезно построить график в масштабе относительно другого набора данных. Абсолютная величина значений сравнивается на логарифмическом графике в верхней части, а сотношение показывается в нижней части графика в линейных осях.

Для того, чтобы вычислить соотношение данных одного ряда по отношению к другому, значения по оси Х должны быть одинаковы для обоих рядов. В примере ниже, первая колонка содержит значения Х, вторая колонка содержит значения по оси Y набора данных А, третья колонка содержит значения Y набора данных Б.

Сначала устанавливаем параметры оси Х, одинаковые для обоих наборов данных:
gnuplot> set xrange [ 0.01 : 30 ]
gnuplot> set nokey
gnuplot> set log x
gnuplot> set xtics 10
gnuplot> set mxtics 10
gnuplot> set lmargin 10
gnuplot> set rmargin 2
Теперь создаём нижнюю часть графика, которая показывает соотношение данных. Так как данные по оси Y находятся во втором и третьем столбце файла с данными, можно построить их соотношение так plot 1:($2/$3). Таким образом, вторая часть выглядит так:

gnuplot> set multiplot
multiplot> set yrange [ 0.5 : 1.5 ]
multiplot> set ytic 0.6,0.2,1.4
multiplot> set ylabel "Ratio"
multiplot> set size 1,0.4
multiplot> set xlabel "Energy [eV]"
multiplot> set origin 0.0,0.0
multiplot> set bmargin 3
multiplot> set tmargin 0
multiplot> plot 1 w l 0,"cross.dat" u 1:($2/$3) w l 1
Осталось доделать верхнюю часть, чем сейчас и займёмся. Сделаем размер графика поменьше и отобразим в логарифмических осях. Наименования по оси Х стираем, и вот что получилось:
multiplot> set log xy
multiplot> set yrange [ 0.1 : 5000 ]
multiplot> set ytic 0.1,10
multiplot> set ylabel "Cross Section [b]"
multiplot> set size 1,0.6
multiplot> set origin 0.0,0.4
multiplot> set bmargin 0
multiplot> set tmargin 1
multiplot> set format x ""
multiplot> set xlabel ""
multiplot> plot "cross.dat" u 1:2 w l,"" u 1:3 w l
multiplot> set nomultiplot
gnuplot>
Результат:

9 комментариев: |высказаться!| RSS-лента дискуссии.|
jetxee комментирует...

Всё хорошо, отличный пост. Только я бы не называл это «двумерными» графиками. Если так, то что тогда такое «одномерные» графики?

В общем, я сторонник классифицировать средства визуализации по размерности данных (функция заданная на 1D-множестве — одномерный график, на двумерном — двумерный).

Поставил ссылки на твои статьи в заметке Строим графики: графический интерфейс для gnuplot.

Анонимный комментирует...

Отличная информация! Особенно понравилось совмещение логирифмического и линейного масштабов.
А может быть Вы знаете как правильно построить график с разрывами по оси абсцисс? Дело в том, что мне нужно строить рентгенограммы. Снимались они широком интервале по углу, однако, интересны только несколько узких участков с пиками. Простой опции разрыва оси не нашел в документации. Можно, конечно, строить мультиплоты, как в примере с разными масштабами, однако придется вручную подбирать ориджины, сложновато будет.

virens комментирует...

2 jetxee пишет...
я бы не называл это «двумерными» графиками. Если так, то что тогда такое «одномерные» графики?
А как же тогда это называть?

Поставил ссылки на твои статьи
Спасибо!

2 Анонимный пишет...
Особенно понравилось совмещение логирифмического и линейного масштабов.
В общем, это довольно экзотический пример, но оказывается, что и ему можно найти применение.

А может быть Вы знаете как правильно построить график с разрывами по оси абсцисс?
Надо смотреть конкретно, а у меня со временем очень туго.

Анонимный комментирует...

Для построения графиков кроме общеизвестного gnuplot в Линуксе есть куда менее известная, но ничуть не менее могучая программа Grace. Вопреки первому впечатлению после запуска, в ней таки ЕСТЬ
командный язык, а не только "мышиный интерфейс".
И может она очень многое - в дебиановском пакете
с ней вместе лежит ряд наглядных примеров в виде
программ на встроенном языке.
Сам я стал пользоваться Grace тогда, когда потребовалось сделать динамически меняющуюся визуализацию поступающих в компьютер данных - программа оказалась способна делать это несколько более интеллигентно чем gnuplot.

Анонимный комментирует...

а-яй-яй. Копируете статью - поставьте ссылку на оригинал! = http://t16web.lanl.gov/Kawano/gnuplot

Denis комментирует...

# RAZRYV OSI
reset
unset key
bm = 0.15
lm = 0.12
rm = 0.95
gap = 0.03
size = 0.75
y1 = 0.0; y2 = 11.5; y3 = 58.5; y4 = 64.0
#kk = 0.7 #relative height of bottom plot
# or to keep proportional scale
kk = (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) )

set multiplot
set xlabel 'Time [ns]'
set border 1+2+8
set xtics nomirror
set ytics nomirror
set lmargin at screen lm
set rmargin at screen rm
set bmargin at screen bm
set tmargin at screen bm + size * kk

set yrange [y1:y2]
plot [0:40] 20.0*atan(x-20.0) + 32 + sin(x)

unset xtics
unset xlabel
set border 2+4+8
set bmargin at screen bm + size * kk + gap
set tmargin at screen bm + size + gap
set yrange [y3:y4]

set label 'Power [mW]' at screen 0.03, bm + 0.5 * (size + gap) offset 0,-strlen("Power [mW]")/4.0 rotate by 90

set arrow from screen lm - gap / 4.0, bm + size * kk - gap / 4.0 to screen \
lm + gap / 4.0, bm + size * kk + gap / 4.0 nohead

set arrow from screen lm - gap / 4.0, bm + size * kk - gap / 4.0 + gap to screen \
lm + gap / 4.0, bm + size * kk + gap / 4.0 + gap nohead
set arrow from screen rm - gap / 4.0, bm + size *kk - gap / 4.0 to screen \
rm + gap / 4.0, bm + size * kk + gap / 4.0 nohead

set arrow from screen rm - gap / 4.0, bm + size * kk - gap / 4.0 + gap to screen \
rm + gap / 4.0, bm + size * kk + gap / 4.0 + gap nohead

plot [0:40] 20.0*atan(x-20.0) + 32 + sin(x)

unset multiplot

Анонимный комментирует...

как можно поставить точки в конкретных (x,y) кординатах

Катерина комментирует...

Насчет logscale-гнуплот умеет это делать только для положительной части оси,а мне нужно ее всю сделать в логарифмическом масштабе,т.е. чтобы на оси ординат откладывались lg(y) при y>0 и -lg(-y) при y<0. Просто брать отрицательные данные со знаком минус - "plot data.dat using 1:(-$2)" и потом сделать set yrange reverse не получится,т.к. рисуется сложная картина,вместе с различными обьектами,данные берутся из многих файлов. Может кто-то сталкивался с таким,подскажите как это сделать?

Сергей комментирует...

Катерина: «Насчет logscale-гнуплот умеет это делать только для положительной части оси,а мне нужно ее всю сделать в логарифмическом масштабе,т.е. чтобы на оси ординат откладывались lg(y) при y>0 и -lg(-y) при y<0.»

Катерина, вещественный логарифм определён только для положительных аргументов. Он отображает положительную полуось на всё множество вещественных чисел. Если параметр не строго положителен, то логарифмический масштаб оси ему не подходит. Не подходит логарифмический масштаб и для параметров, которые могут принимать нулевые значения — в нуле логарифм тоже не определён.

А то, что хотите сделать вы, не является взаимно-однозначным отображением и поэтому не является стандартным масштабом для осей.

Впрочем, в гнуплоте можно построить график функции, которую вы описали. Предполагая, что исходная функция, например x**3, ваш график будет строится вот такой командой:

plot sgn(x**3)*log(abs(x**3)) with lines

Однако в нуле эта функция всё равно не определена.

Отправить комментарий

Подписаться на RSS-ленту комментариев к этому посту.