# 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

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 = StringIO.StringIO(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

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))

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/

# 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)

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)
```