Публикации с меткой «Без рубрики»

Записки океанолога - обработка и визуализация данных

NAO индекс в netCDF формате


Задача: перевести Индекс Северо-Атлантической Осциляции (NAO) из ASCII в netCDF формат
Решение: используем модули Python - PyNio, numpy, time

Индекском NAO (а также его близким родственником AO) пользуется огромное количество народу, но найти его в netCDF формате мне не удалось. Пришлось делать самому. Кому нужен просто файлик - вот он NAO index in netCDF format (up to 2011.04). Кто хочет посмотреть на очередной пример использования Nio для создания netCDF файла, велкам под кат.

Более подробно про NAO можно почитать в википедии. Если коротко, то NAO это индекс, характеризующий изменчивость атмосферного давления, с которым любят связывать (зачастую успешно) различные явления в океане и атмосфере - от ледовитости СЛО, до частоты тропических циклонов. Его упоминание можно найти чуть не в каждой статье посвященной Арктике или северной Атлантике. Тем более странно, что при такой популярности версии NAO в формате netCDF в интернете не нашлось, обычно он распространяется в виде текстовых файлов. Чтобы исправить эту несправедливость я написал небольшой скрипт, при помощи которого можно в принципе конвертировать любой текстовый файл вида:

Год Месяц Значение

в netCDF.
Значения индекса брались с этого сайта (там же можете найти и AO).

Сам скрипт:

#Convert NAO index from http://www.cpc.ncep.noaa.gov/products/precip/CWlink/pna/nao.shtml
#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".

os.system("rm NAO_conv.nc")

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 как мы с вами :)

Записки океанолога - обработка и визуализация данных

Избавляемся от ненужных циклов и ускоряем скрипт на Python

Задача: выбрать из массива данных только данные удовлетворяющие условию и сделать с ними какую ни-будь гадость
Решение: numpy.where

Слухи о тормознутости Python сильно преувеличены, просто нужно уметь его готовить. Конечно скорости C или Fortran вы на нем не добьетесь, но и его вполне можно заставить быстро обрабатывать огромные массивы информации. Если вы хотите считать быстро, то ваш враг номер один в Python (также как и в MATLAB, кстати) это циклы, заданные в явном виде (оператор for). От большинства из них можно избавиться, применяя нехитрые приемы. Об одном таком приеме, позволившем увеличить скорость обработки массива размером более 100 гигабайт в 46 раз, я очень коротко расскажу в этом посте.

Дано: четерехмерный массив с полями температуры (x,y,глубина, время). Поскольку сетка у нас не регулярная, имеются два двумерных массива широт (lat) и долгот (lon).
Задача: вырезать из этого массива хитрую область, и получить среднее по этой области для каждой глубины, за каждый отсчет времени.

Область выглядит следующим образом:

Одним из возможных решений данной задачи является такой код:

for ttime in range(0,487):
    for lev in range(0,51):
        THO_new = []
        for ff in range(285):
            for zz in range(3602):
                if 100 < lon[ff,zz] < 140:
                    if lat[ff,zz] > 66:
                        THO_new.append(ffile.variables["tho"][ttime,lev,ff,zz])
                elif 100 > lon[ff,zz] > 0:
                    if lat[ff,zz] > 80:
                        THO_new.append(ffile.variables["tho"][ttime,lev,ff,zz])
                elif 300 < lon[ff,zz] < 360:
                    if lat[ff,zz] > 80:
                        THO_new.append(ffile.variables["tho"][ttime,lev,ff,zz])

У нас имеется внешний цикл по времени (ttime), внутри него цикл по глубинам (lev), затем цикл по x (ff) и по y (zz). Вот в этом последнем цикле мы и проверяем каждую точку на соответствие нашим условиям по широте и долготе и если она им удовлетворяет, добавляем ее значение в массив (THO_new), с которым будем дальше совершать все необходимые непотребства.
Количество точек в одном шаге по времени, которые небходимо прогнать через циклы и обработать условными операторами составляет в данном случае 52355070 штук, что занимает 2 минуты 18 секунд. Шагов по времени у нас 487, так что ждать окончания работы программы мы будем дооолго.

Способ второй:

i1,j1 = numpy.where((100<lon)&(lon<140)&(lat>66))
i2,j2 = numpy.where((100>lon)&(lon>0)&(lat>80))
i3,j3 = numpy.where((300<lon)&(lon<360)&(lat>80))

