Открываем netCDF в MATLAB (на примере NCEP реанализа)
Задача: Открыть файл формата netCDF в MATLAB
Решение: чистый незамутненный MATLAB
Постараюсь описать здесь ответ на этот животрепещущий вопрос, чтобы было куда отправлять страждущих с различных форумов. Начиная с версии 7.7, Matlab поддерживает работу с форматом netCDF нативно, без различных примочек, которые требовались раньше. Синтаксис, который используется для работы с netCDF файлами довольно странный, ну да, не мне судить. Здесь я опишу, как в Matlab совершить одно простое действие, а именно прочитать данные из файла.
Если вы собираетесь работать с netCDF, то для начала неплохо бы ознакомиться с тем, .
Для начала, давайте скачаем подопытный файл. Это будет файл с шестичасовой приземной температурой любимого всеми гидрометеорологами (20 мегабайт). Чтобы открыть netCDF файл, нужно иметь представление о его структуре, о тех переменных которые в нем находятся и об аттрибутах этих переменных. Для этого служит функция ncdisp.
В результате вы получите табличку с данными по вашему файлу. По большому счету вас должно интересовать только то что находится в разделе Variables, то есть информация о переменных, содержащихся в вашем файле. В данном примере это переменные lat (широты), lon (долготы), time(время прошедшее от 1-1-1 00:00:0.0 в часах), air (температура воздуха в Кельвинах).
UPD: Говорят что не во всех релизах Матлаба есть функция ncdisp. Если у вас тот самый запущенный случай, то для виндоуз вы , для Убунту Линукс и ему подобных пишите в терминале:
Далее в терминале виндоуз или линукс вводите команду
по идее, если вы работаете в Виндоуз, то программа ncdump.exe должна быть в папке с файлом. Эта команда выведет вам примерно ту же информацию что и ncdisp.
Сначала давайте попробуем добыть главное - температуру воздуха. Перво-наперво нужно открыть файл, для того чтобы Matlab мог с ним работать:
По каким-то своим внутренним причинам функции, которые запрашивают данные из переменных netCDF, работают не с их именами, а с их порядковыми номерами, поэтому нам нужно узнать каков порядковый номер переменной air:
varid =
3
Получился порядковый номер 3. Мы в общем и сами могли это посчитать, зная, что счет переменных в данном случае идет с нуля, а не с единицы.
Теперь, зная порядковый номер netCDF переменной, мы можем скопировать значения из нее в переменную Матлаба:
В итоге вы получите трехмерную матрицу [долгота, широта, время]. Казалось бы задача решена, но не стоит торопиться. Если вы взгляните на значения в переменной data, то они будут очень отдаленно напоминать то, что вы ожидаете увидеть, таких температур, даже если они выражены в Кельвинах, на Земле не бывает. Дело в том что данные в файлах реанализа хранятся в виде целых чисел, которые занимают гораздо меньше места чем числа с плавающей запятой. Делается это для того, чтобы файлы были меньше. Чтобы получить температуру, нужно преобразовать эти данные нехитрым способом.
Если вы посмотрите на атрибуты для переменной air, полученные при помощи ncdisp, то увидите там:
scale_factor = 0.01
Для того, чтобы получить данные в Кельвинах, нужно умножить все на scale_factor и прибавить add_offset.
Вы можете просто взять эти цифры из описания файла, либо вытянуть их при помощи следующих команд:
scale_factor = netcdf.getAtt(ncid,3,'scale_factor')
К сожалению, просто так умножить и прибавить не получится. Если вы сейчас попробуете проделать эту операцию, то получите следующую ошибку:
Дело в том, что тип переменной data сейчас int16 и на числа с плавающей запятой они умножаться не хотят. Необходимо перевести данные в тип single
На самом деле можно это сделать уже при копировании данных из переменной netCDF в переменную Матлаб. Далее переводим в Кельвины:
И, если нужно, в Цельсии
Еще немного полезной информации по этому вопросу есть .
наверное должно быть
data_scaled = (data_single *scale_factor) add_off;
вместо
data_scaled = (data*scale_factor) add_off;
2RUS
Да, конечно, спасибо, Руслан, поправил!