При моделировании геофизических процессов постоянно надо рисовать. Речь идет не только о высококачественных иллюстрациях для публикаций — ежедневная рутина вроде "посчитал, нарисовал, поглядел, подумал, исправил, поставил считаться...". Или "нарисовал, послал коллеге, обсудили, отложили для статьи..."
Средств для визуализации именно геофизических данных не так чтобы много. В этой заметке я расскажу по GrADS (Grid Analysis and Display System) — средство удобное именно для постоянной, рутинной работы с данными и моделями.
Что приятно — Градс не надо устанавливать, хотя в исходных кодах он доступен. Скачиваете набор скомпилированных под вашу систему утилит и чуть настраиваете переменные окружения. Запуск grads в командной строке создает графическое окошко и командную строку уже самого Градса, и можно вводить туда команды, в том числе — скрипты, написанные на особом скриптовом языке. Там же есть документация.
ОБНОВЛЕНИЕ (май 2022): по неясным причинам пропал доступ к онлайн-документации. Я нашел зеркало, пользуйтесь им.
GrADS использует пятимерную схему для массивов данных: четыре измерения обычных (долгота, широта, вертикальный уровень и время), плюс еще одно необязательное измерение. Оно реализовано как общее (и можно его употребить для своих надобностей), но предназначено для ансамблей. Данные распределяются по пятимерному массиву согласно описательному файлу. На самом деле, массивы шестимерные, поскольку еще есть дискретное измерение — отдельные переменные, например, температура и соленость или три компоненты вектора скорости). Есть и возможность работ со станционными данными (в отдельных точках, станция в науках о Земле — отдельное измерение).
Есть поддержка стандартных форматов, в том числе самодостаточных (то есть, включающих описание данных): GRIB (версий 1 и 2), NetCDF, HDF (версий 4 и 5) и BUFR (для данных по станциям). А можно работать с сырыми файлами, записанными из фортрана прямым доступом: просто трехмерные массивы геофизических переменных, по порядку.
Пусть, например, каждый день высчитываются трехмерные массивы температуры и солености; тогда в файле последовательно будут лежать: T1,S1, T2,S2, T3,S3, и так далее. Сами массивы трехмерны и упорядочены так: долгота, широта, вертикальный уровень. Если в фортране их определить как real, dimension(N,M,K):: T, S, то можно записывать их один за другим, и все будет правильно. При этом N точек по долготе, M по широте, K по вертикали.
Кстати, важно: точность должна быть одинарной! REAL, а не DOUBLE PRECISION. Четыре байта на число.
Для таких файлов данных нужен описательный файлик, текстовый, такого примерно вида:
DSET ^TS_global.dat — Имя файла, крышечка означает "в этом каталоге"
TITLE My data file — Описание
UNDEF 1.E20 — отсутствующее значение. Оно не отрисовывается.
XDEF 180 LINEAR 0.0 2.0 — сетка по долготе. 180 узлов, равномерный шаг 2 градуса, от 0.0 градусов
YDEF 90 LINEAR -90 2.0 — сетка по широте. 90 узлов, равномерный шаг 2 градуса, от -90 градусов.
ZDEF 10 LEVELS 1000 850 700 500 400 300 250 200 150 100 — неравномерная сетка по глубине. 10 уровней, перечислены
TDEF 4 LINEAR 0Z10apr1991 12hr — сетка по времени. 4 отсчета, равномерный шаг 12 часов, от полуночи (0Z) указанной даты. Единица может быть my (минуты), hr (часы), dy (сутки), mo (месяцы), yr (годы).
VARS 2 — Число переменных
T 10 99 sea water temperature, C — переменная: имя, число уровней по вертикали, 99 просто так, далее комментарий (обычно единица измерения и что за величина).
S 10 99 sea water salinity, ppt
ENDVARS — ну, и всё.
Открывается файл командой open, если самодостаточный — то sdfopen. SDF — это self-describing format, самодостаточный формат. Далее можно выставить диапазон измерений:
set lon 39 42 (долгота),
set lat 66.6 (широта здесь у нас фиксирована)
set lev -42 0 (уровень лучше задавать отрицательный для моря, чтобы дно было внизу, но тогда в описателе нужно уровни описывать отрицательными, и в файл их записывать в обратном порядке — сначала дно, потом поверхность).
Не более двух измерений могут быть диапазонами. Время задается особо: set time 00:00Z10may1978 — время в часах и минутах, потом номер дня в месяце, потом три буквы месяца, и год. Но можно и просто set time jul - если, например, в файле данные по месяцам.
Есть огромное количество опций, которые можно задавать через set. Я обычно первым делом включаю:
set background 1 — белый фон (по умолчанию черный)
set mproj scaled — проекция (по умолчанию шаги по долготе и широте равные, что некрасиво для Севера)
set mpdraw on — рисовать контур берега, включена по умолчанию
set mpset hires — высокое разрешение (по умолчаниию грубый контур, контуры уже есть в поставке!).
set grads off — убрать логотип.
Можно выбрать тип карты: set gxout. Варианты: contour для линий уровня, shaded для закрашенных областей, vector для векторных полей, stream для линий тока (к которым векторное поле касательное). Это не все, но самое ходовое.
Основные команды -- это c, которая очищает рисунок, и d, которая рисует. Вторая принимает параметр — переменную. Например:
d T — нарисовать переменную Т в указанном диапазоне
d u;v — нарисовать векторное поле скорости
d u;v;mag(u,v) — нарисовать векторное поле и раскрасить по третьему аргументу (длина вектора)
d T.1 - T.2 — нарисовать разность температур из файла 1 и файла 2. Оба файла должны быть открыты.
Для линий уровня и областей уровни определяются автоматически. Но можно задать жестко (команда с снимает эту опцию):
set clevs 0 2 4 6 8 10
Чтобы сохранить рисунок, есть команда gxprint, которая заменила команды printim и print. Я пользуюсь printim, которая записывает рисунок в EPS или PNG.
Что еще можно из хитрого. Делать мультики внешней утилитой convert из пакета ImageMagick; добавлять на рисунки текст; менять цветовую шкалу; рисовать произвольные прямолинейные разрезы; писать скрипты вроде "в цикле по годам, открыть файл, нарисовать все дни года с 1 января по 31 мая и с 1 ноября да конца года", а также намного более сложные скрипты. Например, скрипт cbarn.gs, который можно скачать из библиотеки скриптов, добавляет к рисунку цветовую шкалу, и очень полезен для закрашенных областей (set gxout shaded). Обо всем этом расскажу как-нибудь в другой раз.