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