OTN Gliders (animated .gif)

One more post about the OTN Gliders… Previous OTN glider posts include:

Below we use data from the OTN Ocean Glider Programme. We utilize the SCITOOLS Python Library for Scientific Computing to create the animated gif.

NOTE: Click on the image below to play the animation

glider_movie2

CLICK on Image to play the ANIMATION

 

import csv
import numpy as np
import urllib2
import StringIO
import pickle
import scitools.easyviz as scit
from matplotlib.transforms import Bbox, TransformedBbox, \
     blended_transform_factory
from mpl_toolkits.axes_grid1.inset_locator import BboxPatch, BboxConnector,\
     BboxConnectorPatch
import matplotlib.pyplot as plt

# Open file
response = urllib2.urlopen('http://glider.ceotr.ca/data/live/sci_water_temp_live.csv')
data = response.read()
data = StringIO.StringIO(data)

# Read file
r = csv.DictReader(data)

# Initialize empty variables
date, lat, lon, depth, temp = [],[],[],[],[]

# Loop to parse data into our variables
for row in r:
    date.append(float(row['unixtime']))
    lat.append(float(row['lat']))
    lon.append(float(row['lon']))
    depth.append(float(row['depth']))
    temp.append(float(row['sci_water_temp']))

# Estimate "distance along transect *******************************************

# First, design a function to estimate great-circle distance
def distance(origin, destination):
    #Source: http://www.platoscave.net/blog/2009/oct/5/calculate-distance-latitude-longitude-python/
    import math
    lat1, lon1 = origin
    lat2, lon2 = destination
    radius = 6371 # km

    dlat = math.radians(lat2-lat1)
    dlon = math.radians(lon2-lon1)
    a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
        * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    d = radius * c

    return d

# Compute distance along transect
dist = np.zeros((np.size(lon)))
for i in range(2,np.size(lon)):
    dist[i] = dist[i-1] + distance([lat[i-1], lon[i-1]], [lat[i], lon[i]])

# Estimate bathymetry **********************************************************
# Load bathymetry file created here: https://oceanpython.org/2013/03/21/bathymetry-topography-srtm30/
T = pickle.load(open('/home/diego/PythonTutorials/SRTM30/topo.p','rb'))

# Compute bathymetry
bathy = np.zeros((np.size(lon)))
for i in range(np.size(lon)):
    cost_func = ((T['lons']-lon[i])**2) + ((T['lats']-lat[i])**2)
    xmin, ymin = np.unravel_index(cost_func.argmin(), cost_func.shape)
    bathy[i] = -T['topo'][xmin, ymin]

# Fuctions for zoom effect ****************************************************
# Source: http://matplotlib.org/dev/users/annotations_guide.html#zoom-effect-between-axes
def connect_bbox(bbox1, bbox2,
                 loc1a, loc2a, loc1b, loc2b,
                 prop_lines, prop_patches=None):
    if prop_patches is None:
        prop_patches = prop_lines.copy()
        prop_patches["alpha"] = prop_patches.get("alpha", 1)*0.2

    c1 = BboxConnector(bbox1, bbox2, loc1=loc1a, loc2=loc2a, **prop_lines)
    c1.set_clip_on(False)
    c2 = BboxConnector(bbox1, bbox2, loc1=loc1b, loc2=loc2b, **prop_lines)
    c2.set_clip_on(False)

    bbox_patch1 = BboxPatch(bbox1, **prop_patches)
    bbox_patch2 = BboxPatch(bbox2, **prop_patches)

    p = BboxConnectorPatch(bbox1, bbox2,
                           #loc1a=3, loc2a=2, loc1b=4, loc2b=1,
                           loc1a=loc1a, loc2a=loc2a, loc1b=loc1b, loc2b=loc2b,
                           **prop_patches)
    p.set_clip_on(False)

    return c1, c2, bbox_patch1, bbox_patch2, p

def zoom_effect(ax1, ax2, xmin, xmax, **kwargs):
    """
    ax1 : the main axes
    ax1 : the zoomed axes
    (xmin,xmax) : the limits of the colored area in both plot axes.

    connect ax1 & ax2. The x-range of (xmin, xmax) in both axes will
    be marked.  The keywords parameters will be used ti create
    patches.

    Source: http://matplotlib.org/dev/users/annotations_guide.html#zoom-effect-between-axes

    """

    trans1 = blended_transform_factory(ax1.transData, ax1.transAxes)
    trans2 = blended_transform_factory(ax2.transData, ax2.transAxes)

    bbox = Bbox.from_extents(xmin, 0, xmax, 1)

    mybbox1 = TransformedBbox(bbox, trans1)
    mybbox2 = TransformedBbox(bbox, trans2)

    prop_patches=kwargs.copy()
    prop_patches["ec"]="r"
    prop_patches["alpha"]=None
    prop_patches["facecolor"]='none'
    prop_patches["linewidth"]=2

    c1, c2, bbox_patch1, bbox_patch2, p = \
        connect_bbox(mybbox1, mybbox2,
                     loc1a=3, loc2a=2, loc1b=4, loc2b=1,
                     prop_lines=kwargs, prop_patches=prop_patches)

    ax1.add_patch(bbox_patch1)
    ax2.add_patch(bbox_patch2)
    ax2.add_patch(c1)
    ax2.add_patch(c2)
    ax2.add_patch(p)

    return c1, c2, bbox_patch1, bbox_patch2, p

# Make plots
nframes = 20
overlap = 0.95
window = np.floor(max(dist)-min(dist)) / (nframes - (nframes*overlap) + overlap)

xmin = 0
xmax = xmin + window
fig1 = plt.figure()
for i in range(0,nframes):
    ax1 = plt.subplot(211)
    plt.fill_between(dist,bathy,1000,color='k')
    plt.scatter(dist,depth,s=15,c=temp,marker='o', edgecolor='none')
    plt.ylim((-0.5,max(depth)+5))
    ax1.set_ylim(ax1.get_ylim()[::-1])
    cbar = plt.colorbar(orientation='vertical', extend='both')
    cbar.ax.set_ylabel('Temperature ($^\circ$C)')
    plt.title('OTN Glider transect')
    plt.ylabel('Depth (m)')
    ax1.set_xlim(min(dist),max(dist))

    ax2 = plt.subplot(212)
    plt.fill_between(dist,bathy,1000,color='k')
    plt.scatter(dist,depth,s=15,c=temp,marker='o', edgecolor='none')
    plt.ylim((-0.5,max(depth)+5))
    ax2.set_ylim(ax2.get_ylim()[::-1])
    plt.ylabel('Depth (m)')
    plt.xlabel('Distance along transect (km)')
    ax2.set_xlim(xmin,xmax)
    zoom_effect(ax1, ax2,xmin,xmax)

    # Save figure (without 'white' borders)
    if i < 10:
        plt.savefig('glider_0'+str(i)+'.png', bbox_inches='tight')
    else:
        plt.savefig('glider_'+str(i)+'.png', bbox_inches='tight')

    plt.close()

    xmin = xmax - np.floor(window*overlap)
    xmax = xmin + window

# Make animated gif
scit.movie('glider_*.png',encoder='convert',output_file='glider_movie.gif',fps=4)

Leave a comment