for ttime in range(0,487):
    for lev in range(0,51):

        THO_new = []
       
        a = ffile.variables["tho"][ttime,lev,:,:]
        THO_new = numpy.concatenate((THO_new, a[i1,j1]), 0)
        THO_new = numpy.concatenate((THO_new, a[i2,j2]), 0)
        THO_new = numpy.concatenate((THO_new, a[i3,j3]), 0)

Понятное дело, что точки с необходимыми нам координатами будут занимать одинаковое положение во всех полях. Поэтому проще сразу определиться с индексками тех точек что нас интересуют. Для этого используем оператор numpy.where, которому в качестве условия передаем наши пожелания по ограничению региона. К сожалению, конструкции вида 100 <> он не воспринимает, так что небоходимо пользоваться логическими операторами (естественно можно использовать не только AND (&) но и, напримерр OR (|)). В качестве вывода, мы получаем индексы тех точек, что удовлетворяют нашим условиям.

Циклы по времени и глубинам мы оставляем, а вот перебирать каждую точку двумерного поля нам уже не нужно, мы точно знаем какие точки нам нужны. Сначала создаем переменную a, в которую заливаем двумерное поле (это сделано исключительно из-за того что 100 гигабайт в память не влезало :)). Затем добавляем в переменную THO_new те значения, что вписываются в заданную нами область. Дальше уже происходит наложение маски (пропущенных значений) и осреднение THO_new, что для нас в данном контексте не особо важно, поэтому эту часть я не привожу. Время работы нового кода для одного шага по времени составляет 3 секунды.

Записки океанолога - обработка и визуализация данных

CDO (Climate Data Operators) - рабочая лошадка для обработки netCDF файлов

Задача: проводить манипуляции с файлами формата netCDF, в том числе осреднение и выборку по различным осям, установку временной оси, интерполяцию полей, объединение и разделение файлов.
Инструмент: CDO (Climate Data Operators)

Причина, по которой я так долго тянул с постом о cdo, наверное в том, что они настолько незаметны и настолько часто мной используются, что я практически забываю об их существовании, воспринимая больше просто как некие обычные команды шела. Однако без них жизнь человека работающего с netCDF (а также GRIB) файлами становится гораздо неуютнее. На сегодняшний день существует около 400 операторов, позволяющих проводить первичную обработку файлов. Как бы я не любил Python, поручить ему обработку террабайтов информации значит обречь себя на очень долгое ожидание, тогда как cdo, написанные на C++, справляются с крупномасштабными задачами сравнительно быстро, при этом обладают очень простым для понимания синтаксисом.

В посте я расскажу об установке CDO под Ububtu 10.04 и Windows (да, они есть и под винду) покажу как пользоваться несколькими наиболее популярными их функциями.

Записки океанолога - обработка и визуализация данных

F2PY - ускоряем вычисления в Питоне в 500 раз

Лирическое отступление:

Сегодня у меня радостное событие, мне подарили новогодний подарок. Как известно лучший подарок это подарок сделанный своими руками, так и поступил Михаил Иткин из Института Метеорологии им. Макса Планка, подарив мне эту статью. Большое тебе, Миша, человеческое спасибо ) Если у кого появится подобное желание по поводу и без повода - пишите на koldunovn@gmail.com

Собственно статья:

Чистый питон очень сильно проигрывает низкоуровневым языкам программирования, длинные циклы могут замедлить выполнение программы на пару порядков. Часто узкие места можно обойти используя пакеты вроде numpy, в них функции написаны с использованием СИ и Фортрана. Функционала numpy или PyNGL хватит для большинства рутинных задач, но если нужно применить вычисление к каждому элементу массива или, не дай бог, к "бегущему окну" - двигающемуся массиву меньшего размера, то придётся писать рутину самому.

Записки океанолога - обработка и визуализация данных

Массивы в scipy (numpy), шпаргалка.

Решил перевести славную шпаргалку по массивам в scipy. Под катом

Записки океанолога - обработка и визуализация данных

VirtualBox образ системы для океанологов на основе Ubuntu

Задача: Сделать образ Linux системы, содержащей уже установленные программы для океанологов, которым мог бы пользоваться самый прожженный виндузятник.

Инструменты: VirtualBox

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

sudo apt-get install cool-ocean-soft

