python4oceanographers

Turning ripples into waves

How to use IPython notebook

(Updating my exercises and examples for IPython Notebook class. This post was written in Portuguese.)

Exercício 01:

Noções básicas de como mexer no notebook:

* Cada célula representa uma etapa do seu código executada separadamente.
* Para executar a célula digite o código e aperte "shitf+enter" quando terminar.
* Para cancelar/sair de uma célula apert "ESC".
* Para acessar um menu de "help" aperte "CTRL+m" e depois "h".
In [2]:
from matplotlib.pylab import *
In [3]:
# Primeiro gráfico.
plot([1, 2, 3], 'k--')
xlabel("1, 2, 3")
ylabel(u"Contando 1, 2, 3")
title(u"Nosso primeiro plot!")
Out[3]:
<matplotlib.text.Text at 0x7fcdc8064a10>

Digite "comando"? e aperte "shift+enter" para acessar o help daquele comando. Exemplo:

In [4]:
plot?

Agora modifique o gráfico acima e brinque com o notebook antes de passar para o próximo exercício.

In [5]:
plot([1, 2, 3], 'ro')
xlabel("a, b, c")
ylabel(u"?")
title(u"?")
axis([-0.1, 2.1, 0.8, 3.1])
Out[5]:
[-0.1, 2.1, 0.8, 3.1]

Exercício 02:

O script abaixo plota o mapa com as estações e um perfil da batimetria.

Apesar de ser um pouco mais complicado que o nosso primeiro exemplo tente personalizar os seus gráficos.

(Dica: comece mudando o colormap da batimetria)

In [6]:
import os
from glob import glob

import gsw
import numpy as np
import matplotlib.pyplot as plt

from netCDF4 import Dataset
from oceans.ff_tools import wrap_lon360
from mpl_toolkits.basemap import Basemap, shiftgrid, cm

def break_lines(line):
    return [float(num) for num in line.strip().split()]

def get_topo(url, m):
    etopodata = Dataset(url)
    try:
        topoin = etopodata.variables['ROSE'][:]
        lons = etopodata.variables['ETOPO05_X'][:]
        lats = etopodata.variables['ETOPO05_Y'][:]
        topoin, lons = shiftgrid(180., topoin, lons, start=False)
    except:
        topoin = etopodata.variables['topo'][:]
        lons = etopodata.variables['topo_lon'][:]
        lons = wrap_lon360(lons)
        lats = etopodata.variables['topo_lat'][:]        
        topoin, lons = shiftgrid(180., topoin, lons, start=False)
    nx = int((m.xmax - m.xmin) / 5000.) + 1
    ny = int((m.ymax - m.ymin) / 5000.) + 1
    return m.transform_scalar(topoin, lons, lats, nx, ny)


def bathymetry_angle(start=0, end=9):
    opposite = depth[end] - depth[start]
    adjacent = dist[end] - dist[start]
    return np.arctan2(-opposite, adjacent) * 180 / np.pi
In [7]:
lista = sorted(glob(os.path.join('./data/cruise', '*.dat')))

depth, lat, lon = [], [], []
for fname in lista:
    with open(fname, 'r') as f:
        lines = f.readlines()
        d, la, lo = break_lines(lines[0])[3:]
        lon.append(lo)
        lat.append(la)
        depth.append(d)
In [8]:
print('\n'.join(lista))
./data/cruise/estacao01.dat
./data/cruise/estacao02.dat
./data/cruise/estacao03.dat
./data/cruise/estacao04.dat
./data/cruise/estacao05.dat
./data/cruise/estacao06.dat
./data/cruise/estacao07.dat
./data/cruise/estacao08.dat
./data/cruise/estacao09.dat
./data/cruise/estacao10.dat
./data/cruise/estacao11.dat
./data/cruise/estacao12.dat
./data/cruise/estacao13.dat
./data/cruise/estacao14.dat
./data/cruise/estacao15.dat

In [9]:
dist = gsw.distance(lon, lat)
dist = np.r_[0, np.cumsum(dist)] / 1e3
tangent = bathymetry_angle(0, 9)
print("Shelf angle: %.4f" % tangent)

fig, ax = plt.subplots(figsize=(7, 4), facecolor='w')
ax.fill_between(dist, max(depth), depth, color='0.75')
ax.plot(dist, depth, color='k')
ax.set_ylim(0, max(depth))
ax.set_xlim(-5, max(dist) + 10)
ax.invert_yaxis()
ax.set_ylabel("Depth [db]")
ax.set_xlabel("Distance [km]")
ax.plot(dist, len(dist) * [0], 'kv')
ax.xaxis.tick_bottom()
Shelf angle: -67.9015

In [10]:
offset = 2.
llcrnrlon, urcrnrlon = min(lon) - offset, max(lon) + offset
llcrnrlat, urcrnrlat = min(lat) - offset, max(lat) + offset

m = Basemap(llcrnrlon=llcrnrlon, urcrnrlon=urcrnrlon,
            llcrnrlat=llcrnrlat, urcrnrlat=urcrnrlat,
            resolution='i', projection='merc')
fig, ax = plt.subplots(figsize=(7, 7))
m.ax = ax

try:
    topodata = get_topo('/home/filipe/00-NOBKP/OcFisData/etopo5.nc', m)
