[Из песочницы] Gnuplot на домашней страничке

Зачем? 58777357ee79410ba7feee0f1adda5fb.pngПри разработке доступной онлайн базы данных для хранения результатов расчётов возникло непреодолимое желание представлять информацию не только в табличном виде, но и в виде графиков. Можно пойти различными путями, например, рисовать кривые в PHP, но правильнее (в смысле UNIX-way) будет использовать внешнюю программу, уже умеющую строить графики, такую как Gnuplot.Особенно интригует возможность вывода графиков в виде набора JS комманд для рисования на HTML5-холсте (canvas), чем мы и займёмся.О Gnuplot много писали, в том числе и на Хабре (1, 2), поэтому нет необходимости в подробном описании его синтаксиса.

К своему удивлению, я не обнаружил хорошего туториала о том, как связать вывод gnuplot с динамически формируемой страничкой. Возможно, это связано с недостатком знаний о Java Script и на самом деле всё очевидно, но тем не менее, есть надежда, что эта статья окажется полезной.

Вывод Gnuplot в HTML5 Canvas Чтобы получить представления о возможностях такого режима, составим минимальный скрипт, рисующий кусок синусоиды в файле output.html: #!/usr/bin/gnuplot set terminal canvas set output «output.html» plot sin (x) with lines Здесь первая строка задает интерпретатор команд, вторая — устанавливает формат вывода canvas. Для особо удачных графиков здесь можно было бы заменить canvas на pdf и сразу вставить результат в статью для, скажем, Nature. Третья строка указывает имя файла для записи, если ее не будет — то поток будет направлен в stdout, чем мы воспользуемся при генерации html-странички. Последняя строка содержит собственно команду для построения графика синуса.Открыв сгенерированный файл output.html, можно увидеть график:

27578d39d0b0496e8b0ac138d55e8f3a.jpg

Хорошо, но такой результат вполне можно было бы получить, вставляя рисунки, полученные и терминалом png, а хотелось бы интерактивности! Для этого нужно всего лишь указать параметры терминала enhanced mousing:

set terminal canvas enhanced mousing set output «output.html» set xlabel 'Time' set ylabel 'Energy' plot sin (4*x)/x with lines linewidth 2 В результате появится панелька с управляющими кнопками, возможность ставить точки и приближать интересующую область: 8d8029bb4c3846d0bac05fa1c6ddffcc.jpg

Уже больше похоже на примеры с сайта разработчиков, но с удаленного компьютера работать не будет, поскольку за вспомогательными JS-скриптами идет обращение в локальную файловую систему, так как сгенерированный файл содержит строки типа:

То есть, нужно разместить файлы из /usr/share/gnuplot/gnuplot/4.6/js на своем сайте, скопировав их или создав ссылку. Для работы достаточно иметь файлы canvastext.js, gnuplot_common.js, gnuplot_mouse.js, gnuplot_mouse.css и png-иконки. Также необходимо указать путь к этим файлам в параметрах терминала: set terminal canvas enhanced mousing jsdir 'js' Взаимодействие PHP и gnuplot Итак, есть путь к папке расчётов, нужно построить график согласно выбранным пунктам на html-страничке.Разобьем задачу на несколько частей, как показано на диаграмме: 5acbbc0cc7f54e768c7732284935a856.png

Такая схема, возможно, избыточна, и всю функциональность можно реализовать на php, но такое разделение разбивает код по его функциям и правам доступа:

shell-скрипт имеет доступ к файлам на диске и запуску gnuplot, но не должен быть доступен снаружи, php и html — наоборот, доступны снаружи и не должны иметь доступа к файлам за пределами сайта, отдельный .gp файл позволяет повторить построение графика, но в более удобном для публикации формате выбором pdf или png терминалов. PHP/HTML html-форма и php-скрипт объединены в один файл plot_calc.php:

$fSite = 1; // текущий 'сайт' if (isset ($_POST[«fSite»])) { $fSite = $_POST[«fSite»]; }

// опущено описание заголовка и стилей echo 'Back'; echo '

Plot Calculation Data

'; echo '
'; echo ' '; echo ' '; // … echo ' '; echo ' '; echo '
';

if (isset ($_POST[«plotProb»])) { // если нажата кнопка plotProb $input='./plot_calc.sh'.' '.'p '.$nSites.' '.$fullpath.' '.$fSite; echo «Probability plot for Site #».$fSite; } if (isset ($_POST[«plotEnergy»])) { // если нажата кнопка plotEnergy $input='./plot_calc.sh'.' '.'E '.$nSites.' '.$fullpath.' '.$fSite; echo «Energy plot for Site #».$fSite; } // …

$output = shell_exec ($input); // запуск скрипта оболочки echo $output; // вывод результата работы скрипта

echo ' '; echo ''; ?> SHELL Задача скрипта plot_calc.sh — формирование команд для gnuplot согласно заданным внешним параметрам. Скрипт создает файл во временной директории /tmp, содержимое которого передается gnuplot, а результат выполнения возвращается обратно, где его уже ждет php-скрипт. #!/bin/bash # параметры: # 1 — тип # 2 — число сайтов # 3 — путь # 4 — сайт для рисования (требуется для p) # -------------- # тип значение # E energy # p probaility # … #------------------------------#

# создадим новый файл во временном каталоге: TFILE=»/tmp/$(basename $0).$$.gp» # запишем в него команды gnuplot: echo »# Automatically generated Gnuplot script » > $TFILE echo «set terminal canvas enhanced mousing jsdir 'js'» >> $TFILE

### Probability ### if [ $1 == 'p' ] then echo «set xlabel 'Time'»>>$TFILE echo «set ylabel 'Probability'»>>$TFILE let icol=$4+1 echo «plot '$3prob.res' u 1:$icol wi li»>>$TFILE fi

# …

### Energy ### if [ $1 == 'E' ] then let col=$4×2 let col1=$4×2+1 echo «set xlabel 'Time'»>>$TFILE echo «set ylabel 'Energy'»>>$TFILE echo «plot '$3Energ.res' u 1:$col:$col1 wi err»>>$TFILE fi

/usr/bin/gnuplot $TFILE Этому файлу потребуются права на исполнение: chmod +x plot_calc.sh Gnuplot Скрипт оболочки формирует выходной файл в имени которого содержится имя вызвавшего скрипта и случайное число, внутренность у него примерно такая: # Automatically generated Gnuplot script set terminal canvas enhanced mousing jsdir 'js' set xlabel 'Time' set ylabel 'Probability' plot '/srv/calculations/GoodCalc/prob.res' u 1:6 wi li Проверить работу можно направив браузер по адресу http://servername/plot_calc.php? path=GoodCalc&nsites=10.В результате появится возможность построить графики по данным файлов prob.res и Energy.res, и должна получится страничка, похожая на: eededa8af7844150a26ad8082b1f18d1.jpg

Генерируемые файлы в /tmp надо время от времени подчищать, для этого сгодится задание cron (от root’а):

crontab -e 0 */1 * * * rm -v /tmp/plot*.gp >> /var/log/rmplotgp.log Заключение Тестирование и демонстрация проводились на Debian Jessie, но должно работать и на прочих системах; JS-файлы gnuplot должны быть доступны из внешней сети; Есть возможность формирования не только html-страничек, но и js-скриптов, управляемых пользовательским кодом. Вопросы нагрузки и безопасности здесь не рассматривались и потребуют дополнительного внимания…

© Habrahabr.ru