Ipython notebook. Часть II — пример работы

Задача: Показать ipython notebook в действии. В частности будем рисовать нашу любимую температуру из файла NCEP реанализа.
�?нструменты: ipython notebook, scipy, Basemap

Попробуем использовать ipython notebook, установленный нами в первой части, для чего-нибудь полезного и в процессе ближе познакомимся с его возможностями.

Напомню, что для того, чтобы примеры приведённые в этом посте работали нужно удостовериться, что у вас установлены следующие пакеты:

sudo apt-get install python-scipy python-matplotlib python-mpltoolkits.basemap

Для создания вашей первой сессии в notebook вам просто нужно набрать

ipython notebook

При этом откроется браузер и появится список всех книжек находящихся в папке, если до этого их в папке не было, ipython создаст для вас первую книжку (скорее всего с именем Untitled0) самостоятельно. Кликнув на неё вы попадёте в рабочую область notebook, а ваш курсор будет приветливо помигивать в первой ячейке.

Ячейки бывают нескольких видов. Две самых главных: Code — в них вы будете исполнять свой код, и Markdown — в которых можно писать тексты и форматировать их при помощи маркдауна. Разобраться как переключать вид ячеек, соединять их, двигать, удалять, копировать — не сложно, достаточно потратить пару минут на изучение выпадающего меню и иконок действий.

Чтобы выполнить код или отобразить отформатированный текст в случае маркдаун ячейки, необходимо нажать Shift+Enter. При этом код выполнится (или текст отформатируется) и произойдёт переход к следующей ячейке. В случае с Code ячейками можно также пользоваться комбинацией Ctrl+Enter — в этом случае код выполнится, но ячейка останется активной, а код в ней выделится. Это удобно, когда нужно производить некоторые простые действия, которые не нужно сохранять в notebook, например листинг файлов.

Давайте попробуем сделать уже что-нибудь полезное. В качестве примера, по сложившейся традиции, я выбрал работу с netCDF файлом приземной температуры воздуха NCEP реанализа. Мы будем смотреть, что у файла внутри и рисовать карту.

Сами файлы находятся тут и можно выбрать любой, но в моём случая я взял год 2012. Файл должен находиться в одной папке с записной книжкой, в которой вы его будете обрабатывать.

Для начала откроем его:

from scipy.io import netcdf
f = netcdf.netcdf_file('air.sig995.2012.nc', 'r')

Мы создали объект f, который представляет наш netCDF файл. Тут нужно немножко рассказать о справочной системе ipython notebook, которая во многом напоминает чистый ipython, но, на мой взгляд, удобнее. Для того, чтобы узнать, что за зверь такой наш вновь созданный объект f, мы можем просто поставить после него знак вопроса, выполнить код и получить по нему справку.

Это сработает для любой переменной, функции, объекта или метода. Если просто справка вас не устраивает и хочется копнуть поглубже, то поставьте два вопросительных знака и ipython постарается найти для вас файл с исходным кодом, например, функции, и ту часть в нём, где эта функция определена. В нашем случае открылся исходный код, в котором вводится класс netcdf_file:

Если мы хотим посмотреть доступные нам методы для f, то достаточно поставить точку, и нажать TAB:

остаётся просто выбрать из списка то, что вам нужно и нажать на Enter.

Давайте посмотрим на список переменных в нашем файле (тут я решил обойтись без скриншота 🙂 ):

In [16]:

f.variables

Out[16]:

{'air': <scipy.io.netcdf.netcdf_variable at 0xa854aac>,
 'lat': <scipy.io.netcdf.netcdf_variable at 0xa8547ac>,
 'lon': <scipy.io.netcdf.netcdf_variable at 0xa85488c>,
 'time': <scipy.io.netcdf.netcdf_variable at 0xa85496c>}

Эта информация может пригодиться, поэтому оставляем её в notebook и переходим в следующую ячейку. Мы можем «добыть» ту переменную, которую собираемся отображать — air

air = f.variables['air']

Здесь происходит присвоение значения, а этим лучше лишний раз не заниматься, поэтому переходим в следующую ячейку, где сможем узнать всё про внутренний мир нашей новоиспечённой переменной. В частности нам доступно довольно много методов

