GP для построения графиков

Недавно взялся улучшать свою программу GP для построения графиков. Нашлись некоторые идеи и программа стала усложнятся. Сейчас подготовил описание основных особенностей и возможностей GP. Надеюсь это устранит непонимание, зачем нужно делать еще один плоттер. Или я узнаю, что все тоже самое можно сделать с помощью чего-то еще.


Цель GP быть быстрой и простой программой для построения графиков и анализа численных данных. Она не пытается заменить все остальные построители графиков.

Основные особенности:

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

На данным момент программа остается экспериментальной. Для сборки из исходных текстов, необходимы библиотеки SDL2, SDL2_ttf, SDL2_image. Проверена работоспособность в GNU/Linux и Windows с компиляторами GCC и MSVC.

В начале, покажу как можно использовать GP на простом примере. Для этого понадобятся данные в виде текстового файла с несколькими столбцами чисел. Так же необходимо задать конфигурацию GP, в наиболее простом случае она может выглядеть вот так.

#!/tmp/gp/gp

font 16 "/usr/share/fonts/corefonts/cour.ttf"
load 0 -1 text "data.txt"

page "Current"
figure -1 2 "Plant Q"

page "Speed"
figure -1 3 "Plant"
figure -1 13 "Estimated"


Здесь заданы две страницы, на первой один график тока двигателя, на второй два графика, скорость модели и оценка скорости бездатчиковым наблюдателем.

После ключевого слова figure указываются номера столбцов в файле данных, первый используется как значения по оси X второй по Y. Отрицательное значение показывает, что будет использоваться номер строки. Завершающий параметр название графика.

Для загрузки файлов данных используется слово load, после него указывается идентификатор файла, который используется для того чтобы в дальнейшем ссылаться на этот файл данных. Следующий параметр определяет количество строк для которых будет выделена память, отрицательное значение приводит к автоматическому определению параметра основываясь на размере файла. Параметр полезен при построении в реальном времени для задания длины окна в котором строится график. Следующий параметр указывает тип файла, текстовый (text) или бинарный (float, в этом случае указывается еще и количество столбцов), далее имя файла.

GP принимает единственный параметр имя файла конфигурации. При обнаружении ошибок в файле будет выведено сообщение содержащее номер строки и некоторое пояснение произошедшего. Например если указать слишком большой номер столбца который не существует, будет выведено.

10: Column numbers are out of range
10: Failed to parse the line
Invalid configuration


Для более полного описания всех ключевых слов и их параметров смотрите пример конфигурации в репозитории.

В показанной выше конфигурации GP будет выглядеть как показано на рисунке, переключение между страницами осуществляется стрелками вверх/вниз.



Часто бывает полезно посмотреть несколько переменных на одной временной сетке. Переменные могут значительно отличатся по величине, что делает невозможным их построение на одном графике с двумя осями. Такая необходимость подтолкнула к добавлению возможности комбинирования нескольких страниц в одну. Для того чтобы получить комбинацию страниц надо выбрать соответствующий пункт в глобальном меню или воспользоваться назначенной для этого клавишей. Затем выбрать страницу, графики с которой необходимо добавить на текущую. Глобальное меню вызывается правой кнопкой на заголовке с названием графика. Таким образом можно добавлять любое количество графиков на текущую страницу, пока не будет достигнуто максимальное количество графиков или осей. Существует альтернативный вариант комбинирования в котором выбирается только один график со страницы.



При этом будет происходить переназначение осей, так чтобы добавляемые графики не попадали на текущие оси если на них показаны разные данные. Ось X не была переназначена потому что все графики построены от одного столбца данных на оси X, нет смысла создавать две одинаковые оси. Существуют правила переназначения осей. Добавляемый график перекладывается на новую ось если не находится совместимой с ним оси. Ось будет совместимой если на ней уже построен график от того же столбца данных либо если столбцы находятся в одной группе. Оси и столбцы по X рассматриваются отдельно от Y.

Группы столбцов данных задаются в конфигурации ключевым словом group. Может быть полезно группировать все столбцы содержащие данные в одних единицах измерения. Ключевое слово deflabel задает метку для группы, если метки осей не заданы индивидуально на странице то используется метка группы в которую входит соответствующий столбец данных. Дополняя предыдущий пример можно назначить метку столбцу -1. Тогда на всех страницах если график строится от столбца -1 будет добавлена метка.

group 0 -1
deflabel 0 "Tick"