и получить желаемый результат. Более того, зачастую даже для немного продвинутого в *nix системах человека правильно поставить некоторый океанологический софт представляется задачей нетривиальной. Он даже может после пары часов (в лучшем случае дней) плюнуть на это дело. Если же человек сидит на Виндоуз, то от него потребуются и вовсе титанические усилия, связанные с дополнительными трудностями перехода на новую систему.

Чтобы хотя бы частично избавиться от вопросов типа "почему у меня PyNGL на новой Убунте не устанавливается?" и "что прописать в .bashrc чтобы заработал Ferret" я решил создать образ системы в которой все основные программы о которых рассказывается на koldunov.net были бы уже установлены и работали.

За основу был взят LTS дистрибутив Ubuntu 8.04 . Программы были проинсталированы и более-менее проверены на работоспособность. В результате получился образ системы для VirtualBox, который вы можете развернуть как под Линукс, так и под Виндоуз.

Записки океанолога - обработка и визуализация данных

Визуализация кластерного анализа в Python (модули hcluster и matplotlib)


Задача: провести кластерный анализ и его результат представить в виде дендрограммы.
Инструменты: модули hcluster, matplotlib

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

Записки океанолога - обработка и визуализация данных

Обработка данных в Python, простые вещи

Задача: обработать некие абстрактные данные в python
Интструменты: Python, numpy, ma, glob

Приведу набор не особо связанных между собой простейших приёмов обработки данных которые пригодились мне в последнее время. Они хоть и простейшие, но обнаружить их стоило мне некоторых трудов, поэтому я решил подбить их в один небольшой пост. Если кто-то решит поделиться своими простыми приёмами облегчающими жизнь, в частности с использованием numpy, милости прошу в комменты, с удовольствием добавлю их в пост )

Записки океанолога - обработка и визуализация данных

Создание netCDF файла из бинарных при помощи PyNIO

Задача: перевести данные из бинарного формата в netCDF
Инструменты: PyNIO

В одном из предыдущих постов я рассказывал почему бинарники это далеко не всегда хорошо и зачем нам бывает нужно перевести их в формат netCDF. Там я приводил пример того как можно это сделать при помощи NCL. Здесь я рассмотрю способ который возможно подойдёт большему количеству народа, поскольку не предусматривает установку NCL, а даёт возможность воспользоваться уже установленным в составе PyNGL модулем PyNIO. Этот модуль предназначен в частности для открытия и создания netCDF файлов, и по моим впечатлениям делает это гораздо более простым способом чем NCL (хоть PyNGL и производная NCL :)).

Записки океанолога - обработка и визуализация данных

Создание карты для Google Earth при помощи Python

Задача: отобразить наши данные на Google Earth
Инструменты: Python, PyNGL, convert

Я почему-то всегда думал что создание карт для Google Earth это занятие для избранных. С такой помпой очередной институт всегда анонсировал что его данные теперь и на Google Eatrh, что мне казалось группа программистов денно и ношно трудилась над этой непростой задачей год и вот теперь, наконец, долгожданный .kml файл увидел свет.

При ближайшем рассмотрении всё оказалось просто до тривиальности.

Собственно создание карты будет проводиться при помощи PyNGL, питоновского модуля позволяющего отображать двумерные данные на карте. Основы работы с этим модулем описаны в данном блоге и могут быть найдены по тегу PyNGL.
После мы обрежем карту при помощи convert и создадим простейший .kml файл, который и "натянет" наше изображение на Google Earth.

Поехали.

Записки океанолога - обработка и визуализация данных

Matplotlib (pylab) простые вещи 2

Задача: продолжить получать графику высокого качества не выходя из питона
Инструмент: Matplotlib

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

Метки