При помощи которых мы можем узнать, например, единицы измерения, полное имя и коэффициенты перевода в честные градусы K

Дальше мы подготавливаем данные для отрисовки. К notebook это отношения особого не имеет, поэтому коротенько:

# получаем из netCDF переменной собственно данные
airData = air[:]
# переводим в цельсии
airDataCels = ((airData*air.scale_factor)+air.add_offset)-273.15
# вытаскиваем сразу данны по широтам и долготам
lat = f.variables['lat'][:]
lon = f.variables['lon'][:]
# импортируем numpy, который нам понадобится в дальнейшем
import numpy
# делаем из одномерных широт и долгот двумерные
lons, lats = numpy.meshgrid(lon,lat)

При этом надо понимать, что в процессе написания даже этого небольшого куска кода я получал информацию о переменных, что-то пробовал, проверял всё ли получается. Но при этом в отличии от работы в консольном ipython «мусорный» вывод результатов исполнения команд, тот который нужен только раз, не заслоняет действительно необходимый и полезный. Так, например, я могу не вызывать снова и снова размерность моей основной переменной, чтобы проверять правильно ли создаются матрицы для широты и долготы достаточно вывести её один раз и она всегда будет перед глазами на знакомом месте.

Пришло время нам нарисовать нашу карту. Для того, чтобы графика генерируемая Matplotlib встраивалась в notebook нужно выполнить:

%pylab inline

Дальше мы делаем четыре отдельные ячейки. �?мпортируем Basemap

from mpl_toolkits.basemap import Basemap

Во второй ячейке мы будем генерировать простейшую карту при помощи Basemap.

m = Basemap(llcrnrlon=0,llcrnrlat=40,urcrnrlon=190,urcrnrlat=85,projection='mill', resolution='l')

Обычно саму карту (проекцию, нулевые широты и долготы) мы меняем редко, а процесс её генерации не быстрый, так что лучше оставить этот код в отдельной ячейке, чтобы исполнять его только тогда, когда это необходимо.

То же справедливо и для перевода наших широт и долгот в координаты рисунка, их достаточно сделать один раз:

x, y = m(lons, lats)

А вот следующий код помещаем весь в одну ячейку, поскольку каждый раз, когда мы захотим перерисовать карту, изменив интересующий нас день нужно будет исполнять весь этот код:

# Создаём рисунок и задаём его размеры
fig = plt.figure(figsize=(15,15))
# Выбираем день года
dayNumber = 85
# Рисуем береговую линию
m.drawcoastlines(linewidth=1)
# Рисуем границы стран
m.drawcountries(linewidth=0.5)
# Рисуем границу карты
m.drawmapboundary
# Создаём карту с залитыми изолинииями, 20 интервалов
cs = m.contourf(x,y,airDataCels[dayNumber,:,:],20)
# Создаём легенду
cbar = m.colorbar(cs,location='bottom',pad="5%")
# Подписываем легенду
cbar.set_label(r'$^{\circ}\mathrm{C}$')
# Переводим время в человеческое
difference1 = datetime.timedelta(hours=time[dayNumber])
present = first_date+difference1
# Отрисовываем заголовок
plt.title(present.ctime())

В результате у вас в тело notebook будет вставлена карта, которую вы сможете тут же обновлять, меняя день (dayNumber) и исполняя только код из последней ячейки. Никаких всплывающих окон или файлов на диске — всё в одном месте и код и результат:

Надеюсь, что я убедил вас хотя бы попробовать ipython notebook. Буду рад услышать ваши отзывы о нём в комментариях.

Вынесу сюда комментарий от Сергея:
«Можно добавить, что готовый ноутбук можно выложить текстовым (JSON) файлом на любой pastebin, и потом его показывать, вместе с формулами и графиками всем желающим, используя сервис http://nbviewer.ipython.org/

http://tmblr.co/ZQhv1xUASdma

Очень удобно, чтоб делиться с коллегами графиками и результатами расчетов.»

Вот, к примеру, сессия похожая на ту, что описана в этом посте.