except:
    topodata = get_topo('http://ferret.pmel.noaa.gov/thredds/dodsC/data/PMEL/etopo5.nc', m)
    

im = m.imshow(topodata, cm.GMT_haxby)
m.drawstates()
m.drawcountries()
m.drawcoastlines()
m.fillcontinents()
meridians = np.arange(int(llcrnrlon), int(urcrnrlon), 1.)
parallels = np.arange(int(llcrnrlat), int(urcrnrlat), 1.)

m.plot(lon, lat, 'r*', latlon=True)
cb = m.colorbar(im, 'right', size='5%', pad='2%')
kw = dict(fontsize=12, fontweight='demibold')
m.drawparallels(parallels, labels=[1, 0, 0, 0], **kw)
_ = m.drawmeridians(meridians, labels=[0, 0, 0, 1], **kw)

Encontre no script a linha que calcula a distância usando a latitude e a longitude.

Observe as estações estão dispostas numa linha perpendicular à costa. Para obtermos velocidades ao longo e cruzando a secção precisamos saber o ângulo dessa seção com o norte verdadeiro.

Isso é muito útil para comparar dados perfiladores contínuos como ADCP (que nos fornece dados em coordenadas geográficas) com as velocidades calculadas por método dinâmico.

Exercício 03:

O script abaixo lê os dados hidrográficos e plota um perfil de salinidade e temperatura. Note que ele é uma função, logo, precisamos chamar ela para executá-la.

In [11]:
import os
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as AA
from mpl_toolkits.axes_grid1 import host_subplot

deg = u"\u00b0"

def plot_station(est=15):
    if est < 10:
        est = '0%s' % est
    fname = 'estacao%s.dat' % est
    fname = os.path.join('./data/cruise', fname)

    P, T, S = np.loadtxt(fname, unpack=True, usecols=(0, 3, 4),
                        skiprows=1)

    fig = plt.figure(figsize=(4.2, 6))

    ax0 = host_subplot(111, axes_class=AA.Axes)
    new = ax0.get_grid_helper()
    ax0.axis["bottom"] = new.new_fixed_axis(loc="bottom",
                        offset=(0, -40),
                        axes=ax0)
    p0, = ax0.plot(T, P, linewidth=2.0,
                color='green', label=r'Temperature')

    ax0.set_ylabel("Pressure [dbar]")
    ax0.set_xlabel(u"Temperature[%sC]" % deg)
    ax0.axis["bottom"].label.set_color(p0.get_color())
    ax0.set_title("CTD %s" % est)

    ax1 = ax0.twiny()
    new = ax1.get_grid_helper()
    ax1.axis["top"] = new.new_fixed_axis(loc="bottom",
                                                    offset=(0, 0),
                                                    axes=ax1)
    p1, = ax1.plot(S, P, linewidth=2.0,
                color='blue', label=r'Salinity')

    ax1.set_xlabel("Salinity [Kg g$^{-1}$]")
    ax1.axis["top"].label.set_color(p1.get_color())
    ax1.invert_yaxis()
    ax1.axis("tight")

    ax0.legend(shadow=True, fancybox=True, numpoints=1,
            loc=2, bbox_to_anchor=(.6, 0.2))

Primeiro vamos chamar a função com o argumento default.

In [12]:
plot_station()

Exercício:

Crie um loop para plotar todas as estações.

Exercício 04:

Esse script produz um diagrama TS espalhado com os mesmos dados da secção oceanográfica anterior.

In [13]:
import os
from glob import glob

import gsw
import numpy as np
import matplotlib.pyplot as plt

from pandas import DataFrame

def basename(fname):
    return os.path.splitext(os.path.basename(fname))

def read_station(fname):
    P, T, S = np.loadtxt(fname, unpack=True, usecols=(0, 3, 4),
                         skiprows=1)
    column = basename(fname)[0]
    return (DataFrame(T, index=P, columns=[column]),
            DataFrame(S, index=P, columns=[column]))
In [14]:
lista = sorted(glob(os.path.join('./data/cruise', '*.dat')))

first = lista.pop(0)
tmp, sal = read_station(first)

for fname in lista:
    T, S = read_station(fname)
    tmp = tmp.join(T, how='right')
    sal = sal.join(S, how='right')

Te = np.arange(0, 32, 2)
Se = np.arange(32, 38.25, 0.25)

Sg, Tg = np.meshgrid(Se, Te)
cnt = np.arange(20, 34)

sigma_theta = gsw.sigma0_pt0_exact(Sg, Tg)

fig, ax = plt.subplots(figsize=(6, 6))
ax.plot(sal, tmp, 'k.')
ax.set_ylabel(u"Temperatura u\u00b0C")  # Unicode.
ax.set_xlabel(r"Salinidade [g kg$^{-1}$]")  # Latex.

cs = ax.contour(Se, Te, sigma_theta, colors='black', levels=cnt)
ax.clabel(cs, fontsize=9, inline=1, fmt='%2.1f')
_ = ax.axis([31.8, 37.2, 0.0, 30.0])
In [15]:
HTML(html)
Out[15]:

This post was written as an IPython notebook. It is available for download or as a static html.

Creative Commons License
python4oceanographers by Filipe Fernandes is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Based on a work at https://ocefpaf.github.io/.

Comments