.net .NET C# .sort 1.2 2009 2010 404 error admin ajax amazon analytics and apache api archlinux asp.net async asynchronous autocomplete bash blender blog blogengine blogs book bootstrap bot bpython buildout byteflow bzr C c plus plus C++ cache cbv Chaco checkio chrome ci ckeditor class based views clojure closure cms cms с удобной админкой code coding style collectd COM comet competition conference ConfigParser contest Context continuous integration CouchDB coverage CppCMS cpyext cpython crud csrf CSS ctypes curl custom model fields cx_freeze cython database db dbm dbqueries debian debug debugging decorator decorators deploy deployment descriptor design dev devconf developers development diveintopython Django django 1.2 django 1.3 django advent django framework django template django trunk django weblog django-admin-tools django-cms django-compressor django-hosts django-piston django-registration django-sphinx django.admin djangoadvent djangocms djangodash doc documentation drupal e-legion eclipse EGit emacs encoding Enthought epoll erlang event exception ExtJS fabric facebook fastcgi finaloption fixtures fonts forms formset fp framework freebsd freeswitch fs2web ftp fun funcparserlib functional gae gamin gandi generic views gettext gevent gil git github gitosis Google Google App Engine google picasa Google Translate google wave Google Web Toolkit grab grablab greenlet gtd gui haskell hg hgshelve highlighter host hosting how-to howto html html5lib Hudson humor i18n icfpc ide idiomatic image-scripting improvements Internet interpreter ipython ironpython izmenimsya.ru jabber java javascript jenkins jetbrains JIT job jquery json jstree jython kde kiev kiyv kyivpy l10n ldap library libs Life Links linux Linux & Unix LLVM logging logs lxml Mac OS X magic mail markdown Matplotlib Mayavi maybe mediavirus meetup memcache Memcached memory messages metaclass middleware migration mikrotik mkd model models mod_python mod_wsgi mongodb monitoring mptt musicmans.ru musicx mvc my-projects mysql netCDF networkx newforms newforms-admin news nginx Nhibernate nix nose NoSQL numpy oop open source OpenID openoffice opster optimization oracle orm os pagination parsing path patterns pdf PDF-принтер PEP PEP8 performance performance optimization perl personality photo php picture-driven computing PIL pinax pingback pip plasma plone plugin plugins postgresql programming progress bar psycopg2 py2exe pybb pybbm pycamp pycharm pycon pycow pycurl pydev pygtk pylons PyNGL pypy pyqt PyQt4 pyrad pyramid PySide Python Python 2.5 python 2.7 python 3 python c api python speed python-mssql python3 pywinauto Qt Qt4 queue rabbitmq radius raw sql re redis redsolution redsolution cms regexp regular expressions release repoze.bfg RequestContext reusable apps robokassa rss ru ruby ruby-on-rails sample satchmo scalability SciPy scraping screencast search selenium self.error seo server setattr settings setuptools shell sikuli sms snippet socket.io software sorting south sphinx spider sql sqlalchemy sqlite ssh startup step-by-step subdomain subversion svn SyntaxHighlighter system tags tdd tddspry teh drama template templates templatetags test testing thinkpad threading threads tips tips and tricks tools tornadio tornado tornado server tricks tutorial tweepy twisted twitter typography uapycon Ubuntu ucsvlog uml Uncategorized unicode unit test unit testing UnitTest Unladen Swallow upload urllib urls utf-8 uwsgi validation vcs versioning video vim virtualenv Visual Studio vkontakte voip wave web web-devel web-services web-разработка webdev webfaction webkit webpy websockets webtest widget widgets Win API windows Wirbel work wrapper wsgi wxPython wxWidgets wysiwyg xapian xml xmonad xmpp xpath yandex youtube zip zomg zope [cdata[cbv]] [cdata[ci]] [cdata[class based views]] [cdata[continuous integration]] [cdata[django framework]] [cdata[django-sphinx]] [cdata[django]] [cdata[nginx]] [cdata[python]] [cdata[virtualenv]] [cdata[программирование]] автоматизация администрирование администрирование django админка алгоритмы архитектура атрибуты базы данных Без рубрики безопасность библиотеки блоге бот веб-разработка видео Визуализация данных вконтакте Все записи гвидо ван россум граббер графика графы декоратор декораторы дескриптор дескрипторы документация заметки игра жизнь идея интересное киев Клиентам книги конференция личное математика метаклассы модели модули монады морфология мысли невозможное новости о облачные вычисления обо мне Обработка данных оптимизация оптимизация кода Основная лента основы парсинг парсинг сайтов перевод песочница Питон поебень поиск правила кодирования программирование Проектирование производительность работа рабочее размышлизмы Разное разработка разработка приложений разработки регулярные выражения сайт событие события ссылки статьи тестирование тесты Тюмень убунтариум фигня философия формы форум Хабрахабр хакинг хостинг шаблоны шаблоны проектирования эксперимент Эксперименты юмор я пиарюсь Яндекс