Для поиска страниц в списке контекстного меню существует нечеткий поиск который начинается как только происходит текстовый набор строки поиска. Номер графика включается в поиск, поэтому можно искать и по номеру и по названию.



Соответствие графиков и осей можно изменять как в конфигурационном файле так и во время просмотра. Путем выбора пунктов контекстных меню на осях и на названиях графиков. Удерживая клавишу Shift при наведении курсора на ось можно увидеть с какими графиками она связана и наоборот. При удалении оси, все графики с нее переносятся на текущую. Соответственно, удалить текущую ось нельзя. При удалении графика, если образовались оси с которыми не связан ни один график то они удаляются.



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

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



Для задания в конфигурационном файле отдельных осей для графика после определения figure, на следующей строке используется слово map с двумя параметрами задающими номера осей для X и Y соответственно. Без явного указания номера всегда выбираются 0 и 1. Конфигурация осей сохраняется при комбинировании страницы, за исключением случая выбора отдельного графика со страницы.

В пределах страницы может быть использовано слово slave задающее связи между осями. В этом случае необходимо явно указать множитель и сдвиг определяющий преобразование между осями.

Если необходимо перенести график на бумагу, то существует две цветовые схемы с белым фоном, цветная и черно-белая. Цветовые схемы переключаются так же через глобальное меню или клавишу. Всего существует три схемы, темная, светлая и черно-белая. Для того чтобы можно было разобрать на черно-белом рисунке, какая линия к какому графику относится, существуют метки. Включить и расставить метки на графики можно через глобальное меню или соответствующую клавишу. Метки могут быть расставлены по сетке оси X либо по оси Y для чего нужно удерживать Shift при включении режима отображения меток.



Так же возможно назначение способа рисования и толщины для каждого графика. С помощью линий либо точек. В конфигурационном файле этому соответствует слово style после определения графика либо глобальный defstyle. Описание параметров можно найти в примере конфигурации. В контекстном меню графиков так же присутствуют соответствующие пункты чтобы изменить способ рисования графика или толщину.

При загрузке нескольких файлов данных, переключение между ними может производится с помощью ключевого слова bind. Так что каждый график на странице может быть построен из отдельного файла данных. В следующем примере загрузим два файла данных. Назначим группу 0 в которую войдут нулевые столбцы из каждого файла данных. Затем зададим две страницы с графиками из разных источников. Вторая страница содержит три графика два из которых строятся по данным из файла 0, один оставшийся по данным из файла 1. Задать два столбца из разных файлов одному графику невозможно.

load 0 -1 text "data1.txt"
load 1 -1 float 100 "data2.f"

bind 0
group 0 0

bind 1
group 0 0

page "Current"
bind 0
figure 0 2 "Plant Q"

page "Speed"
bind 1
figure 0 3 "Plant"
figure 0 13 "Estimated"
bind 0
figure 0 1 "Plant D"


В настоящее время функция построения разности графиков работает только для графиков построенных из одного файла данных.

Для построения графиков в реальном времени в качестве файла данных указывается например последовательный порт. Так же в этом случаен необходимо задать параметр batch равным 1. Это означает, что график необходимо перестроить после прочтения одной строки файла данных. Для регулярных файлов этот параметр следует задавать достаточно большим для ускорения чтения. В режиме реального времени, при сбросе масштабов осей они переходят в особый режим. В этом режиме пересчет масштабов происходит каждый раз когда поступают новые данные. Режим отключается как только все входные файлы будут прочитаны или когда масштаб будет изменен вручную.

batch 1
load 0 500 text "/dev/rfcomm0"


Некоторые другие особенности и возможности программы здесь не рассмотрены по причини их незначительности либо недостаточной степени готовности. Вот некоторые из возможностей которые находятся на ранних стадиях.

— Срез данных, вывод координат пересечения графиков с указанной линией (недавно реализовано).
— Измерение расстояний между точками графиков.
— Глобальная разметка, не исчезающая при переключении страниц.
— Еще несколько типов преобразования данных. Масштабирование, взятие приращений и сумм.
— Выравнивание сетки всех осей по активным осям.
— Редактирование текстовых меток через контекстное меню.
— Поддержка более точного внутреннего представления данных (сейчас только одинарный float).

bitbucket.org/amaora/gp/overview

// gif-ки на стороннем хостинге, т.к. местный обработчик картинок обрубает всю анимацию.
  • +1
  • 07 января 2017, 22:20
  • amaora

Комментарии (12)

