Формат хранения научных данных, ориентированный на многомерные массивы - netCDF. Расшифровывается Network Common Data Form (Сетевое общее представление данных). Подробнее у авторов, на Вики , здесь и тут.
Формат самодокументируемый, платформонезависимый и рассчитан на эффективное выделение подмножеств (из массивов данных). Упрощенно, суть в следующем. Есть понятие переменной, которая представляет собой одно- или многомерный массив. Есть измерения, которые описывают измерения этого массива, то есть одной или нескольких переменных, и сами являются переменными (одномерными).
Например, температура воздуха в приводном слое. Это трехмерный массив, потому что температура зависит от долготы, широты и времени. А если речь идет о температуре воздуха вообще, то массив четырехмерный, потому что еще добавляется высота. Каждое измерение (долгота, широта, время, высота и т.д.) - это тоже массив, так как данные заданы на сетке, той или иной. Поэтому в netCDF-файле с температурой в приводном слое (это реальный пример) будут переменные lat lon time air и измерения lat lon time. Имея доступ к переменным, мы можем узнать все про сетку и получить температуру на ней.
Еще есть атрибуты - у файла в целом и у каждой переменной. Некоторые атрибуты файла (с температурой): history - кто и когда создал файл, references - ссылка, title - намек на содержимое, description = "Data is from NMC initialized reanalysis (4x/day). It consists of T62 variables interpolated to pressure surfaces from model (sigma) surfaces". Атрибуты переменных позволяют, главное, выяснить размерность переменной (units). Если для долготы и широты можно сделать предположение, то со временем труднее. Там значения типа 17338818. А это часы от полуночи 1 января 0001 года. Еще диапазон, длинное имя (latitude вместо lat), стандартное имя. Время, например, имеет еще шаг и средний интервал.
У основной переменной есть еще атрибуты. Важными являются: пропущенное значение - число, которое "безумно" и ставится вместо пропущенных по тем или иным причинам значений. Для температуры это свыше 700 градусов (Кельвина). И вот что очень, очень важно! Данные хранятся не в бинарной форме, а закодированы так, что хранятся как целые. Преобразование линейно, умножить на множитель и прибавить сдвиг. Это тоже атрибуты. Иногда (у меня было) распаковка производится некорректно - тогда надо ее отключать и делать это вручную. Когда температура зашкаливает - это заметно, но когда давление 1.3 атмосферы - новичок скумекает не сразу. А я был новичком как раз. Но решил, что многовато - я бы знал, что там такая аномалия круглый год.
На сайте разработчиков есть софт и интерфейсы для C, Фортрана и Перла. Есть, конечно, и для многих других языков, но это не интересно (мне). Я читаю на Перле и вот почему. Если "все известно", то нет нужды возиться с netCDF - программа читает, что ей надо, и пишет, куда считает нужным, и нечего ее тормозить и привязывать к библиотекам. Если ничего не известно, то программа не настолько сметлива, чтобы найти, что ей надо - мы же расчет моря делаем, а не систему искусственного интеллекта. Так что данные так и так заботливо готовлю я. А Perl позволяет интерактивно почитать файл, узнать содержимое и атрибуты, вырезать кусочек (у меня берется северное полушарие и четверть экватора от Гринвича на восток). Можно даже интерполировать на удобную сетку вместо исходной. См. заметку про PDL.
Теперь о средствах. Модуль PDL::NetCDF в комплекте с PDL не идет, но легко ставится из CPAN. Объектно-ориентированный модуль. Подключаем его, как обычно, use PDL::NetCDF; потом заводим объект: my $nc = PDL::NetCDF->new($filename,{MODE=>PDL::NetCDF::O_RDONLY}); Получаем список переменных: my @var = @{$nc->getvariablenames()}; и так далее. Получаем список атрибутов и т.п. Затем читаем выбранную переменную (без распаковки):
my $t = $nc->get($var,{NOCOMPRESS => 1}); Кстати, тут и выше, что это за фигурные скобки? А это анонимный хэш, удобное средство для передачи необязательных параметров без учета порядка. В данном случае в хэше одно значение 1 с ключом NOCOMPRESS.
Теперь получаем коэффициенты преобразования:
my $sc = pdl $nc->getatt('scale_factor',$var);my $sh = pdl$nc->getatt('add_offset',$var);
И преобразуем: $t = $t * $sc + $sh;
Для записи в сырой формат (совместимый с прямым доступом Фортрана) я использую модуль Flexraw из CPAN.
Еще есть модуль NetCDF для Перла. Он аналогичен модулям для Фортрана и С - процедурный. Я про него много сказать не могу, пользуюсь вышеописанным, хотя он неправильно распаковывает (этим и объясняется ключ NOCOMPRESS). Разработчикам отписал...