NAO индекс в netCDF формате
Задача: перевести ?ндекс Северо-Атлантической Осциляции (NAO) из ASCII в netCDF формат
Решение: используем модули Python - PyNio, numpy, time
?ндексом NAO (а также его близким родственником AO) пользуется огромное количество народа, но найти его в netCDF формате мне не удалось. Пришлось делать самому. Кому нужен просто файлик - вот он (up to 2011.04). Кто хочет посмотреть на очередной пример использования Nio для создания netCDF файла, велкам под кат.
Более подробно про NAO . Если коротко, то NAO это индекс, характеризующий изменчивость атмосферного давления, с которым любят связывать (зачастую успешно) различные явления в океане и атмосфере - от ледовитости СЛО до частоты тропических циклонов. Его упоминание можно найти чуть не в каждой статье посвященной Арктике или северной Атлантике. Тем более странно, что при такой популярности версии NAO в формате netCDF в интернете не нашлось, обычно он распространяется в виде текстовых файлов. Чтобы исправить эту несправедливость я написал небольшой скрипт, при помощи которого можно в принципе конвертировать любой текстовый файл вида:
Год Месяц Значение
в netCDF.
Значения индекса брались с (там же можете найти и AO).
Сам скрипт:
#to netCDF file
#
#Created by Nikolay Koldunov
#koldunovn@gmail.com
#Description in Russian at http://koldunov.net/?p=521
import numpy
import Nio
import os
import time
def timetostep(start_date_time,time_step, present_time):
""" Convert date to amount of timesteps since start date
Usage:
timetostep(start_date_time, time_step, present_time )
Input:
start_date_time - should be string in form of YYYYDDMMhhmmss
time_step - model timestep (deltaT) in seconds
present_time - should be string in form of YYYYDDMMhhmmss
Output: time step
"""
start_date_time_in_python_format = time.strptime(start_date_time,"%Y%m%d%H%M%S")
start_date_time_in_seconds = time.mktime(start_date_time_in_python_format)
present_time_in_python_format = time.strptime(present_time,"%Y%m%d%H%M%S")
present_time_in_seconds = time.mktime(present_time_in_python_format)
seconds_from_start_date = present_time_in_seconds - start_date_time_in_seconds
present_time_step = seconds_from_start_date/time_step
return present_time_step
os.system("rm NAO_conv.nc")
input_file = './norm.nao.monthly.b5001.current.ascii'
ifile = open(input_file, 'r')
lines = ifile.readlines()
nao = numpy.array(())
ttime = numpy.array(())
for line in lines[:]:
ttime = numpy.append(ttime, timetostep("19480101000000", 3600 , line.split()[0]+line.split()[1].zfill(2)+"15000000"))
nao = numpy.append(nao,float(line.split()[2]))
opt = Nio.options()
opt.PreFill = False
opt.HeaderReserveSpace = 4000
f = Nio.open_file("NAO_conv.nc","w",opt)
f.title = "NAO index in netCDF format"
f.source = "http://www.cpc.ncep.noaa.gov/products/precip/CWlink/pna/nao.shtml"
f.author = "Nikolay Koldunov, koldunovn@gmail.com"
f.url = "http://koldunov.net/?p=521"
f.create_dimension('time',ttime.shape[0])
f.create_variable('time','d',('time',))
f.variables['time'].units = "hours since 1948-01-01 00:00:00"
f.variables['time'].calendar = "proleptic_gregorian"
f.variables['time'][:] = ttime[:]
f.create_variable('NAO','d',('time',))
f.variables['NAO'].long_name = "NAO index"
f.variables['NAO'].units = "non dimensional"
f.variables['NAO'][:] = nao
f.close()
Небольшие пояснения. Функция timetostep работает очень похоже на то, что , только наоборот
У нее страшные имена переменных, но уж так мне захотелось сделать в тот момент, когда я ее писал. Нужна она нам для того, чтобы рассчитать для каждой даты, на которую у нас есть индекс (считаем, что индекс задан на 15 число каждого месяца), количество часов прошедшее с "начального" момента времени, который будет стоять в аттрибуте units нашей переменной time. Напомню, что в netCDF файле время может задаваться разными способами и один из них "hours since" - количество часов, прошедшее с какого-нибудь момента времени. В нашем случае это "1948-01-01 00:00:00".
PyNio будет ругаться если файл, уже существует, так что стираем его, если он у нас вдруг уже есть.
Далее стандартно открываем текстовый файл, считываем его построчно в переменную lines, создаем пустые пока переменные nao и ttime. В цикле обрабатываем каждую строку. К переменной time присоединяем результат работы функции timetostep, которой частично передаем значения полученные из нашего текстового файла, а именно год и месяц. Заметьте, что при передаче месяца используется zfill(2), чтобы номер месяца всегда состоял из двух цифр (например не 3, а 03 для марта). Величина временного шага задана в 3600 - что соответствует одному часу в секундах.
Дальше создается netCDF файл, подобно тому как это описано в . ?змерение (dimension) у нас только одно - время. Единицы измеререния - часы с 1 января 1948 года. Можно, при желании, сделать и "seconds since 1948-01-01 00:00:00", тогда нужно будет поменять 3600 на 1 при вызове функции timetostep.
Если вы сконвертируете при помощи этого скрипта какие-нибудь полезные индексы, то с удовольствием размещу их netCDF файлы здесь, либо на Oceanographers.RU для использования людьми, которые не так нежно любят Python как мы с вами
Здравствуйте!
А каким инструментом создается сам график, т.е. изображение ?
Nickolay
Картинку в начале поста я сделал в Ferret. Но, естественно, изображение вы можете создавать в любой программе, которая открывает netCDF и позволяет рисовать графики, от MATLAB до ncview или Pyhton.
brainslugs
Привет Николай! У меня есть глобальный архив месячных осадков с 1901 по 2010 гг. для сетки 0.5 градуса по широте и долготе. Понятие времени в вашем смысле в этом архиве отсутствует. Возможно его надо задавать формально. На моем компутере имеется Питон 25, которым я не владею и не пользуюсь. Возможно ли с помощью вашего скрипта АВТОМАТ?ЧЕСК? и сразу (т.е. в одном запуске программы) конвертировать все мои текстовые файлы в формат NetCDF? ?ли это надо делать отдельно для каждого файла, а их 1320 штук.
Прошу ответить. Спасибо!
The requested URL /koldunov.net/netcdf/NAO_conv.nc was not found on this server
2Vladimir
Привет. Кроме самого питона вам нужны модули для него – Numpy и PyNIO (скороее всего time и os у вас установлены по умолчанию). Конечно скрипт сможет автоматически и сразу сконвертировать ваши файлы в NetCDF, но для этого его надо будет модифицировать (вставить цикл, перебирающий ваши файлы), для чего требуются всё таки некие минимальные знания питона.
Ссылку на файл поправил, спасибо.