RSS свернуть / развернуть
Возможно, под Win стоило выложить бинарные сборки? Я бы с удовольствием попробовал программу в деле, но разбираться с тонкостями компиляции…
0
// gif-ки на стороннем хостинге, т.к. местный обработчик картинок обрубает всю анимацию.
Что по своему неплохо, мигающие гифки раздражают.
Для загрузки файлов данных используется слово load, после него указывается идентификатор файла
Не думал более по-человечески обозначать идентификаторы, нежели цифрами?
Проверена работоспособность в GNU/Linux и Windows с компиляторами GCC и MSVC.
Хреновато оно под виндой билдится, по крайней мере в комбинации TCC + SDL 2.0.5. Пришлось не только в мейкфайл лезть, но и в сырки. А, и еще оно создает папку tmp в корне, что несколько неуместно в винде)
Сама прожка тоже не очень красиво себя ведет под виндой, например в деле загрузки шрифтов. Неплохо бы под виндой автоматически искать их в %WINDIR%\Fonts. Ну или хотя бы уметь открывать файлы по такому пути, чтобы не хардкодить путь к винде в .gp-файле) Кстати, если шрифт не находит — падает.
P.S. Сборка под Win32. Чуть фикшеные сырки в комплекте.
0
  • avatar
  • Vga
  • 10 января 2017, 10:38
Спасибо за бинарники — поколупаю на досуге.
0
Что по своему неплохо, мигающие гифки раздражают.
А без них будет понятно, что такое комбинирование страниц? Переназначение осей? Или с ними тоже не понятно?

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

Хреновато оно под виндой билдится, по крайней мере в комбинации TCC + SDL 2.0.5.
Да, я сопротивляюсь написанию платформозависимого кода. Пытаюсь обойтись тем, что умеет SDL. Находить путь к шрифтам она не умеет. Makefile написан только для GNU. Корректный выход при неудачном открытии файлов сделаю, спасибо.

Использование GP подразумевает, что конфиг пишется однократно а используется очень много раз. Что-то поменяли, получили новые данные, смотрим графики. Поэтому я не нахожу большой проблемы в ручном указании пути к шрифту.
0
Или с ними тоже не понятно?
Честно говоря, с такой скоростью мигания я не успеваю разобрать. Уж лучше три отдельные картинки.
Нет, пока не имею конфигураций с сотнями файлов.
И чем это мешает переделать иды с числовых на строковые?
Находить путь к шрифтам она не умеет.
Хотя бы подстановку переменных среды сделай. Хотя ИМХО, не помешало бы и немного платформозависимого кода, иначе платформозависимыми становятся уже файлы конфигурации.
Поэтому я не нахожу большой проблемы в ручном указании пути к шрифту.
Проблема будет, как только .gp попадет в репозиторий, которым пользуются несколько девелоперов… Даже в случае если у обоих ОС одного семейства, путь к шрифту может различаться. В принципе, можно решить это введением системного конфига, где указываются пути для скриншотов, папки со шрифтами, etc.
Корректный выход при неудачном открытии файлов сделаю, спасибо.
Для шрифта лучше делать фоллбэк к дефолтному. Отказываться работать вообще при проблемах с чисто косметическими опциями — имхо некрасиво.
0
Управление программой, конечно, далеко от интуитивного. Как, например, вызвать упоминающееся «главное меню»?)
0
  • avatar
  • Vga
  • 10 января 2017, 11:30
Это было в тексте.

Глобальное меню вызывается правой кнопкой на заголовке с названием графика.
0
Несколько раз искал — не заметил) Подумай над введением гуя.
0
Что значит, введением гуя? Контекстное меню не оно? Я их добавил от того, что на все действия клавиш не хватит, точнее я сам быстро начну забывать куда какое действие назначено.
0
Не только меню, но и явная кнопка его вызова. Возможно — вкладки для страниц. В общем, чтобы в этом можно было разобраться методом тыка мышью, не читая документацию.
0
Когда надо что-то по-быстрому рассчитать, обработать какие-то данные всякими алгоритмами, и всё это удобно визуализировать — использую Python с дополнительным пакетом Numpy, в составе которого есть Matplotlib. Возможности и удобство просто потрясающие.
0
Интерактивная смотрелка очень примитивная, как и у gnuplot. Им хорошо строить графики на бумагу, а не анализировать численные данные. У GP другие цели.

Можно было бы попробовать сделать то, что мне нужно на питоне через matplotlib, написать свой бэкенд. Но этот путь для меня сложнее, чем C и SDL.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.